@nicia-ai/typegraph 0.45.0 → 0.46.0

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