@nicia-ai/typegraph 0.44.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 -43
- 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 -39
- 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 -44
- 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 -40
- 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-XMYJY7NI.js → chunk-2LG2XB2M.js} +3 -3
- package/dist/{chunk-XMYJY7NI.js.map → chunk-2LG2XB2M.js.map} +1 -1
- package/dist/{chunk-QGKILWGZ.cjs → chunk-2NA5DYLO.cjs} +4 -4
- package/dist/{chunk-QGKILWGZ.cjs.map → chunk-2NA5DYLO.cjs.map} +1 -1
- package/dist/{chunk-5MUSU4ZP.cjs → chunk-3DHZCOT7.cjs} +20 -20
- package/dist/chunk-3DHZCOT7.cjs.map +1 -0
- package/dist/{chunk-OVUUTCPJ.cjs → chunk-4UGOKMI5.cjs} +268 -150
- package/dist/chunk-4UGOKMI5.cjs.map +1 -0
- package/dist/{chunk-FRHHDHKH.js → chunk-5262ZMTR.js} +26 -5
- package/dist/chunk-5262ZMTR.js.map +1 -0
- package/dist/{chunk-HOIFFY4M.js → chunk-5763DULU.js} +248 -76
- package/dist/chunk-5763DULU.js.map +1 -0
- package/dist/{chunk-7G32LIQM.js → chunk-5UVRGXD3.js} +277 -7
- package/dist/chunk-5UVRGXD3.js.map +1 -0
- package/dist/{chunk-IIT5K7SK.cjs → chunk-62ZP23AW.cjs} +15 -15
- package/dist/{chunk-IIT5K7SK.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-QYWINYEA.cjs → chunk-7BQXPCGN.cjs} +830 -170
- 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-7GT72YHH.cjs +1979 -0
- package/dist/chunk-7GT72YHH.cjs.map +1 -0
- package/dist/{chunk-SQRD2CYF.js → chunk-7VQXLT5O.js} +717 -76
- package/dist/chunk-7VQXLT5O.js.map +1 -0
- package/dist/{chunk-BCP7LLOY.js → chunk-7Z5OR7KO.js} +2706 -625
- 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-FMMIX6N4.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-PAW2XUZN.js → chunk-ASTI57H3.js} +3 -3
- package/dist/{chunk-PAW2XUZN.js.map → chunk-ASTI57H3.js.map} +1 -1
- package/dist/{chunk-FMGEZBAQ.js → chunk-BKCUOV7A.js} +27 -5
- package/dist/chunk-BKCUOV7A.js.map +1 -0
- package/dist/chunk-BSFJMMV3.cjs +268 -0
- package/dist/chunk-BSFJMMV3.cjs.map +1 -0
- package/dist/{chunk-63KCKSSH.js → chunk-C23WSN5E.js} +209 -24
- package/dist/chunk-C23WSN5E.js.map +1 -0
- package/dist/{chunk-JRP3VGHS.js → chunk-CBTIUB76.js} +3 -3
- package/dist/{chunk-JRP3VGHS.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-46GDII45.js → chunk-DCQVHAYQ.js} +5 -5
- package/dist/{chunk-46GDII45.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-BNUFUFAU.js → chunk-HFHTMECK.js} +7 -7
- package/dist/chunk-HFHTMECK.js.map +1 -0
- package/dist/{chunk-TFMVL4QH.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-2Y4IFKW7.js → chunk-JXA2ZP2Q.js} +6 -17
- 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-K5ELX2GT.js +248 -0
- package/dist/chunk-K5ELX2GT.js.map +1 -0
- package/dist/chunk-LBJKZXDE.cjs +257 -0
- package/dist/chunk-LBJKZXDE.cjs.map +1 -0
- package/dist/{chunk-FGO5JFVJ.cjs → chunk-M4BDU5RX.cjs} +12 -12
- package/dist/{chunk-FGO5JFVJ.cjs.map → chunk-M4BDU5RX.cjs.map} +1 -1
- package/dist/{chunk-MIJKEVV7.js → chunk-MSY7FSX4.js} +37 -4
- package/dist/chunk-MSY7FSX4.js.map +1 -0
- package/dist/{chunk-ST3LPB2V.cjs → chunk-MUK4BU7K.cjs} +788 -146
- package/dist/chunk-MUK4BU7K.cjs.map +1 -0
- package/dist/{chunk-MCHP7RHZ.cjs → chunk-MXJDTH5B.cjs} +64 -41
- package/dist/chunk-MXJDTH5B.cjs.map +1 -0
- package/dist/{chunk-2VLBGQBY.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-EE7N5XXQ.cjs → chunk-NK5Q7UNE.cjs} +10 -21
- package/dist/chunk-NK5Q7UNE.cjs.map +1 -0
- package/dist/{chunk-PHXITZE4.js → chunk-NMWDXFPH.js} +4 -4
- package/dist/{chunk-PHXITZE4.js.map → chunk-NMWDXFPH.js.map} +1 -1
- package/dist/{chunk-FSXTPBRN.js → chunk-NQ6BRJBE.js} +416 -850
- 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-STQ3BSED.cjs → chunk-PNN7RHVR.cjs} +66 -44
- 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-BEFM74L2.js → chunk-QLRESYPU.js} +637 -493
- package/dist/chunk-QLRESYPU.js.map +1 -0
- package/dist/{chunk-SBPC5IP3.js → chunk-QWX5YA3K.js} +784 -202
- package/dist/chunk-QWX5YA3K.js.map +1 -0
- package/dist/{chunk-TCRIQMBU.js → chunk-RJS7DECT.js} +8 -9
- package/dist/chunk-RJS7DECT.js.map +1 -0
- package/dist/{chunk-6JZUSDY2.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-IJTLXNGJ.js → chunk-T4XNKYXB.js} +780 -127
- package/dist/chunk-T4XNKYXB.js.map +1 -0
- package/dist/{chunk-PDGEXGS6.cjs → chunk-TQR4KBY2.cjs} +354 -182
- 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-NN3QSOVS.cjs → chunk-U5SON7R2.cjs} +27 -27
- package/dist/{chunk-NN3QSOVS.cjs.map → chunk-U5SON7R2.cjs.map} +1 -1
- package/dist/{chunk-A2I2XO52.cjs → chunk-U63GDNRC.cjs} +32 -26
- package/dist/chunk-U63GDNRC.cjs.map +1 -0
- package/dist/{chunk-YNULOIR5.cjs → chunk-UDISNXDL.cjs} +64 -43
- package/dist/chunk-UDISNXDL.cjs.map +1 -0
- package/dist/{chunk-GWEDD3DH.js → chunk-UV3SN74I.js} +5 -5
- package/dist/{chunk-GWEDD3DH.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-EFELJVLA.js → chunk-VGTJPTIC.js} +28 -5
- package/dist/chunk-VGTJPTIC.js.map +1 -0
- package/dist/chunk-VQH4VAWD.cjs +12 -0
- package/dist/{chunk-EPTSMFH7.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-3PRKZW6D.cjs → chunk-XBYVV3MP.cjs} +60 -5
- package/dist/chunk-XBYVV3MP.cjs.map +1 -0
- package/dist/{chunk-GFRGG2US.cjs → chunk-XCAGZAKP.cjs} +7 -7
- package/dist/{chunk-GFRGG2US.cjs.map → chunk-XCAGZAKP.cjs.map} +1 -1
- package/dist/{chunk-XR4YZFKW.cjs → chunk-XDF2UPEQ.cjs} +3864 -1783
- package/dist/chunk-XDF2UPEQ.cjs.map +1 -0
- package/dist/{chunk-7V2FGGI2.cjs → chunk-XMQSEJCF.cjs} +632 -1080
- 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-66UVLHQA.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-HJH3RMXG.cjs → chunk-YAAM3M2S.cjs} +10 -10
- package/dist/{chunk-HJH3RMXG.cjs.map → chunk-YAAM3M2S.cjs.map} +1 -1
- package/dist/{chunk-ATLN63JA.js → chunk-YBFHZUXX.js} +6 -6
- package/dist/{chunk-ATLN63JA.js.map → chunk-YBFHZUXX.js.map} +1 -1
- package/dist/{chunk-K3BUWSFR.js → chunk-YDFDBE6D.js} +119 -6
- package/dist/chunk-YDFDBE6D.js.map +1 -0
- package/dist/{chunk-OSZPLZIV.cjs → chunk-YVWGEQJE.cjs} +318 -132
- 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 -41
- package/dist/core/index.d.cts +4 -5
- package/dist/core/index.d.ts +4 -5
- package/dist/core/index.js +8 -9
- package/dist/{ddl-eWg7hx6R.d.cts → ddl-BJcOp4WZ.d.cts} +3 -3
- package/dist/{ddl-D5369kOY.d.ts → ddl-BXfGHbPN.d.ts} +3 -3
- package/dist/graph-extension/index.cjs +26 -23
- 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 -8
- package/dist/graph-merge/index.cjs +2459 -655
- 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 -468
- package/dist/graph-merge/index.js.map +1 -1
- package/dist/{index-By89Sezh.d.ts → index-BSHvKfok.d.ts} +221 -10
- package/dist/{index-DcQ3Sxs-.d.cts → index-DxaYCv8Y.d.cts} +221 -10
- package/dist/index.cjs +330 -269
- 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 -50
- 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 -50
- 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 -24
- package/dist/interchange/index.js.map +1 -1
- package/dist/{manager-B0KjKE93.d.ts → manager-CfZAimti.d.ts} +36 -5
- package/dist/{manager-Cn0NFIhN.d.cts → manager-HGk6E_HW.d.cts} +36 -5
- package/dist/{materialize-indexes-BD4V3svD.d.ts → materialize-indexes-6A7dWGtb.d.cts} +10 -2
- package/dist/{materialize-indexes-DVRhd5h4.d.cts → materialize-indexes-BMJP6Tms.d.ts} +10 -2
- package/dist/{postgres-DaEWvN4x.d.cts → postgres-DFYWENdR.d.cts} +1961 -439
- package/dist/{postgres-u0a0HN2D.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 -49
- package/dist/schema/index.d.cts +9 -16
- package/dist/schema/index.d.ts +9 -16
- package/dist/schema/index.js +23 -22
- package/dist/{searchable-CnYEancP.d.ts → searchable-9OQoPuRs.d.ts} +1 -2
- package/dist/{searchable-BT7j9_IK.d.cts → searchable-CIje5XYD.d.cts} +1 -2
- package/dist/{sqlite-BrMoSsI7.d.cts → sqlite-DerU5tc7.d.ts} +2029 -347
- package/dist/{sqlite-CHhZUyO5.d.ts → sqlite-DitnISa9.d.cts} +2029 -347
- package/dist/{store-view-Bvdku0Ht.d.ts → store-DawaWWjJ.d.ts} +3145 -2556
- package/dist/{store-view-w-md0nQ4.d.cts → store-RwTJx8LX.d.cts} +3145 -2556
- package/dist/{temporal-BCORwUau.d.cts → temporal-Bn-Fi8FJ.d.cts} +1 -1
- package/dist/{temporal--x9T8K4S.d.ts → temporal-BtM4UALv.d.ts} +1 -1
- package/dist/{types-6-WJmSD4.d.cts → types-CoIx8HX5.d.cts} +1 -1
- package/dist/{types-Cjvkj0jA.d.ts → types-HkveCCx0.d.cts} +866 -21
- package/dist/{types-Cjvkj0jA.d.cts → types-HkveCCx0.d.ts} +866 -21
- package/dist/{types-COODtTJU.d.ts → types-KFfk-8Ah.d.ts} +1 -1
- package/dist/{where-CUQmCR6d.d.cts → where--fk7_0kv.d.cts} +1 -1
- package/dist/{where-5xVawAwL.d.ts → where-ws5hf-Ov.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-2BIG7U6E.cjs +0 -83
- package/dist/chunk-2BIG7U6E.cjs.map +0 -1
- package/dist/chunk-2L54C2C2.js +0 -144
- package/dist/chunk-2L54C2C2.js.map +0 -1
- package/dist/chunk-2VLBGQBY.cjs.map +0 -1
- package/dist/chunk-2WDD2NO3.js +0 -59
- package/dist/chunk-2WDD2NO3.js.map +0 -1
- package/dist/chunk-2Y4IFKW7.js.map +0 -1
- package/dist/chunk-35S6P5ZU.js +0 -27
- package/dist/chunk-35S6P5ZU.js.map +0 -1
- package/dist/chunk-3PRKZW6D.cjs.map +0 -1
- package/dist/chunk-4MB3AQAQ.js.map +0 -1
- package/dist/chunk-4SZ6XPTG.cjs +0 -12
- package/dist/chunk-5MUSU4ZP.cjs.map +0 -1
- package/dist/chunk-63KCKSSH.js.map +0 -1
- package/dist/chunk-66UVLHQA.cjs.map +0 -1
- package/dist/chunk-6JZUSDY2.cjs.map +0 -1
- package/dist/chunk-764JHTLT.cjs +0 -15
- package/dist/chunk-764JHTLT.cjs.map +0 -1
- package/dist/chunk-7G32LIQM.js.map +0 -1
- package/dist/chunk-7V2FGGI2.cjs.map +0 -1
- package/dist/chunk-A2I2XO52.cjs.map +0 -1
- package/dist/chunk-A4PBRX4C.cjs +0 -100
- package/dist/chunk-A4PBRX4C.cjs.map +0 -1
- package/dist/chunk-ACSVZPK7.cjs.map +0 -1
- package/dist/chunk-ALFUGRYB.cjs +0 -1282
- package/dist/chunk-ALFUGRYB.cjs.map +0 -1
- package/dist/chunk-B75XRV3O.js +0 -125
- package/dist/chunk-B75XRV3O.js.map +0 -1
- package/dist/chunk-BCP7LLOY.js.map +0 -1
- package/dist/chunk-BEFM74L2.js.map +0 -1
- package/dist/chunk-BNUFUFAU.js.map +0 -1
- package/dist/chunk-C4F7VJ5D.cjs.map +0 -1
- package/dist/chunk-CPEL3YIR.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-EE7N5XXQ.cjs.map +0 -1
- package/dist/chunk-EFELJVLA.js.map +0 -1
- package/dist/chunk-EPTSMFH7.cjs +0 -12
- 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-FMGEZBAQ.js.map +0 -1
- package/dist/chunk-FMMIX6N4.js.map +0 -1
- package/dist/chunk-FRHHDHKH.js.map +0 -1
- package/dist/chunk-FSXTPBRN.js.map +0 -1
- package/dist/chunk-G6Q5UM7U.js.map +0 -1
- package/dist/chunk-GYA4JRP5.js.map +0 -1
- package/dist/chunk-HOHAJ2NR.cjs +0 -61
- package/dist/chunk-HOHAJ2NR.cjs.map +0 -1
- package/dist/chunk-HOIFFY4M.js.map +0 -1
- package/dist/chunk-IIMQJYAM.js +0 -81
- package/dist/chunk-IIMQJYAM.js.map +0 -1
- package/dist/chunk-IJTLXNGJ.js.map +0 -1
- package/dist/chunk-ITE4IXAK.js +0 -25
- package/dist/chunk-ITE4IXAK.js.map +0 -1
- package/dist/chunk-K3BUWSFR.js.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-MCHP7RHZ.cjs.map +0 -1
- package/dist/chunk-MIJKEVV7.js.map +0 -1
- package/dist/chunk-NCX65HBY.cjs +0 -1396
- package/dist/chunk-NCX65HBY.cjs.map +0 -1
- package/dist/chunk-OSZPLZIV.cjs.map +0 -1
- package/dist/chunk-OVUUTCPJ.cjs.map +0 -1
- package/dist/chunk-PDGEXGS6.cjs.map +0 -1
- package/dist/chunk-QB6VMOJ2.cjs.map +0 -1
- package/dist/chunk-QMQLUA66.js +0 -12
- package/dist/chunk-QMQLUA66.js.map +0 -1
- package/dist/chunk-QYWINYEA.cjs.map +0 -1
- package/dist/chunk-S4KQ5LV4.js.map +0 -1
- package/dist/chunk-SBPC5IP3.js.map +0 -1
- package/dist/chunk-SJDMVITW.cjs.map +0 -1
- package/dist/chunk-SNXVDZAJ.js.map +0 -1
- package/dist/chunk-SQRD2CYF.js.map +0 -1
- package/dist/chunk-ST3LPB2V.cjs.map +0 -1
- package/dist/chunk-STQ3BSED.cjs.map +0 -1
- package/dist/chunk-SVJ5GEXW.cjs.map +0 -1
- package/dist/chunk-TCRIQMBU.js.map +0 -1
- package/dist/chunk-TDXIBCGY.cjs.map +0 -1
- package/dist/chunk-TFMVL4QH.js.map +0 -1
- package/dist/chunk-TRF4EBJT.cjs +0 -30
- package/dist/chunk-TRF4EBJT.cjs.map +0 -1
- package/dist/chunk-TVLKA4AY.js +0 -94
- package/dist/chunk-TVLKA4AY.js.map +0 -1
- package/dist/chunk-UR7W5YQK.js.map +0 -1
- package/dist/chunk-VITTKBWF.js +0 -1263
- package/dist/chunk-VITTKBWF.js.map +0 -1
- package/dist/chunk-WBUFJ7BS.cjs +0 -131
- package/dist/chunk-WBUFJ7BS.cjs.map +0 -1
- package/dist/chunk-XR4YZFKW.cjs.map +0 -1
- package/dist/chunk-YNULOIR5.cjs.map +0 -1
- package/dist/chunk-ZDH3DX3C.cjs +0 -30
- package/dist/chunk-ZDH3DX3C.cjs.map +0 -1
- package/dist/chunk-ZTAJL4DT.cjs +0 -85
- package/dist/chunk-ZTAJL4DT.cjs.map +0 -1
- package/dist/define-graph-DVF-oN1i.d.cts +0 -173
- package/dist/define-graph-SvYXOl78.d.ts +0 -173
|
@@ -1,48 +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-A2I2XO52.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
|
-
require('../chunk-
|
|
36
|
-
var
|
|
37
|
-
require('../chunk-TDXIBCGY.cjs');
|
|
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');
|
|
38
35
|
var zod = require('zod');
|
|
39
36
|
|
|
40
37
|
// src/graph-merge/canonical-props.ts
|
|
41
38
|
function canonicalizeProps(props) {
|
|
42
|
-
return JSON.stringify(props,
|
|
39
|
+
return JSON.stringify(props, chunkPWLJ77UV_cjs.sortedReplacer);
|
|
43
40
|
}
|
|
44
41
|
function canonicalValueKey(value) {
|
|
45
|
-
return JSON.stringify(value,
|
|
42
|
+
return JSON.stringify(value, chunkPWLJ77UV_cjs.sortedReplacer);
|
|
46
43
|
}
|
|
47
44
|
function edgeStateSignature(edge) {
|
|
48
45
|
return JSON.stringify([
|
|
@@ -103,8 +100,834 @@ function compareMergeKeys(left, right) {
|
|
|
103
100
|
return leftKind < rightKind ? -1 : leftKind > rightKind ? 1 : 0;
|
|
104
101
|
}
|
|
105
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
|
+
|
|
106
919
|
// src/graph-merge/state-diff.ts
|
|
107
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
|
+
}
|
|
108
931
|
async function enumerateAllNodes(backend, graphId, kind) {
|
|
109
932
|
const collected = [];
|
|
110
933
|
let after;
|
|
@@ -123,7 +946,7 @@ async function enumerateAllNodes(backend, graphId, kind) {
|
|
|
123
946
|
if (page.length < ENUMERATION_PAGE_SIZE) {
|
|
124
947
|
break;
|
|
125
948
|
}
|
|
126
|
-
after =
|
|
949
|
+
after = chunkN66HCGCY_cjs.requireDefined(page.at(-1)).id;
|
|
127
950
|
}
|
|
128
951
|
return collected;
|
|
129
952
|
}
|
|
@@ -145,7 +968,7 @@ async function enumerateAllEdges(backend, graphId, kind) {
|
|
|
145
968
|
if (page.length < ENUMERATION_PAGE_SIZE) {
|
|
146
969
|
break;
|
|
147
970
|
}
|
|
148
|
-
after =
|
|
971
|
+
after = chunkN66HCGCY_cjs.requireDefined(page.at(-1)).id;
|
|
149
972
|
}
|
|
150
973
|
return collected;
|
|
151
974
|
}
|
|
@@ -165,6 +988,7 @@ function diffNodeKind(kind, baseRows, forkRows) {
|
|
|
165
988
|
const created = [];
|
|
166
989
|
const modified = [];
|
|
167
990
|
const deleted = [];
|
|
991
|
+
const windowed = [];
|
|
168
992
|
for (const forkRow of forkRows) {
|
|
169
993
|
if (!isLive(forkRow)) {
|
|
170
994
|
continue;
|
|
@@ -190,6 +1014,16 @@ function diffNodeKind(kind, baseRows, forkRows) {
|
|
|
190
1014
|
row: forkRow
|
|
191
1015
|
});
|
|
192
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
|
+
}
|
|
193
1027
|
}
|
|
194
1028
|
for (const baseRow of baseRows) {
|
|
195
1029
|
if (!isLive(baseRow)) {
|
|
@@ -197,10 +1031,14 @@ function diffNodeKind(kind, baseRows, forkRows) {
|
|
|
197
1031
|
}
|
|
198
1032
|
const forkRow = forkIndex.get(baseRow.id);
|
|
199
1033
|
if (forkRow === void 0 || !isLive(forkRow)) {
|
|
200
|
-
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
|
+
});
|
|
201
1039
|
}
|
|
202
1040
|
}
|
|
203
|
-
return { new: created, modified, deleted };
|
|
1041
|
+
return { new: created, modified, deleted, windowed };
|
|
204
1042
|
}
|
|
205
1043
|
function diffEdgeKind(kind, baseRows, forkRows) {
|
|
206
1044
|
const baseIndex = indexById(baseRows);
|
|
@@ -208,6 +1046,7 @@ function diffEdgeKind(kind, baseRows, forkRows) {
|
|
|
208
1046
|
const created = [];
|
|
209
1047
|
const modified = [];
|
|
210
1048
|
const deleted = [];
|
|
1049
|
+
const windowed = [];
|
|
211
1050
|
for (const forkRow of forkRows) {
|
|
212
1051
|
if (!isLive(forkRow)) {
|
|
213
1052
|
continue;
|
|
@@ -241,6 +1080,22 @@ function diffEdgeKind(kind, baseRows, forkRows) {
|
|
|
241
1080
|
row: forkRow
|
|
242
1081
|
});
|
|
243
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
|
+
}
|
|
244
1099
|
}
|
|
245
1100
|
for (const baseRow of baseRows) {
|
|
246
1101
|
if (!isLive(baseRow)) {
|
|
@@ -251,27 +1106,82 @@ function diffEdgeKind(kind, baseRows, forkRows) {
|
|
|
251
1106
|
deleted.push({ id: baseRow.id, kind });
|
|
252
1107
|
}
|
|
253
1108
|
}
|
|
254
|
-
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
|
+
}));
|
|
255
1154
|
}
|
|
256
1155
|
function byId(left, right) {
|
|
257
|
-
return
|
|
1156
|
+
return chunkXMQSEJCF_cjs.compareStrings(left.id, right.id);
|
|
258
1157
|
}
|
|
259
1158
|
async function diffAgainstBase(baseStore, forkStore, captureForkState = true) {
|
|
260
1159
|
const graph = baseStore.graph;
|
|
261
|
-
const nodeKinds =
|
|
262
|
-
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
|
+
);
|
|
263
1172
|
const newNodes = [];
|
|
264
1173
|
const modifiedNodes = [];
|
|
265
1174
|
const deletedNodes = [];
|
|
1175
|
+
const windowedNodes = [];
|
|
266
1176
|
const forkNodeVersions = /* @__PURE__ */ new Map();
|
|
267
1177
|
for (const kind of nodeKinds) {
|
|
268
1178
|
const baseRows = await enumerateAllNodes(
|
|
269
|
-
|
|
1179
|
+
chunkTTAITEPJ_cjs.storeBackend(baseStore),
|
|
270
1180
|
baseStore.graphId,
|
|
271
1181
|
kind
|
|
272
1182
|
);
|
|
273
1183
|
const forkRows = await enumerateAllNodes(
|
|
274
|
-
|
|
1184
|
+
chunkTTAITEPJ_cjs.storeBackend(forkStore),
|
|
275
1185
|
forkStore.graphId,
|
|
276
1186
|
kind
|
|
277
1187
|
);
|
|
@@ -290,19 +1200,23 @@ async function diffAgainstBase(baseStore, forkStore, captureForkState = true) {
|
|
|
290
1200
|
for (const entry of delta.deleted) {
|
|
291
1201
|
deletedNodes.push(entry);
|
|
292
1202
|
}
|
|
1203
|
+
for (const entry of delta.windowed) {
|
|
1204
|
+
windowedNodes.push(entry);
|
|
1205
|
+
}
|
|
293
1206
|
}
|
|
294
1207
|
const newEdges = [];
|
|
295
1208
|
const modifiedEdges = [];
|
|
296
1209
|
const deletedEdges = [];
|
|
1210
|
+
const windowedEdges = [];
|
|
297
1211
|
const forkEdgeSignatures = /* @__PURE__ */ new Map();
|
|
298
1212
|
for (const kind of edgeKinds) {
|
|
299
1213
|
const baseRows = await enumerateAllEdges(
|
|
300
|
-
|
|
1214
|
+
chunkTTAITEPJ_cjs.storeBackend(baseStore),
|
|
301
1215
|
baseStore.graphId,
|
|
302
1216
|
kind
|
|
303
1217
|
);
|
|
304
1218
|
const forkRows = await enumerateAllEdges(
|
|
305
|
-
|
|
1219
|
+
chunkTTAITEPJ_cjs.storeBackend(forkStore),
|
|
306
1220
|
forkStore.graphId,
|
|
307
1221
|
kind
|
|
308
1222
|
);
|
|
@@ -331,17 +1245,46 @@ async function diffAgainstBase(baseStore, forkStore, captureForkState = true) {
|
|
|
331
1245
|
for (const entry of delta.deleted) {
|
|
332
1246
|
deletedEdges.push(entry);
|
|
333
1247
|
}
|
|
1248
|
+
for (const entry of delta.windowed) {
|
|
1249
|
+
windowedEdges.push(entry);
|
|
1250
|
+
}
|
|
334
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
|
+
);
|
|
335
1261
|
return {
|
|
336
1262
|
nodes: {
|
|
337
1263
|
new: newNodes.sort((left, right) => byId(left, right)),
|
|
338
1264
|
modified: modifiedNodes.sort((left, right) => byId(left, right)),
|
|
339
|
-
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))
|
|
340
1267
|
},
|
|
341
1268
|
edges: {
|
|
342
1269
|
new: newEdges.sort((left, right) => byId(left, right)),
|
|
343
1270
|
modified: modifiedEdges.sort((left, right) => byId(left, right)),
|
|
344
|
-
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
|
|
345
1288
|
},
|
|
346
1289
|
forkNodeVersions,
|
|
347
1290
|
forkEdgeSignatures
|
|
@@ -355,9 +1298,11 @@ function asBranchId(value) {
|
|
|
355
1298
|
function asBaseVersion(value) {
|
|
356
1299
|
return value;
|
|
357
1300
|
}
|
|
1301
|
+
var VALIDITY_END_TARGET_PRECEDENCE = "target";
|
|
358
1302
|
|
|
359
1303
|
// src/graph-merge/base-version.ts
|
|
360
1304
|
var TOKEN_SEPARATOR = "\0";
|
|
1305
|
+
var SCHEMA_VERSION_TAG = "#s";
|
|
361
1306
|
var REVISION_COMPONENT_PREFIX = "revision:";
|
|
362
1307
|
var REVISION_COMPONENT_SEPARATOR = ":";
|
|
363
1308
|
var INITIAL_REVISION = "initial";
|
|
@@ -368,19 +1313,19 @@ async function readActiveSchemaVersion(backend, graphId) {
|
|
|
368
1313
|
}
|
|
369
1314
|
async function computeSchemaComponent(store) {
|
|
370
1315
|
const version = await readActiveSchemaVersion(
|
|
371
|
-
|
|
1316
|
+
chunkTTAITEPJ_cjs.storeBackend(store),
|
|
372
1317
|
store.graphId
|
|
373
1318
|
);
|
|
374
|
-
return
|
|
1319
|
+
return chunkN3257XE6_cjs.computeSchemaHash(chunkN3257XE6_cjs.serializeSchema(store.graph, version));
|
|
375
1320
|
}
|
|
376
1321
|
function byDigestEntry(left, right) {
|
|
377
|
-
const byKind =
|
|
378
|
-
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;
|
|
379
1324
|
}
|
|
380
1325
|
var CONTENT_FINGERPRINT_BYTES = 16;
|
|
381
|
-
async function computeContentComponent(backend, graphId, graph) {
|
|
382
|
-
const nodeKinds =
|
|
383
|
-
const edgeKinds =
|
|
1326
|
+
async function computeContentComponent(backend, graphId, graph, identityAssertions) {
|
|
1327
|
+
const nodeKinds = chunkCXBHOOIQ_cjs.getNodeKinds(graph);
|
|
1328
|
+
const edgeKinds = chunkCXBHOOIQ_cjs.getEdgeKinds(graph);
|
|
384
1329
|
const nodeDigest = [];
|
|
385
1330
|
for (const kind of nodeKinds) {
|
|
386
1331
|
const rows = await enumerateAllNodes(backend, graphId, kind);
|
|
@@ -418,30 +1363,41 @@ async function computeContentComponent(backend, graphId, graph) {
|
|
|
418
1363
|
return chunkZY4GXIVN_cjs.sha256Hex(
|
|
419
1364
|
canonicalizeProps({
|
|
420
1365
|
nodes: nodeDigest.sort((left, right) => byDigestEntry(left, right)),
|
|
421
|
-
edges: edgeDigest.sort((left, right) => byDigestEntry(left, right))
|
|
1366
|
+
edges: edgeDigest.sort((left, right) => byDigestEntry(left, right)),
|
|
1367
|
+
...identityAssertions.length === 0 ? {} : { identity: identityAssertions }
|
|
422
1368
|
}),
|
|
423
1369
|
CONTENT_FINGERPRINT_BYTES
|
|
424
1370
|
);
|
|
425
1371
|
}
|
|
426
1372
|
async function computeBaseVersion(store) {
|
|
427
1373
|
if (store.revisionTrackingEnabled) {
|
|
428
|
-
const [schemaComponent2, origin, revision] = await Promise.all([
|
|
1374
|
+
const [schemaComponent2, origin, revision, activeVersion] = await Promise.all([
|
|
429
1375
|
computeSchemaComponent(store),
|
|
430
1376
|
store.revisionOriginNow(),
|
|
431
|
-
store.revisionNow()
|
|
1377
|
+
store.revisionNow(),
|
|
1378
|
+
readActiveSchemaVersion(chunkTTAITEPJ_cjs.storeBackend(store), store.graphId)
|
|
432
1379
|
]);
|
|
433
1380
|
return asBaseVersion(
|
|
434
|
-
`${schemaComponent2}${TOKEN_SEPARATOR}${revisionComponent(origin, revision)}`
|
|
1381
|
+
`${schemaComponent2}${SCHEMA_VERSION_TAG}${activeVersion}${TOKEN_SEPARATOR}${revisionComponent(origin, revision)}`
|
|
435
1382
|
);
|
|
436
1383
|
}
|
|
437
1384
|
const [schemaComponent, contentComponent] = await Promise.all([
|
|
438
1385
|
computeSchemaComponent(store),
|
|
439
|
-
|
|
1386
|
+
computeStoreContentComponent(store)
|
|
440
1387
|
]);
|
|
441
1388
|
return asBaseVersion(
|
|
442
1389
|
`${schemaComponent}${TOKEN_SEPARATOR}${contentComponent}`
|
|
443
1390
|
);
|
|
444
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
|
+
}
|
|
445
1401
|
function revisionComponent(origin, revision) {
|
|
446
1402
|
return `${REVISION_COMPONENT_PREFIX}${origin}${REVISION_COMPONENT_SEPARATOR}${revision ?? INITIAL_REVISION}`;
|
|
447
1403
|
}
|
|
@@ -471,70 +1427,6 @@ function contentComponentOf(version) {
|
|
|
471
1427
|
return separatorIndex === -1 ? version : version.slice(separatorIndex + 1);
|
|
472
1428
|
}
|
|
473
1429
|
|
|
474
|
-
// src/graph-merge/errors.ts
|
|
475
|
-
var MERGE_ERROR_CODES = {
|
|
476
|
-
merge: "GRAPH_MERGE_ERROR",
|
|
477
|
-
branch: "GRAPH_MERGE_BRANCH_ERROR",
|
|
478
|
-
similarityUnavailable: "GRAPH_MERGE_SIMILARITY_UNAVAILABLE",
|
|
479
|
-
conflict: "GRAPH_MERGE_CONFLICT",
|
|
480
|
-
baseVersionMismatch: "GRAPH_MERGE_BASE_VERSION_MISMATCH"
|
|
481
|
-
};
|
|
482
|
-
function toTypeGraphErrorOptions(category, options) {
|
|
483
|
-
return {
|
|
484
|
-
category,
|
|
485
|
-
...options.details === void 0 ? {} : { details: options.details },
|
|
486
|
-
...options.suggestion === void 0 ? {} : { suggestion: options.suggestion },
|
|
487
|
-
...options.cause === void 0 ? {} : { cause: options.cause }
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
var MergeError = class extends chunkC4F7VJ5D_cjs.TypeGraphError {
|
|
491
|
-
constructor(message, options = {}) {
|
|
492
|
-
super(
|
|
493
|
-
message,
|
|
494
|
-
MERGE_ERROR_CODES.merge,
|
|
495
|
-
toTypeGraphErrorOptions("system", options)
|
|
496
|
-
);
|
|
497
|
-
this.name = "MergeError";
|
|
498
|
-
}
|
|
499
|
-
};
|
|
500
|
-
var BranchError = class extends chunkC4F7VJ5D_cjs.TypeGraphError {
|
|
501
|
-
constructor(message, options = {}) {
|
|
502
|
-
super(
|
|
503
|
-
message,
|
|
504
|
-
MERGE_ERROR_CODES.branch,
|
|
505
|
-
toTypeGraphErrorOptions("system", options)
|
|
506
|
-
);
|
|
507
|
-
this.name = "BranchError";
|
|
508
|
-
}
|
|
509
|
-
};
|
|
510
|
-
var SimilarityUnavailableError = class extends MergeError {
|
|
511
|
-
code = MERGE_ERROR_CODES.similarityUnavailable;
|
|
512
|
-
constructor(message, options = {}) {
|
|
513
|
-
super(message, {
|
|
514
|
-
...options,
|
|
515
|
-
suggestion: options.suggestion ?? "Pass MergeOptions.embedder (a local model), or use a fulltext/custom similarity strategy."
|
|
516
|
-
});
|
|
517
|
-
this.name = "SimilarityUnavailableError";
|
|
518
|
-
}
|
|
519
|
-
};
|
|
520
|
-
var MergeConflictError = class extends MergeError {
|
|
521
|
-
code = MERGE_ERROR_CODES.conflict;
|
|
522
|
-
constructor(message, options = {}) {
|
|
523
|
-
super(message, options);
|
|
524
|
-
this.name = "MergeConflictError";
|
|
525
|
-
}
|
|
526
|
-
};
|
|
527
|
-
var BaseVersionMismatchError = class extends MergeError {
|
|
528
|
-
code = MERGE_ERROR_CODES.baseVersionMismatch;
|
|
529
|
-
constructor(message, options = {}) {
|
|
530
|
-
super(message, {
|
|
531
|
-
...options,
|
|
532
|
-
suggestion: options.suggestion ?? "Re-branch from the current target so the branch base matches before merging."
|
|
533
|
-
});
|
|
534
|
-
this.name = "BaseVersionMismatchError";
|
|
535
|
-
}
|
|
536
|
-
};
|
|
537
|
-
|
|
538
1430
|
// src/graph-merge/working-copy.ts
|
|
539
1431
|
var CLONE_IMPORT_BATCH_SIZE = 1e3;
|
|
540
1432
|
function cloneWorkingCopyStrategy(makeBackend) {
|
|
@@ -542,7 +1434,7 @@ function cloneWorkingCopyStrategy(makeBackend) {
|
|
|
542
1434
|
create: async (baseStore) => {
|
|
543
1435
|
const backend = await makeBackend();
|
|
544
1436
|
try {
|
|
545
|
-
const [freshStore] = await
|
|
1437
|
+
const [freshStore] = await chunkXDF2UPEQ_cjs.createStoreWithSchema(
|
|
546
1438
|
baseStore.graph,
|
|
547
1439
|
backend,
|
|
548
1440
|
{
|
|
@@ -551,20 +1443,29 @@ function cloneWorkingCopyStrategy(makeBackend) {
|
|
|
551
1443
|
revisionTracking: baseStore.revisionTrackingEnabled
|
|
552
1444
|
}
|
|
553
1445
|
);
|
|
554
|
-
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(
|
|
555
1462
|
freshStore,
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
{
|
|
563
|
-
onConflict: "error",
|
|
564
|
-
onUnknownProperty: "error",
|
|
565
|
-
validateReferences: true,
|
|
566
|
-
batchSize: CLONE_IMPORT_BATCH_SIZE
|
|
567
|
-
}
|
|
1463
|
+
chunkONU3HIED_cjs.exportGraphStream(baseStore, exportOptions),
|
|
1464
|
+
importOptions
|
|
1465
|
+
) : await chunkONU3HIED_cjs.importGraph(
|
|
1466
|
+
freshStore,
|
|
1467
|
+
await chunkONU3HIED_cjs.exportGraph(baseStore, exportOptions),
|
|
1468
|
+
importOptions
|
|
568
1469
|
);
|
|
569
1470
|
if (!result.success) {
|
|
570
1471
|
throw new BranchError(
|
|
@@ -588,18 +1489,36 @@ function cloneWorkingCopyStrategy(makeBackend) {
|
|
|
588
1489
|
async function branch(baseStore, makeBackend, options, strategy) {
|
|
589
1490
|
try {
|
|
590
1491
|
const base = await computeBaseVersion(baseStore);
|
|
591
|
-
const id = options?.id ?? asBranchId(
|
|
1492
|
+
const id = options?.id ?? asBranchId(chunkXMQSEJCF_cjs.generateId());
|
|
592
1493
|
const workingCopyStrategy = strategy ?? cloneWorkingCopyStrategy(makeBackend);
|
|
593
1494
|
const store = await workingCopyStrategy.create(baseStore);
|
|
594
|
-
|
|
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
|
+
});
|
|
595
1502
|
} catch (error) {
|
|
596
|
-
return
|
|
1503
|
+
return chunk7BQXPCGN_cjs.err(
|
|
597
1504
|
new BranchError("Failed to create working-copy branch of base store", {
|
|
598
1505
|
cause: error
|
|
599
1506
|
})
|
|
600
1507
|
);
|
|
601
1508
|
}
|
|
602
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
|
+
}
|
|
603
1522
|
|
|
604
1523
|
// src/graph-merge/blocking.ts
|
|
605
1524
|
var UNBLOCKED_BUCKET_KEY = "unblocked";
|
|
@@ -612,12 +1531,12 @@ function isUniqueBucketKey(key) {
|
|
|
612
1531
|
function constraintSignature(node, constraint) {
|
|
613
1532
|
const props = node;
|
|
614
1533
|
for (const field of constraint.fields) {
|
|
615
|
-
const value = props
|
|
1534
|
+
const value = chunkN66HCGCY_cjs.readOwnProperty(props, field);
|
|
616
1535
|
if (value === void 0 || value === null) {
|
|
617
1536
|
return void 0;
|
|
618
1537
|
}
|
|
619
1538
|
}
|
|
620
|
-
return `${constraint.name}${KEY_PART_SEPARATOR}${
|
|
1539
|
+
return `${constraint.name}${KEY_PART_SEPARATOR}${chunkE4WNQBEF_cjs.computeUniqueKey(
|
|
621
1540
|
props,
|
|
622
1541
|
constraint.fields,
|
|
623
1542
|
constraint.collation
|
|
@@ -654,12 +1573,12 @@ function blockNodes(newNodes, resolveConfig, uniqueConstraints = []) {
|
|
|
654
1573
|
}
|
|
655
1574
|
}
|
|
656
1575
|
const sortedKeys = [...buckets.keys()].sort(
|
|
657
|
-
(left, right) =>
|
|
1576
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
658
1577
|
);
|
|
659
1578
|
const ordered = /* @__PURE__ */ new Map();
|
|
660
1579
|
for (const key of sortedKeys) {
|
|
661
|
-
const members = [...
|
|
662
|
-
(left, right) =>
|
|
1580
|
+
const members = [...chunkN66HCGCY_cjs.requireDefined(buckets.get(key))].sort(
|
|
1581
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
663
1582
|
);
|
|
664
1583
|
ordered.set(key, members);
|
|
665
1584
|
}
|
|
@@ -676,7 +1595,7 @@ function buildBranchRank(branchOrder, allBranchIds) {
|
|
|
676
1595
|
next += 1;
|
|
677
1596
|
}
|
|
678
1597
|
}
|
|
679
|
-
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));
|
|
680
1599
|
for (const branchId of remaining) {
|
|
681
1600
|
if (!rank.has(branchId)) {
|
|
682
1601
|
rank.set(branchId, next);
|
|
@@ -686,7 +1605,7 @@ function buildBranchRank(branchOrder, allBranchIds) {
|
|
|
686
1605
|
return rank;
|
|
687
1606
|
}
|
|
688
1607
|
function pickByPriority(values, branchRank) {
|
|
689
|
-
let chosen =
|
|
1608
|
+
let chosen = chunkN66HCGCY_cjs.requireDefined(values[0]);
|
|
690
1609
|
let chosenRank = branchRank.get(chosen.branchId) ?? Number.MAX_SAFE_INTEGER;
|
|
691
1610
|
for (const candidate of values.slice(1)) {
|
|
692
1611
|
const candidateRank = branchRank.get(candidate.branchId) ?? Number.MAX_SAFE_INTEGER;
|
|
@@ -700,7 +1619,7 @@ function pickByPriority(values, branchRank) {
|
|
|
700
1619
|
return chosen.value;
|
|
701
1620
|
}
|
|
702
1621
|
function pickByWeight(values, weights, branchRank) {
|
|
703
|
-
let chosen =
|
|
1622
|
+
let chosen = chunkN66HCGCY_cjs.requireDefined(values[0]);
|
|
704
1623
|
let chosenWeight = weights.get(chosen.branchId) ?? 0;
|
|
705
1624
|
let chosenRank = branchRank.get(chosen.branchId) ?? Number.MAX_SAFE_INTEGER;
|
|
706
1625
|
for (const candidate of values.slice(1)) {
|
|
@@ -727,7 +1646,7 @@ function allValuesEqual(values) {
|
|
|
727
1646
|
if (values.length <= 1) {
|
|
728
1647
|
return true;
|
|
729
1648
|
}
|
|
730
|
-
const first = canonicalValueKey(
|
|
1649
|
+
const first = canonicalValueKey(chunkN66HCGCY_cjs.requireDefined(values[0]).value);
|
|
731
1650
|
return values.every(
|
|
732
1651
|
(candidate) => canonicalValueKey(candidate.value) === first
|
|
733
1652
|
);
|
|
@@ -736,7 +1655,7 @@ function collectConflictingValues(property, contributions) {
|
|
|
736
1655
|
const seen = /* @__PURE__ */ new Set();
|
|
737
1656
|
const values = [];
|
|
738
1657
|
for (const { branchId, props } of contributions) {
|
|
739
|
-
if (!(property
|
|
1658
|
+
if (!chunkN66HCGCY_cjs.hasOwnKey(props, property)) {
|
|
740
1659
|
continue;
|
|
741
1660
|
}
|
|
742
1661
|
const value = props[property];
|
|
@@ -748,8 +1667,8 @@ function collectConflictingValues(property, contributions) {
|
|
|
748
1667
|
values.push({ branchId, value });
|
|
749
1668
|
}
|
|
750
1669
|
return [...values].sort((left, right) => {
|
|
751
|
-
const byBranch =
|
|
752
|
-
return byBranch === 0 ?
|
|
1670
|
+
const byBranch = chunkXMQSEJCF_cjs.compareStrings(left.branchId, right.branchId);
|
|
1671
|
+
return byBranch === 0 ? chunkXMQSEJCF_cjs.compareStrings(
|
|
753
1672
|
canonicalValueKey(left.value),
|
|
754
1673
|
canonicalValueKey(right.value)
|
|
755
1674
|
) : byBranch;
|
|
@@ -809,11 +1728,14 @@ function resolvePropertyUnion(input, context, branchRank) {
|
|
|
809
1728
|
|
|
810
1729
|
// src/graph-merge/canonicalize.ts
|
|
811
1730
|
var BASE_PROVENANCE_BRANCH = asBranchId("__committed_base__");
|
|
1731
|
+
var COMMITTED_TARGET_BRANCH = asBranchId(
|
|
1732
|
+
"__committed_target__"
|
|
1733
|
+
);
|
|
812
1734
|
function pickClusterSurvivor(members, cluster, canonicalOverride, preferKind) {
|
|
813
1735
|
const byKey = (left, right) => compareMergeKeys(mergeKeyOf(left), mergeKeyOf(right));
|
|
814
1736
|
const baseMembers = members.filter((member) => member.origin === "base").sort(byKey);
|
|
815
1737
|
if (baseMembers.length > 0) {
|
|
816
|
-
return
|
|
1738
|
+
return chunkN66HCGCY_cjs.requireDefined(baseMembers[0]);
|
|
817
1739
|
}
|
|
818
1740
|
let canonicalId;
|
|
819
1741
|
if (canonicalOverride !== void 0) {
|
|
@@ -826,26 +1748,26 @@ function pickClusterSurvivor(members, cluster, canonicalOverride, preferKind) {
|
|
|
826
1748
|
const minIdentity = [...cluster.members].sort(
|
|
827
1749
|
(left, right) => compareMergeKeys(left, right)
|
|
828
1750
|
)[0];
|
|
829
|
-
canonicalId = minIdentity === void 0 ?
|
|
1751
|
+
canonicalId = minIdentity === void 0 ? chunkN66HCGCY_cjs.requireDefined(members[0]).id : idOf(minIdentity);
|
|
830
1752
|
}
|
|
831
1753
|
const membersAtId = members.filter((member) => member.id === canonicalId);
|
|
832
1754
|
if (membersAtId.length === 0) {
|
|
833
|
-
return
|
|
1755
|
+
return chunkN66HCGCY_cjs.requireDefined([...members].sort(byKey)[0]);
|
|
834
1756
|
}
|
|
835
1757
|
const kinds = [...new Set(membersAtId.map((member) => member.kind))];
|
|
836
1758
|
const chosenKind = preferKind !== void 0 && kinds.length > 1 ? preferKind(kinds) : void 0;
|
|
837
|
-
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]);
|
|
838
1760
|
}
|
|
839
1761
|
function findPreferredMember(members, property, preferredBranchId) {
|
|
840
1762
|
if (preferredBranchId === void 0) {
|
|
841
1763
|
return void 0;
|
|
842
1764
|
}
|
|
843
1765
|
return members.find(
|
|
844
|
-
(member) => member.branchId === preferredBranchId &&
|
|
1766
|
+
(member) => member.branchId === preferredBranchId && chunkN66HCGCY_cjs.hasOwnKey(member.props, property)
|
|
845
1767
|
);
|
|
846
1768
|
}
|
|
847
1769
|
function memberPropertyValue(member, property) {
|
|
848
|
-
if (!(
|
|
1770
|
+
if (!chunkN66HCGCY_cjs.hasOwnKey(member.props, property)) {
|
|
849
1771
|
return void 0;
|
|
850
1772
|
}
|
|
851
1773
|
return member.props[property];
|
|
@@ -861,7 +1783,7 @@ function pickCanonicalPropertyValue(canonicalMember, members, property, values,
|
|
|
861
1783
|
return preferredValue;
|
|
862
1784
|
}
|
|
863
1785
|
const canonicalValue = memberPropertyValue(canonicalMember, property);
|
|
864
|
-
return canonicalValue === void 0 ?
|
|
1786
|
+
return canonicalValue === void 0 ? chunkN66HCGCY_cjs.requireDefined(values[0]).value : canonicalValue;
|
|
865
1787
|
}
|
|
866
1788
|
function unionProperties(canonicalMember, members, context, baseContext, branchRank, preferredBranchId) {
|
|
867
1789
|
const canonicalId = canonicalMember.id;
|
|
@@ -873,10 +1795,10 @@ function unionProperties(canonicalMember, members, context, baseContext, branchR
|
|
|
873
1795
|
propertyNames.add(name);
|
|
874
1796
|
}
|
|
875
1797
|
}
|
|
876
|
-
const props =
|
|
1798
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
877
1799
|
const conflicts = [];
|
|
878
1800
|
for (const property of [...propertyNames].sort(
|
|
879
|
-
(left, right) =>
|
|
1801
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
880
1802
|
)) {
|
|
881
1803
|
const values = collectConflictingValues(property, members);
|
|
882
1804
|
if (values.length === 0) {
|
|
@@ -890,7 +1812,7 @@ function unionProperties(canonicalMember, members, context, baseContext, branchR
|
|
|
890
1812
|
preferredBranchId
|
|
891
1813
|
);
|
|
892
1814
|
const baseInvolved = hasBaseMember && members.some(
|
|
893
|
-
(member) => member.origin === "base" &&
|
|
1815
|
+
(member) => member.origin === "base" && chunkN66HCGCY_cjs.hasOwnKey(member.props, property)
|
|
894
1816
|
);
|
|
895
1817
|
const reportedValues = values.filter(
|
|
896
1818
|
(value2) => value2.branchId !== BASE_PROVENANCE_BRANCH && value2.branchId !== preferredBranchId
|
|
@@ -931,89 +1853,56 @@ function canonicalizeCluster(cluster, members, policy, branchRank, weights, cano
|
|
|
931
1853
|
policy: basePolicy,
|
|
932
1854
|
...weights === void 0 ? {} : { weights }
|
|
933
1855
|
};
|
|
934
|
-
const { props, conflicts } = unionProperties(
|
|
935
|
-
survivor,
|
|
936
|
-
members,
|
|
937
|
-
context,
|
|
938
|
-
baseContext,
|
|
939
|
-
branchRank,
|
|
940
|
-
preferredBranchId
|
|
941
|
-
);
|
|
942
|
-
const memberIds = [
|
|
943
|
-
...new Set(cluster.members.map((member) => idOf(member)))
|
|
944
|
-
].sort((left, right) =>
|
|
945
|
-
const branchOrigins = [
|
|
946
|
-
...new Set(
|
|
947
|
-
members.map((member) => member.branchId).filter(
|
|
948
|
-
(branchId) => branchId !== BASE_PROVENANCE_BRANCH && branchId !== preferredBranchId
|
|
949
|
-
)
|
|
950
|
-
)
|
|
951
|
-
].sort((left, right) =>
|
|
952
|
-
const resolution = {
|
|
953
|
-
canonicalId,
|
|
954
|
-
memberIds,
|
|
955
|
-
kind,
|
|
956
|
-
branchOrigins
|
|
957
|
-
};
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
this.parent.set(value, value);
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
/** Returns the representative of `value`'s set, compressing the path to it. */
|
|
975
|
-
find(value) {
|
|
976
|
-
this.add(value);
|
|
977
|
-
let root = value;
|
|
978
|
-
while (this.parent.get(root) !== root) {
|
|
979
|
-
root = chunk764JHTLT_cjs.requireDefined(this.parent.get(root));
|
|
980
|
-
}
|
|
981
|
-
let cursor = value;
|
|
982
|
-
while (cursor !== root) {
|
|
983
|
-
const next = chunk764JHTLT_cjs.requireDefined(this.parent.get(cursor));
|
|
984
|
-
this.parent.set(cursor, root);
|
|
985
|
-
cursor = next;
|
|
986
|
-
}
|
|
987
|
-
return root;
|
|
988
|
-
}
|
|
989
|
-
/** Merges the sets of `left` and `right`; the `compare`-minimal root wins. */
|
|
990
|
-
union(left, right) {
|
|
991
|
-
const leftRoot = this.find(left);
|
|
992
|
-
const rightRoot = this.find(right);
|
|
993
|
-
if (leftRoot === rightRoot) {
|
|
994
|
-
return;
|
|
995
|
-
}
|
|
996
|
-
if (this.compare(leftRoot, rightRoot) <= 0) {
|
|
997
|
-
this.parent.set(rightRoot, leftRoot);
|
|
998
|
-
} else {
|
|
999
|
-
this.parent.set(leftRoot, rightRoot);
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
/** Every value seen by {@link add}/{@link find}/{@link union}, insertion order. */
|
|
1003
|
-
members() {
|
|
1004
|
-
return [...this.parent.keys()];
|
|
1005
|
-
}
|
|
1006
|
-
};
|
|
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
|
+
}
|
|
1007
1893
|
|
|
1008
1894
|
// src/graph-merge/closures.ts
|
|
1009
1895
|
var SUB_CLASS_OF_META_EDGE = "subClassOf";
|
|
1010
|
-
var
|
|
1896
|
+
var EQUIVALENCE_META_EDGES = /* @__PURE__ */ new Set([
|
|
1897
|
+
chunkXUO3KQFO_cjs.META_EDGE_EQUIVALENT_TO,
|
|
1898
|
+
chunkXUO3KQFO_cjs.META_EDGE_SAME_AS
|
|
1899
|
+
]);
|
|
1011
1900
|
function buildSubClassClosure(ontology) {
|
|
1012
|
-
const unionFind = new UnionFind(
|
|
1901
|
+
const unionFind = new UnionFind(chunkXMQSEJCF_cjs.compareStrings);
|
|
1013
1902
|
for (const relation of ontology) {
|
|
1014
1903
|
unionFind.add(relation.from);
|
|
1015
1904
|
unionFind.add(relation.to);
|
|
1016
|
-
if (relation.metaEdge
|
|
1905
|
+
if (EQUIVALENCE_META_EDGES.has(relation.metaEdge)) {
|
|
1017
1906
|
unionFind.union(relation.from, relation.to);
|
|
1018
1907
|
}
|
|
1019
1908
|
}
|
|
@@ -1040,7 +1929,7 @@ function buildSubClassClosure(ontology) {
|
|
|
1040
1929
|
relations.push([child, parent]);
|
|
1041
1930
|
}
|
|
1042
1931
|
return {
|
|
1043
|
-
closure:
|
|
1932
|
+
closure: chunk7BQXPCGN_cjs.computeTransitiveClosure(relations),
|
|
1044
1933
|
canonicalOf
|
|
1045
1934
|
};
|
|
1046
1935
|
}
|
|
@@ -1053,7 +1942,7 @@ function isReachable2(closure, from, to) {
|
|
|
1053
1942
|
if (fromRep === toRep) {
|
|
1054
1943
|
return from !== to;
|
|
1055
1944
|
}
|
|
1056
|
-
return
|
|
1945
|
+
return chunk7BQXPCGN_cjs.isReachable(closure.closure, fromRep, toRep);
|
|
1057
1946
|
}
|
|
1058
1947
|
|
|
1059
1948
|
// src/graph-merge/similarity.ts
|
|
@@ -1075,7 +1964,7 @@ function clampScore(value) {
|
|
|
1075
1964
|
return value;
|
|
1076
1965
|
}
|
|
1077
1966
|
function readField(node, field) {
|
|
1078
|
-
return node
|
|
1967
|
+
return chunkN66HCGCY_cjs.readOwnProperty(node, field);
|
|
1079
1968
|
}
|
|
1080
1969
|
function fieldText(node, fields) {
|
|
1081
1970
|
const parts = [];
|
|
@@ -1166,8 +2055,8 @@ function cosineSimilarity(left, right) {
|
|
|
1166
2055
|
let leftMagnitude = 0;
|
|
1167
2056
|
let rightMagnitude = 0;
|
|
1168
2057
|
for (let index = 0; index < left.length; index += 1) {
|
|
1169
|
-
const leftComponent =
|
|
1170
|
-
const rightComponent =
|
|
2058
|
+
const leftComponent = chunkN66HCGCY_cjs.requireDefined(left[index]);
|
|
2059
|
+
const rightComponent = chunkN66HCGCY_cjs.requireDefined(right[index]);
|
|
1171
2060
|
dot += leftComponent * rightComponent;
|
|
1172
2061
|
leftMagnitude += leftComponent * leftComponent;
|
|
1173
2062
|
rightMagnitude += rightComponent * rightComponent;
|
|
@@ -1236,37 +2125,37 @@ function scorePrepared(left, right, strategy, ctx) {
|
|
|
1236
2125
|
switch (strategy.kind) {
|
|
1237
2126
|
case "custom": {
|
|
1238
2127
|
const raw = strategy.score(left.node, right.node);
|
|
1239
|
-
return
|
|
2128
|
+
return chunk7BQXPCGN_cjs.ok(clampScore(raw));
|
|
1240
2129
|
}
|
|
1241
2130
|
case "fulltext": {
|
|
1242
2131
|
if (left.text.length === 0 || right.text.length === 0) {
|
|
1243
|
-
return
|
|
2132
|
+
return chunk7BQXPCGN_cjs.ok(NO_EVIDENCE_SCORE);
|
|
1244
2133
|
}
|
|
1245
|
-
return
|
|
2134
|
+
return chunk7BQXPCGN_cjs.ok(clampScore(diceFromMultisets(left.grams, right.grams)));
|
|
1246
2135
|
}
|
|
1247
2136
|
case "vector": {
|
|
1248
2137
|
if (ctx.embeddings === void 0) {
|
|
1249
|
-
return
|
|
2138
|
+
return chunk7BQXPCGN_cjs.err(embedderUnavailable("vector", ctx));
|
|
1250
2139
|
}
|
|
1251
2140
|
if (left.text.length === 0 || right.text.length === 0) {
|
|
1252
|
-
return
|
|
2141
|
+
return chunk7BQXPCGN_cjs.ok(NO_EVIDENCE_SCORE);
|
|
1253
2142
|
}
|
|
1254
2143
|
const cosine = cosineFromLookup(ctx.embeddings, left.text, right.text);
|
|
1255
|
-
return
|
|
2144
|
+
return chunk7BQXPCGN_cjs.ok(clampScore(cosine));
|
|
1256
2145
|
}
|
|
1257
2146
|
case "hybrid": {
|
|
1258
2147
|
if (ctx.embeddings === void 0) {
|
|
1259
|
-
return
|
|
2148
|
+
return chunk7BQXPCGN_cjs.err(embedderUnavailable("hybrid", ctx));
|
|
1260
2149
|
}
|
|
1261
2150
|
if (left.text.length === 0 || right.text.length === 0) {
|
|
1262
|
-
return
|
|
2151
|
+
return chunk7BQXPCGN_cjs.ok(NO_EVIDENCE_SCORE);
|
|
1263
2152
|
}
|
|
1264
2153
|
const vectorScore = clampScore(
|
|
1265
2154
|
cosineFromLookup(ctx.embeddings, left.text, right.text)
|
|
1266
2155
|
);
|
|
1267
2156
|
const fulltextScore = diceFromMultisets(left.grams, right.grams);
|
|
1268
2157
|
const weights = normalizeHybridWeights(strategy.weights);
|
|
1269
|
-
return
|
|
2158
|
+
return chunk7BQXPCGN_cjs.ok(
|
|
1270
2159
|
clampScore(
|
|
1271
2160
|
weights.vector * vectorScore + weights.fulltext * fulltextScore
|
|
1272
2161
|
)
|
|
@@ -1324,7 +2213,7 @@ function scoreCandidates(input, resolveConfig, ctx, ceilingPolicy, maxComparison
|
|
|
1324
2213
|
}
|
|
1325
2214
|
if (maxComparisonsPerKind !== void 0 && fuzzy.length > maxComparisonsPerKind) {
|
|
1326
2215
|
if (ceilingPolicy === "error") {
|
|
1327
|
-
return
|
|
2216
|
+
return chunk7BQXPCGN_cjs.err(
|
|
1328
2217
|
new MergeError(
|
|
1329
2218
|
`Comparison ceiling exceeded: ${fuzzy.length} candidate pairs > maxComparisonsPerKind ${maxComparisonsPerKind}.`,
|
|
1330
2219
|
{
|
|
@@ -1337,7 +2226,7 @@ function scoreCandidates(input, resolveConfig, ctx, ceilingPolicy, maxComparison
|
|
|
1337
2226
|
)
|
|
1338
2227
|
);
|
|
1339
2228
|
}
|
|
1340
|
-
return
|
|
2229
|
+
return chunk7BQXPCGN_cjs.ok({
|
|
1341
2230
|
edges: [...forced].sort(
|
|
1342
2231
|
(left, right) => compareCandidateEdges(left, right)
|
|
1343
2232
|
),
|
|
@@ -1355,14 +2244,14 @@ function scoreCandidates(input, resolveConfig, ctx, ceilingPolicy, maxComparison
|
|
|
1355
2244
|
const edges = [...forced];
|
|
1356
2245
|
for (const { left, right, a, b } of fuzzy) {
|
|
1357
2246
|
const scored = scorer(a, left, b, right);
|
|
1358
|
-
if (
|
|
1359
|
-
return
|
|
2247
|
+
if (chunk7BQXPCGN_cjs.isErr(scored)) {
|
|
2248
|
+
return chunk7BQXPCGN_cjs.err(scored.error);
|
|
1360
2249
|
}
|
|
1361
2250
|
if (scored.data >= threshold) {
|
|
1362
2251
|
edges.push({ a, b, score: scored.data });
|
|
1363
2252
|
}
|
|
1364
2253
|
}
|
|
1365
|
-
return
|
|
2254
|
+
return chunk7BQXPCGN_cjs.ok({
|
|
1366
2255
|
edges: edges.sort((left, right) => compareCandidateEdges(left, right)),
|
|
1367
2256
|
warnings: []
|
|
1368
2257
|
});
|
|
@@ -1402,8 +2291,8 @@ function buildComponents(edges, nodeIds, edgesSorted = false) {
|
|
|
1402
2291
|
}
|
|
1403
2292
|
clusters.sort(
|
|
1404
2293
|
(left, right) => compareMergeKeys(
|
|
1405
|
-
|
|
1406
|
-
|
|
2294
|
+
chunkN66HCGCY_cjs.requireDefined(left.members[0]),
|
|
2295
|
+
chunkN66HCGCY_cjs.requireDefined(right.members[0])
|
|
1407
2296
|
)
|
|
1408
2297
|
);
|
|
1409
2298
|
return clusters;
|
|
@@ -1416,8 +2305,8 @@ function adjacencyOf(members, edges) {
|
|
|
1416
2305
|
}
|
|
1417
2306
|
for (const edge of edges) {
|
|
1418
2307
|
if (memberSet.has(edge.a) && memberSet.has(edge.b)) {
|
|
1419
|
-
|
|
1420
|
-
|
|
2308
|
+
chunkN66HCGCY_cjs.requireDefined(adjacency.get(edge.a)).add(edge.b);
|
|
2309
|
+
chunkN66HCGCY_cjs.requireDefined(adjacency.get(edge.b)).add(edge.a);
|
|
1421
2310
|
}
|
|
1422
2311
|
}
|
|
1423
2312
|
return adjacency;
|
|
@@ -1432,10 +2321,10 @@ function exceedsDiameter(members, edges, maxDiameter) {
|
|
|
1432
2321
|
const queue = [source];
|
|
1433
2322
|
let head = 0;
|
|
1434
2323
|
while (head < queue.length) {
|
|
1435
|
-
const current =
|
|
2324
|
+
const current = chunkN66HCGCY_cjs.requireDefined(queue[head]);
|
|
1436
2325
|
head += 1;
|
|
1437
|
-
const currentDistance =
|
|
1438
|
-
for (const neighbor of
|
|
2326
|
+
const currentDistance = chunkN66HCGCY_cjs.requireDefined(distance.get(current));
|
|
2327
|
+
for (const neighbor of chunkN66HCGCY_cjs.requireDefined(adjacency.get(current))) {
|
|
1439
2328
|
if (!distance.has(neighbor)) {
|
|
1440
2329
|
const neighborDistance = currentDistance + 1;
|
|
1441
2330
|
if (neighborDistance > maxDiameter) {
|
|
@@ -1519,8 +2408,8 @@ function enforceDiameter(clusters, candidateEdges, clusterMaxDiameter) {
|
|
|
1519
2408
|
}
|
|
1520
2409
|
guarded.sort(
|
|
1521
2410
|
(left, right) => compareMergeKeys(
|
|
1522
|
-
|
|
1523
|
-
|
|
2411
|
+
chunkN66HCGCY_cjs.requireDefined(left.members[0]),
|
|
2412
|
+
chunkN66HCGCY_cjs.requireDefined(right.members[0])
|
|
1524
2413
|
)
|
|
1525
2414
|
);
|
|
1526
2415
|
return guarded;
|
|
@@ -1567,8 +2456,8 @@ function enforceBaseGuard(clusters, candidateEdges, baseIds) {
|
|
|
1567
2456
|
}
|
|
1568
2457
|
result.sort(
|
|
1569
2458
|
(left, right) => compareMergeKeys(
|
|
1570
|
-
|
|
1571
|
-
|
|
2459
|
+
chunkN66HCGCY_cjs.requireDefined(left.members[0]),
|
|
2460
|
+
chunkN66HCGCY_cjs.requireDefined(right.members[0])
|
|
1572
2461
|
)
|
|
1573
2462
|
);
|
|
1574
2463
|
return { clusters: result, events };
|
|
@@ -1577,11 +2466,11 @@ function enforceBaseGuard(clusters, candidateEdges, baseIds) {
|
|
|
1577
2466
|
// src/graph-merge/delete-modify.ts
|
|
1578
2467
|
var DELETED_NODE_DROP_REASON = "delete-modify:deleteWins";
|
|
1579
2468
|
function pickHighestPriorityBranch(branchIds, branchRank) {
|
|
1580
|
-
let chosen =
|
|
2469
|
+
let chosen = chunkN66HCGCY_cjs.requireDefined(branchIds[0]);
|
|
1581
2470
|
let chosenRank = branchRank.get(chosen) ?? Number.MAX_SAFE_INTEGER;
|
|
1582
2471
|
for (const candidate of branchIds.slice(1)) {
|
|
1583
2472
|
const candidateRank = branchRank.get(candidate) ?? Number.MAX_SAFE_INTEGER;
|
|
1584
|
-
if (candidateRank < chosenRank || candidateRank === chosenRank &&
|
|
2473
|
+
if (candidateRank < chosenRank || candidateRank === chosenRank && chunkXMQSEJCF_cjs.compareStrings(candidate, chosen) < 0) {
|
|
1585
2474
|
chosen = candidate;
|
|
1586
2475
|
chosenRank = candidateRank;
|
|
1587
2476
|
}
|
|
@@ -1613,7 +2502,7 @@ function groupByEntity(items, entityOf) {
|
|
|
1613
2502
|
}
|
|
1614
2503
|
return grouped;
|
|
1615
2504
|
}
|
|
1616
|
-
function resolveDeleteModifyOver(modified, deleted, modifiedEntity, deletedEntity,
|
|
2505
|
+
function resolveDeleteModifyOver(modified, deleted, modifiedEntity, deletedEntity, dropDeleted, policy, branchRank, preferredBranchId) {
|
|
1617
2506
|
const modifiedByKey = groupByEntity(modified, modifiedEntity);
|
|
1618
2507
|
const deletedByKey = groupByEntity(deleted, deletedEntity);
|
|
1619
2508
|
const survivingModifications = [];
|
|
@@ -1633,8 +2522,8 @@ function resolveDeleteModifyOver(modified, deleted, modifiedEntity, deletedEntit
|
|
|
1633
2522
|
}
|
|
1634
2523
|
continue;
|
|
1635
2524
|
}
|
|
1636
|
-
const deletionsForKey =
|
|
1637
|
-
const { id, kind } = modifiedEntity(
|
|
2525
|
+
const deletionsForKey = chunkN66HCGCY_cjs.requireDefined(deletedByKey.get(key));
|
|
2526
|
+
const { id, kind } = modifiedEntity(chunkN66HCGCY_cjs.requireDefined(modifications[0]));
|
|
1638
2527
|
const deletedBy = pickHighestPriorityBranch(
|
|
1639
2528
|
deletionsForKey.map((deletion) => deletion.branchId),
|
|
1640
2529
|
branchRank
|
|
@@ -1658,7 +2547,7 @@ function resolveDeleteModifyOver(modified, deleted, modifiedEntity, deletedEntit
|
|
|
1658
2547
|
});
|
|
1659
2548
|
if (effectivePolicy === "deleteWins") {
|
|
1660
2549
|
deletions.push({ id, kind });
|
|
1661
|
-
dropped.push(
|
|
2550
|
+
dropped.push(dropDeleted(id));
|
|
1662
2551
|
continue;
|
|
1663
2552
|
}
|
|
1664
2553
|
for (const modification of modifications) {
|
|
@@ -1669,25 +2558,25 @@ function resolveDeleteModifyOver(modified, deleted, modifiedEntity, deletedEntit
|
|
|
1669
2558
|
if (conflictedKeys.has(key)) {
|
|
1670
2559
|
continue;
|
|
1671
2560
|
}
|
|
1672
|
-
const { id, kind } = deletedEntity(
|
|
2561
|
+
const { id, kind } = deletedEntity(chunkN66HCGCY_cjs.requireDefined(deletionsForKey[0]));
|
|
1673
2562
|
deletions.push({ id, kind });
|
|
1674
2563
|
}
|
|
1675
2564
|
return {
|
|
1676
2565
|
survivingModifications: [...survivingModifications].sort((left, right) => {
|
|
1677
|
-
const byId2 =
|
|
2566
|
+
const byId2 = chunkXMQSEJCF_cjs.compareStrings(
|
|
1678
2567
|
modifiedEntity(left).id,
|
|
1679
2568
|
modifiedEntity(right).id
|
|
1680
2569
|
);
|
|
1681
|
-
return byId2 === 0 ?
|
|
2570
|
+
return byId2 === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.branchId, right.branchId) : byId2;
|
|
1682
2571
|
}),
|
|
1683
2572
|
deletions: [...deletions].sort(
|
|
1684
|
-
(left, right) =>
|
|
2573
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
1685
2574
|
),
|
|
1686
2575
|
conflicts: [...conflicts].sort(
|
|
1687
|
-
(left, right) =>
|
|
2576
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.entityId, right.entityId)
|
|
1688
2577
|
),
|
|
1689
2578
|
dropped: [...dropped].sort(
|
|
1690
|
-
(left, right) =>
|
|
2579
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
1691
2580
|
)
|
|
1692
2581
|
};
|
|
1693
2582
|
}
|
|
@@ -1701,10 +2590,10 @@ function reconcileOver(survivingModifications, entityOf, rebuild, policy, branch
|
|
|
1701
2590
|
const conflicts = [];
|
|
1702
2591
|
for (const modifications of grouped.values()) {
|
|
1703
2592
|
if (modifications.length === 1) {
|
|
1704
|
-
out.push(
|
|
2593
|
+
out.push(chunkN66HCGCY_cjs.requireDefined(modifications[0]));
|
|
1705
2594
|
continue;
|
|
1706
2595
|
}
|
|
1707
|
-
const first = entityOf(
|
|
2596
|
+
const first = entityOf(chunkN66HCGCY_cjs.requireDefined(modifications[0]));
|
|
1708
2597
|
const { props, conflicts: propertyConflicts } = threeWayMergeProps(
|
|
1709
2598
|
first.id,
|
|
1710
2599
|
first.kind,
|
|
@@ -1723,7 +2612,7 @@ function reconcileOver(survivingModifications, entityOf, rebuild, policy, branch
|
|
|
1723
2612
|
);
|
|
1724
2613
|
const representative = modifications.find(
|
|
1725
2614
|
(modification) => modification.branchId === chosenBranch
|
|
1726
|
-
) ??
|
|
2615
|
+
) ?? chunkN66HCGCY_cjs.requireDefined(modifications[0]);
|
|
1727
2616
|
out.push(rebuild(representative, chosenBranch, props));
|
|
1728
2617
|
for (const conflict of propertyConflicts) {
|
|
1729
2618
|
conflicts.push(conflict);
|
|
@@ -1731,11 +2620,11 @@ function reconcileOver(survivingModifications, entityOf, rebuild, policy, branch
|
|
|
1731
2620
|
}
|
|
1732
2621
|
return {
|
|
1733
2622
|
survivingModifications: [...out].sort((left, right) => {
|
|
1734
|
-
const byId2 =
|
|
1735
|
-
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;
|
|
1736
2625
|
}),
|
|
1737
2626
|
conflicts: conflicts.sort(
|
|
1738
|
-
(left, right) =>
|
|
2627
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(
|
|
1739
2628
|
`${left.entityId}|${left.property}`,
|
|
1740
2629
|
`${right.entityId}|${right.property}`
|
|
1741
2630
|
)
|
|
@@ -1748,7 +2637,7 @@ function resolveDeleteModify(staging, policy, branchRank, preferredBranchId) {
|
|
|
1748
2637
|
staging.deletedNodes,
|
|
1749
2638
|
(item) => item.node,
|
|
1750
2639
|
(item) => item.node,
|
|
1751
|
-
"node",
|
|
2640
|
+
(id) => ({ kind: "node", id, reason: DELETED_NODE_DROP_REASON }),
|
|
1752
2641
|
policy,
|
|
1753
2642
|
branchRank,
|
|
1754
2643
|
preferredBranchId
|
|
@@ -1761,7 +2650,7 @@ function resolveDeleteModify(staging, policy, branchRank, preferredBranchId) {
|
|
|
1761
2650
|
};
|
|
1762
2651
|
}
|
|
1763
2652
|
function threeWayMergeProps(entityId, kind, baseProps, contributions, context, branchRank, preferredBranchId) {
|
|
1764
|
-
const merged =
|
|
2653
|
+
const merged = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
1765
2654
|
const conflicts = [];
|
|
1766
2655
|
const propertyNames = new Set(Object.keys(baseProps));
|
|
1767
2656
|
for (const contribution of contributions) {
|
|
@@ -1769,11 +2658,11 @@ function threeWayMergeProps(entityId, kind, baseProps, contributions, context, b
|
|
|
1769
2658
|
propertyNames.add(name);
|
|
1770
2659
|
}
|
|
1771
2660
|
}
|
|
1772
|
-
for (const property of [...propertyNames].sort(
|
|
1773
|
-
const baseHas = property
|
|
1774
|
-
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;
|
|
1775
2664
|
const changed = contributions.filter((contribution) => {
|
|
1776
|
-
if (!(
|
|
2665
|
+
if (!chunkN66HCGCY_cjs.hasOwnKey(contribution.forkProps, property)) {
|
|
1777
2666
|
return false;
|
|
1778
2667
|
}
|
|
1779
2668
|
const value2 = contribution.forkProps[property];
|
|
@@ -1785,10 +2674,10 @@ function threeWayMergeProps(entityId, kind, baseProps, contributions, context, b
|
|
|
1785
2674
|
const values = collectConflictingValues(property, changed);
|
|
1786
2675
|
if (values.length === 0) {
|
|
1787
2676
|
const deletedByFork = baseHas && contributions.some(
|
|
1788
|
-
(contribution) => !(
|
|
2677
|
+
(contribution) => !chunkN66HCGCY_cjs.hasOwnKey(contribution.forkProps, property)
|
|
1789
2678
|
);
|
|
1790
2679
|
if (baseHas && !deletedByFork) {
|
|
1791
|
-
merged[property] =
|
|
2680
|
+
merged[property] = chunkN66HCGCY_cjs.requireDefined(baseProps[property]);
|
|
1792
2681
|
}
|
|
1793
2682
|
continue;
|
|
1794
2683
|
}
|
|
@@ -1796,13 +2685,13 @@ function threeWayMergeProps(entityId, kind, baseProps, contributions, context, b
|
|
|
1796
2685
|
values.map((candidate) => canonicalValueKey(candidate.value))
|
|
1797
2686
|
);
|
|
1798
2687
|
if (distinctValues.size === 1) {
|
|
1799
|
-
merged[property] =
|
|
2688
|
+
merged[property] = chunkN66HCGCY_cjs.requireDefined(values[0]).value;
|
|
1800
2689
|
continue;
|
|
1801
2690
|
}
|
|
1802
2691
|
const preferredValue = values.find(
|
|
1803
2692
|
(value2) => value2.branchId === preferredBranchId
|
|
1804
2693
|
)?.value;
|
|
1805
|
-
const canonicalValue = preferredValue ?? (baseHas ?
|
|
2694
|
+
const canonicalValue = preferredValue ?? (baseHas ? chunkN66HCGCY_cjs.requireDefined(baseProps[property]) : chunkN66HCGCY_cjs.requireDefined(values[0]).value);
|
|
1806
2695
|
const reportedValues = preferredBranchId === void 0 ? values : values.filter((value2) => value2.branchId !== preferredBranchId);
|
|
1807
2696
|
const { value, conflict } = resolvePropertyUnion(
|
|
1808
2697
|
{ entityId, kind, property, values, reportedValues, canonicalValue },
|
|
@@ -1836,7 +2725,7 @@ function resolveEdgeDeleteModify(staging, policy, branchRank, preferredBranchId)
|
|
|
1836
2725
|
staging.deletedEdges,
|
|
1837
2726
|
(item) => item.edge,
|
|
1838
2727
|
(item) => item.edge,
|
|
1839
|
-
"edge",
|
|
2728
|
+
(id) => ({ kind: "edge", id, reason: DELETED_NODE_DROP_REASON }),
|
|
1840
2729
|
policy,
|
|
1841
2730
|
branchRank,
|
|
1842
2731
|
preferredBranchId
|
|
@@ -1863,8 +2752,166 @@ function reconcileEdgeModifications(survivingModifications, policy, branchRank,
|
|
|
1863
2752
|
);
|
|
1864
2753
|
}
|
|
1865
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
|
+
|
|
1866
2911
|
// src/graph-merge/edge-repoint.ts
|
|
1867
2912
|
var ENDPOINT_DELETED_DROP_REASON = "edge:endpoint-deleted";
|
|
2913
|
+
var INHERITED_EDGE_ORIGIN = "inherited";
|
|
2914
|
+
var BRANCH_CREATED_EDGE_ORIGIN = "branch-created";
|
|
1868
2915
|
function buildCanonicalMap(clusters, canonicalOf) {
|
|
1869
2916
|
const map = /* @__PURE__ */ new Map();
|
|
1870
2917
|
for (const cluster of clusters) {
|
|
@@ -1884,16 +2931,97 @@ function dedupeKey(fromKey, type, toKey, props) {
|
|
|
1884
2931
|
function groupKey(fromKey, type, toKey) {
|
|
1885
2932
|
return JSON.stringify([fromKey, type, toKey]);
|
|
1886
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
|
+
}
|
|
1887
2994
|
function pickSurvivor(edges, preferredBranchId) {
|
|
2995
|
+
const inherited = edges.filter(
|
|
2996
|
+
(edge) => edge.staged.origin === INHERITED_EDGE_ORIGIN
|
|
2997
|
+
);
|
|
1888
2998
|
const preferred = preferredBranchId === void 0 ? [] : edges.filter((edge) => edge.staged.branchId === preferredBranchId);
|
|
1889
|
-
const candidates = preferred.length > 0 ? preferred : edges;
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
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;
|
|
1895
3013
|
}
|
|
1896
|
-
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];
|
|
1897
3025
|
}
|
|
1898
3026
|
function unionEdgeProps(survivorId, kind, survivor, edges, context, branchRank, preferredBranchId) {
|
|
1899
3027
|
const propertyNames = /* @__PURE__ */ new Set();
|
|
@@ -1902,17 +3030,18 @@ function unionEdgeProps(survivorId, kind, survivor, edges, context, branchRank,
|
|
|
1902
3030
|
propertyNames.add(name);
|
|
1903
3031
|
}
|
|
1904
3032
|
}
|
|
1905
|
-
const props =
|
|
3033
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
1906
3034
|
const conflicts = [];
|
|
1907
|
-
const contributions = edges.map((edge) => edge.staged);
|
|
1908
3035
|
for (const property of [...propertyNames].sort(
|
|
1909
|
-
(left, right) =>
|
|
3036
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
1910
3037
|
)) {
|
|
1911
|
-
const
|
|
3038
|
+
const claimants = edges.filter((edge) => authoredProperty(edge, property)).map((edge) => edge.staged);
|
|
3039
|
+
const values = collectConflictingValues(property, claimants);
|
|
1912
3040
|
if (values.length === 0) {
|
|
3041
|
+
props[property] = chunkN66HCGCY_cjs.hasOwnKey(survivor.staged.props, property) ? survivor.staged.props[property] : unauthoredValue(property, edges);
|
|
1913
3042
|
continue;
|
|
1914
3043
|
}
|
|
1915
|
-
const survivorValue =
|
|
3044
|
+
const survivorValue = chunkN66HCGCY_cjs.hasOwnKey(survivor.staged.props, property) ? survivor.staged.props[property] : chunkN66HCGCY_cjs.requireDefined(values[0]).value;
|
|
1916
3045
|
const canonicalValue = values.find((value2) => value2.branchId === preferredBranchId)?.value ?? survivorValue;
|
|
1917
3046
|
const reportedValues = preferredBranchId === void 0 ? values : values.filter((value2) => value2.branchId !== preferredBranchId);
|
|
1918
3047
|
const { value, conflict } = resolvePropertyUnion(
|
|
@@ -1934,16 +3063,75 @@ function unionEdgeProps(survivorId, kind, survivor, edges, context, branchRank,
|
|
|
1934
3063
|
}
|
|
1935
3064
|
return { props, conflicts };
|
|
1936
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
|
+
}
|
|
1937
3127
|
function repointEdges(stagedEdges, canonicalOf, deletedNodeIds, policy, branchRank, weights, preferredBranchId) {
|
|
1938
3128
|
const dropped = [];
|
|
1939
|
-
const
|
|
1940
|
-
const dedupeKeyByGroup = /* @__PURE__ */ new Map();
|
|
3129
|
+
const liveByGroup = /* @__PURE__ */ new Map();
|
|
1941
3130
|
for (const staged of stagedEdges) {
|
|
1942
|
-
const
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
);
|
|
1946
|
-
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);
|
|
1947
3135
|
if (deletedNodeIds.has(fromKey) || deletedNodeIds.has(toKey)) {
|
|
1948
3136
|
dropped.push({
|
|
1949
3137
|
kind: "edge",
|
|
@@ -1952,21 +3140,20 @@ function repointEdges(stagedEdges, canonicalOf, deletedNodeIds, policy, branchRa
|
|
|
1952
3140
|
});
|
|
1953
3141
|
continue;
|
|
1954
3142
|
}
|
|
1955
|
-
const repointed = {
|
|
1956
|
-
|
|
1957
|
-
|
|
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);
|
|
1958
3152
|
if (bucket === void 0) {
|
|
1959
|
-
|
|
3153
|
+
liveByGroup.set(group, [repointed]);
|
|
1960
3154
|
} else {
|
|
1961
3155
|
bucket.push(repointed);
|
|
1962
3156
|
}
|
|
1963
|
-
const group = groupKey(fromKey, staged.kind, toKey);
|
|
1964
|
-
const keysForGroup = dedupeKeyByGroup.get(group);
|
|
1965
|
-
if (keysForGroup === void 0) {
|
|
1966
|
-
dedupeKeyByGroup.set(group, /* @__PURE__ */ new Set([key]));
|
|
1967
|
-
} else {
|
|
1968
|
-
keysForGroup.add(key);
|
|
1969
|
-
}
|
|
1970
3157
|
}
|
|
1971
3158
|
const context = {
|
|
1972
3159
|
policy,
|
|
@@ -1974,74 +3161,41 @@ function repointEdges(stagedEdges, canonicalOf, deletedNodeIds, policy, branchRa
|
|
|
1974
3161
|
};
|
|
1975
3162
|
const merged = [];
|
|
1976
3163
|
const conflicts = [];
|
|
1977
|
-
const sortedGroups = [...
|
|
1978
|
-
(left, right) =>
|
|
3164
|
+
const sortedGroups = [...liveByGroup.keys()].sort(
|
|
3165
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
1979
3166
|
);
|
|
1980
3167
|
for (const group of sortedGroups) {
|
|
1981
|
-
const
|
|
1982
|
-
const groupEdges
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
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);
|
|
1986
3179
|
}
|
|
1987
3180
|
}
|
|
1988
|
-
const survivor = pickSurvivor(groupEdges, preferredBranchId);
|
|
1989
|
-
const survivorId = survivor.staged.id;
|
|
1990
|
-
const mergedIds = [...groupEdges].map((edge) => edge.staged.id).sort((left, right) => chunkTRF4EBJT_cjs.compareStrings(left, right));
|
|
1991
|
-
const fromId = idOf(survivor.fromKey);
|
|
1992
|
-
const fromKind = kindOf(survivor.fromKey);
|
|
1993
|
-
const toId = idOf(survivor.toKey);
|
|
1994
|
-
const toKind = kindOf(survivor.toKey);
|
|
1995
|
-
if (dedupeKeys.length === 1) {
|
|
1996
|
-
merged.push({
|
|
1997
|
-
id: survivorId,
|
|
1998
|
-
kind: survivor.staged.kind,
|
|
1999
|
-
fromId,
|
|
2000
|
-
toId,
|
|
2001
|
-
fromKind,
|
|
2002
|
-
toKind,
|
|
2003
|
-
props: survivor.staged.props,
|
|
2004
|
-
mergedIds
|
|
2005
|
-
});
|
|
2006
|
-
continue;
|
|
2007
|
-
}
|
|
2008
|
-
const { props, conflicts: groupConflicts } = unionEdgeProps(
|
|
2009
|
-
survivorId,
|
|
2010
|
-
survivor.staged.kind,
|
|
2011
|
-
survivor,
|
|
2012
|
-
groupEdges,
|
|
2013
|
-
context,
|
|
2014
|
-
branchRank,
|
|
2015
|
-
preferredBranchId
|
|
2016
|
-
);
|
|
2017
|
-
for (const conflict of groupConflicts) {
|
|
2018
|
-
conflicts.push(conflict);
|
|
2019
|
-
}
|
|
2020
|
-
merged.push({
|
|
2021
|
-
id: survivorId,
|
|
2022
|
-
kind: survivor.staged.kind,
|
|
2023
|
-
fromId,
|
|
2024
|
-
toId,
|
|
2025
|
-
fromKind,
|
|
2026
|
-
toKind,
|
|
2027
|
-
props,
|
|
2028
|
-
mergedIds
|
|
2029
|
-
});
|
|
2030
3181
|
}
|
|
2031
3182
|
const sortedEdges = merged.map((edge) => ({
|
|
2032
3183
|
edge,
|
|
2033
|
-
sortKey:
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
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);
|
|
2040
3194
|
return {
|
|
2041
3195
|
edges: sortedEdges,
|
|
2042
|
-
dropped: dropped.sort((left, right) =>
|
|
3196
|
+
dropped: dropped.sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)),
|
|
2043
3197
|
conflicts: conflicts.sort(
|
|
2044
|
-
(left, right) =>
|
|
3198
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(
|
|
2045
3199
|
`${left.entityId}|${left.property}`,
|
|
2046
3200
|
`${right.entityId}|${right.property}`
|
|
2047
3201
|
)
|
|
@@ -2087,7 +3241,7 @@ function validateResolveMap(resolve) {
|
|
|
2087
3241
|
return {};
|
|
2088
3242
|
}
|
|
2089
3243
|
const configs = resolve;
|
|
2090
|
-
const validated =
|
|
3244
|
+
const validated = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
2091
3245
|
for (const [kind, config] of Object.entries(configs)) {
|
|
2092
3246
|
const parsed = resolveConfigScalarSchema.safeParse({
|
|
2093
3247
|
threshold: config.threshold
|
|
@@ -2115,7 +3269,7 @@ function validateResolveMap(resolve) {
|
|
|
2115
3269
|
}
|
|
2116
3270
|
validated[kind] = config;
|
|
2117
3271
|
}
|
|
2118
|
-
return validated;
|
|
3272
|
+
return { ...validated };
|
|
2119
3273
|
}
|
|
2120
3274
|
function validateProvenanceWeights(weights) {
|
|
2121
3275
|
for (const [branchId, weight] of weights) {
|
|
@@ -2170,7 +3324,9 @@ function normalizeMergeOptions(options = {}) {
|
|
|
2170
3324
|
...provenanceWeights === void 0 ? {} : { provenanceWeights }
|
|
2171
3325
|
};
|
|
2172
3326
|
}
|
|
2173
|
-
var
|
|
3327
|
+
var PROVENANCE_KIND = "Provenance";
|
|
3328
|
+
var PROVENANCE_OWNER_KIND = "ProvenanceOwner";
|
|
3329
|
+
var Provenance = chunkNK5Q7UNE_cjs.defineNode(PROVENANCE_KIND, {
|
|
2174
3330
|
schema: zod.z.object({
|
|
2175
3331
|
targetGraphId: zod.z.string(),
|
|
2176
3332
|
role: zod.z.enum(["node", "edge"]),
|
|
@@ -2180,38 +3336,308 @@ var Provenance = chunkEE7N5XXQ_cjs.defineNode("Provenance", {
|
|
|
2180
3336
|
sourceId: zod.z.string()
|
|
2181
3337
|
})
|
|
2182
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
|
+
});
|
|
2183
3349
|
function provenanceGraphId(targetGraphId) {
|
|
2184
3350
|
return `${targetGraphId}::merge-provenance`;
|
|
2185
3351
|
}
|
|
2186
|
-
function
|
|
2187
|
-
return
|
|
2188
|
-
id: provenanceGraphId(targetGraphId),
|
|
2189
|
-
nodes: {
|
|
2190
|
-
|
|
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
|
|
2191
3615
|
});
|
|
2192
|
-
|
|
2193
|
-
async function openProvenanceStore(...args) {
|
|
2194
|
-
const [backend, targetGraphId] = args.length === 1 ? [chunk7V2FGGI2_cjs.storeBackend(args[0]), args[0].graphId] : args;
|
|
2195
|
-
const [store] = await chunkXR4YZFKW_cjs.createStoreWithSchema(
|
|
2196
|
-
buildProvenanceGraph(targetGraphId),
|
|
2197
|
-
backend
|
|
2198
|
-
);
|
|
2199
|
-
return store;
|
|
3616
|
+
return row.id === expectedId;
|
|
2200
3617
|
}
|
|
2201
3618
|
var ID_SEPARATOR = "\0";
|
|
2202
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
|
+
}
|
|
2203
3632
|
async function provenanceNodeId(targetGraphId, record) {
|
|
2204
|
-
const tuple = [
|
|
3633
|
+
const tuple = encodeProvenanceTuple([
|
|
2205
3634
|
targetGraphId,
|
|
2206
3635
|
record.role,
|
|
2207
|
-
// canonicalKind is part of node identity: two contributions to different-kind
|
|
2208
|
-
// canonicals that share a bare id (e.g. base Patient:x and Encounter:x) must NOT
|
|
2209
|
-
// hash to the same sidecar row and clobber each other (the (kind,id) identity model).
|
|
2210
3636
|
record.canonicalKind,
|
|
2211
3637
|
record.canonicalId,
|
|
2212
3638
|
record.branchId,
|
|
2213
3639
|
record.sourceId
|
|
2214
|
-
]
|
|
3640
|
+
]);
|
|
2215
3641
|
const digest = await chunkZY4GXIVN_cjs.sha256Hex(tuple, ID_DIGEST_BYTES);
|
|
2216
3642
|
return `prov_${digest}`;
|
|
2217
3643
|
}
|
|
@@ -2219,7 +3645,7 @@ async function persistProvenanceRecords(store, targetGraphId, records) {
|
|
|
2219
3645
|
if (records.length === 0) {
|
|
2220
3646
|
return 0;
|
|
2221
3647
|
}
|
|
2222
|
-
const
|
|
3648
|
+
const identified = await Promise.all(
|
|
2223
3649
|
records.map(async (record) => ({
|
|
2224
3650
|
id: await provenanceNodeId(targetGraphId, record),
|
|
2225
3651
|
props: {
|
|
@@ -2232,6 +3658,11 @@ async function persistProvenanceRecords(store, targetGraphId, records) {
|
|
|
2232
3658
|
}
|
|
2233
3659
|
}))
|
|
2234
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()];
|
|
2235
3666
|
await store.nodes.Provenance.bulkUpsertById(items);
|
|
2236
3667
|
return items.length;
|
|
2237
3668
|
}
|
|
@@ -2239,7 +3670,7 @@ async function readProvenance(store, query = {}) {
|
|
|
2239
3670
|
const all = await store.nodes.Provenance.find();
|
|
2240
3671
|
return all.filter(
|
|
2241
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)
|
|
2242
|
-
).sort((left, right) =>
|
|
3673
|
+
).sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id));
|
|
2243
3674
|
}
|
|
2244
3675
|
|
|
2245
3676
|
// src/graph-merge/sources.ts
|
|
@@ -2249,14 +3680,14 @@ function orderEndpoints(left, right) {
|
|
|
2249
3680
|
return compareMergeKeys(leftKey, rightKey) <= 0 ? { a: leftKey, b: rightKey, left, right } : { a: rightKey, b: leftKey, left: right, right: left };
|
|
2250
3681
|
}
|
|
2251
3682
|
function sortMembersById(members) {
|
|
2252
|
-
return [...members].sort((left, right) =>
|
|
3683
|
+
return [...members].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id));
|
|
2253
3684
|
}
|
|
2254
3685
|
function sortedBucketKeys(blocks) {
|
|
2255
|
-
return [...blocks.keys()].sort((left, right) =>
|
|
3686
|
+
return [...blocks.keys()].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
2256
3687
|
}
|
|
2257
3688
|
var NODE_SYSTEM_FIELDS = /* @__PURE__ */ new Set(["id", "kind", "meta"]);
|
|
2258
3689
|
function nodeProps(node) {
|
|
2259
|
-
const props =
|
|
3690
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
2260
3691
|
for (const [key, value] of Object.entries(
|
|
2261
3692
|
node
|
|
2262
3693
|
)) {
|
|
@@ -2280,7 +3711,7 @@ function windowedPairs(members, config) {
|
|
|
2280
3711
|
key: fieldText(node, config.sortFields)
|
|
2281
3712
|
}));
|
|
2282
3713
|
keyed.sort(
|
|
2283
|
-
(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)
|
|
2284
3715
|
);
|
|
2285
3716
|
const pairs = [];
|
|
2286
3717
|
for (let index = 0; index < keyed.length; index += 1) {
|
|
@@ -2288,8 +3719,8 @@ function windowedPairs(members, config) {
|
|
|
2288
3719
|
for (let index_ = index + 1; index_ <= last; index_ += 1) {
|
|
2289
3720
|
pairs.push(
|
|
2290
3721
|
orderEndpoints(
|
|
2291
|
-
|
|
2292
|
-
|
|
3722
|
+
chunkN66HCGCY_cjs.requireDefined(keyed[index]).node,
|
|
3723
|
+
chunkN66HCGCY_cjs.requireDefined(keyed[index_]).node
|
|
2293
3724
|
)
|
|
2294
3725
|
);
|
|
2295
3726
|
}
|
|
@@ -2311,8 +3742,8 @@ function pairsFromBlocks(blocks, keyless) {
|
|
|
2311
3742
|
for (let index_ = index + 1; index_ < members.length; index_ += 1) {
|
|
2312
3743
|
pairs.push(
|
|
2313
3744
|
orderEndpoints(
|
|
2314
|
-
|
|
2315
|
-
|
|
3745
|
+
chunkN66HCGCY_cjs.requireDefined(members[index]),
|
|
3746
|
+
chunkN66HCGCY_cjs.requireDefined(members[index_])
|
|
2316
3747
|
)
|
|
2317
3748
|
);
|
|
2318
3749
|
}
|
|
@@ -2330,8 +3761,8 @@ function forcedEdgesFromBlocks(blocks) {
|
|
|
2330
3761
|
for (let index = 0; index < members.length; index += 1) {
|
|
2331
3762
|
for (let index_ = index + 1; index_ < members.length; index_ += 1) {
|
|
2332
3763
|
const { a, b } = orderEndpoints(
|
|
2333
|
-
|
|
2334
|
-
|
|
3764
|
+
chunkN66HCGCY_cjs.requireDefined(members[index]),
|
|
3765
|
+
chunkN66HCGCY_cjs.requireDefined(members[index_])
|
|
2335
3766
|
);
|
|
2336
3767
|
edges.push({ a, b, score: FORCED_MATCH_SCORE });
|
|
2337
3768
|
}
|
|
@@ -2351,7 +3782,7 @@ function ontologyRetypeEdges(stagedIdentities, isRetypeCompatible) {
|
|
|
2351
3782
|
}
|
|
2352
3783
|
}
|
|
2353
3784
|
const edges = [];
|
|
2354
|
-
for (const id of [...identitiesById.keys()].sort(
|
|
3785
|
+
for (const id of [...identitiesById.keys()].sort(chunkXMQSEJCF_cjs.compareStrings)) {
|
|
2355
3786
|
const identities = [...new Set(identitiesById.get(id))].sort(
|
|
2356
3787
|
compareMergeKeys
|
|
2357
3788
|
);
|
|
@@ -2365,8 +3796,8 @@ function ontologyRetypeEdges(stagedIdentities, isRetypeCompatible) {
|
|
|
2365
3796
|
}
|
|
2366
3797
|
for (let index = 1; index < members.length; index += 1) {
|
|
2367
3798
|
edges.push({
|
|
2368
|
-
a:
|
|
2369
|
-
b:
|
|
3799
|
+
a: chunkN66HCGCY_cjs.requireDefined(members[0]),
|
|
3800
|
+
b: chunkN66HCGCY_cjs.requireDefined(members[index]),
|
|
2370
3801
|
score: FORCED_MATCH_SCORE
|
|
2371
3802
|
});
|
|
2372
3803
|
}
|
|
@@ -2382,12 +3813,12 @@ function unionByCompatibility(identities, isRetypeCompatible) {
|
|
|
2382
3813
|
for (let index = 0; index < identities.length; index += 1) {
|
|
2383
3814
|
for (let index_ = index + 1; index_ < identities.length; index_ += 1) {
|
|
2384
3815
|
if (isRetypeCompatible([
|
|
2385
|
-
kindOf(
|
|
2386
|
-
kindOf(
|
|
3816
|
+
kindOf(chunkN66HCGCY_cjs.requireDefined(identities[index])),
|
|
3817
|
+
kindOf(chunkN66HCGCY_cjs.requireDefined(identities[index_]))
|
|
2387
3818
|
])) {
|
|
2388
3819
|
forest.union(
|
|
2389
|
-
|
|
2390
|
-
|
|
3820
|
+
chunkN66HCGCY_cjs.requireDefined(identities[index]),
|
|
3821
|
+
chunkN66HCGCY_cjs.requireDefined(identities[index_])
|
|
2391
3822
|
);
|
|
2392
3823
|
}
|
|
2393
3824
|
}
|
|
@@ -2399,7 +3830,7 @@ function unionByCompatibility(identities, isRetypeCompatible) {
|
|
|
2399
3830
|
function groupsOf(identities, representativeOf) {
|
|
2400
3831
|
const byRoot = /* @__PURE__ */ new Map();
|
|
2401
3832
|
for (const identity of identities) {
|
|
2402
|
-
const root =
|
|
3833
|
+
const root = chunkN66HCGCY_cjs.requireDefined(representativeOf.get(identity));
|
|
2403
3834
|
const bucket = byRoot.get(root);
|
|
2404
3835
|
if (bucket === void 0) {
|
|
2405
3836
|
byRoot.set(root, [identity]);
|
|
@@ -2446,7 +3877,7 @@ var baseUniqueSource = {
|
|
|
2446
3877
|
const forcedEdges = [];
|
|
2447
3878
|
const baseMembers = /* @__PURE__ */ new Map();
|
|
2448
3879
|
const constraints = [...uniqueConstraints].sort(
|
|
2449
|
-
(left, right) =>
|
|
3880
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.name, right.name)
|
|
2450
3881
|
);
|
|
2451
3882
|
const items = nodes.map((node) => ({ props: nodeProps(node) }));
|
|
2452
3883
|
const matchesByConstraint = await Promise.all(
|
|
@@ -2489,7 +3920,7 @@ var baseUniqueSource = {
|
|
|
2489
3920
|
pairs: [],
|
|
2490
3921
|
forcedEdges,
|
|
2491
3922
|
baseMembers: [...baseMembers.values()].sort(
|
|
2492
|
-
(left, right) =>
|
|
3923
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
2493
3924
|
)
|
|
2494
3925
|
};
|
|
2495
3926
|
}
|
|
@@ -2546,7 +3977,7 @@ var baseKeySource = {
|
|
|
2546
3977
|
pairs,
|
|
2547
3978
|
forcedEdges: [],
|
|
2548
3979
|
baseMembers: [...baseMembers.values()].sort(
|
|
2549
|
-
(left, right) =>
|
|
3980
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id)
|
|
2550
3981
|
)
|
|
2551
3982
|
};
|
|
2552
3983
|
}
|
|
@@ -2558,16 +3989,16 @@ var CANDIDATE_SOURCES = [
|
|
|
2558
3989
|
|
|
2559
3990
|
// src/graph-merge/staging.ts
|
|
2560
3991
|
function compareByIdThenBranch(left, right) {
|
|
2561
|
-
const byId2 =
|
|
2562
|
-
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;
|
|
2563
3994
|
}
|
|
2564
3995
|
function compareByKindIdBranch(left, right) {
|
|
2565
|
-
const byKind =
|
|
3996
|
+
const byKind = chunkXMQSEJCF_cjs.compareStrings(left.kind, right.kind);
|
|
2566
3997
|
if (byKind !== 0) {
|
|
2567
3998
|
return byKind;
|
|
2568
3999
|
}
|
|
2569
|
-
const byId2 =
|
|
2570
|
-
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;
|
|
2571
4002
|
}
|
|
2572
4003
|
function groupByKind(items) {
|
|
2573
4004
|
const buckets = /* @__PURE__ */ new Map();
|
|
@@ -2581,11 +4012,11 @@ function groupByKind(items) {
|
|
|
2581
4012
|
}
|
|
2582
4013
|
const ordered = /* @__PURE__ */ new Map();
|
|
2583
4014
|
for (const kind of [...buckets.keys()].sort(
|
|
2584
|
-
(left, right) =>
|
|
4015
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
2585
4016
|
)) {
|
|
2586
4017
|
ordered.set(
|
|
2587
4018
|
kind,
|
|
2588
|
-
[...
|
|
4019
|
+
[...chunkN66HCGCY_cjs.requireDefined(buckets.get(kind))].sort(
|
|
2589
4020
|
(left, right) => compareByIdThenBranch(left, right)
|
|
2590
4021
|
)
|
|
2591
4022
|
);
|
|
@@ -2599,6 +4030,11 @@ async function stageBranches(baseStore, branches, captureTargetStateFor) {
|
|
|
2599
4030
|
const newEdges = [];
|
|
2600
4031
|
const modifiedEdges = [];
|
|
2601
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");
|
|
2602
4038
|
let targetNodeVersions = /* @__PURE__ */ new Map();
|
|
2603
4039
|
let targetEdgeSignatures = /* @__PURE__ */ new Map();
|
|
2604
4040
|
for (const branch2 of branches) {
|
|
@@ -2630,6 +4066,22 @@ async function stageBranches(baseStore, branches, captureTargetStateFor) {
|
|
|
2630
4066
|
for (const edge of diff.edges.deleted) {
|
|
2631
4067
|
deletedEdges.push({ branchId, edge, kind: edge.kind, id: edge.id });
|
|
2632
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
|
+
}
|
|
2633
4085
|
}
|
|
2634
4086
|
return {
|
|
2635
4087
|
newNodesByKind: groupByKind(newNodes),
|
|
@@ -2646,6 +4098,25 @@ async function stageBranches(baseStore, branches, captureTargetStateFor) {
|
|
|
2646
4098
|
deletedEdges: [...deletedEdges].sort(
|
|
2647
4099
|
(left, right) => compareByKindIdBranch(left, right)
|
|
2648
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
|
+
),
|
|
2649
4120
|
targetNodeVersions,
|
|
2650
4121
|
targetEdgeSignatures
|
|
2651
4122
|
};
|
|
@@ -2696,7 +4167,7 @@ async function withTxConflictRetry(commit) {
|
|
|
2696
4167
|
// src/graph-merge/type-reconcile.ts
|
|
2697
4168
|
var INCOMPATIBLE_TYPES_FLAG_REASON = "type-reconcile:incompatible-kinds";
|
|
2698
4169
|
function distinctKinds(kinds) {
|
|
2699
|
-
return [...new Set(kinds)].sort((left, right) =>
|
|
4170
|
+
return [...new Set(kinds)].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right));
|
|
2700
4171
|
}
|
|
2701
4172
|
function areEquivalent(closure, left, right) {
|
|
2702
4173
|
return left !== right && isReachable2(closure, left, right) && isReachable2(closure, right, left);
|
|
@@ -2714,8 +4185,8 @@ function mostSpecificCommonKind(closure, kinds) {
|
|
|
2714
4185
|
if (qualifiers.length === 0) {
|
|
2715
4186
|
return void 0;
|
|
2716
4187
|
}
|
|
2717
|
-
return
|
|
2718
|
-
[...qualifiers].sort((left, right) =>
|
|
4188
|
+
return chunkN66HCGCY_cjs.requireDefined(
|
|
4189
|
+
[...qualifiers].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right))[0]
|
|
2719
4190
|
);
|
|
2720
4191
|
}
|
|
2721
4192
|
function reconcileTypes(clusters, closure, mode) {
|
|
@@ -2753,15 +4224,14 @@ function reconcileTypes(clusters, closure, mode) {
|
|
|
2753
4224
|
}
|
|
2754
4225
|
return {
|
|
2755
4226
|
reconciliations: reconciliations.sort(
|
|
2756
|
-
(left, right) =>
|
|
4227
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left.entityId, right.entityId)
|
|
2757
4228
|
),
|
|
2758
4229
|
retypeMap,
|
|
2759
|
-
dropped: dropped.sort((left, right) =>
|
|
4230
|
+
dropped: dropped.sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left.id, right.id))
|
|
2760
4231
|
};
|
|
2761
4232
|
}
|
|
2762
4233
|
|
|
2763
4234
|
// src/graph-merge/merge.ts
|
|
2764
|
-
var COMMITTED_TARGET_BRANCH = asBranchId("__committed_target__");
|
|
2765
4235
|
function asNode(staged) {
|
|
2766
4236
|
return {
|
|
2767
4237
|
kind: staged.node.kind,
|
|
@@ -2775,8 +4245,8 @@ function newNodesByKind(staging) {
|
|
|
2775
4245
|
ordered.set(
|
|
2776
4246
|
kind,
|
|
2777
4247
|
[...items].sort((left, right) => {
|
|
2778
|
-
const byId2 =
|
|
2779
|
-
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;
|
|
2780
4250
|
})
|
|
2781
4251
|
);
|
|
2782
4252
|
}
|
|
@@ -2803,12 +4273,14 @@ async function precomputeEmbeddings(byKind, resolve, embedder) {
|
|
|
2803
4273
|
}
|
|
2804
4274
|
}
|
|
2805
4275
|
}
|
|
2806
|
-
const lookup = /* @__PURE__ */ new Map();
|
|
2807
4276
|
if (texts.size === 0) {
|
|
2808
|
-
return
|
|
4277
|
+
return /* @__PURE__ */ new Map();
|
|
2809
4278
|
}
|
|
4279
|
+
return embedSortedTexts(texts, embedder);
|
|
4280
|
+
}
|
|
4281
|
+
async function embedSortedTexts(texts, embedder) {
|
|
2810
4282
|
const orderedTexts = [...texts].sort(
|
|
2811
|
-
(left, right) =>
|
|
4283
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
2812
4284
|
);
|
|
2813
4285
|
const vectors = await embedder(orderedTexts);
|
|
2814
4286
|
if (vectors.length !== orderedTexts.length) {
|
|
@@ -2820,8 +4292,9 @@ async function precomputeEmbeddings(byKind, resolve, embedder) {
|
|
|
2820
4292
|
}
|
|
2821
4293
|
);
|
|
2822
4294
|
}
|
|
4295
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
2823
4296
|
for (const [index, text] of orderedTexts.entries()) {
|
|
2824
|
-
lookup.set(text,
|
|
4297
|
+
lookup.set(text, chunkN66HCGCY_cjs.requireDefined(vectors[index]));
|
|
2825
4298
|
}
|
|
2826
4299
|
return lookup;
|
|
2827
4300
|
}
|
|
@@ -2843,24 +4316,7 @@ async function embedMissingPairTexts(base, pairs, strategy, embedder) {
|
|
|
2843
4316
|
if (missing.size === 0) {
|
|
2844
4317
|
return existing;
|
|
2845
4318
|
}
|
|
2846
|
-
|
|
2847
|
-
(left, right) => chunkTRF4EBJT_cjs.compareStrings(left, right)
|
|
2848
|
-
);
|
|
2849
|
-
const vectors = await embedder(orderedTexts);
|
|
2850
|
-
if (vectors.length !== orderedTexts.length) {
|
|
2851
|
-
throw new MergeError(
|
|
2852
|
-
`Embedder returned ${vectors.length} vectors for ${orderedTexts.length} texts; expected exactly one per text.`,
|
|
2853
|
-
{
|
|
2854
|
-
details: { texts: orderedTexts.length, vectors: vectors.length },
|
|
2855
|
-
suggestion: "Ensure MergeOptions.embedder returns one vector per input text, in order."
|
|
2856
|
-
}
|
|
2857
|
-
);
|
|
2858
|
-
}
|
|
2859
|
-
const augmented = new Map(existing);
|
|
2860
|
-
for (const [index, text] of orderedTexts.entries()) {
|
|
2861
|
-
augmented.set(text, chunk764JHTLT_cjs.requireDefined(vectors[index]));
|
|
2862
|
-
}
|
|
2863
|
-
return augmented;
|
|
4319
|
+
return new Map([...existing, ...await embedSortedTexts(missing, embedder)]);
|
|
2864
4320
|
}
|
|
2865
4321
|
async function generateAllCandidates(target, staging, options, introspectionKinds, ctx, useBaseSources, embedder) {
|
|
2866
4322
|
const allEdges = [];
|
|
@@ -2874,7 +4330,7 @@ async function generateAllCandidates(target, staging, options, introspectionKind
|
|
|
2874
4330
|
async ([kind, items]) => {
|
|
2875
4331
|
const resolveConfig = options.resolve[kind];
|
|
2876
4332
|
if (resolveConfig === void 0) {
|
|
2877
|
-
return
|
|
4333
|
+
return chunk7BQXPCGN_cjs.ok({ edges: [], warnings: [], baseMembers: [] });
|
|
2878
4334
|
}
|
|
2879
4335
|
const nodes = items.map((staged) => asNode(staged));
|
|
2880
4336
|
const uniqueConstraints = uniqueConstraintsFor(
|
|
@@ -2917,10 +4373,10 @@ async function generateAllCandidates(target, staging, options, introspectionKind
|
|
|
2917
4373
|
options.onComparisonCeiling,
|
|
2918
4374
|
options.maxComparisonsPerKind
|
|
2919
4375
|
);
|
|
2920
|
-
if (
|
|
2921
|
-
return
|
|
4376
|
+
if (chunk7BQXPCGN_cjs.isErr(scored)) {
|
|
4377
|
+
return chunk7BQXPCGN_cjs.err(scored.error);
|
|
2922
4378
|
}
|
|
2923
|
-
return
|
|
4379
|
+
return chunk7BQXPCGN_cjs.ok({
|
|
2924
4380
|
edges: scored.data.edges,
|
|
2925
4381
|
warnings: scored.data.warnings.map(
|
|
2926
4382
|
(warning) => `[${kind}] ${warning.message}`
|
|
@@ -2931,14 +4387,14 @@ async function generateAllCandidates(target, staging, options, introspectionKind
|
|
|
2931
4387
|
)
|
|
2932
4388
|
);
|
|
2933
4389
|
for (const result of perKind) {
|
|
2934
|
-
if (
|
|
2935
|
-
return
|
|
4390
|
+
if (chunk7BQXPCGN_cjs.isErr(result)) {
|
|
4391
|
+
return chunk7BQXPCGN_cjs.err(result.error);
|
|
2936
4392
|
}
|
|
2937
4393
|
allEdges.push(...result.data.edges);
|
|
2938
4394
|
warnings.push(...result.data.warnings);
|
|
2939
4395
|
baseMembers.push(...result.data.baseMembers);
|
|
2940
4396
|
}
|
|
2941
|
-
return
|
|
4397
|
+
return chunk7BQXPCGN_cjs.ok({
|
|
2942
4398
|
// The ONE shared `(a, b)` edge comparator (id-first `(kind, id)` order), so this
|
|
2943
4399
|
// stage emits edges in exactly the order clustering consumes them.
|
|
2944
4400
|
edges: allEdges.sort((left, right) => compareCandidateEdges(left, right)),
|
|
@@ -2959,7 +4415,9 @@ function clusterMembersFor(cluster, newNodesById, baseMembersById) {
|
|
|
2959
4415
|
id: staged.node.id,
|
|
2960
4416
|
kind: staged.node.kind,
|
|
2961
4417
|
branchId: staged.branchId,
|
|
2962
|
-
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 }
|
|
2963
4421
|
});
|
|
2964
4422
|
}
|
|
2965
4423
|
const base = baseMembersById.get(key);
|
|
@@ -2990,37 +4448,70 @@ function indexNewNodesById(staging) {
|
|
|
2990
4448
|
}
|
|
2991
4449
|
return index;
|
|
2992
4450
|
}
|
|
2993
|
-
function buildStagedEdges(staging, modifiedEdges) {
|
|
4451
|
+
function buildStagedEdges(staging, modifiedEdges, edgeValidityEnds, edgeDeletions) {
|
|
2994
4452
|
const staged = [];
|
|
4453
|
+
const stagedIdentities = /* @__PURE__ */ new Set();
|
|
4454
|
+
const windowOnlyCarried = /* @__PURE__ */ new Set();
|
|
2995
4455
|
for (const items of staging.newEdgesByKind.values()) {
|
|
2996
4456
|
for (const item of items) {
|
|
2997
4457
|
staged.push(toStagedEdge(item.branchId, item));
|
|
2998
4458
|
}
|
|
2999
4459
|
}
|
|
3000
4460
|
for (const item of modifiedEdges) {
|
|
4461
|
+
const identity = mergeKeyOf(item.edge);
|
|
4462
|
+
stagedIdentities.add(identity);
|
|
4463
|
+
const validTo = edgeValidityEnds.get(identity);
|
|
3001
4464
|
staged.push({
|
|
3002
4465
|
id: item.edge.id,
|
|
3003
4466
|
kind: item.edge.kind,
|
|
4467
|
+
origin: INHERITED_EDGE_ORIGIN,
|
|
3004
4468
|
fromId: item.edge.fromId,
|
|
3005
4469
|
toId: item.edge.toId,
|
|
3006
4470
|
fromKind: item.edge.fromKind,
|
|
3007
4471
|
toKind: item.edge.toKind,
|
|
3008
4472
|
props: item.edge.forkProps,
|
|
3009
|
-
|
|
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
|
|
3010
4498
|
});
|
|
3011
4499
|
}
|
|
3012
|
-
return staged;
|
|
4500
|
+
return { edges: staged, windowOnlyCarried };
|
|
3013
4501
|
}
|
|
3014
4502
|
function toStagedEdge(branchId, item) {
|
|
3015
4503
|
return {
|
|
3016
4504
|
id: item.edge.id,
|
|
3017
4505
|
kind: item.edge.kind,
|
|
4506
|
+
origin: BRANCH_CREATED_EDGE_ORIGIN,
|
|
3018
4507
|
fromId: item.edge.fromId,
|
|
3019
4508
|
toId: item.edge.toId,
|
|
3020
4509
|
fromKind: item.edge.fromKind,
|
|
3021
4510
|
toKind: item.edge.toKind,
|
|
3022
4511
|
props: item.edge.props,
|
|
3023
|
-
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 }
|
|
3024
4515
|
};
|
|
3025
4516
|
}
|
|
3026
4517
|
function buildProvenanceIndex(records) {
|
|
@@ -3041,34 +4532,38 @@ function buildProvenanceIndex(records) {
|
|
|
3041
4532
|
for (const [branchId, sets] of byBranch) {
|
|
3042
4533
|
frozen.set(branchId, {
|
|
3043
4534
|
nodeIds: [...sets.nodeIds].sort(
|
|
3044
|
-
(left, right) =>
|
|
4535
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)
|
|
3045
4536
|
),
|
|
3046
|
-
edgeIds: [...sets.edgeIds].sort((left, right) =>
|
|
4537
|
+
edgeIds: [...sets.edgeIds].sort((left, right) => chunkXMQSEJCF_cjs.compareStrings(left, right)).map((id) => id)
|
|
3047
4538
|
});
|
|
3048
4539
|
}
|
|
3049
4540
|
return {
|
|
3050
4541
|
byBranch: (branchId) => frozen.get(branchId) ?? { nodeIds: [], edgeIds: [] }
|
|
3051
4542
|
};
|
|
3052
4543
|
}
|
|
3053
|
-
function pushProvenance(records, role, branchId, canonicalId, canonicalKind, sourceId) {
|
|
3054
|
-
records.push({ role, canonicalId, canonicalKind, branchId, sourceId });
|
|
3055
|
-
}
|
|
3056
4544
|
var EMPTY_WEIGHTS = /* @__PURE__ */ new Map();
|
|
3057
|
-
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);
|
|
3058
4547
|
const provenanceRecords = [];
|
|
4548
|
+
const recordedContributions = /* @__PURE__ */ new Set();
|
|
3059
4549
|
const weights = options.provenanceWeights ?? EMPTY_WEIGHTS;
|
|
3060
4550
|
const recordProvenance = (role, branchId, canonicalId, canonicalKind, sourceId) => {
|
|
3061
4551
|
if (branchId === preferredBranchId) {
|
|
3062
4552
|
return;
|
|
3063
4553
|
}
|
|
3064
|
-
|
|
3065
|
-
provenanceRecords,
|
|
4554
|
+
const record = {
|
|
3066
4555
|
role,
|
|
3067
|
-
branchId,
|
|
3068
4556
|
canonicalId,
|
|
3069
4557
|
canonicalKind,
|
|
4558
|
+
branchId,
|
|
3070
4559
|
sourceId
|
|
3071
|
-
|
|
4560
|
+
};
|
|
4561
|
+
const key = contributionKey(record);
|
|
4562
|
+
if (recordedContributions.has(key)) {
|
|
4563
|
+
return;
|
|
4564
|
+
}
|
|
4565
|
+
recordedContributions.add(key);
|
|
4566
|
+
provenanceRecords.push(record);
|
|
3072
4567
|
};
|
|
3073
4568
|
const newNodesById = indexNewNodesById(staging);
|
|
3074
4569
|
const acceptedEndpointKeys = /* @__PURE__ */ new Set();
|
|
@@ -3161,6 +4656,34 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3161
4656
|
for (const deletion of deleteModify.nodeDeletions) {
|
|
3162
4657
|
nodeDeletions.set(mergeKey(deletion.kind, deletion.id), deletion.kind);
|
|
3163
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;
|
|
3164
4687
|
for (const modification of deleteModify.survivingModifications) {
|
|
3165
4688
|
recordProvenance(
|
|
3166
4689
|
"node",
|
|
@@ -3209,6 +4732,31 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3209
4732
|
for (const conflict of reconciledEdgeModifications.conflicts) {
|
|
3210
4733
|
propertyConflicts.push(conflict);
|
|
3211
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
|
+
}
|
|
3212
4760
|
const reconciliation = reconcileTypes(
|
|
3213
4761
|
reconcileInputs,
|
|
3214
4762
|
subClassClosure,
|
|
@@ -3222,18 +4770,57 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3222
4770
|
clusters,
|
|
3223
4771
|
(cluster) => pickClusterCanonical(cluster, entityByIdentity)
|
|
3224
4772
|
);
|
|
3225
|
-
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(
|
|
3226
4808
|
staging,
|
|
3227
|
-
reconciledEdgeModifications.survivingModifications
|
|
4809
|
+
reconciledEdgeModifications.survivingModifications,
|
|
4810
|
+
validWindows.edgeEnds,
|
|
4811
|
+
edgeDeletions
|
|
3228
4812
|
);
|
|
3229
4813
|
const stagedEdgeBranches = /* @__PURE__ */ new Map();
|
|
3230
4814
|
for (const staged of stagedEdges) {
|
|
3231
|
-
const
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
} else {
|
|
4815
|
+
const identity2 = mergeKeyOf(staged);
|
|
4816
|
+
const branches = stagedEdgeBranches.get(staged.id) ?? /* @__PURE__ */ new Set();
|
|
4817
|
+
if (!windowOnlyCarried.has(identity2)) {
|
|
3235
4818
|
branches.add(staged.branchId);
|
|
3236
4819
|
}
|
|
4820
|
+
for (const branchId of validWindows.edgeCredits.get(identity2) ?? []) {
|
|
4821
|
+
branches.add(branchId);
|
|
4822
|
+
}
|
|
4823
|
+
stagedEdgeBranches.set(staged.id, branches);
|
|
3237
4824
|
}
|
|
3238
4825
|
const deletedNodeIdSet = new Set(nodeDeletions.keys());
|
|
3239
4826
|
const repoint2 = repointEdges(
|
|
@@ -3256,9 +4843,13 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3256
4843
|
...deleteModify.dropped,
|
|
3257
4844
|
...edgeDeleteModify.dropped,
|
|
3258
4845
|
...repoint2.dropped,
|
|
3259
|
-
...reconciliation.dropped
|
|
4846
|
+
...reconciliation.dropped,
|
|
4847
|
+
...identity.dropped,
|
|
4848
|
+
...overruledRetractionDrops,
|
|
4849
|
+
...identityRemap.dropped,
|
|
4850
|
+
...validWindows.dropped
|
|
3260
4851
|
].sort(
|
|
3261
|
-
(left, right) =>
|
|
4852
|
+
(left, right) => chunkXMQSEJCF_cjs.compareStrings(`${left.kind}|${left.id}`, `${right.kind}|${right.id}`)
|
|
3262
4853
|
);
|
|
3263
4854
|
return {
|
|
3264
4855
|
canonicalEntities,
|
|
@@ -3273,6 +4864,10 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3273
4864
|
])
|
|
3274
4865
|
),
|
|
3275
4866
|
retypeMap: reconciliation.retypeMap,
|
|
4867
|
+
canonicalOf,
|
|
4868
|
+
nodeValidityEnds: validWindows.nodeEnds,
|
|
4869
|
+
edgeValidityEnds: validWindows.edgeEnds,
|
|
4870
|
+
validityEnds: validWindows.resolutions,
|
|
3276
4871
|
// Order report arrays by the composite (kind, id) identity — never a bare id
|
|
3277
4872
|
// or a `|`-joined string. A bare id ties two different-kind entities that
|
|
3278
4873
|
// share an id, and a `|` separator collides on caller-supplied ids/property
|
|
@@ -3291,7 +4886,7 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3291
4886
|
mergeKey(left.kind, left.entityId),
|
|
3292
4887
|
mergeKey(right.kind, right.entityId)
|
|
3293
4888
|
);
|
|
3294
|
-
return byEntity === 0 ?
|
|
4889
|
+
return byEntity === 0 ? chunkXMQSEJCF_cjs.compareStrings(left.property, right.property) : byEntity;
|
|
3295
4890
|
}
|
|
3296
4891
|
),
|
|
3297
4892
|
deleteModifyConflicts: [
|
|
@@ -3308,17 +4903,19 @@ function planMerge(staging, candidateEdges, candidateWarnings, baseMembers, opti
|
|
|
3308
4903
|
baseAmbiguities: baseAmbiguities.sort(
|
|
3309
4904
|
(left, right) => compareMergeKeys(
|
|
3310
4905
|
mergeKey(
|
|
3311
|
-
|
|
3312
|
-
|
|
4906
|
+
chunkN66HCGCY_cjs.requireDefined(left.baseIds[0]).kind,
|
|
4907
|
+
chunkN66HCGCY_cjs.requireDefined(left.baseIds[0]).id
|
|
3313
4908
|
),
|
|
3314
4909
|
mergeKey(
|
|
3315
|
-
|
|
3316
|
-
|
|
4910
|
+
chunkN66HCGCY_cjs.requireDefined(right.baseIds[0]).kind,
|
|
4911
|
+
chunkN66HCGCY_cjs.requireDefined(right.baseIds[0]).id
|
|
3317
4912
|
)
|
|
3318
4913
|
)
|
|
3319
4914
|
),
|
|
3320
4915
|
provenanceRecords,
|
|
3321
|
-
warnings: candidateWarnings
|
|
4916
|
+
warnings: candidateWarnings,
|
|
4917
|
+
identityAssertions: identityRemap.assertions,
|
|
4918
|
+
identityRetractions: survivingRetractions
|
|
3322
4919
|
};
|
|
3323
4920
|
}
|
|
3324
4921
|
function pickClusterCanonical(cluster, entityByIdentity) {
|
|
@@ -3333,78 +4930,125 @@ function pickClusterCanonical(cluster, entityByIdentity) {
|
|
|
3333
4930
|
);
|
|
3334
4931
|
}
|
|
3335
4932
|
function commitModificationProps(baseProps, forkProps) {
|
|
3336
|
-
const props =
|
|
4933
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
4934
|
+
for (const key of Object.keys(forkProps)) {
|
|
4935
|
+
props[key] = forkProps[key];
|
|
4936
|
+
}
|
|
3337
4937
|
for (const key of Object.keys(baseProps)) {
|
|
3338
|
-
if (!(key
|
|
4938
|
+
if (!chunkN66HCGCY_cjs.hasOwnKey(forkProps, key)) {
|
|
3339
4939
|
props[key] = void 0;
|
|
3340
4940
|
}
|
|
3341
4941
|
}
|
|
3342
4942
|
return props;
|
|
3343
4943
|
}
|
|
3344
|
-
|
|
3345
|
-
|
|
4944
|
+
function finalEdgeEndpoint(plan, kind, id) {
|
|
4945
|
+
return { kind: plan.retypeMap.get(mergeKey(kind, id)) ?? kind, id };
|
|
4946
|
+
}
|
|
4947
|
+
function plannedNodeWrites(plan) {
|
|
3346
4948
|
const canonicalIdentities = /* @__PURE__ */ new Set();
|
|
3347
4949
|
for (const entity of plan.canonicalEntities) {
|
|
3348
4950
|
canonicalIdentities.add(mergeKey(entity.kind, entity.canonicalId));
|
|
3349
4951
|
}
|
|
3350
|
-
const
|
|
4952
|
+
const modificationsByIdentity = /* @__PURE__ */ new Map();
|
|
3351
4953
|
for (const modification of plan.survivingModifications) {
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
4954
|
+
modificationsByIdentity.set(
|
|
4955
|
+
mergeKeyOf(modification.node),
|
|
4956
|
+
modification.node
|
|
4957
|
+
);
|
|
3356
4958
|
}
|
|
4959
|
+
const writes = [];
|
|
4960
|
+
const written = /* @__PURE__ */ new Set();
|
|
3357
4961
|
for (const modification of plan.survivingModifications) {
|
|
3358
4962
|
const identity = mergeKeyOf(modification.node);
|
|
3359
4963
|
if (plan.nodeDeletions.has(identity) || canonicalIdentities.has(identity)) {
|
|
3360
4964
|
continue;
|
|
3361
4965
|
}
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
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
|
+
});
|
|
3371
4975
|
}
|
|
3372
4976
|
for (const entity of plan.canonicalEntities) {
|
|
3373
|
-
const
|
|
3374
|
-
if (plan.nodeDeletions.has(
|
|
4977
|
+
const sourceIdentity = mergeKey(entity.kind, entity.canonicalId);
|
|
4978
|
+
if (plan.nodeDeletions.has(sourceIdentity)) {
|
|
3375
4979
|
continue;
|
|
3376
4980
|
}
|
|
3377
|
-
const kind = plan.retypeMap.get(
|
|
3378
|
-
const modification =
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
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
|
+
});
|
|
3389
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();
|
|
3390
5019
|
for (const [identity, kind] of plan.nodeDeletions) {
|
|
3391
5020
|
const collection = nodeCollection(nodesApi, kind);
|
|
3392
5021
|
await collection.delete(idOf(identity));
|
|
3393
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
|
+
}
|
|
3394
5038
|
for (const [identity, kind] of plan.edgeDeletions) {
|
|
3395
5039
|
await edgeCollection(edgesApi, kind).delete(idOf(identity));
|
|
3396
5040
|
}
|
|
3397
5041
|
const edgesByKind = /* @__PURE__ */ new Map();
|
|
3398
5042
|
for (const edge of plan.mergedEdges) {
|
|
3399
|
-
const fromKind = plan.retypeMap.get(mergeKey(edge.fromKind, edge.fromId));
|
|
3400
|
-
const toKind = plan.retypeMap.get(mergeKey(edge.toKind, edge.toId));
|
|
3401
5043
|
const edgeBaseProps = plan.inheritedEdgeBaseProps.get(edge.id);
|
|
3402
5044
|
const props = edgeBaseProps === void 0 ? edge.props : commitModificationProps(edgeBaseProps, edge.props);
|
|
3403
5045
|
const item = {
|
|
3404
5046
|
id: edge.id,
|
|
3405
|
-
from:
|
|
3406
|
-
to:
|
|
3407
|
-
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 }
|
|
3408
5052
|
};
|
|
3409
5053
|
const existing = edgesByKind.get(edge.kind);
|
|
3410
5054
|
if (existing === void 0) {
|
|
@@ -3418,10 +5062,34 @@ async function applyMergePlan(plan, nodesApi, edgesApi) {
|
|
|
3418
5062
|
await edgeCollection(edgesApi, kind).bulkUpsertById(items);
|
|
3419
5063
|
committedEdges += items.length;
|
|
3420
5064
|
}
|
|
3421
|
-
|
|
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
|
+
};
|
|
3422
5090
|
}
|
|
3423
5091
|
async function commitPlan(target, plan, expectedBaseVersion) {
|
|
3424
|
-
if (!
|
|
5092
|
+
if (!chunkTTAITEPJ_cjs.storeBackend(target).capabilities.transactions) {
|
|
3425
5093
|
throw new MergeError(
|
|
3426
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.)",
|
|
3427
5095
|
{ details: { capability: "transactions" } }
|
|
@@ -3431,15 +5099,18 @@ async function commitPlan(target, plan, expectedBaseVersion) {
|
|
|
3431
5099
|
() => target.transaction(async (tx) => {
|
|
3432
5100
|
if (expectedBaseVersion !== void 0) {
|
|
3433
5101
|
await assertTargetUnchanged(
|
|
3434
|
-
|
|
5102
|
+
chunkTTAITEPJ_cjs.transactionBackend(tx),
|
|
3435
5103
|
target,
|
|
3436
5104
|
expectedBaseVersion
|
|
3437
5105
|
);
|
|
3438
5106
|
}
|
|
5107
|
+
await assertPlannedIdentityIdsFresh(target, chunkTTAITEPJ_cjs.transactionBackend(tx), plan);
|
|
3439
5108
|
return applyMergePlan(
|
|
3440
5109
|
plan,
|
|
3441
5110
|
tx.nodes,
|
|
3442
|
-
tx.edges
|
|
5111
|
+
tx.edges,
|
|
5112
|
+
target,
|
|
5113
|
+
chunkTTAITEPJ_cjs.transactionBackend(tx)
|
|
3443
5114
|
);
|
|
3444
5115
|
}, mergeCommitTransactionOptions(target))
|
|
3445
5116
|
);
|
|
@@ -3452,9 +5123,9 @@ function mergeCommitTransactionOptions(target) {
|
|
|
3452
5123
|
}
|
|
3453
5124
|
async function assertTargetUnchanged(txBackend, target, expectedBaseVersion) {
|
|
3454
5125
|
if (hasRevisionAnchor(expectedBaseVersion)) {
|
|
3455
|
-
await
|
|
5126
|
+
await chunkXMQSEJCF_cjs.lockRecordedGraphWrite(txBackend, target.graphId);
|
|
3456
5127
|
const expectedOrigin = revisionOriginOf(expectedBaseVersion);
|
|
3457
|
-
const liveOrigin = await
|
|
5128
|
+
const liveOrigin = await chunkXMQSEJCF_cjs.readRevisionOrigin(
|
|
3458
5129
|
txBackend,
|
|
3459
5130
|
target.revisionSchema,
|
|
3460
5131
|
target.graphId
|
|
@@ -3468,7 +5139,7 @@ async function assertTargetUnchanged(txBackend, target, expectedBaseVersion) {
|
|
|
3468
5139
|
}
|
|
3469
5140
|
);
|
|
3470
5141
|
}
|
|
3471
|
-
const liveRevision = await
|
|
5142
|
+
const liveRevision = await chunkXMQSEJCF_cjs.readRecordedClock(
|
|
3472
5143
|
txBackend,
|
|
3473
5144
|
target.revisionSchema,
|
|
3474
5145
|
target.graphId
|
|
@@ -3488,7 +5159,8 @@ async function assertTargetUnchanged(txBackend, target, expectedBaseVersion) {
|
|
|
3488
5159
|
const liveContent = await computeContentComponent(
|
|
3489
5160
|
txBackend,
|
|
3490
5161
|
target.graphId,
|
|
3491
|
-
target.graph
|
|
5162
|
+
target.graph,
|
|
5163
|
+
await chunkTTAITEPJ_cjs.storeRuntime(target).identityAssertionsAtTarget(txBackend, "state")
|
|
3492
5164
|
);
|
|
3493
5165
|
const expectedContent = contentComponentOf(expectedBaseVersion);
|
|
3494
5166
|
if (liveContent !== expectedContent) {
|
|
@@ -3526,7 +5198,7 @@ async function validateBaseVersions(target, branches) {
|
|
|
3526
5198
|
const targetVersion = await computeBaseVersion(target);
|
|
3527
5199
|
for (const branch2 of branches) {
|
|
3528
5200
|
if (branch2.base !== targetVersion) {
|
|
3529
|
-
return
|
|
5201
|
+
return chunk7BQXPCGN_cjs.err(
|
|
3530
5202
|
new BaseVersionMismatchError(
|
|
3531
5203
|
`Branch "${branch2.id}" forked from base@V "${branch2.base}", which does not match the merge target's current base@V "${targetVersion}".`,
|
|
3532
5204
|
{
|
|
@@ -3540,20 +5212,50 @@ async function validateBaseVersions(target, branches) {
|
|
|
3540
5212
|
);
|
|
3541
5213
|
}
|
|
3542
5214
|
}
|
|
3543
|
-
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
|
+
}
|
|
3544
5236
|
}
|
|
3545
|
-
function
|
|
5237
|
+
async function tryOpenProvenanceStore(target) {
|
|
3546
5238
|
try {
|
|
3547
|
-
return
|
|
5239
|
+
return chunk7BQXPCGN_cjs.ok(await openProvenanceStore(target));
|
|
3548
5240
|
} catch (error) {
|
|
3549
|
-
|
|
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
|
+
);
|
|
3550
5252
|
}
|
|
3551
5253
|
}
|
|
3552
5254
|
async function resolveMerge(store, target, branches, options, useBaseSources, incremental, expectedBaseVersion) {
|
|
3553
5255
|
let targetBranchSeen = false;
|
|
3554
5256
|
for (const branch2 of branches) {
|
|
3555
5257
|
if (branch2.id === BASE_PROVENANCE_BRANCH) {
|
|
3556
|
-
return
|
|
5258
|
+
return chunk7BQXPCGN_cjs.err(
|
|
3557
5259
|
new MergeError(
|
|
3558
5260
|
`Branch id "${BASE_PROVENANCE_BRANCH}" is reserved for committed-base provenance and cannot be used as a branch id.`,
|
|
3559
5261
|
{ details: { branchId: branch2.id } }
|
|
@@ -3562,7 +5264,7 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3562
5264
|
}
|
|
3563
5265
|
if (branch2.id === COMMITTED_TARGET_BRANCH) {
|
|
3564
5266
|
if (incremental?.targetBranchId !== COMMITTED_TARGET_BRANCH || targetBranchSeen) {
|
|
3565
|
-
return
|
|
5267
|
+
return chunk7BQXPCGN_cjs.err(
|
|
3566
5268
|
new MergeError(
|
|
3567
5269
|
`Branch id "${COMMITTED_TARGET_BRANCH}" is reserved for the committed incremental target and cannot be used as a branch id.`,
|
|
3568
5270
|
{ details: { branchId: branch2.id } }
|
|
@@ -3572,9 +5274,44 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3572
5274
|
targetBranchSeen = true;
|
|
3573
5275
|
}
|
|
3574
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
|
+
}
|
|
3575
5311
|
try {
|
|
3576
5312
|
const preferredBranchId = incremental?.targetBranchId;
|
|
3577
5313
|
const staging = await stageBranches(store, branches, preferredBranchId);
|
|
5314
|
+
const stagedNewByKind = newNodesByKind(staging);
|
|
3578
5315
|
const branchIds = branches.map((branch2) => branch2.id);
|
|
3579
5316
|
const branchOrder = preferredBranchId === void 0 ? options.branchOrder ?? [] : [
|
|
3580
5317
|
preferredBranchId,
|
|
@@ -3590,12 +5327,12 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3590
5327
|
}
|
|
3591
5328
|
const subClassClosure = buildSubClassClosure(introspection.ontology);
|
|
3592
5329
|
const embeddings = options.embedder === void 0 ? void 0 : await precomputeEmbeddings(
|
|
3593
|
-
|
|
5330
|
+
stagedNewByKind,
|
|
3594
5331
|
options.resolve,
|
|
3595
5332
|
options.embedder
|
|
3596
5333
|
);
|
|
3597
5334
|
const ctx = {
|
|
3598
|
-
backend:
|
|
5335
|
+
backend: chunkTTAITEPJ_cjs.storeBackend(store),
|
|
3599
5336
|
...embeddings === void 0 ? {} : { embeddings }
|
|
3600
5337
|
};
|
|
3601
5338
|
const candidates = await generateAllCandidates(
|
|
@@ -3607,9 +5344,38 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3607
5344
|
useBaseSources,
|
|
3608
5345
|
options.embedder
|
|
3609
5346
|
);
|
|
3610
|
-
if (
|
|
3611
|
-
return
|
|
5347
|
+
if (chunk7BQXPCGN_cjs.isErr(candidates)) {
|
|
5348
|
+
return chunk7BQXPCGN_cjs.err(candidates.error);
|
|
3612
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
|
+
};
|
|
3613
5379
|
const plan = planMerge(
|
|
3614
5380
|
staging,
|
|
3615
5381
|
candidates.data.edges,
|
|
@@ -3618,12 +5384,63 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3618
5384
|
options,
|
|
3619
5385
|
branchRank,
|
|
3620
5386
|
subClassClosure,
|
|
5387
|
+
identityContext,
|
|
5388
|
+
storedIdentityRowsById,
|
|
5389
|
+
targetPeers,
|
|
3621
5390
|
preferredBranchId
|
|
3622
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
|
+
}
|
|
3623
5438
|
const merged = incremental === void 0 ? await commitPlan(target, plan, expectedBaseVersion) : await commitIncrementalPlan(target, plan, {
|
|
3624
|
-
stagedNewByKind
|
|
5439
|
+
stagedNewByKind,
|
|
3625
5440
|
options,
|
|
3626
5441
|
introspectionKinds,
|
|
5442
|
+
forkPoint: incremental.forkPoint,
|
|
5443
|
+
...identityGuard === void 0 ? {} : { identityPeerProbe: identityGuard },
|
|
3627
5444
|
// The committed (kind, id) keys the base sources matched at PLAN time;
|
|
3628
5445
|
// anything NEW the in-tx re-probe surfaces is a window write.
|
|
3629
5446
|
plannedBaseMatchKeys: new Set(
|
|
@@ -3635,11 +5452,10 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3635
5452
|
const provenance = options.provenance ? buildProvenanceIndex(plan.provenanceRecords) : { byBranch: () => ({ nodeIds: [], edgeIds: [] }) };
|
|
3636
5453
|
const warnings = [...plan.warnings];
|
|
3637
5454
|
let provenancePersisted;
|
|
3638
|
-
if (
|
|
5455
|
+
if (provenanceStore !== void 0 && !chunk7BQXPCGN_cjs.isErr(provenanceStore)) {
|
|
3639
5456
|
try {
|
|
3640
|
-
const provenanceStore = await openProvenanceStore(target);
|
|
3641
5457
|
const count = await persistProvenanceRecords(
|
|
3642
|
-
provenanceStore,
|
|
5458
|
+
provenanceStore.data,
|
|
3643
5459
|
target.graphId,
|
|
3644
5460
|
plan.provenanceRecords
|
|
3645
5461
|
);
|
|
@@ -3660,17 +5476,18 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3660
5476
|
deleteModifyConflicts: plan.deleteModifyConflicts,
|
|
3661
5477
|
typeReconciliations: plan.typeReconciliations,
|
|
3662
5478
|
dropped: plan.dropped,
|
|
5479
|
+
validityEnds: plan.validityEnds,
|
|
3663
5480
|
baseAmbiguities: plan.baseAmbiguities,
|
|
3664
5481
|
provenance,
|
|
3665
5482
|
warnings,
|
|
3666
5483
|
...provenancePersisted === void 0 ? {} : { provenancePersisted }
|
|
3667
5484
|
};
|
|
3668
|
-
return
|
|
5485
|
+
return chunk7BQXPCGN_cjs.ok(report);
|
|
3669
5486
|
} catch (error) {
|
|
3670
5487
|
if (error instanceof MergeError) {
|
|
3671
|
-
return
|
|
5488
|
+
return chunk7BQXPCGN_cjs.err(error);
|
|
3672
5489
|
}
|
|
3673
|
-
return
|
|
5490
|
+
return chunk7BQXPCGN_cjs.err(
|
|
3674
5491
|
new MergeError(
|
|
3675
5492
|
`Merge failed while staging or committing: ${describeCause(error)}`,
|
|
3676
5493
|
{ cause: error }
|
|
@@ -3680,14 +5497,14 @@ async function resolveMerge(store, target, branches, options, useBaseSources, in
|
|
|
3680
5497
|
}
|
|
3681
5498
|
async function merge(store, branches, optionsInput = {}) {
|
|
3682
5499
|
const normalized = tryNormalize(optionsInput);
|
|
3683
|
-
if (
|
|
3684
|
-
return
|
|
5500
|
+
if (chunk7BQXPCGN_cjs.isErr(normalized)) {
|
|
5501
|
+
return chunk7BQXPCGN_cjs.err(normalized.error);
|
|
3685
5502
|
}
|
|
3686
5503
|
const options = normalized.data;
|
|
3687
5504
|
const target = options.target ?? store;
|
|
3688
5505
|
const precondition = await validateBaseVersions(target, branches);
|
|
3689
|
-
if (
|
|
3690
|
-
return
|
|
5506
|
+
if (chunk7BQXPCGN_cjs.isErr(precondition)) {
|
|
5507
|
+
return chunk7BQXPCGN_cjs.err(precondition.error);
|
|
3691
5508
|
}
|
|
3692
5509
|
return resolveMerge(
|
|
3693
5510
|
store,
|
|
@@ -3703,7 +5520,7 @@ async function validateForkPointVersions(forkPoint, branches) {
|
|
|
3703
5520
|
const forkVersion = await computeBaseVersion(forkPoint);
|
|
3704
5521
|
for (const branch2 of branches) {
|
|
3705
5522
|
if (branch2.base !== forkVersion) {
|
|
3706
|
-
return
|
|
5523
|
+
return chunk7BQXPCGN_cjs.err(
|
|
3707
5524
|
new BaseVersionMismatchError(
|
|
3708
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.`,
|
|
3709
5526
|
{
|
|
@@ -3717,7 +5534,7 @@ async function validateForkPointVersions(forkPoint, branches) {
|
|
|
3717
5534
|
);
|
|
3718
5535
|
}
|
|
3719
5536
|
}
|
|
3720
|
-
return
|
|
5537
|
+
return chunk7BQXPCGN_cjs.ok(forkVersion);
|
|
3721
5538
|
}
|
|
3722
5539
|
function nodeSchemaFor(target, kind) {
|
|
3723
5540
|
const registry = target.graph.nodes;
|
|
@@ -3753,7 +5570,7 @@ function analyzeRevalidatingWrite(schema, current, planned) {
|
|
|
3753
5570
|
};
|
|
3754
5571
|
}
|
|
3755
5572
|
function nodeProps2(node) {
|
|
3756
|
-
const props =
|
|
5573
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
3757
5574
|
for (const [key, value] of Object.entries(node)) {
|
|
3758
5575
|
if (key === "id" || key === "kind" || key === "meta") continue;
|
|
3759
5576
|
props[key] = value;
|
|
@@ -3761,7 +5578,7 @@ function nodeProps2(node) {
|
|
|
3761
5578
|
return props;
|
|
3762
5579
|
}
|
|
3763
5580
|
function edgeProps(edge) {
|
|
3764
|
-
const props =
|
|
5581
|
+
const props = chunkN66HCGCY_cjs.createDataKeyedBag();
|
|
3765
5582
|
for (const [key, value] of Object.entries(edge)) {
|
|
3766
5583
|
if (key === "id" || key === "kind" || key === "fromKind" || key === "fromId" || key === "toKind" || key === "toId" || key === "meta") {
|
|
3767
5584
|
continue;
|
|
@@ -3771,70 +5588,14 @@ function edgeProps(edge) {
|
|
|
3771
5588
|
return props;
|
|
3772
5589
|
}
|
|
3773
5590
|
var INCLUDE_TOMBSTONES = { temporalMode: "includeTombstones" };
|
|
3774
|
-
function finalEdgeFrom(edge, plan) {
|
|
3775
|
-
return {
|
|
3776
|
-
kind: plan.retypeMap.get(mergeKey(edge.fromKind, edge.fromId)) ?? edge.fromKind,
|
|
3777
|
-
id: edge.fromId
|
|
3778
|
-
};
|
|
3779
|
-
}
|
|
3780
|
-
function finalEdgeTo(edge, plan) {
|
|
3781
|
-
return {
|
|
3782
|
-
kind: plan.retypeMap.get(mergeKey(edge.toKind, edge.toId)) ?? edge.toKind,
|
|
3783
|
-
id: edge.toId
|
|
3784
|
-
};
|
|
3785
|
-
}
|
|
3786
5591
|
function assertValidRevalidatingWrite(analysis, message, details) {
|
|
3787
5592
|
if (analysis.status === "invalid") {
|
|
3788
5593
|
throw new MergeError(message, { details });
|
|
3789
5594
|
}
|
|
3790
5595
|
}
|
|
3791
|
-
function describeCause(cause) {
|
|
3792
|
-
return cause instanceof Error ? cause.message : String(cause);
|
|
3793
|
-
}
|
|
3794
|
-
function plannedNodeWrites(plan) {
|
|
3795
|
-
const canonicalIdentities = /* @__PURE__ */ new Set();
|
|
3796
|
-
for (const entity of plan.canonicalEntities) {
|
|
3797
|
-
canonicalIdentities.add(mergeKey(entity.kind, entity.canonicalId));
|
|
3798
|
-
}
|
|
3799
|
-
const survivingModProps = /* @__PURE__ */ new Map();
|
|
3800
|
-
for (const modification of plan.survivingModifications) {
|
|
3801
|
-
survivingModProps.set(
|
|
3802
|
-
mergeKeyOf(modification.node),
|
|
3803
|
-
modification.node.forkProps
|
|
3804
|
-
);
|
|
3805
|
-
}
|
|
3806
|
-
const writes = [];
|
|
3807
|
-
for (const modification of plan.survivingModifications) {
|
|
3808
|
-
const identity = mergeKeyOf(modification.node);
|
|
3809
|
-
if (plan.nodeDeletions.has(identity) || canonicalIdentities.has(identity)) {
|
|
3810
|
-
continue;
|
|
3811
|
-
}
|
|
3812
|
-
writes.push({
|
|
3813
|
-
identity,
|
|
3814
|
-
kind: modification.node.kind,
|
|
3815
|
-
id: modification.node.id,
|
|
3816
|
-
props: modification.node.forkProps
|
|
3817
|
-
});
|
|
3818
|
-
}
|
|
3819
|
-
for (const entity of plan.canonicalEntities) {
|
|
3820
|
-
const sourceIdentity = mergeKey(entity.kind, entity.canonicalId);
|
|
3821
|
-
if (plan.nodeDeletions.has(sourceIdentity)) {
|
|
3822
|
-
continue;
|
|
3823
|
-
}
|
|
3824
|
-
const kind = plan.retypeMap.get(sourceIdentity) ?? entity.kind;
|
|
3825
|
-
const forkProps = survivingModProps.get(sourceIdentity);
|
|
3826
|
-
writes.push({
|
|
3827
|
-
identity: mergeKey(kind, entity.canonicalId),
|
|
3828
|
-
kind,
|
|
3829
|
-
id: entity.canonicalId,
|
|
3830
|
-
props: forkProps === void 0 ? entity.props : { ...entity.props, ...forkProps }
|
|
3831
|
-
});
|
|
3832
|
-
}
|
|
3833
|
-
return writes;
|
|
3834
|
-
}
|
|
3835
5596
|
function edgeWriteSignature(edge, plan) {
|
|
3836
|
-
const from =
|
|
3837
|
-
const to =
|
|
5597
|
+
const from = finalEdgeEndpoint(plan, edge.fromKind, edge.fromId);
|
|
5598
|
+
const to = finalEdgeEndpoint(plan, edge.toKind, edge.toId);
|
|
3838
5599
|
return JSON.stringify([
|
|
3839
5600
|
edge.kind,
|
|
3840
5601
|
from.kind,
|
|
@@ -3876,7 +5637,7 @@ async function validateIncrementalNodeWrites(target, nodesApi, plan) {
|
|
|
3876
5637
|
const analysis = analyzeRevalidatingWrite(
|
|
3877
5638
|
nodeSchemaFor(target, write.kind),
|
|
3878
5639
|
nodeProps2(current),
|
|
3879
|
-
write.
|
|
5640
|
+
nodeWriteProps(write, (modification) => modification.forkProps)
|
|
3880
5641
|
);
|
|
3881
5642
|
assertValidRevalidatingWrite(
|
|
3882
5643
|
analysis,
|
|
@@ -3928,7 +5689,7 @@ async function validateIncrementalEdgeWrites(target, edgesApi, plan) {
|
|
|
3928
5689
|
}
|
|
3929
5690
|
}
|
|
3930
5691
|
}
|
|
3931
|
-
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));
|
|
3932
5693
|
if (notFound.length > 0) {
|
|
3933
5694
|
const crossKindById = /* @__PURE__ */ new Map();
|
|
3934
5695
|
for (const kind of Object.keys(target.graph.edges)) {
|
|
@@ -3955,12 +5716,12 @@ async function validateIncrementalEdgeWrites(target, edgesApi, plan) {
|
|
|
3955
5716
|
);
|
|
3956
5717
|
}
|
|
3957
5718
|
throw new MergeError(
|
|
3958
|
-
`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.`,
|
|
3959
5720
|
{
|
|
3960
5721
|
details: {
|
|
3961
5722
|
id,
|
|
3962
5723
|
committedKind: row.kind,
|
|
3963
|
-
plannedKind:
|
|
5724
|
+
plannedKind: chunkN66HCGCY_cjs.requireDefined(plannedKindById.get(id))
|
|
3964
5725
|
}
|
|
3965
5726
|
}
|
|
3966
5727
|
);
|
|
@@ -3977,8 +5738,8 @@ async function validateIncrementalEdgeWrites(target, edgesApi, plan) {
|
|
|
3977
5738
|
{ details: { id: edge.id, committedKind: current.kind } }
|
|
3978
5739
|
);
|
|
3979
5740
|
}
|
|
3980
|
-
const from =
|
|
3981
|
-
const to =
|
|
5741
|
+
const from = finalEdgeEndpoint(plan, edge.fromKind, edge.fromId);
|
|
5742
|
+
const to = finalEdgeEndpoint(plan, edge.toKind, edge.toId);
|
|
3982
5743
|
if (current.fromId !== from.id || current.fromKind !== from.kind || current.toId !== to.id || current.toKind !== to.kind) {
|
|
3983
5744
|
throw new MergeError(
|
|
3984
5745
|
`mergeIncremental() would overwrite committed edge "${edge.id}" (kind "${edge.kind}") with different endpoints.`,
|
|
@@ -4080,7 +5841,7 @@ async function assertInheritedUnchanged(args) {
|
|
|
4080
5841
|
for (const [kind, ids] of idsByKind) {
|
|
4081
5842
|
const rows = await args.fetchRows(kind, ids);
|
|
4082
5843
|
for (const [index, id] of ids.entries()) {
|
|
4083
|
-
const expected =
|
|
5844
|
+
const expected = chunkN66HCGCY_cjs.requireDefined(args.expected.get(mergeKey(kind, id)));
|
|
4084
5845
|
const current = args.deriveValue(rows[index]);
|
|
4085
5846
|
if (current === expected) {
|
|
4086
5847
|
continue;
|
|
@@ -4150,8 +5911,22 @@ async function assertInheritedEdgesUnchanged(edgesApi, guard, plan) {
|
|
|
4150
5911
|
)
|
|
4151
5912
|
});
|
|
4152
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
|
+
}
|
|
4153
5928
|
async function commitIncrementalPlan(target, plan, guard) {
|
|
4154
|
-
if (!
|
|
5929
|
+
if (!chunkTTAITEPJ_cjs.storeBackend(target).capabilities.transactions) {
|
|
4155
5930
|
throw new MergeError(
|
|
4156
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.",
|
|
4157
5932
|
{ details: { capability: "transactions" } }
|
|
@@ -4160,36 +5935,56 @@ async function commitIncrementalPlan(target, plan, guard) {
|
|
|
4160
5935
|
return withTxConflictRetry(
|
|
4161
5936
|
() => target.transaction(async (tx) => {
|
|
4162
5937
|
if (target.revisionTrackingEnabled) {
|
|
4163
|
-
await
|
|
5938
|
+
await chunkXMQSEJCF_cjs.lockRecordedGraphWrite(chunkTTAITEPJ_cjs.transactionBackend(tx), target.graphId);
|
|
4164
5939
|
}
|
|
5940
|
+
await assertForkPointUnchanged(guard.forkPoint);
|
|
4165
5941
|
const nodesApi = tx.nodes;
|
|
4166
5942
|
const edgesApi = tx.edges;
|
|
4167
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
|
+
);
|
|
4168
5951
|
await assertInheritedTargetUnchanged(nodesApi, edgesApi, guard, plan);
|
|
4169
5952
|
await validateIncrementalNodeWrites(target, nodesApi, plan);
|
|
4170
5953
|
await validateIncrementalEdgeWrites(target, edgesApi, plan);
|
|
4171
|
-
return applyMergePlan(
|
|
5954
|
+
return applyMergePlan(
|
|
5955
|
+
plan,
|
|
5956
|
+
nodesApi,
|
|
5957
|
+
edgesApi,
|
|
5958
|
+
target,
|
|
5959
|
+
chunkTTAITEPJ_cjs.transactionBackend(tx)
|
|
5960
|
+
);
|
|
4172
5961
|
}, mergeCommitTransactionOptions(target))
|
|
4173
5962
|
);
|
|
4174
5963
|
}
|
|
4175
5964
|
async function mergeIncremental(args) {
|
|
4176
5965
|
const { forkPoint, target, branches } = args;
|
|
4177
|
-
const normalized = tryNormalize(args.options ?? {});
|
|
4178
|
-
if (
|
|
4179
|
-
return
|
|
5966
|
+
const normalized = tryNormalize(args.options ?? {}, ["target"]);
|
|
5967
|
+
if (chunk7BQXPCGN_cjs.isErr(normalized)) {
|
|
5968
|
+
return chunk7BQXPCGN_cjs.err(normalized.error);
|
|
4180
5969
|
}
|
|
4181
5970
|
const options = normalized.data;
|
|
4182
5971
|
if (options.onBasePropertyConflict !== "flag") {
|
|
4183
|
-
return
|
|
4184
|
-
new
|
|
5972
|
+
return chunk7BQXPCGN_cjs.err(
|
|
5973
|
+
new InvalidMergeOptionsError(
|
|
4185
5974
|
'mergeIncremental() requires onBasePropertyConflict: "flag" (keep-base); a non-keep-base policy could overwrite a newer committed base value with a stale branch value.',
|
|
4186
|
-
{
|
|
5975
|
+
{
|
|
5976
|
+
details: {
|
|
5977
|
+
option: "onBasePropertyConflict",
|
|
5978
|
+
accepted: "flag",
|
|
5979
|
+
received: options.onBasePropertyConflict
|
|
5980
|
+
}
|
|
5981
|
+
}
|
|
4187
5982
|
)
|
|
4188
5983
|
);
|
|
4189
5984
|
}
|
|
4190
5985
|
const forkPrecondition = await validateForkPointVersions(forkPoint, branches);
|
|
4191
|
-
if (
|
|
4192
|
-
return
|
|
5986
|
+
if (chunk7BQXPCGN_cjs.isErr(forkPrecondition)) {
|
|
5987
|
+
return chunk7BQXPCGN_cjs.err(forkPrecondition.error);
|
|
4193
5988
|
}
|
|
4194
5989
|
const forkVersion = forkPrecondition.data;
|
|
4195
5990
|
const [forkSchema, targetSchema] = await Promise.all([
|
|
@@ -4197,7 +5992,7 @@ async function mergeIncremental(args) {
|
|
|
4197
5992
|
computeSchemaComponent(target)
|
|
4198
5993
|
]);
|
|
4199
5994
|
if (forkSchema !== targetSchema) {
|
|
4200
|
-
return
|
|
5995
|
+
return chunk7BQXPCGN_cjs.err(
|
|
4201
5996
|
new MergeError(
|
|
4202
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).",
|
|
4203
5998
|
{ details: {} }
|
|
@@ -4215,29 +6010,38 @@ async function mergeIncremental(args) {
|
|
|
4215
6010
|
[targetBranch, ...branches],
|
|
4216
6011
|
options,
|
|
4217
6012
|
true,
|
|
4218
|
-
{
|
|
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
|
+
}
|
|
4219
6020
|
);
|
|
4220
6021
|
}
|
|
4221
6022
|
|
|
4222
6023
|
Object.defineProperty(exports, "isErr", {
|
|
4223
6024
|
enumerable: true,
|
|
4224
|
-
get: function () { return
|
|
6025
|
+
get: function () { return chunk7BQXPCGN_cjs.isErr; }
|
|
4225
6026
|
});
|
|
4226
6027
|
Object.defineProperty(exports, "isOk", {
|
|
4227
6028
|
enumerable: true,
|
|
4228
|
-
get: function () { return
|
|
6029
|
+
get: function () { return chunk7BQXPCGN_cjs.isOk; }
|
|
4229
6030
|
});
|
|
4230
6031
|
Object.defineProperty(exports, "unwrap", {
|
|
4231
6032
|
enumerable: true,
|
|
4232
|
-
get: function () { return
|
|
6033
|
+
get: function () { return chunk7BQXPCGN_cjs.unwrap; }
|
|
4233
6034
|
});
|
|
4234
6035
|
exports.BaseVersionMismatchError = BaseVersionMismatchError;
|
|
4235
6036
|
exports.BranchError = BranchError;
|
|
6037
|
+
exports.IdentityMergeConflictError = IdentityMergeConflictError;
|
|
6038
|
+
exports.InvalidMergeOptionsError = InvalidMergeOptionsError;
|
|
4236
6039
|
exports.MERGE_ERROR_CODES = MERGE_ERROR_CODES;
|
|
4237
6040
|
exports.MERGE_OPTION_DEFAULTS = MERGE_OPTION_DEFAULTS;
|
|
4238
6041
|
exports.MergeConflictError = MergeConflictError;
|
|
4239
6042
|
exports.MergeError = MergeError;
|
|
4240
6043
|
exports.SimilarityUnavailableError = SimilarityUnavailableError;
|
|
6044
|
+
exports.VALIDITY_END_TARGET_PRECEDENCE = VALIDITY_END_TARGET_PRECEDENCE;
|
|
4241
6045
|
exports.asBaseVersion = asBaseVersion;
|
|
4242
6046
|
exports.asBranchId = asBranchId;
|
|
4243
6047
|
exports.branch = branch;
|