@nicia-ai/typegraph 0.58.0 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +15 -0
- package/dist/{atomic-mutation-program-CPcn0ZPu.d.ts → atomic-mutation-program-BNvJ13bq.d.ts} +1 -1
- package/dist/{atomic-mutation-program-AqOe51XD.d.cts → atomic-mutation-program-DOVE147J.d.cts} +1 -1
- package/dist/backend/drizzle/engine/index.cjs +8 -8
- package/dist/backend/drizzle/engine/index.d.cts +9 -9
- package/dist/backend/drizzle/engine/index.d.ts +9 -9
- package/dist/backend/drizzle/engine/index.js +3 -3
- package/dist/backend/drizzle/indexes.cjs +6 -6
- package/dist/backend/drizzle/indexes.d.cts +1 -1
- package/dist/backend/drizzle/indexes.d.ts +1 -1
- package/dist/backend/drizzle/indexes.js +2 -2
- package/dist/backend/index.d.cts +7 -7
- package/dist/backend/index.d.ts +7 -7
- package/dist/backend/postgres/index.cjs +17 -17
- package/dist/backend/postgres/index.d.cts +8 -8
- package/dist/backend/postgres/index.d.ts +8 -8
- package/dist/backend/postgres/index.js +3 -3
- package/dist/backend/postgres/pglite-store.cjs +1 -1
- package/dist/backend/postgres/pglite-store.d.cts +6 -6
- package/dist/backend/postgres/pglite-store.d.ts +6 -6
- package/dist/backend/postgres/pglite-store.js +1 -1
- package/dist/backend/postgres/pglite.cjs +5 -5
- package/dist/backend/postgres/pglite.d.cts +3 -3
- package/dist/backend/postgres/pglite.d.ts +3 -3
- package/dist/backend/postgres/pglite.js +4 -4
- package/dist/backend/sqlite/index.cjs +16 -16
- package/dist/backend/sqlite/index.d.cts +7 -7
- package/dist/backend/sqlite/index.d.ts +7 -7
- package/dist/backend/sqlite/index.js +3 -3
- package/dist/backend/sqlite/libsql.cjs +7 -7
- package/dist/backend/sqlite/libsql.d.cts +3 -3
- package/dist/backend/sqlite/libsql.d.ts +3 -3
- package/dist/backend/sqlite/libsql.js +3 -3
- package/dist/backend/sqlite/local-store.cjs +1 -1
- package/dist/backend/sqlite/local-store.d.cts +6 -6
- package/dist/backend/sqlite/local-store.d.ts +6 -6
- package/dist/backend/sqlite/local-store.js +1 -1
- package/dist/backend/sqlite/local.cjs +5 -5
- package/dist/backend/sqlite/local.d.cts +3 -3
- package/dist/backend/sqlite/local.d.ts +3 -3
- package/dist/backend/sqlite/local.js +4 -4
- package/dist/{chunk-7JUD57B4.js → chunk-2DKIJP2R.js} +1044 -84
- package/dist/chunk-2DKIJP2R.js.map +1 -0
- package/dist/{chunk-QIKO6DL5.js → chunk-2QNFFAMF.js} +3 -3
- package/dist/{chunk-QIKO6DL5.js.map → chunk-2QNFFAMF.js.map} +1 -1
- package/dist/{chunk-6BVZHDAZ.js → chunk-43DOTETB.js} +3 -3
- package/dist/{chunk-6BVZHDAZ.js.map → chunk-43DOTETB.js.map} +1 -1
- package/dist/{chunk-US3BLFWM.js → chunk-7GNPCBS2.js} +3 -3
- package/dist/{chunk-US3BLFWM.js.map → chunk-7GNPCBS2.js.map} +1 -1
- package/dist/{chunk-IV5W7LKW.cjs → chunk-A22XPVBQ.cjs} +2 -2
- package/dist/chunk-A22XPVBQ.cjs.map +1 -0
- package/dist/{chunk-CVO2ZPW5.js → chunk-B4P4DAW3.js} +4 -4
- package/dist/{chunk-CVO2ZPW5.js.map → chunk-B4P4DAW3.js.map} +1 -1
- package/dist/{chunk-FHFPUORN.cjs → chunk-CNFKFE5L.cjs} +1375 -415
- package/dist/chunk-CNFKFE5L.cjs.map +1 -0
- package/dist/{chunk-4MZQVVPX.cjs → chunk-D5CHUSW7.cjs} +33 -2
- package/dist/chunk-D5CHUSW7.cjs.map +1 -0
- package/dist/{chunk-TKEJR2UL.cjs → chunk-DWO6WZP5.cjs} +6 -6
- package/dist/{chunk-TKEJR2UL.cjs.map → chunk-DWO6WZP5.cjs.map} +1 -1
- package/dist/{chunk-GUMNJJFP.cjs → chunk-EHDLHPMK.cjs} +9 -9
- package/dist/{chunk-GUMNJJFP.cjs.map → chunk-EHDLHPMK.cjs.map} +1 -1
- package/dist/{chunk-DV24YZHG.js → chunk-FTDRMXIJ.js} +6 -6
- package/dist/{chunk-DV24YZHG.js.map → chunk-FTDRMXIJ.js.map} +1 -1
- package/dist/{chunk-BYBMDK6X.js → chunk-GYOQAV6R.js} +3 -3
- package/dist/{chunk-BYBMDK6X.js.map → chunk-GYOQAV6R.js.map} +1 -1
- package/dist/{chunk-GTW5YKFV.js → chunk-HCNC53MU.js} +3 -3
- package/dist/{chunk-GTW5YKFV.js.map → chunk-HCNC53MU.js.map} +1 -1
- package/dist/{chunk-M7TRJXFE.js → chunk-ILVXUOQY.js} +3 -3
- package/dist/{chunk-M7TRJXFE.js.map → chunk-ILVXUOQY.js.map} +1 -1
- package/dist/{chunk-FGKWXSHF.cjs → chunk-KGQVK2II.cjs} +40 -40
- package/dist/{chunk-FGKWXSHF.cjs.map → chunk-KGQVK2II.cjs.map} +1 -1
- package/dist/{chunk-BMATB57B.cjs → chunk-KW3ON5IU.cjs} +11 -11
- package/dist/{chunk-BMATB57B.cjs.map → chunk-KW3ON5IU.cjs.map} +1 -1
- package/dist/{chunk-GK62U3S5.js → chunk-LOFUF6L7.js} +3 -3
- package/dist/{chunk-GK62U3S5.js.map → chunk-LOFUF6L7.js.map} +1 -1
- package/dist/{chunk-BPYZUJX5.cjs → chunk-MTJAT6UO.cjs} +5 -5
- package/dist/{chunk-BPYZUJX5.cjs.map → chunk-MTJAT6UO.cjs.map} +1 -1
- package/dist/{chunk-YTYB5KCQ.js → chunk-OH7QRGPQ.js} +33 -2
- package/dist/chunk-OH7QRGPQ.js.map +1 -0
- package/dist/{chunk-U53HFE4L.cjs → chunk-OKA6H3B3.cjs} +22 -22
- package/dist/{chunk-U53HFE4L.cjs.map → chunk-OKA6H3B3.cjs.map} +1 -1
- package/dist/{chunk-QR6V2BXA.cjs → chunk-PTFO3JI5.cjs} +114 -114
- package/dist/{chunk-QR6V2BXA.cjs.map → chunk-PTFO3JI5.cjs.map} +1 -1
- package/dist/{chunk-C3CN2C2T.cjs → chunk-Q6ZVQWH7.cjs} +38 -38
- package/dist/{chunk-C3CN2C2T.cjs.map → chunk-Q6ZVQWH7.cjs.map} +1 -1
- package/dist/{chunk-WAG3NVD7.cjs → chunk-QBQ465OX.cjs} +12 -12
- package/dist/{chunk-WAG3NVD7.cjs.map → chunk-QBQ465OX.cjs.map} +1 -1
- package/dist/{chunk-CRROO6PK.cjs → chunk-QHP2BCBJ.cjs} +4 -4
- package/dist/{chunk-CRROO6PK.cjs.map → chunk-QHP2BCBJ.cjs.map} +1 -1
- package/dist/{chunk-HWWPL2YL.js → chunk-QWIR5533.js} +2 -2
- package/dist/chunk-QWIR5533.js.map +1 -0
- package/dist/{chunk-ZHLWPHNT.cjs → chunk-RJ3GVX73.cjs} +6 -6
- package/dist/{chunk-ZHLWPHNT.cjs.map → chunk-RJ3GVX73.cjs.map} +1 -1
- package/dist/{chunk-SYKR6MVR.cjs → chunk-T2M2S5YZ.cjs} +59 -59
- package/dist/{chunk-SYKR6MVR.cjs.map → chunk-T2M2S5YZ.cjs.map} +1 -1
- package/dist/{chunk-OESX3T5K.js → chunk-TNNDNSNH.js} +4 -4
- package/dist/{chunk-OESX3T5K.js.map → chunk-TNNDNSNH.js.map} +1 -1
- package/dist/{chunk-5C4OYYDD.js → chunk-UVQMUBZ6.js} +6 -6
- package/dist/{chunk-5C4OYYDD.js.map → chunk-UVQMUBZ6.js.map} +1 -1
- package/dist/{chunk-IV3FENV2.js → chunk-W6K6NSRT.js} +5 -5
- package/dist/{chunk-IV3FENV2.js.map → chunk-W6K6NSRT.js.map} +1 -1
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/{ddl-wlEdaCQK.d.cts → ddl-B9lzB8Zi.d.cts} +3 -3
- package/dist/{ddl-DkFrUTn_.d.ts → ddl-DuZWvxBb.d.ts} +3 -3
- package/dist/graph-extension/index.d.cts +2 -2
- package/dist/graph-extension/index.d.ts +2 -2
- package/dist/graph-merge/index.cjs +122 -122
- package/dist/graph-merge/index.d.cts +7 -6
- package/dist/graph-merge/index.d.ts +7 -6
- package/dist/graph-merge/index.js +10 -10
- package/dist/{graph-templates-B4gkXVqg.d.ts → graph-templates-ClBhrXiA.d.ts} +2 -2
- package/dist/{graph-templates-6zTU7bNe.d.cts → graph-templates-DfmKDARd.d.cts} +2 -2
- package/dist/index.cjs +73 -73
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +11 -11
- package/dist/indexes/index.cjs +8 -8
- package/dist/indexes/index.d.cts +4 -4
- package/dist/indexes/index.d.ts +4 -4
- package/dist/indexes/index.js +3 -3
- package/dist/{ingestion-import-target-im9wEB00.d.cts → ingestion-import-target-BSgJagqI.d.cts} +1 -1
- package/dist/{ingestion-import-target-SopMSm-T.d.ts → ingestion-import-target-PNw10V4T.d.ts} +1 -1
- package/dist/interchange/index.cjs +29 -29
- package/dist/interchange/index.d.cts +7 -6
- package/dist/interchange/index.d.ts +7 -6
- package/dist/interchange/index.js +6 -6
- package/dist/{local-store-impl-ARNXBBSF.cjs → local-store-impl-QGSRYFZF.cjs} +17 -17
- package/dist/{local-store-impl-ARNXBBSF.cjs.map → local-store-impl-QGSRYFZF.cjs.map} +1 -1
- package/dist/{local-store-impl-FTGRP2V7.js → local-store-impl-VEVK2VGA.js} +14 -14
- package/dist/{local-store-impl-FTGRP2V7.js.map → local-store-impl-VEVK2VGA.js.map} +1 -1
- package/dist/{pglite-store-impl-CNQZYRBC.cjs → pglite-store-impl-33CI3P3M.cjs} +17 -17
- package/dist/{pglite-store-impl-CNQZYRBC.cjs.map → pglite-store-impl-33CI3P3M.cjs.map} +1 -1
- package/dist/{pglite-store-impl-NULC2IHH.js → pglite-store-impl-RDPTOOP3.js} +14 -14
- package/dist/{pglite-store-impl-NULC2IHH.js.map → pglite-store-impl-RDPTOOP3.js.map} +1 -1
- package/dist/{postgres-Dd3TrFku.d.ts → postgres-2FBMdOE_.d.ts} +3 -3
- package/dist/{postgres-cLQPlKtp.d.cts → postgres-BR3AeXm9.d.ts} +1 -1
- package/dist/{postgres-CLPfTNYN.d.ts → postgres-CRatyTVL.d.cts} +1 -1
- package/dist/{postgres-B4VD_rVy.d.cts → postgres-lbZf0zyg.d.cts} +3 -3
- package/dist/{profile-Co154QBx.d.ts → profile-BipG05-8.d.ts} +2 -2
- package/dist/{profile-BqThShR_.d.cts → profile-DKtvxVyA.d.cts} +2 -2
- package/dist/profiler/index.d.cts +8 -7
- package/dist/profiler/index.d.ts +8 -7
- package/dist/provenance/index.cjs +15 -15
- package/dist/provenance/index.cjs.map +1 -1
- package/dist/provenance/index.d.cts +6 -5
- package/dist/provenance/index.d.ts +6 -5
- package/dist/provenance/index.js +2 -2
- package/dist/provenance/index.js.map +1 -1
- package/dist/{repair-validity-windows-BLoClfCq.d.cts → repair-validity-windows-BnSHFIsR.d.cts} +1 -1
- package/dist/{repair-validity-windows-C__28ckL.d.ts → repair-validity-windows-DfRb4gZm.d.ts} +1 -1
- package/dist/{resolve-DgFSIK99.d.ts → resolve-BbjZDYTw.d.ts} +1 -1
- package/dist/{resolve-DSUxNIqw.d.cts → resolve-mLksuBg2.d.cts} +1 -1
- package/dist/schema/index.cjs +36 -36
- package/dist/schema/index.d.cts +7 -7
- package/dist/schema/index.d.ts +7 -7
- package/dist/schema/index.js +6 -6
- package/dist/{searchable-CZKn12eY.d.cts → searchable-BEAN91Ce.d.cts} +1 -1
- package/dist/{searchable-CUWWphQI.d.ts → searchable-Bg2lMPRm.d.ts} +1 -1
- package/dist/{sqlite-mSd_eVk4.d.ts → sqlite-Cal3rHgZ.d.ts} +3 -3
- package/dist/{sqlite-RdH7w-ix.d.cts → sqlite-CvajLABd.d.cts} +1 -1
- package/dist/{sqlite-qXLIybR2.d.cts → sqlite-DQxKoWAH.d.cts} +3 -3
- package/dist/{sqlite-CoBmhiFd.d.ts → sqlite-jH5J-Jb8.d.ts} +1 -1
- package/dist/{store-BzmMsCcw.d.ts → store-B5WZ8E5m.d.ts} +313 -177
- package/dist/{store-CL6uTm_W.d.cts → store-DdhFpX53.d.cts} +313 -177
- package/dist/{types-BUoh7cc3.d.cts → types-BUA3dZ99.d.cts} +1 -1
- package/dist/{types-ClC0IFIS.d.ts → types-CPtb7KNf.d.ts} +1 -1
- package/dist/{types-Blq8PG_N.d.cts → types-Dky3sCFz.d.cts} +9 -0
- package/dist/{types-Blq8PG_N.d.ts → types-Dky3sCFz.d.ts} +9 -0
- package/dist/{where-61C-QoM8.d.ts → where-BReEkAiy.d.ts} +1 -1
- package/dist/{where-o3Me5iJx.d.cts → where-Cz11nPRu.d.cts} +1 -1
- package/package.json +2 -2
- package/dist/chunk-4MZQVVPX.cjs.map +0 -1
- package/dist/chunk-7JUD57B4.js.map +0 -1
- package/dist/chunk-FHFPUORN.cjs.map +0 -1
- package/dist/chunk-HWWPL2YL.js.map +0 -1
- package/dist/chunk-IV5W7LKW.cjs.map +0 -1
- package/dist/chunk-YTYB5KCQ.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store/claims/sites.ts","../src/store/claims/node-claims.ts","../src/store/claims/resolved-node-claims.ts","../src/store/embedding-sync.ts","../src/store/fulltext-sync.ts","../src/store/operations/node-write-pipeline.ts"],"names":["disjointnessClaimAxis","DISJOINT_CONSTRAINT_NAME","uniquenessClaimTarget","checkWherePredicate","computeUniqueKey","UniquenessError","DisjointError","constraintFenceRefusal","uniquenessProbeKinds","encodeTupleKey","isSameClaimOwner","compareClaimTargets","bindExtraIfReachable","UNIQUE_SIDECAR_BATCH","requireDefined","ConfigurationError","claimOwnerKey","requireExtras","resolveEmbeddingFields","readOwnProperty","UnsupportedBackendCapabilityError","DEFAULT_SEARCHABLE_LANGUAGE","getSearchableFields","resolveBackendFulltext","RestrictedDeleteError","purgeEdgeClaims","rowPropsToObject","assertsStoredLowerBound","missingRequiredExtras","validateNodeProps","canonicalEqual","ValidationError"],"mappings":";;;;;;;;;;;;;;;AA+GA,SAAS,iBAAA,CACP,UACA,IAAA,EAC0B;AAC1B,EAAA,OAAO,SAAS,gBAAA,CAAiB,IAAI,CAAA,CAAE,GAAA,CAAI,CAAC,SAAA,MAAe;AAAA,IACzD,IAAA,EAAMA,uCAAA,CAAsB,IAAA,EAAM,SAAA,EAAW,QAAQ,CAAA;AAAA,IACrD,cAAA,EAAgBC,0CAAA;AAAA,IAChB,cAAA,EAAgB,IAAA;AAAA,IAChB,SAAA,EAAW,YAAA;AAAA,IACX,aAAA,EAAe,kBAAA;AAAA,IACf,SAAS,EAAE,IAAA,EAAM,cAAA,EAAyB,OAAA,EAAS,MAAM,SAAA;AAAU,GACrE,CAAE,CAAA;AACJ;AAyDO,SAAS,cAAA,CACd,QAAA,EACA,IAAA,EACA,iBAAA,EACA,SAAA,EAC0B;AAC1B,EAAA,MAAM,UAAA,GAAa,iBAAA,CAAkB,GAAA,CAAI,CAAC,UAAA,KAAe;AACvD,IAAA,MAAM,MAAA,GAASC,uCAAA,CAAsB,IAAA,EAAM,UAAA,CAAW,OAAO,QAAQ,CAAA;AACrE,IAAA,OAAO;AAAA,MACL,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,gBAAgB,UAAA,CAAW,IAAA;AAAA,MAC3B,gBAAgB,MAAA,CAAO,SAAA;AAAA,MACvB,SAAA,EACE,SAAA,KAAc,QAAA,IAAY,MAAA,CAAO,YAC/B,YAAA,GACC,aAAA;AAAA,MACL,aAAA,EACE,MAAA,CAAO,SAAA,GACJ,qBAAA,GACA,qBAAA;AAAA,MACL,OAAA,EAAS,EAAE,IAAA,EAAM,YAAA,EAAuB,UAAA;AAAW,KACrD;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,SAAA,KAAc,QAAA,GAAW,UAAA,GAC5B,CAAC,GAAG,kBAAkB,QAAA,EAAU,IAAI,CAAA,EAAG,GAAG,UAAU,CAAA;AAE1D;;;ACtHO,SAAS,uBAAA,CAGd,OAAA,EACA,QAAA,EACA,OAAA,EACA,kBAAA,EAMC;AACD,EAAA,OAAO,EAAE,OAAA,EAAS,QAAA,EAAU,OAAA,EAAS,kBAAA,EAAmB;AAC1D;AAqCA,SAAS,WAAA,CACP,OAAA,EACA,EAAA,EACA,KAAA,EACoB;AACpB,EAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,cAAA,EAAgB,OAAO,EAAA;AAC5C,EAAA,OAAOC,qCAAA,CAAoB,OAAA,CAAQ,UAAA,EAAY,KAAK,CAAA,GAChDC,kCAAA;AAAA,IACE,KAAA;AAAA,IACA,QAAQ,UAAA,CAAW,MAAA;AAAA,IACnB,QAAQ,UAAA,CAAW;AAAA,GACrB,GACA,MAAA;AACN;AAqBO,SAAS,iBACd,QAAA,EACA,IAAA,EACA,EAAA,EACA,KAAA,EACA,aACA,SAAA,EAC2B;AAC3B,EAAA,OAAO,cAAA,CAAe,QAAA,EAAU,IAAA,EAAM,WAAA,EAAa,SAAS,CAAA,CAAE,OAAA;AAAA,IAC5D,CAAC,IAAA,KAAS;AACR,MAAA,MAAM,GAAA,GAAM,WAAA,CAAY,IAAA,CAAK,OAAA,EAAS,IAAI,KAAK,CAAA;AAC/C,MAAA,OAAO,GAAA,KAAQ,MAAA,GACX,EAAC,GACD;AAAA,QACE;AAAA,UACE,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,gBAAgB,IAAA,CAAK,cAAA;AAAA,UACrB,GAAA;AAAA,UACA,WAAW,IAAA,CAAK,SAAA;AAAA,UAChB,eAAe,IAAA,CAAK,aAAA;AAAA,UACpB,SAAS,IAAA,CAAK;AAAA;AAChB,OACF;AAAA,IACN;AAAA,GACF;AACF;AAkCA,SAAS,eAAA,CACP,KAAA,EACA,OAAA,EACA,QAAA,GAA8C,EAAC,EACxC;AACP,EAAA,MAAM,UAAU,QAAA,CAAS,IAAA;AAAA,IACvB,CAAC,SAAA,KACC,SAAA,CAAU,MAAM,cAAA,KAAmB,KAAA,CAAM,QAAQ,cAAA,KAChD,SAAA,CAAU,OAAA,CAAQ,IAAA,KAAS,gBAC1B,SAAA,CAAU,KAAA,CAAM,QAAQ,KAAA,CAAM,OAAA,CAAQ,WACvC,KAAA,CAAM,OAAA,CAAQ,IAAA,KAAS,MAAA,IACtB,UAAU,KAAA,CAAM,IAAA,KAAS,MAAM,OAAA,CAAQ,IAAA,IACtC,UAAU,KAAA,CAAM,OAAA,CAAQ,IAAA,KAAS,YAAA,IAChC,UAAU,KAAA,CAAM,OAAA,CAAQ,UAAU,QAAA,CAAS,KAAA,CAAM,QAAQ,IAAI,CAAA;AAAA,GACrE;AACA,EAAA,MAAM,oBACJ,OAAA,KAAY,MAAA,IAAa,6BAAA,CAA8B,OAAO,IAC5D,OAAA,GACA,MAAA;AACJ,EAAA,IAAI,sBAAsB,MAAA,IAAa,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,WAAW,CAAA,EAAG;AACxE,IAAA,MAAM,IAAIC,iCAAA;AAAA,MACR;AAAA,QACE,GAAG,KAAA,CAAM,OAAA;AAAA,QACT,MAAA,EAAQ,iBAAA,CAAkB,OAAA,CAAQ,UAAA,CAAW;AAAA,OAC/C;AAAA,MACA,EAAE,OAAO,KAAA;AAAM,KACjB;AAAA,EACF;AACA,EAAA,MAAM,OAAO,OAAA,CAAQ,IAAA;AAAA,IACnB,CAAC,UACC,KAAA,CAAM,OAAA,CAAQ,SAAS,cAAA,IACvB,KAAA,CAAM,cAAA,KAAmB,KAAA,CAAM,OAAA,CAAQ,cAAA,IACvC,MAAM,GAAA,KAAQ,KAAA,CAAM,OAAA,CAAQ,KAAA,KAC3B,KAAA,CAAM,OAAA,CAAQ,SAAS,MAAA,IAAa,KAAA,CAAM,IAAA,KAAS,KAAA,CAAM,OAAA,CAAQ,IAAA;AAAA,GACtE;AACA,EAAA,IAAI,IAAA,KAAS,QAAW,MAAM,KAAA;AAC9B,EAAA,MAAM,IAAIC,+BAAA;AAAA,IACR;AAAA,MACE,MAAA,EAAQ,MAAM,OAAA,CAAQ,KAAA;AAAA,MACtB,aAAA,EAAe,KAAK,OAAA,CAAQ,OAAA;AAAA,MAC5B,eAAA,EAAiB,MAAM,OAAA,CAAQ;AAAA,KACjC;AAAA,IACA,EAAE,OAAO,KAAA;AAAM,GACjB;AACF;AAGO,SAAS,0BAAA,CACd,OACA,IAAA,EACO;AACP,EAAA,IAAI,iBAAiBD,iCAAA,EAAiB;AACpC,IAAA,eAAA,CAAgB,KAAA,EAAO,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,QAAQ,CAAA;AAAA,EACpD;AACA,EAAA,MAAM,KAAA;AACR;AAkBA,eAAe,aAAA,CACb,SACA,KAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,EAAM;AAAA,EACd,SAAS,KAAA,EAAO;AACd,IAAA,IAAI,KAAA,YAAiBA,iCAAA,EAAiB,eAAA,CAAgB,KAAA,EAAO,OAAO,CAAA;AACpE,IAAA,MAAM,KAAA;AAAA,EACR;AACF;AAuBA,SAAS,iBAAA,CACP,GAAA,EACA,OAAA,EACA,OAAA,EACgC;AAChC,EAAA,MAAM,SAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,KAAA,KAAU,KAAA,CAAM,cAAc,YAAY,CAAA;AACvE,EAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AACjC,EAAA,OAAOE,wCAAA,CAAuB,GAAA,EAAK,OAAA,EAAS,MAAA,CAAO,aAAa,CAAA;AAClE;AAoBO,SAAS,uBACd,KAAA,EAC+B;AAC/B,EAAA,OAAO,KAAA,CAAM,QAAQ,IAAA,KAAS,YAAA;AAChC;AAiBO,SAAS,yBAAA,CACd,UACA,KAAA,EAIqC;AAMrC,EAAA,MAAM,MAAA,uBAAa,GAAA,EAA+B;AAClD,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,OAAA,EAAS;AAChC,MAAA,IAAI,CAAC,sBAAA,CAAuB,KAAK,CAAA,EAAG;AACpC,MAAA,KAAA,MAAW,QAAA,IAAYC,sCAAA;AAAA,QACrB,IAAA,CAAK,IAAA;AAAA,QACL,KAAA,CAAM,QAAQ,UAAA,CAAW,KAAA;AAAA,QACzB;AAAA,OACF,EAAG;AACD,QAAA,MAAM,WAAWC,gCAAA,CAAe,CAAC,QAAA,EAAU,KAAA,CAAM,cAAc,CAAC,CAAA;AAChE,QAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,QAAQ,CAAA,IAAK;AAAA,UACpC,QAAA;AAAA,UACA,gBAAgB,KAAA,CAAM,cAAA;AAAA,UACtB,IAAA,sBAAU,GAAA;AAAY,SACxB;AACA,QAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AACxB,QAAA,MAAA,CAAO,GAAA,CAAI,UAAU,KAAK,CAAA;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,CAAC,GAAG,MAAA,CAAO,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,IAC1C,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,gBAAgB,KAAA,CAAM,cAAA;AAAA,IACtB,IAAA,EAAM,CAAC,GAAG,KAAA,CAAM,IAAI;AAAA,GACtB,CAAE,CAAA;AACJ;AAyBA,eAAsB,cAAA,CACpB,GAAA,EACA,IAAA,EACA,EAAA,EACA,KAAA,EACA,MAAA,GAG8D,OAC5D,QAAA,EACA,UAAA,KAEA,GAAA,CAAI,OAAA,CAAQ,WAAA,CAAY;AAAA,EACtB,SAAS,GAAA,CAAI,OAAA;AAAA,EACb,QAAA;AAAA,EACA,gBAAgB,UAAA,CAAW,cAAA;AAAA,EAC3B,KAAK,UAAA,CAAW;AAClB,CAAC,CAAA,EACe;AAGlB,EAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,EAAA,KAAA,MAAW,WAAA,IAAeD,sCAAA;AAAA,IACxB,IAAA;AAAA,IACA,KAAA,CAAM,QAAQ,UAAA,CAAW,KAAA;AAAA,IACzB,GAAA,CAAI;AAAA,GACN,EAAG;AACD,IAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,WAAA,EAAa,KAAK,CAAA;AAEhD,IAAA,IAAI,aAAa,MAAA,EAAW;AAC5B,IAAA,MAAM,OAAA,GAAU,sBAAA,CAAuB,IAAA,EAAM,EAAA,EAAI,OAAO,QAAQ,CAAA;AAChE,IAAA,IAAI,OAAA,KAAY,QAAW,MAAM,OAAA;AACjC,IAAA,IAAI,WAAA,KAAgB,KAAA,CAAM,IAAA,EAAM,cAAA,GAAiB,IAAA;AAAA,EACnD;AACA,EAAA,OAAO,cAAA;AACT;AASA,SAAS,sBAAA,CACP,IAAA,EACA,EAAA,EACA,KAAA,EACA,QAAA,EAC6B;AAC7B,EAAA,MAAM,aAAA,GAA4B,EAAE,YAAA,EAAc,IAAA,EAAM,QAAQ,EAAA,EAAG;AACnE,EAAA,IACEE,kCAAA;AAAA,IACE,EAAE,YAAA,EAAc,QAAA,CAAS,aAAA,EAAe,MAAA,EAAQ,SAAS,OAAA,EAAQ;AAAA,IACjE;AAAA,GACF,EACA;AACA,IAAA;AAAA,EACF;AACA,EAAA,OAAO,IAAIL,iCAAA,CAAgB;AAAA,IACzB,gBAAgB,KAAA,CAAM,cAAA;AAAA,IACtB,MAAM,QAAA,CAAS,aAAA;AAAA,IACf,YAAY,QAAA,CAAS,OAAA;AAAA,IACrB,KAAA,EAAO,EAAA;AAAA,IACP,MAAA,EAAQ,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW;AAAA,GAClC,CAAA;AACH;AAOA,eAAsB,0BAAA,CACpB,GAAA,EACA,IAAA,EACA,EAAA,EACA,OACA,WAAA,EACe;AAMf,EAAA,KAAA,MAAW,KAAA,IAAS,gBAAA;AAAA,IAClB,GAAA,CAAI,QAAA;AAAA,IACJ,IAAA;AAAA,IACA,EAAA;AAAA,IACA,KAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF,EAAG;AACD,IAAA,IAAI,uBAAuB,KAAK,CAAA;AAC9B,MAAA,MAAM,cAAA,CAAe,GAAA,EAAK,IAAA,EAAM,EAAA,EAAI,KAAK,CAAA;AAAA,EAC7C;AACF;AA0DA,SAAS,8BACP,OAAA,EAIA;AACA,EAAA,OAAO,OAAA,CAAQ,QAAQ,IAAA,KAAS,YAAA;AAClC;AA8BA,SAAS,WAAA,CAAY,SAAiB,KAAA,EAAoC;AACxE,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,SAAA;AAAA,IACV,OAAA;AAAA,IACA,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,gBAAgB,KAAA,CAAM,cAAA;AAAA,IACtB,KAAK,KAAA,CAAM;AAAA,GACb;AACF;AAEA,SAAS,iBAAA,CACP,SACA,KAAA,EACoB;AACpB,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,QAAA,EAAU,MAAM,KAAA,CAAM,IAAA;AAAA,IACtB,cAAA,EAAgB,MAAM,KAAA,CAAM,cAAA;AAAA,IAC5B,GAAA,EAAK,MAAM,KAAA,CAAM,GAAA;AAAA,IACjB,MAAA,EAAQ,MAAM,IAAA,CAAK,EAAA;AAAA,IACnB,YAAA,EAAc,MAAM,IAAA,CAAK;AAAA,GAC3B;AACF;AAEA,SAAS,sBAAA,CACP,KACA,KAAA,EACwB;AACxB,EAAA,OAAO,KAAA,CAAM,OAAA;AAAA,IAAQ,CAAC,IAAA,KACpB,gBAAA;AAAA,MACE,GAAA,CAAI,QAAA;AAAA,MACJ,IAAA,CAAK,IAAA;AAAA,MACL,IAAA,CAAK,EAAA;AAAA,MACL,IAAA,CAAK,KAAA;AAAA,MACL,IAAA,CAAK,WAAA;AAAA,MACL;AAAA,KACF,CAAE,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,MAChB,IAAA;AAAA,MACA,KAAA;AAAA,MACA,MAAA,EAAQ,WAAA,CAAY,GAAA,CAAI,OAAA,EAAS,KAAK;AAAA,KACxC,CAAE;AAAA,GACJ;AACF;AAOO,SAAS,oBAAA,CACd,KACA,IAAA,EACqB;AACrB,EAAA,MAAM,MAAA,GAAS,sBAAA,CAAuB,GAAA,EAAK,CAAC,IAAI,CAAC,CAAA,CAAE,QAAA,CAAS,CAAC,IAAA,EAAM,KAAA,KAAU;AAC3E,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,SAAA,KAAc,KAAA,CAAM,MAAM,SAAA,EAAW;AAClD,MAAA,OAAO,IAAA,CAAK,KAAA,CAAM,SAAA,KAAc,YAAA,GAAe,EAAA,GAAK,CAAA;AAAA,IACtD;AACA,IAAA,OAAOM,qCAAA,CAAoB,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,MAAM,CAAA;AAAA,EACtD,CAAC,CAAA;AACD,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACrC,IAAA,MAAM,SAAA,GAAY;AAAA,MAChB,IAAA,EAAM,MAAM,KAAA,CAAM,IAAA;AAAA,MAClB,cAAA,EAAgB,MAAM,KAAA,CAAM,cAAA;AAAA,MAC5B,GAAA,EAAK,MAAM,KAAA,CAAM,GAAA;AAAA,MACjB,SAAA,EAAW,MAAM,KAAA,CAAM;AAAA,KACzB;AACA,IAAA,IAAI,KAAA,CAAM,KAAA,CAAM,OAAA,CAAQ,IAAA,KAAS,YAAA,EAAc;AAC7C,MAAA,MAAM,UAAA,GAAaH,sCAAA;AAAA,QACjB,MAAM,IAAA,CAAK,IAAA;AAAA,QACX,KAAA,CAAM,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW,KAAA;AAAA,QAC/B,GAAA,CAAI;AAAA,OACN;AACA,MAAA,OAAO;AAAA,QACL,KAAA,EAAO;AAAA,UACL,GAAG,SAAA;AAAA,UACH,OAAA,EAAS;AAAA,YACP,IAAA,EAAM,YAAA;AAAA,YACN,SAAA,EAAW,UAAA;AAAA,YACX,MAAA,EAAQ,KAAA,CAAM,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW;AAAA;AACzC,SACF;AAAA,QACA,UAAA;AAAA,QACA,iBAAA,EAAmB,MAAA;AAAA,QACnB,OAAA,EAAS,MAAM,KAAA,CAAM;AAAA,OACvB;AAAA,IACF;AACA,IAAA,OAAO;AAAA,MACL,KAAA,EAAO;AAAA,QACL,GAAG,SAAA;AAAA,QACH,OAAA,EAAS;AAAA,UACP,IAAA,EAAM,cAAA;AAAA,UACN,gBAAA,EAAkB,CAAC,KAAA,CAAM,KAAA,CAAM,QAAQ,SAAS;AAAA;AAClD,OACF;AAAA,MACA,YAAY,EAAC;AAAA,MACb,iBAAA,EAAmB,KAAA,CAAM,KAAA,CAAM,OAAA,CAAQ,SAAA;AAAA,MACvC,OAAA,EAAS,MAAM,KAAA,CAAM;AAAA,KACvB;AAAA,EACF,CAAC,CAAA;AACD,EAAA,OAAO;AAAA,IACL,SAAS,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU,MAAM,KAAK,CAAA;AAAA,IAC1C,QAAQ,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,KAAY,QAAQ,KAAK,CAAA;AAAA,IAC/C;AAAA,GACF;AACF;AAGA,eAAe,uBAAA,CACb,GAAA,EACA,MAAA,EACA,QAAA,EACe;AACf,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,aAAA;AAAA,MAAc,CAAC,MAAM,KAAK,CAAA;AAAA,MAAG,MACjC,IAAI,OAAA,CAAQ,YAAA,CAAa,kBAAkB,GAAA,CAAI,OAAA,EAAS,KAAK,CAAC;AAAA,KAChE;AACA,IAAA,QAAA,GAAW,CAAC,KAAK,CAAC,CAAA;AAAA,EACpB;AACF;AAQA,eAAe,kBAAA,CACb,GAAA,EACA,MAAA,EACA,QAAA,EACe;AACf,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACzB,EAAA,MAAM,KAAA,GAAQI,sCAAA;AAAA,IACZ,GAAA,CAAI,OAAA;AAAA,IACJ,GAAA,CAAI,mBAAmB,MAAA,CAAO,iBAAA;AAAA,IAC9BC,sCAAA,CAAqB;AAAA,GACvB;AACA,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,MAAM,uBAAA,CAAwB,GAAA,EAAK,MAAA,EAAQ,QAAQ,CAAA;AACnD,IAAA;AAAA,EACF;AACA,EAAA,MAAM,aAAA;AAAA,IACJ,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU,MAAM,KAAK,CAAA;AAAA,IACjC,YAAY;AACV,MAAA,MAAM,KAAA,CAAM,iBAAA;AAAA,QACV,MAAA,CAAO,IAAI,CAAC,KAAA,KAAU,kBAAkB,GAAA,CAAI,OAAA,EAAS,KAAK,CAAC;AAAA,OAC7D;AAAA,IACF;AAAA,GACF;AACA,EAAA,QAAA,GAAW,MAAM,CAAA;AACnB;AAaA,eAAe,mBAAA,CACb,GAAA,EACA,KAAA,EACA,MAAA,EACA,UAAA,EACY;AACZ,EAAA,MAAM,SAAwB,EAAC;AAC/B,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,CAAM,GAAA,EAAK,MAAA,EAAQ,CAAC,MAAA,KAAW;AACnC,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,MAAM,CAAA;AAAA,IACvB,CAAC,CAAA;AACD,IAAA,OAAO,MAAM,UAAA,EAAW;AAAA,EAC1B,SAAS,KAAA,EAAO;AACd,IAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,UAAA,EAAW,EAAG;AACvC,MAAA,MAAM,yBAAyB,GAAA,EAAK,KAAA,CAAM,KAAK,IAAA,EAAM,KAAA,CAAM,KAAK,EAAA,EAAI;AAAA,QAClE;AAAA,UACE,IAAA,EAAM,MAAM,KAAA,CAAM,IAAA;AAAA,UAClB,cAAA,EAAgB,MAAM,KAAA,CAAM,cAAA;AAAA,UAC5B,GAAA,EAAK,MAAM,KAAA,CAAM;AAAA;AACnB,OACD,CAAA;AAAA,IACH;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF;AA0BA,eAAe,4BAAA,CACb,GAAA,EACA,KAAA,EACA,OAAA,EACA,OACA,WAAA,EACY;AACZ,EAAA,MAAM,YAAA,GAAe,uBAAA;AAAA,IACnB,GAAA,CAAI,OAAA;AAAA,IACJ,GAAA,CAAI,QAAA;AAAA,IACJ,OAAA;AAAA,IACA,GAAA,CAAI;AAAA,GACN;AACA,EAAA,MAAM,MAAA,GAAS,sBAAA,CAAuB,GAAA,EAAK,KAAK,CAAA;AAEhD,EAAA,MAAM,OAAA,GAAU,iBAAA;AAAA,IACd,GAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU,MAAM,KAAK;AAAA,GACnC;AACA,EAAA,IAAI,OAAA,KAAY,QAAW,MAAM,OAAA;AAEjC,EAAA,MAAM,WAAA,GAAc,CAAC,SAAA,KACnB,MAAA,CACG,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,KAAA,CAAM,SAAA,KAAc,SAAS,CAAA,CACrD,QAAA;AAAA,IAAS,CAAC,IAAA,EAAM,KAAA,KACfF,sCAAoB,IAAA,CAAK,MAAA,EAAQ,MAAM,MAAM;AAAA,GAC/C;AAEJ,EAAA,MAAM,SAAS,MAAM,mBAAA;AAAA,IACnB,YAAA;AAAA,IACA,KAAA;AAAA,IACA,YAAY,YAAY,CAAA;AAAA,IACxB;AAAA,GACF;AACA,EAAA,MAAM,KAAA,CAAM,YAAA,EAAc,WAAA,CAAY,aAAa,CAAC,CAAA;AACpD,EAAA,OAAO,MAAA;AACT;AAMO,SAAS,oBAAA,CACd,GAAA,EACA,IAAA,EACA,OAAA,EACA,WAAA,EACY;AACZ,EAAA,OAAO,4BAAA;AAAA,IACL,GAAA;AAAA,IACA,CAAC,IAAI,CAAA;AAAA,IACL,OAAA;AAAA,IACA,uBAAA;AAAA,IACA;AAAA,GACF;AACF;AAMO,SAAS,yBAAA,CACd,GAAA,EACA,KAAA,EACA,OAAA,EACA,WAAA,EACY;AACZ,EAAA,OAAO,4BAAA;AAAA,IACL,GAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACF;AACF;AAWO,SAAS,sBAAA,GAA6C;AAC3D,EAAA,OAAO,OAAA,CAAQ,QAAQ,MAAS,CAAA;AAClC;AAOA,eAAsB,uBAAA,CACpB,GAAA,EACA,IAAA,EACA,EAAA,EACA,OACA,WAAA,EACe;AAGf,EAAA,MAAM,sBAAA;AAAA,IACJ,GAAA;AAAA,IACA,IAAA;AAAA,IACA,EAAA;AAAA,IACA,iBAAiB,GAAA,CAAI,QAAA,EAAU,MAAM,EAAA,EAAI,KAAA,EAAO,aAAa,QAAQ;AAAA,GACvE;AACF;AAmBA,eAAsB,yBAAA,CACpB,GAAA,EACA,YAAA,EACA,OAAA,EACe;AACf,EAAA,MAAMG,gCAAA;AAAA,IACJF,sCAAA;AAAA,MACE,GAAA,CAAI,OAAA;AAAA,MACJ,GAAA,CAAI,mBAAmB,MAAA,CAAO,0BAAA;AAAA,MAC9BC,sCAAA,CAAqB;AAAA,KACvB,EAAG;AAAA,GACL,CAAE;AAAA,IACA,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,YAAA;AAAA,IACA;AAAA,GACD,CAAA;AACH;AAmDA,eAAsB,oBACpB,GAAA,EACA,IAAA,EACA,EAAA,EACA,QAAA,EACA,UACA,WAAA,EAC+B;AAG/B,EAAA,MAAM,UAAU,IAAI,GAAA;AAAA,IAClB,gBAAA;AAAA,MACE,GAAA,CAAI,QAAA;AAAA,MACJ,IAAA;AAAA,MACA,EAAA;AAAA,MACA,QAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA,KACF,CAAE,IAAI,CAAC,KAAA,KAAU,CAAC,KAAA,CAAM,cAAA,EAAgB,KAAA,CAAM,GAAG,CAAC;AAAA,GACpD;AACA,EAAA,MAAM,aAAa,IAAI,GAAA;AAAA,IACrB,gBAAA,CAAiB,IAAI,QAAA,EAAU,IAAA,EAAM,IAAI,QAAA,EAAU,WAAA,EAAa,QAAQ,CAAA,CACrE,MAAA;AAAA,MAAO,CAAC,KAAA,KACP,sBAAA,CAAuB,KAAK;AAAA,KAC9B,CACC,IAAI,CAAC,KAAA,KAAU,CAAC,KAAA,CAAM,cAAA,EAAgB,KAAK,CAAC;AAAA,GACjD;AAEA,EAAA,MAAM,UAAmC,EAAC;AAC1C,EAAA,KAAA,MAAW,cAAc,WAAA,EAAa;AACpC,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA;AAC1C,IAAA,MAAM,QAAA,GAAW,UAAA,CAAW,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA;AAG/C,IAAA,IAAI,MAAA,KAAW,MAAA,IAAa,QAAA,KAAa,MAAA,EAAW;AAGpD,IAAA,IAAI,MAAA,KAAW,MAAA,IAAa,MAAA,KAAW,QAAA,EAAU,GAAA,EAAK;AAKtD,IAAA,MAAM,WAAA,GACJ,aAAa,MAAA,GAAY,KAAA,GACvB,MAAM,cAAA,CAAe,GAAA,EAAK,IAAA,EAAM,EAAA,EAAI,QAAQ,CAAA;AAGhD,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,gBAAgB,UAAA,CAAW,IAAA;AAAA,MAC3B,OAAA,EAAS,MAAA;AAAA,MACT,KAAA,EAAO,QAAA,KAAa,MAAA,IAAa,WAAA,GAAc,MAAA,GAAY;AAAA,KAC5D,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,OAAA;AACT;AA4BA,eAAsB,qBAAA,CACpB,GAAA,EACA,IAAA,EACA,EAAA,EACA,OACA,WAAA,EAC+B;AAC/B,EAAA,MAAM,UAAmC,EAAC;AAC1C,EAAA,KAAA,MAAW,KAAA,IAAS,gBAAA;AAAA,IAClB,GAAA,CAAI,QAAA;AAAA,IACJ,IAAA;AAAA,IACA,EAAA;AAAA,IACA,KAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF,EAAG;AACD,IAAA,MAAM,WAAA,GACJ,sBAAA,CAAuB,KAAK,CAAA,GAC1B,MAAM,eAAe,GAAA,EAAK,IAAA,EAAM,EAAA,EAAI,KAAK,CAAA,GACzC,KAAA;AAEJ,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,gBAAgB,KAAA,CAAM,cAAA;AAAA,MACtB,OAAA,EAAS,MAAA;AAAA,MACT,KAAA,EAAO,cAAc,MAAA,GAAY;AAAA,KAClC,CAAA;AAAA,EACH;AACA,EAAA,OAAO,OAAA;AACT;AAqBA,eAAe,sBAAA,CACb,GAAA,EACA,IAAA,EACA,EAAA,EACA,IAAA,EACe;AACf,EAAA,KAAA,MAAW,SAAS,IAAA,EAAM;AACxB,IAAA,MAAM,GAAA,CAAI,QAAQ,YAAA,CAAa;AAAA,MAC7B,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,gBAAgB,KAAA,CAAM,cAAA;AAAA,MACtB,KAAK,KAAA,CAAM,GAAA;AAAA,MACX,YAAA,EAAc,IAAA;AAAA,MACd,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AACF;AAWA,eAAe,wBAAA,CACb,GAAA,EACA,IAAA,EACA,EAAA,EACA,IAAA,EACe;AACf,EAAA,KAAA,MAAW,SAAS,IAAA,EAAM;AACxB,IAAA,MAAM,GAAA,CAAI,QAAQ,YAAA,CAAa;AAAA,MAC7B,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,UAAU,KAAA,CAAM,IAAA;AAAA,MAChB,gBAAgB,KAAA,CAAM,cAAA;AAAA,MACtB,KAAK,KAAA,CAAM,GAAA;AAAA,MACX,YAAA,EAAc,IAAA;AAAA,MACd,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AACF;AAWA,eAAe,mBAAA,CACb,GAAA,EACA,IAAA,EACA,EAAA,EACA,MACA,UAAA,EACY;AACZ,EAAA,MAAM,UAAwB,EAAC;AAC/B,EAAA,IAAI;AACF,IAAA,KAAA,MAAW,YAAY,IAAA,EAAM;AAC3B,MAAA,MAAM,QAAQ,QAAA,CAAS,KAAA;AACvB,MAAA,IAAI,UAAU,KAAA,CAAA,EAAW;AACzB,MAAA,MAAM,aAAA;AAAA,QAAc,CAAC,KAAK,CAAA;AAAA,QAAG,MAC3B,GAAA,CAAI,OAAA,CAAQ,YAAA,CAAa;AAAA,UACvB,SAAS,GAAA,CAAI,OAAA;AAAA,UACb,UAAU,KAAA,CAAM,IAAA;AAAA,UAChB,gBAAgB,QAAA,CAAS,cAAA;AAAA,UACzB,KAAK,KAAA,CAAM,GAAA;AAAA,UACX,MAAA,EAAQ,EAAA;AAAA,UACR,YAAA,EAAc;AAAA,SACf;AAAA,OACH;AACA,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,gBAAgB,QAAA,CAAS,cAAA;AAAA,QACzB,KAAK,KAAA,CAAM;AAAA,OACZ,CAAA;AAAA,IACH;AACA,IAAA,OAAO,MAAM,UAAA,EAAW;AAAA,EAC1B,SAAS,KAAA,EAAO;AA2Bd,IAAA,MAAM,wBAAA,CAAyB,GAAA,EAAK,IAAA,EAAM,EAAA,EAAI,OAAO,CAAA;AACrD,IAAA,MAAM,KAAA;AAAA,EACR;AACF;AAyCA,eAAsB,uBAAA,CACpB,GAAA,EACA,IAAA,EACA,EAAA,EACA,MACA,UAAA,EACY;AACZ,EAAA,MAAM,OAAA,GAAU,iBAAA;AAAA,IACd,GAAA;AAAA,IACA,GAAA,CAAI,OAAA;AAAA,IACJ,IAAA,CAAK,OAAA;AAAA,MAAQ,CAAC,aACZ,QAAA,CAAS,KAAA,KAAU,SAAY,EAAC,GAAI,CAAC,QAAA,CAAS,KAAK;AAAA;AACrD,GACF;AACA,EAAA,IAAI,OAAA,KAAY,QAAW,MAAM,OAAA;AAEjC,EAAA,MAAM,SAAS,MAAM,mBAAA,CAAoB,KAAK,IAAA,EAAM,EAAA,EAAI,MAAM,UAAU,CAAA;AACxE,EAAA,MAAM,sBAAA;AAAA,IACJ,GAAA;AAAA,IACA,IAAA;AAAA,IACA,EAAA;AAAA,IACA,IAAA,CAAK,OAAA;AAAA,MAAQ,CAAC,QAAA,KACZ,QAAA,CAAS,OAAA,KAAY,SACnB,EAAC,GACD,CAAC,EAAE,gBAAgB,QAAA,CAAS,cAAA,EAAgB,GAAA,EAAK,QAAA,CAAS,SAAS;AAAA;AACvE,GACF;AACA,EAAA,OAAO,MAAA;AACT;;;AC3wCA,SAAS,YAAY,KAAA,EAAqC;AACxD,EAAA,OAAOJ,iCAAe,CAAC,KAAA,CAAM,cAAA,EAAgB,KAAA,CAAM,GAAG,CAAC,CAAA;AACzD;AAcA,SAAS,aAAA,CAAc,MAAqB,KAAA,EAA+B;AACzE,EAAA,OACE,WAAA,CAAY,KAAK,KAAK,CAAA,KAAM,YAAY,KAAA,CAAM,KAAK,MAClD,KAAA,CAAM,UAAA,CAAW,SAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,IACxC,IAAA,CAAK,WAAW,QAAA,CAAS,KAAA,CAAM,MAAM,IAAI,CAAA,CAAA;AAE/C;AAEA,SAAS,oBAAA,CACP,WACA,UAAA,EACiB;AACjB,EAAA,OAAO,IAAIJ,iCAAA,CAAgB;AAAA,IACzB,cAAA,EAAgB,WAAW,KAAA,CAAM,cAAA;AAAA,IACjC,IAAA,EAAM,UAAU,KAAA,CAAM,YAAA;AAAA,IACtB,UAAA,EAAY,UAAU,KAAA,CAAM,MAAA;AAAA,IAC5B,KAAA,EAAO,WAAW,KAAA,CAAM,MAAA;AAAA,IACxB,MAAA,EAAQ,UAAA,CAAW,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW;AAAA,GAC7C,CAAA;AACH;AAeA,SAAS,cAAA,CACP,KACA,OAAA,EAC0B;AAC1B,EAAA,MAAM,WAA4B,EAAC;AACnC,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAM,KAAA,GAAoB;AAAA,MACxB,cAAc,MAAA,CAAO,IAAA;AAAA,MACrB,QAAQ,MAAA,CAAO;AAAA,KACjB;AACA,IAAA,MAAM,OAAA,GAAU,gBAAA;AAAA,MACd,GAAA,CAAI,QAAA;AAAA,MACJ,MAAA,CAAO,IAAA;AAAA,MACP,MAAA,CAAO,EAAA;AAAA,MACP,EAAE,GAAG,MAAA,CAAO,KAAA,EAAM;AAAA,MAClB,MAAA,CAAO,WAAA;AAAA,MACP;AAAA,KACF;AACA,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,IAAI,CAAC,sBAAA,CAAuB,KAAK,CAAA,EAAG;AACpC,MAAA,MAAM,QAAA,GAA0B;AAAA,QAC9B,KAAA;AAAA,QACA,KAAA;AAAA,QACA,UAAA,EAAYG,sCAAA;AAAA,UACV,MAAA,CAAO,IAAA;AAAA,UACP,KAAA,CAAM,QAAQ,UAAA,CAAW,KAAA;AAAA,UACzB,GAAA,CAAI;AAAA;AACN,OACF;AACA,MAAA,MAAM,YAAY,QAAA,CAAS,IAAA;AAAA,QACzB,CAAC,SAAA,KACC,CAACE,kCAAA,CAAiB,SAAA,CAAU,KAAA,EAAO,QAAA,CAAS,KAAK,CAAA,IACjD,aAAA,CAAc,SAAA,EAAW,QAAQ;AAAA,OACrC;AACA,MAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,QAAA,MAAM,oBAAA,CAAqB,WAAW,QAAQ,CAAA;AAAA,MAChD;AACA,MAAA,QAAA,CAAS,KAAK,QAAQ,CAAA;AAAA,IACxB;AAAA,EACF;AACA,EAAA,OAAO,QAAA;AACT;AAiBA,SAAS,oBACP,MAAA,EAC4B;AAC5B,EAAA,MAAM,MAAA,uBAAa,GAAA,EAOjB;AACF,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,KAAA,MAAW,SAAA,IAAa,MAAM,UAAA,EAAY;AACxC,MAAA,MAAM,WAAWD,gCAAA,CAAe,CAAC,WAAW,KAAA,CAAM,KAAA,CAAM,cAAc,CAAC,CAAA;AACvE,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,GAAA,CAAI,QAAQ,CAAA;AACpC,MAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,QAAA,MAAA,CAAO,IAAI,QAAA,EAAU;AAAA,UACnB,SAAA;AAAA,UACA,cAAA,EAAgB,MAAM,KAAA,CAAM,cAAA;AAAA,UAC5B,WAAA,kBAAa,IAAI,GAAA,CAAI,CAAC,CAAC,MAAM,KAAA,CAAM,GAAA,EAAK,KAAK,CAAC,CAAC;AAAA,SAChD,CAAA;AACD,QAAA;AAAA,MACF;AACA,MAAA,QAAA,CAAS,WAAA,CAAY,GAAA,CAAI,KAAA,CAAM,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,IACjD;AAAA,EACF;AACA,EAAA,OAAO,CAAC,GAAG,MAAA,CAAO,MAAA,EAAQ,CAAA;AAC5B;AA0BA,SAAS,kBACP,GAAA,EAC+D;AAC/D,EAAA,MAAM,KAAA,GAAQG,sCAAA;AAAA,IACZ,GAAA,CAAI,OAAA;AAAA,IACJ,GAAA,CAAI,mBAAmB,MAAA,CAAO,gBAAA;AAAA,IAC9BC,sCAAA,CAAqB;AAAA,GACvB;AACA,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,MAAM,IAAIE,oCAAA;AAAA,MACR,wDAAA;AAAA,MACA,EAAE,MAAM,sCAAA;AAAuC,KACjD;AAAA,EACF;AACA,EAAA,OAAO,KAAA,CAAM,gBAAA;AACf;AAWA,eAAsB,0BAAA,CACpB,GAAA,EACA,OAAA,EACA,QAAA,GAA2C,EAAC,EAC7B;AACf,EAAA,MAAM,gBAAA,GAAmB,kBAAkB,GAAG,CAAA;AAC9C,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,GAAA,EAAK,OAAO,CAAA;AAC1C,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AAEzB,EAAA,MAAM,iBAAiB,IAAI,GAAA;AAAA,IACzB,CAAC,GAAG,OAAA,EAAS,GAAG,QAAQ,CAAA,CAAE,GAAA;AAAA,MAAI,CAAC,SAAA,KAC7BC,+BAAA,CAAc,EAAE,YAAA,EAAc,UAAU,IAAA,EAAM,MAAA,EAAQ,SAAA,CAAU,EAAA,EAAI;AAAA;AACtE,GACF;AACA,EAAA,KAAA,MAAW,KAAA,IAAS,mBAAA,CAAoB,MAAM,CAAA,EAAG;AAC/C,IAAA,MAAM,YAAA,GAAe,MAAM,gBAAA,CAAiB;AAAA,MAC1C,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,UAAU,KAAA,CAAM,SAAA;AAAA,MAChB,gBAAgB,KAAA,CAAM,cAAA;AAAA,MACtB,MAAM,CAAC,GAAG,KAAA,CAAM,WAAA,CAAY,MAAM;AAAA,KACnC,CAAA;AACD,IAAA,KAAA,MAAW,YAAY,YAAA,EAAc;AACnC,MAAA,IACE,cAAA,CAAe,GAAA;AAAA,QACbA,+BAAA,CAAc;AAAA,UACZ,cAAc,QAAA,CAAS,aAAA;AAAA,UACvB,QAAQ,QAAA,CAAS;AAAA,SAClB;AAAA,OACH,EACA;AACA,QAAA;AAAA,MACF;AACA,MAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,WAAA,CAAY,GAAA,CAAI,SAAS,GAAG,CAAA;AAChD,MAAA,IAAI,UAAU,MAAA,EAAW;AACzB,MAAA,MAAM,IAAIX,iCAAA,CAAgB;AAAA,QACxB,gBAAgB,KAAA,CAAM,cAAA;AAAA;AAAA;AAAA;AAAA,QAItB,MAAM,QAAA,CAAS,aAAA;AAAA,QACf,YAAY,QAAA,CAAS,OAAA;AAAA,QACrB,KAAA,EAAO,MAAM,KAAA,CAAM,MAAA;AAAA,QACnB,MAAA,EAAQ,KAAA,CAAM,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW;AAAA,OACxC,CAAA;AAAA,IACH;AAAA,EACF;AACF;AASA,SAAS,uCAAA,GAA8D;AACrE,EAAA,OAAO,IAAIU,oCAAA;AAAA,IACT,4DAAA;AAAA,IACA,EAAE,MAAM,sCAAA;AAAuC,GACjD;AACF;AAEA,eAAe,yBAAA,CACb,GAAA,EACA,OAAA,EACA,QAAA,EACe;AACf,EAAAE,+BAAA;AAAA,IACEJ,sCAAA;AAAA,IACA,GAAA,CAAI,kBAAA;AAAA,IACJ,qBAAA;AAAA,IACA,MAAM;AACJ,MAAA,MAAM,uCAAA,EAAwC;AAAA,IAChD;AAAA,GACF;AAMA,EAAA,MAAM,eAAA,GAAkBD,sCAAA;AAAA,IACtB,GAAA,CAAI,OAAA;AAAA,IACJ,GAAA,CAAI,mBAAmB,MAAA,CAAO,0BAAA;AAAA,IAC9BC,sCAAA,CAAqB;AAAA,GACvB;AACA,EAAA,IAAI,oBAAoB,MAAA,EAAW;AACjC,IAAA,MAAM,uCAAA,EAAwC;AAAA,EAChD;AACA,EAAA,MAAM,EAAE,4BAA2B,GAAI,eAAA;AAQvC,EAAA,IACED,sCAAA;AAAA,IACE,GAAA,CAAI,OAAA;AAAA,IACJ,GAAA,CAAI,mBAAmB,MAAA,CAAO,iBAAA;AAAA,IAC9BC,sCAAA,CAAqB;AAAA,QACjB,MAAA,EACN;AACA,IAAA,MAAM,uCAAA,EAAwC;AAAA,EAChD;AACA,EAAA,MAAM,0BAAA,CAA2B,GAAA,EAAK,OAAA,EAAS,QAAQ,CAAA;AAEvD,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAyB;AAC/C,EAAA,KAAA,MAAW,aAAa,CAAC,GAAG,OAAA,EAAS,GAAG,QAAQ,CAAA,EAAG;AACjD,IAAA,MAAM,MAAM,SAAA,CAAU,GAAA,CAAI,UAAU,IAAI,CAAA,wBAAS,GAAA,EAAY;AAC7D,IAAA,GAAA,CAAI,GAAA,CAAI,UAAU,EAAE,CAAA;AACpB,IAAA,SAAA,CAAU,GAAA,CAAI,SAAA,CAAU,IAAA,EAAM,GAAG,CAAA;AAAA,EACnC;AACA,EAAA,KAAA,MAAW,CAAC,YAAA,EAAc,OAAO,CAAA,IAAK,SAAA,EAAW;AAC/C,IAAA,MAAM,0BAAA,CAA2B;AAAA,MAC/B,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,YAAA;AAAA,MACA,OAAA,EAAS,CAAC,GAAG,OAAO;AAAA,KACrB,CAAA;AAAA,EACH;AACF;AAyBA,eAAsB,uBAAA,CACpB,GAAA,EACA,OAAA,EACA,OAAA,EACA,UACA,KAAA,EACiB;AACjB,EAAA,MAAM,YAAA,GAAkC;AAAA,IACtC,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,UAAU,GAAA,CAAI,QAAA;AAAA,IACd,OAAA;AAAA,IACA,oBAAoB,GAAA,CAAI;AAAA,GAC1B;AACA,EAAA,MAAM,yBAAA,CAA0B,YAAA,EAAc,OAAA,EAAS,QAAQ,CAAA;AAC/D,EAAA,MAAM,MAAA,GAAS,MAAM,KAAA,EAAM;AAC3B,EAAA,MAAM,yBAAA;AAAA,IACJ,GAAA;AAAA,IACA,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,MAAY;AAAA,MACvB,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,IAAI,MAAA,CAAO,EAAA;AAAA,MACX,KAAA,EAAO,EAAE,GAAG,MAAA,CAAO,KAAA,EAAM;AAAA,MACzB,aAAa,MAAA,CAAO;AAAA,KACtB,CAAE,CAAA;AAAA,IACF,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,OAAO,MAAA;AACT;;;AC5XA,SAAS,mCACP,KAAA,EAC6B;AAC7B,EAAA,IAAI,qBAAA,CAAsB,KAAK,CAAA,EAAG;AAChC,IAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,SAAA,EAAW,KAAA,EAAM;AAAA,EAC5C;AACA,EAAA,OAAO,KAAA,KAAU,SAAY,EAAE,IAAA,EAAM,UAAS,GAAI,EAAE,MAAM,QAAA,EAAS;AACrE;AAUA,IAAM,oBAAA,uBAA2B,OAAA,EAG/B;AAUK,SAAS,mBACd,MAAA,EAC+B;AAC/B,EAAA,MAAM,MAAA,GAAS,oBAAA,CAAqB,GAAA,CAAI,MAAM,CAAA;AAC9C,EAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,EAAA,MAAM,MAAA,GAASK,yCAAuB,MAAM,CAAA;AAC5C,EAAA,oBAAA,CAAqB,GAAA,CAAI,QAAQ,MAAM,CAAA;AACvC,EAAA,OAAO,MAAA;AACT;AAYO,SAAS,+BAAA,CACd,QACA,KAAA,EACiC;AACjC,EAAA,OAAO,kBAAA,CAAmB,MAAM,CAAA,CAAE,OAAA;AAAA,IAChC,CAAC,KAAA,KAA2C;AAC1C,MAAA,MAAM,KAAA,GAAQC,iCAAA,CAAgB,KAAA,EAAO,KAAA,CAAM,SAAS,CAAA;AACpD,MAAA,MAAM,QAAA,GAAW,mCAAmC,KAAK,CAAA;AACzD,MAAA,OAAO,QAAA,CAAS,SAAS,QAAA,GACrB;AAAA,QACE;AAAA,UACE,IAAA,EAAM,WAAA;AAAA,UACN,WAAW,KAAA,CAAM,SAAA;AAAA,UACjB,WAAW,QAAA,CAAS,SAAA;AAAA,UACpB,YAAY,KAAA,CAAM,UAAA;AAAA,UAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,UACd,WAAW,KAAA,CAAM;AAAA;AACnB,UAEF,EAAC;AAAA,IACP;AAAA,GACF;AACF;AAOO,SAAS,yCAAA,CACd,MAAA,EACA,KAAA,EACA,OAAA,EACiC;AACjC,EAAA,OAAO,kBAAA,CAAmB,MAAM,CAAA,CAAE,OAAA;AAAA,IAChC,CAAC,KAAA,KAA2C;AAC1C,MAAA,MAAM,KAAA,GAAQA,iCAAA,CAAgB,KAAA,EAAO,KAAA,CAAM,SAAS,CAAA;AACpD,MAAA,MAAM,MAAA,GAAS;AAAA,QACb,IAAA,EAAM,WAAA;AAAA,QACN,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,WAAW,KAAA,CAAM;AAAA,OACnB;AACA,MAAA,MAAM,QAAA,GAAW,mCAAmC,KAAK,CAAA;AACzD,MAAA,IAAI,QAAA,CAAS,SAAS,QAAA,EAAU;AAC9B,QAAA,OAAO;AAAA,UACL;AAAA,YACE,GAAG,MAAA;AAAA,YACH,MAAA,EAAQ,QAAA;AAAA,YACR,WAAW,QAAA,CAAS;AAAA;AACtB,SACF;AAAA,MACF;AACA,MAAA,OAAO,QAAA,CAAS,IAAA,KAAS,QAAA,IAAY,OAAA,EAAS,gBAAgB,IAAA,GAC1D,CAAC,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAmB,IACzC,EAAC;AAAA,IACP;AAAA,GACF;AACF;AASA,eAAsB,cAAA,CACpB,GAAA,EACA,MAAA,EACA,KAAA,EACe;AACf,EAAA,MAAM,EAAE,SAAQ,GAAI,GAAA;AAGpB,EAAA,IAAI,CAAC,OAAA,CAAQ,eAAA,IAAmB,CAAC,QAAQ,eAAA,EAAiB;AACxD,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,eAAA,GAAkB,mBAAmB,MAAM,CAAA;AACjD,EAAA,IAAI,eAAA,CAAgB,WAAW,CAAA,EAAG;AAChC,IAAA;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,SAAS,eAAA,EAAiB;AACnC,IAAA,MAAM,KAAA,GAAQA,iCAAA,CAAgB,KAAA,EAAO,KAAA,CAAM,SAAS,CAAA;AAEpD,IAAA,MAAM,QAAA,GAAW,mCAAmC,KAAK,CAAA;AACzD,IAAA,IAAI,QAAA,CAAS,SAAS,QAAA,EAAU;AAE9B,MAAA,MAAM,QAAQ,eAAA,CAAgB;AAAA,QAC5B,SAAS,GAAA,CAAI,OAAA;AAAA,QACb,UAAU,GAAA,CAAI,QAAA;AAAA,QACd,QAAQ,GAAA,CAAI,MAAA;AAAA,QACZ,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,WAAW,QAAA,CAAS,SAAA;AAAA,QACpB,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,WAAW,KAAA,CAAM;AAAA,OAClB,CAAA;AAAA,IACH,CAAA,MAAA,IAAW,QAAA,CAAS,IAAA,KAAS,QAAA,EAAU;AAErC,MAAA,MAAM,QAAQ,eAAA,CAAgB;AAAA,QAC5B,SAAS,GAAA,CAAI,OAAA;AAAA,QACb,UAAU,GAAA,CAAI,QAAA;AAAA,QACd,QAAQ,GAAA,CAAI,MAAA;AAAA,QACZ,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,WAAW,KAAA,CAAM;AAAA,OAClB,CAAA;AAAA,IACH;AAAA,EAEF;AACF;AASA,eAAsB,0BAAA,CACpB,IAAA,EAKA,MAAA,EACA,KAAA,EAIe;AACf,EAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAU,OAAA,EAAQ,GAAI,IAAA;AACvC,EAAA,IAAI,CAAC,OAAA,CAAQ,eAAA,IAAmB,CAAC,QAAQ,eAAA,EAAiB;AACxD,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,eAAA,GAAkB,mBAAmB,MAAM,CAAA;AACjD,EAAA,IAAI,eAAA,CAAgB,WAAW,CAAA,EAAG;AAChC,IAAA;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,SAAS,eAAA,EAAiB;AACnC,IAAA,MAAM,OAA2D,EAAC;AAClE,IAAA,MAAM,cAAwB,EAAC;AAC/B,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,MAAM,KAAA,GAAQA,iCAAA,CAAgB,IAAA,CAAK,KAAA,EAAO,MAAM,SAAS,CAAA;AACzD,MAAA,MAAM,QAAA,GAAW,mCAAmC,KAAK,CAAA;AACzD,MAAA,IAAI,QAAA,CAAS,SAAS,QAAA,EAAU;AAC9B,QAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,IAAA,CAAK,QAAQ,SAAA,EAAW,QAAA,CAAS,WAAW,CAAA;AAAA,MAClE,CAAA,MAAA,IAAW,QAAA,CAAS,IAAA,KAAS,QAAA,EAAU;AACrC,QAAA,WAAA,CAAY,IAAA,CAAK,KAAK,MAAM,CAAA;AAAA,MAC9B;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACnB,MAAA,IAAI,OAAA,CAAQ,yBAAyB,MAAA,EAAW;AAC9C,QAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,UAAA,MAAM,QAAQ,eAAA,CAAgB;AAAA,YAC5B,OAAA;AAAA,YACA,QAAA;AAAA,YACA,QAAQ,GAAA,CAAI,MAAA;AAAA,YACZ,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,WAAW,GAAA,CAAI,SAAA;AAAA,YACf,YAAY,KAAA,CAAM,UAAA;AAAA,YAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,YACd,WAAW,KAAA,CAAM;AAAA,WAClB,CAAA;AAAA,QACH;AAAA,MACF,CAAA,MAAO;AACL,QAAA,MAAM,QAAQ,oBAAA,CAAqB;AAAA,UACjC,OAAA;AAAA,UACA,QAAA;AAAA,UACA,WAAW,KAAA,CAAM,SAAA;AAAA,UACjB,YAAY,KAAA,CAAM,UAAA;AAAA,UAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,UACd,WAAW,KAAA,CAAM,SAAA;AAAA,UACjB;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,IAAI,WAAA,CAAY,MAAA,GAAS,CAAA,IAAK,OAAA,CAAQ,yBAAyB,MAAA,EAAW;AACxE,MAAA,MAAM,QAAQ,oBAAA,CAAqB;AAAA,QACjC,OAAA;AAAA,QACA,QAAA;AAAA,QACA,OAAA,EAAS,WAAA;AAAA,QACT,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,WAAW,KAAA,CAAM;AAAA,OAClB,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,KAAA,MAAW,UAAU,WAAA,EAAa;AAChC,QAAA,MAAM,QAAQ,eAAA,CAAgB;AAAA,UAC5B,OAAA;AAAA,UACA,QAAA;AAAA,UACA,MAAA;AAAA,UACA,WAAW,KAAA,CAAM,SAAA;AAAA,UACjB,YAAY,KAAA,CAAM,UAAA;AAAA,UAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,UACd,WAAW,KAAA,CAAM;AAAA,SAClB,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAWA,eAAsB,oBAAA,CACpB,KACA,MAAA,EACe;AACf,EAAA,MAAM,EAAE,SAAQ,GAAI,GAAA;AAGpB,EAAA,IAAI,CAAC,QAAQ,eAAA,EAAiB;AAC5B,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,eAAA,GAAkB,mBAAmB,MAAM,CAAA;AACjD,EAAA,IAAI,eAAA,CAAgB,WAAW,CAAA,EAAG;AAChC,IAAA;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,SAAS,eAAA,EAAiB;AACnC,IAAA,MAAM,QAAQ,eAAA,CAAgB;AAAA,MAC5B,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,UAAU,GAAA,CAAI,QAAA;AAAA,MACd,QAAQ,GAAA,CAAI,MAAA;AAAA,MACZ,WAAW,KAAA,CAAM,SAAA;AAAA,MACjB,YAAY,KAAA,CAAM,UAAA;AAAA,MAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,WAAW,KAAA,CAAM;AAAA,KAClB,CAAA;AAAA,EACH;AACF;AASA,SAAS,sBAAsB,KAAA,EAA4C;AACzE,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,KAAM,OAAO,MAAM,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,CAAC,CAAC,CAAA;AACvE;;;ACnUA,IAAM,eAAA,GAAkB,IAAA;AAgBjB,SAAS,yBAAA,CACd,SACA,QAAA,EACO;AACP,EAAA,MAAM,IAAIC,mDAAA;AAAA,IACR,cAAc,QAAQ,CAAA,8BAAA,CAAA;AAAA,IACtB,UAAA;AAAA,IACA,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAS,QAAA,EAAU,QAAQ,sBAAA,EAAuB;AAAA,IACrE;AAAA,GAEF;AACF;AAYO,SAAS,oBAAA,CACd,MAAA,EACA,UAAA,EACA,OAAA,EACqB;AACrB,EAAA,IAAI,WAAW,MAAA,EAAW;AAC1B,EAAA,MAAM,IAAIL,oCAAA;AAAA,IACR,8DAA8D,UAAU,CAAA,QAAA,CAAA;AAAA,IACxE;AAAA,MACE,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,UAAA,EAAY,UAAA;AAAA,MACZ,aAAA,EAAe;AAAA;AACjB,GACF;AACF;AAOA,SAAS,wBACP,MAAA,EACQ;AACR,EAAA,OAAO,MAAA,CAAO,CAAC,CAAA,EAAG,QAAA,CAAS,QAAA,IAAYM,6CAAA;AACzC;AASO,SAAS,sBAAA,CACd,QACA,KAAA,EACmD;AACnD,EAAA,MAAM,gBAAA,GAAmBC,sCAAoB,MAAM,CAAA;AACnD,EAAA,IAAI,gBAAA,CAAiB,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAE1C,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,SAAS,gBAAA,EAAkB;AACpC,IAAA,MAAM,KAAA,GAAQH,iCAAA,CAAgB,KAAA,EAAO,KAAA,CAAM,SAAS,CAAA;AACpD,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,SAAS,CAAA,EAAG;AACjD,MAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,IAClB;AAAA,EACF;AACA,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAE/B,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,eAAe,CAAA;AAAA,IACnC,QAAA,EAAU,wBAAwB,gBAAgB;AAAA,GACpD;AACF;AAOO,SAAS,6BAAA,CACd,QACA,KAAA,EACiE;AACjE,EAAA,IAAIG,qCAAA,CAAoB,MAAM,CAAA,CAAE,MAAA,KAAW,GAAG,OAAO,MAAA;AACrD,EAAA,MAAM,QAAA,GAAW,sBAAA,CAAuB,MAAA,EAAQ,KAAK,CAAA;AACrD,EAAA,OAAO,QAAA,KAAa,MAAA,GAChB,EAAE,IAAA,EAAM,YAAY,MAAA,EAAQ,QAAA,EAAS,GACrC,EAAE,IAAA,EAAM,UAAA,EAAY,MAAA,EAAQ,QAAA,EAAU,GAAG,QAAA,EAAS;AACxD;AAGA,SAAS,uBAAA,CACP,MAAA,EACA,KAAA,EACA,QAAA,EAK8B;AAC9B,EAAA,IAAIA,qCAAA,CAAoB,MAAM,CAAA,CAAE,MAAA,KAAW,GAAG,OAAO,MAAA;AACrD,EAAA,MAAM,QAAA,GAAW,sBAAA,CAAuB,MAAA,EAAQ,KAAK,CAAA;AACrD,EAAA,OAAO,QAAA,KAAa,MAAA,GAChB,EAAE,GAAG,UAAU,MAAA,EAAQ,QAAA,EAAS,GAChC,EAAE,GAAG,QAAA,EAAU,MAAA,EAAQ,QAAA,EAAU,GAAG,QAAA,EAAS;AACnD;AASA,eAAsB,YAAA,CACpB,GAAA,EACA,MAAA,EACA,KAAA,EACe;AACf,EAAA,MAAM,EAAE,SAAQ,GAAI,GAAA;AAEpB,EAAA,IAAIA,qCAAA,CAAoB,MAAM,CAAA,CAAE,MAAA,KAAW,CAAA,EAAG;AAK9C,EAAA,IAAIC,wCAAA,CAAuB,OAAO,CAAA,KAAM,KAAA,EAAO;AAC7C,IAAA,yBAAA,CAA0B,OAAA,EAAS,IAAI,QAAQ,CAAA;AAAA,EACjD;AACA,EAAA,oBAAA,CAAqB,OAAA,CAAQ,cAAA,EAAgB,gBAAA,EAAkB,OAAO,CAAA;AACtE,EAAA,oBAAA,CAAqB,OAAA,CAAQ,cAAA,EAAgB,gBAAA,EAAkB,OAAO,CAAA;AAEtE,EAAA,MAAM,IAAA,GAAO,uBAAA,CAAwB,MAAA,EAAQ,KAAA,EAAO,GAAG,CAAA;AACvD,EAAA,IAAI,IAAA,EAAM,WAAW,QAAA,EAAU;AAC7B,IAAA,MAAM,QAAQ,cAAA,CAAe;AAAA,MAC3B,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,UAAU,GAAA,CAAI,QAAA;AAAA,MACd,QAAQ,GAAA,CAAI,MAAA;AAAA,MACZ,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,UAAU,IAAA,CAAK;AAAA,KAChB,CAAA;AACD,IAAA;AAAA,EACF;AACA,EAAA,IAAI,SAAS,MAAA,EAAW;AACxB,EAAA,MAAM,QAAQ,cAAA,CAAe;AAAA,IAC3B,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,UAAU,GAAA,CAAI,QAAA;AAAA,IACd,QAAQ,GAAA,CAAI;AAAA,GACb,CAAA;AACH;AASA,eAAsB,wBAAA,CACpB,IAAA,EAKA,MAAA,EACA,KAAA,EAIe;AACf,EAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAU,OAAA,EAAQ,GAAI,IAAA;AACvC,EAAA,IAAID,qCAAA,CAAoB,MAAM,CAAA,CAAE,MAAA,KAAW,CAAA,EAAG;AAK9C,EAAA,IAAIC,wCAAA,CAAuB,OAAO,CAAA,KAAM,KAAA,EAAO;AAC7C,IAAA,yBAAA,CAA0B,SAAS,QAAQ,CAAA;AAAA,EAC7C;AACA,EAAA,oBAAA,CAAqB,OAAA,CAAQ,cAAA,EAAgB,gBAAA,EAAkB,OAAO,CAAA;AACtE,EAAA,oBAAA,CAAqB,OAAA,CAAQ,cAAA,EAAgB,gBAAA,EAAkB,OAAO,CAAA;AAKtE,EAAA,MAAM,OAAgE,EAAC;AACvE,EAAA,MAAM,kBAA4B,EAAC;AACnC,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,QAAA,GAAW,sBAAA,CAAuB,MAAA,EAAQ,IAAA,CAAK,KAAK,CAAA;AAC1D,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,eAAA,CAAgB,IAAA,CAAK,KAAK,MAAM,CAAA;AAAA,IAClC,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,IAAA,CAAK;AAAA,QACR,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,SAAS,QAAA,CAAS,OAAA;AAAA,QAClB,UAAU,QAAA,CAAS;AAAA,OACpB,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACnB,IAAA,IAAI,OAAA,CAAQ,wBAAwB,MAAA,EAAW;AAC7C,MAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,QAAA,MAAM,QAAQ,cAAA,CAAe;AAAA,UAC3B,OAAA;AAAA,UACA,QAAA;AAAA,UACA,QAAQ,GAAA,CAAI,MAAA;AAAA,UACZ,SAAS,GAAA,CAAI,OAAA;AAAA,UACb,UAAU,GAAA,CAAI;AAAA,SACf,CAAA;AAAA,MACH;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAAM,QAAQ,mBAAA,CAAoB,EAAE,OAAA,EAAS,QAAA,EAAU,MAAM,CAAA;AAAA,IAC/D;AAAA,EACF;AAEA,EAAA,IAAI,eAAA,CAAgB,SAAS,CAAA,EAAG;AAC9B,IAAA,IAAI,OAAA,CAAQ,wBAAwB,MAAA,EAAW;AAC7C,MAAA,KAAA,MAAW,UAAU,eAAA,EAAiB;AACpC,QAAA,MAAM,QAAQ,cAAA,CAAe,EAAE,OAAA,EAAS,QAAA,EAAU,QAAQ,CAAA;AAAA,MAC5D;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAAM,QAAQ,mBAAA,CAAoB;AAAA,QAChC,OAAA;AAAA,QACA,QAAA;AAAA,QACA,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH;AAAA,EACF;AACF;AAMA,eAAsB,kBAAA,CACpB,KACA,MAAA,EACe;AACf,EAAA,MAAM,EAAE,SAAQ,GAAI,GAAA;AAEpB,EAAA,IAAID,qCAAA,CAAoB,MAAM,CAAA,CAAE,MAAA,KAAW,CAAA,EAAG;AAQ9C,EAAA,IAAIC,wCAAA,CAAuB,OAAO,CAAA,KAAM,KAAA,EAAO;AAE/C,EAAA,oBAAA,CAAqB,OAAA,CAAQ,cAAA,EAAgB,gBAAA,EAAkB,OAAO,CAAA;AAEtE,EAAA,MAAM,QAAQ,cAAA,CAAe;AAAA,IAC3B,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,UAAU,GAAA,CAAI,QAAA;AAAA,IACd,QAAQ,GAAA,CAAI;AAAA,GACb,CAAA;AACH;;;AC5NO,SAAS,sBAAA,CACd,OAAA,EACA,QAAA,EACA,IAAA,EACA,eACA,kBAAA,EACkB;AAClB,EAAA,OAAO,EAAE,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,eAAe,kBAAA,EAAmB;AACtE;AAmBA,SAAS,iBAAA,CAAkB,KAAuB,OAAA,EAAkB;AAClE,EAAA,OAAO,uBAAA;AAAA,IACL,GAAA,CAAI,OAAA;AAAA,IACJ,GAAA,CAAI,QAAA;AAAA,IACJ,OAAA;AAAA,IACA,GAAA,CAAI;AAAA,GACN;AACF;AAOA,SAAS,eAAA,CACP,GAAA,EACA,IAAA,EACA,EAAA,EACA,OAAA,EACA;AACA,EAAA,OAAO,EAAE,SAAS,GAAA,CAAI,OAAA,EAAS,UAAU,IAAA,EAAM,MAAA,EAAQ,IAAI,OAAA,EAAQ;AACrE;AAQA,eAAe,yBAAA,CACb,GAAA,EACA,IAAA,EAMA,OAAA,EACA,MAAA,EACe;AACf,EAAA,IAAI,MAAA,EAAQ,0BAA0B,KAAA,EAAO;AAC7C,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,UAAA;AAClC,EAAA,MAAM,cAAA,GAAiB,MAAM,OAAA,CAAQ,oBAAA,CAAqB;AAAA,IACxD,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,UAAU,IAAA,CAAK,IAAA;AAAA,IACf,QAAQ,IAAA,CAAK;AAAA,GACd,CAAA;AAED,EAAA,IAAI,cAAA,CAAe,WAAW,CAAA,EAAG;AAEjC,EAAA,QAAQ,QAAA;AAAU,IAChB,KAAK,UAAA,EAAY;AACf,MAAA,MAAM,IAAIC,uCAAA,CAAsB;AAAA,QAC9B,UAAU,IAAA,CAAK,IAAA;AAAA,QACf,QAAQ,IAAA,CAAK,EAAA;AAAA,QACb,WAAW,cAAA,CAAe,MAAA;AAAA,QAC1B,SAAA,EAAW,CAAC,GAAG,IAAI,GAAA,CAAI,cAAA,CAAe,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,IAAI,CAAC,CAAC;AAAA,OAChE,CAAA;AAAA,IACH;AAAA,IAEA,KAAK,SAAA;AAAA,IACL,KAAK,YAAA,EAAc;AAOjB,MAAA,MAAM,mBAAmB,cAAA,CAAe,GAAA,CAAI,CAAC,IAAA,KAAS,KAAK,EAAE,CAAA;AAC7D,MAAA,MAAM,cACJ,IAAA,CAAK,IAAA,KAAS,MAAA,GACZ,OAAA,CAAQ,uBACR,OAAA,CAAQ,gBAAA;AACZ,MAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,QAAA,KAAA,MAAW,QAAQ,cAAA,EAAgB;AACjC,UAAA,OAAO,IAAA,CAAK,SAAS,MAAA,GACnB,OAAA,CAAQ,eAAe,EAAE,OAAA,EAAS,GAAA,CAAI,OAAA,EAAS,EAAA,EAAI,IAAA,CAAK,IAAI,CAAA,GAC5D,OAAA,CAAQ,UAAA,CAAW,EAAE,OAAA,EAAS,IAAI,OAAA,EAAS,EAAA,EAAI,IAAA,CAAK,EAAA,EAAI,CAAA,CAAA;AAAA,QAC5D;AAAA,MACF,CAAA,MAAO;AACL,QAAA,MAAM,WAAA,CAAY;AAAA,UAChB,SAAS,GAAA,CAAI,OAAA;AAAA,UACb,GAAA,EAAK;AAAA,SACN,CAAA;AAAA,MACH;AAKA,MAAA,IAAI,IAAA,CAAK,SAAS,MAAA,EAAQ;AACxB,QAAA,MAAMC,iCAAA;AAAA,UACJ,OAAA;AAAA,UACA,IAAI,aAAA,EAAc;AAAA,UAClB,GAAA,CAAI,OAAA;AAAA,UACJ;AAAA,SACF;AAAA,MACF;AACA,MAAA;AAAA,IACF;AAAA;AAEJ;AAuBA,eAAsB,uBAAA,CACpB,GAAA,EACA,IAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,cAAc,eAAA,CAAgB,GAAA,EAAK,KAAK,IAAA,EAAM,IAAA,CAAK,IAAI,OAAO,CAAA;AACpE,EAAA,IAAI,IAAA,CAAK,qBAAqB,IAAA,EAAM;AACpC,EAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,IAChB,cAAA,CAAe,WAAA,EAAa,IAAA,CAAK,MAAA,EAAQ,KAAK,KAAK,CAAA;AAAA,IACnD,YAAA,CAAa,WAAA,EAAa,IAAA,CAAK,MAAA,EAAQ,KAAK,KAAK;AAAA,GAClD,CAAA;AACH;AAOA,eAAsB,4BAAA,CACpB,GAAA,EACA,KAAA,EACA,OAAA,EACe;AACf,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AAMxB,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAuB;AAC1C,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,IAAK,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,IAAA,EAAM,EAAC,EAAE;AACvE,IAAA,KAAA,CAAM,IAAA,CAAK,KAAK,EAAE,MAAA,EAAQ,KAAK,EAAA,EAAI,KAAA,EAAO,IAAA,CAAK,KAAA,EAAO,CAAA;AACtD,IAAA,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM,KAAK,CAAA;AAAA,EAC7B;AAEA,EAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,IACZ,CAAC,GAAG,MAAA,CAAO,OAAA,EAAS,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,IAAA,EAAM,KAAK,CAAA,KAAM;AAC/C,MAAA,MAAM,gBAAgB,EAAE,OAAA,EAAS,IAAI,OAAA,EAAS,QAAA,EAAU,MAAM,OAAA,EAAQ;AACtE,MAAA,OAAO;AAAA,QACL,0BAAA,CAA2B,aAAA,EAAe,KAAA,CAAM,MAAA,EAAQ,MAAM,IAAI,CAAA;AAAA,QAClE,wBAAA,CAAyB,aAAA,EAAe,KAAA,CAAM,MAAA,EAAQ,MAAM,IAAI;AAAA,OAClE;AAAA,IACF,CAAC;AAAA,GACH;AACF;AAEA,SAAS,cAAc,GAAA,EAAuC;AAC5D,EAAA,OAAOC,kCAAA,CAAiB,IAAI,KAAK,CAAA;AACnC;AAwBA,eAAe,wBAAA,CACb,GAAA,EACA,IAAA,EAKA,OAAA,EAC+B;AAC/B,EAAA,MAAM,EAAE,IAAA,EAAM,EAAA,EAAG,GAAI,IAAA,CAAK,QAAA;AAE1B,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,UAAA,KAAe,MAAA,EAAW;AAC1C,IAAA,OAAO,qBAAA;AAAA,MACL,iBAAA,CAAkB,KAAK,OAAO,CAAA;AAAA,MAC9B,IAAA;AAAA,MACA,EAAA;AAAA,MACA,IAAA,CAAK,cAAA;AAAA,MACL,IAAA,CAAK;AAAA,KACP;AAAA,EACF;AAEA,EAAA,OAAO,mBAAA;AAAA,IACL,iBAAA,CAAkB,KAAK,OAAO,CAAA;AAAA,IAC9B,IAAA;AAAA,IACA,EAAA;AAAA,IACA,aAAA,CAAc,KAAK,QAAQ,CAAA;AAAA,IAC3B,IAAA,CAAK,cAAA;AAAA,IACL,IAAA,CAAK;AAAA,GACP;AACF;AAsBA,eAAsB,eAAA,CACpB,GAAA,EACA,IAAA,EAWA,OAAA,EACkB;AAClB,EAAA,MAAM,EAAE,IAAA,EAAM,EAAA,EAAG,GAAI,IAAA,CAAK,QAAA;AAI1B,EAAA,MAAM,OAAO,MAAM,wBAAA;AAAA,IACjB,GAAA;AAAA,IACA;AAAA,MACE,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,gBAAgB,IAAA,CAAK,cAAA;AAAA,MACrB,mBAAmB,IAAA,CAAK;AAAA,KAC1B;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,YAAA,GASF;AAAA,IACF,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,IAAA;AAAA,IACA,EAAA;AAAA,IACA,OAAO,IAAA,CAAK,cAAA;AAAA,IACZ,gBAAA,EAAkB;AAAA,GACpB;AACA,EAAA,IAAI,IAAA,CAAK,SAAA,KAAc,MAAA,EAAW,YAAA,CAAa,YAAY,IAAA,CAAK,SAAA;AAIhE,EAAA,IAAIC,yCAAA,CAAwB,IAAI,CAAA,EAAG;AACjC,IAAA,YAAA,CAAa,oBAAoB,IAAA,CAAK,iBAAA;AAAA,EACxC;AACA,EAAA,IAAI,IAAA,CAAK,YAAA,EAAc,YAAA,CAAa,YAAA,GAAe,IAAA;AAEnD,EAAA,MAAM,MAAM,MAAM,uBAAA;AAAA,IAChB,iBAAA,CAAkB,KAAK,OAAO,CAAA;AAAA,IAC9B,IAAA;AAAA,IACA,EAAA;AAAA,IACA,IAAA;AAAA,IACA,MACE,QAAQ,UAAA,CAAW;AAAA,MACjB,GAAG,YAAA;AAAA,MACH,GAAI,IAAA,CAAK,YAAA,KAAiB,IAAA,GAAO,EAAE,cAAc,IAAA,EAAc,GAC7D,IAAA,CAAK,OAAA,KAAY,SAAY,EAAC,GAC9B,EAAE,OAAA,EAAS,KAAK,OAAA;AAAQ,KAC3B;AAAA,GACL;AAEA,EAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,IAChB,cAAA;AAAA,MACE,eAAA,CAAgB,GAAA,EAAK,IAAA,EAAM,EAAA,EAAI,OAAO,CAAA;AAAA,MACtC,IAAA,CAAK,MAAA;AAAA,MACL,IAAA,CAAK;AAAA,KACP;AAAA,IACA,YAAA;AAAA,MACE,eAAA,CAAgB,GAAA,EAAK,IAAA,EAAM,EAAA,EAAI,OAAO,CAAA;AAAA,MACtC,IAAA,CAAK,MAAA;AAAA,MACL,IAAA,CAAK;AAAA;AACP,GACD,CAAA;AAED,EAAA,OAAO,GAAA;AACT;AAQA,eAAsB,mBAAA,CACpB,GAAA,EACA,IAAA,EAMA,OAAA,EACA,MAAA,EACe;AACf,EAAA,MAAM,EAAE,IAAA,EAAM,EAAA,EAAG,GAAI,IAAA,CAAK,QAAA;AAC1B,EAAA,MAAM,yBAAA;AAAA,IACJ,GAAA;AAAA,IACA,EAAE,IAAA,EAAM,EAAA,EAAI,MAAM,MAAA,EAAQ,QAAA,EAAU,KAAK,QAAA,EAAS;AAAA,IAClD,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,QAAQ,UAAA,CAAW;AAAA,IACvB,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,IAAA;AAAA,IACA;AAAA,GACD,CAAA;AACD,EAAA,MAAM,uBAAA;AAAA,IACJ,iBAAA,CAAkB,KAAK,OAAO,CAAA;AAAA,IAC9B,IAAA;AAAA,IACA,EAAA;AAAA,IACA,aAAA,CAAc,KAAK,QAAQ,CAAA;AAAA,IAC3B,IAAA,CAAK;AAAA,GACP;AACA,EAAA,MAAM,oBAAA;AAAA,IACJ,eAAA,CAAgB,GAAA,EAAK,IAAA,EAAM,EAAA,EAAI,OAAO,CAAA;AAAA,IACtC,IAAA,CAAK;AAAA,GACP;AACA,EAAA,MAAM,kBAAA;AAAA,IACJ,eAAA,CAAgB,GAAA,EAAK,IAAA,EAAM,EAAA,EAAI,OAAO,CAAA;AAAA,IACtC,IAAA,CAAK;AAAA,GACP;AACF;AASA,eAAsB,mBAAA,CACpB,GAAA,EACA,IAAA,EAMA,OAAA,EACe;AACf,EAAA,MAAM,yBAAA;AAAA,IACJ,GAAA;AAAA,IACA,EAAE,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,EAAA,EAAI,IAAA,CAAK,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAU,IAAA,CAAK,QAAA,EAAS;AAAA,IACtE;AAAA,GACF;AACA,EAAA,MAAM,QAAQ,cAAA,CAAe;AAAA,IAC3B,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,IAAI,IAAA,CAAK;AAAA,GACV,CAAA;AACD,EAAA,MAAM,oBAAA;AAAA,IACJ,gBAAgB,GAAA,EAAK,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,IAAI,OAAO,CAAA;AAAA,IAChD,IAAA,CAAK;AAAA,GACP;AACF;AAYA,eAAsB,kBAAA,CACpB,GAAA,EACA,IAAA,EAKA,OAAA,EACkB;AAClB,EAAA,MAAM,EAAE,IAAA,EAAM,EAAA,EAAG,GAAI,IAAA,CAAK,QAAA;AAC1B,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,IAAA,CAAK,QAAQ,CAAA;AAMzC,EAAA,MAAM,OAAO,MAAM,qBAAA;AAAA,IACjB,iBAAA,CAAkB,KAAK,OAAO,CAAA;AAAA,IAC9B,IAAA;AAAA,IACA,EAAA;AAAA,IACA,KAAA;AAAA,IACA,IAAA,CAAK;AAAA,GACP;AACA,EAAA,MAAM,MAAM,MAAM,uBAAA;AAAA,IAChB,iBAAA,CAAkB,KAAK,OAAO,CAAA;AAAA,IAC9B,IAAA;AAAA,IACA,EAAA;AAAA,IACA,IAAA;AAAA,IACA,MACE,QAAQ,UAAA,CAAW;AAAA,MACjB,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,IAAA;AAAA,MACA,EAAA;AAAA,MACA,KAAA;AAAA,MACA,gBAAA,EAAkB,IAAA;AAAA,MAClB,YAAA,EAAc;AAAA,KACf;AAAA,GACL;AACA,EAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,IAChB,cAAA,CAAe,gBAAgB,GAAA,EAAK,IAAA,EAAM,IAAI,OAAO,CAAA,EAAG,IAAA,CAAK,MAAA,EAAQ,KAAK,CAAA;AAAA,IAC1E,YAAA,CAAa,gBAAgB,GAAA,EAAK,IAAA,EAAM,IAAI,OAAO,CAAA,EAAG,IAAA,CAAK,MAAA,EAAQ,KAAK;AAAA,GACzE,CAAA;AACD,EAAA,OAAO,GAAA;AACT;AAyDA,eAAsB,kBAAA,CACpB,GAAA,EACA,IAAA,EACA,OAAA,EAC8B;AAC9B,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,iBAAA,EAAkB,GAAI,IAAA;AAC5C,EAAA,MAAM,YAAA,GAAe;AAAA,IACnB,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,IAAA;AAAA,IACA,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,iBAAiB,IAAA,CAAK,eAAA;AAAA,IACtB,cAAc,IAAA,CAAK,YAAA;AAAA,IACnB,mBAAmB,IAAA,CAAK;AAAA,GAC1B;AACA,EAAA,IAAI,oBAAA;AACJ,EAAA,IAAI,IAAA,CAAK,cAAc,eAAA,EAAiB;AACtC,IAAA,MAAM,oBAAoB,OAAA,CAAQ,iBAAA;AAClC,IAAA,IAAI,sBAAsB,MAAA,EAAW;AACnC,MAAA,MAAM,IAAIZ,oCAAA;AAAA,QACR,+DAAA;AAAA,QACA,EAAE,IAAA,EAAM,6BAAA,EAA+B,IAAA;AAAK,OAC9C;AAAA,IACF;AACA,IAAA,oBAAA,GAAuB,MACrB,iBAAA,CAAkB;AAAA,MAChB,GAAG,YAAA;AAAA,MACH,SAAA,EAAW,eAAA;AAAA,MACX,UAAU,IAAA,CAAK;AAAA,KAChB,CAAA;AAAA,EACL,CAAA,MAAO;AACL,IAAA,MAAM,gBAAgB,OAAA,CAAQ,aAAA;AAC9B,IAAA,IAAI,kBAAkB,MAAA,EAAW;AAC/B,MAAA,MAAM,IAAIA,oCAAA;AAAA,QACR,iEAAA;AAAA,QACA,EAAE,IAAA,EAAM,wBAAA,EAA0B,IAAA;AAAK,OACzC;AAAA,IACF;AACA,IAAA,oBAAA,GAAuB,MACrB,aAAA,CAAc,EAAE,GAAG,YAAA,EAAc,SAAA,EAAW,eAAe,CAAA;AAAA,EAC/D;AACA,EAAA,IACE,iBAAA,CAAkB,SAAS,CAAA,IAC3Ba,uCAAA;AAAA,IACEf,sCAAA;AAAA,IACA,GAAA,CAAI,kBAAA;AAAA,IACJ;AAAA,GACF,CAAE,SAAS,CAAA,EACX;AACA,IAAA,MAAM,IAAIE,oCAAA;AAAA,MACR,6DAAA;AAAA,MACA,EAAE,IAAA,EAAM,mCAAA,EAAqC,IAAA;AAAK,KACpD;AAAA,EACF;AACA,EAAA,IAAIO,qCAAA,CAAoB,MAAM,CAAA,CAAE,MAAA,GAAS,CAAA,EAAG;AAO1C,IAAA,IAAIC,wCAAA,CAAuB,OAAO,CAAA,KAAM,KAAA,EAAO;AAC7C,MAAA,yBAAA,CAA0B,SAAS,IAAI,CAAA;AAAA,IACzC;AAIA,IAAA,oBAAA,CAAqB,OAAA,CAAQ,cAAA,EAAgB,gBAAA,EAAkB,OAAO,CAAA;AACtE,IAAA,oBAAA,CAAqB,OAAA,CAAQ,cAAA,EAAgB,gBAAA,EAAkB,OAAO,CAAA;AACtE,IAAA,oBAAA;AAAA,MACE,OAAA,CAAQ,mBAAA;AAAA,MACR,qBAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,oBAAA;AAAA,MACE,OAAA,CAAQ,mBAAA;AAAA,MACR,qBAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AACA,EAAA,IACE,mBAAmB,MAAM,CAAA,CAAE,MAAA,GAAS,CAAA,KACnC,QAAQ,eAAA,KAAoB,MAAA,IAC3B,OAAA,CAAQ,eAAA,KAAoB,UAC5B,OAAA,CAAQ,oBAAA,KAAyB,MAAA,IACjC,OAAA,CAAQ,yBAAyB,MAAA,CAAA,EACnC;AACA,IAAA,MAAM,IAAIR,oCAAA;AAAA,MACR,yDAAA;AAAA,MACA,EAAE,IAAA,EAAM,+BAAA,EAAiC,IAAA;AAAK,KAChD;AAAA,EACF;AACA,EAAA,MAAM,MAAA,GAAS,MAAM,oBAAA,EAAqB;AAC1C,EAAA,IAAI,OAAO,aAAA,KAAkB,CAAA,EAAG,OAAO,EAAE,eAAe,CAAA,EAAE;AAE1D,EAAA,MAAM,YAAA,GAAe,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AAC5C,IAAA,MAAM,KAAA,GAAQW,kCAAA,CAAiB,GAAA,CAAI,KAAK,CAAA;AACxC,IAAA,MAAM,cAAA,GAAiBG,mCAAA,CAAkB,MAAA,EAAQ,KAAA,EAAO;AAAA,MACtD,IAAA;AAAA,MACA,SAAA,EAAW,QAAA;AAAA,MACX,IAAI,GAAA,CAAI;AAAA,KACT,CAAA;AACD,IAAA,IAAI,CAACC,gCAAA,CAAe,cAAA,EAAgB,KAAK,CAAA,EAAG;AAC1C,MAAA,MAAM,IAAIC,iCAAA;AAAA,QACR,4CAA4C,IAAI,CAAA,IAAA,CAAA;AAAA,QAChD;AAAA,UACE,UAAA,EAAY,MAAA;AAAA,UACZ,IAAA;AAAA,UACA,SAAA,EAAW,QAAA;AAAA,UACX,IAAI,GAAA,CAAI,EAAA;AAAA,UACR,MAAA,EAAQ;AAAA,YACN;AAAA,cACE,IAAA,EAAM,OAAA;AAAA,cACN,OAAA,EAAS;AAAA;AACX;AACF;AACF,OACF;AAAA,IACF;AACA,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,IAAI,GAAA,CAAI,EAAA;AAAA,MACR,MAAA;AAAA,MACA,KAAA,EAAO,cAAA;AAAA,MACP;AAAA,KACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,UAAA,GAAa,YAAA,CAAa,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,IAC7C,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,IAAI,IAAA,CAAK,EAAA;AAAA,IACT,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,aAAa,IAAA,CAAK;AAAA,GACpB,CAAE,CAAA;AACF,EAAA,IAAI,iBAAA,CAAkB,SAAS,CAAA,EAAG;AAShC,IAAA,IACEnB,sCAAA;AAAA,MACE,OAAA;AAAA,MACA,GAAA,CAAI,mBAAmB,MAAA,CAAO,iBAAA;AAAA,MAC9BC,sCAAA,CAAqB;AAAA,UACjB,MAAA,EACN;AACA,MAAA,MAAM,IAAIE,oCAAA;AAAA,QACR,6DAAA;AAAA,QACA,EAAE,IAAA,EAAM,mCAAA,EAAqC,IAAA;AAAK,OACpD;AAAA,IACF;AAKA,IAAA,MAAM,0BAAA;AAAA,MACJ,uBAAA;AAAA,QACE,GAAA,CAAI,OAAA;AAAA,QACJ,GAAA,CAAI,QAAA;AAAA,QACJ,OAAA;AAAA,QACA,GAAA,CAAI;AAAA,OACN;AAAA,MACA,UAAA;AAAA,MACA;AAAC,KACH;AACA,IAAA,MAAM,yBAAA;AAAA,MACJ,iBAAA,CAAkB,KAAK,OAAO,CAAA;AAAA,MAC9B,IAAA;AAAA,MACA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ,IAAI,EAAE;AAAA,KACjC;AAAA,EACF;AAUA,EAAA,MAAM,yBAAA;AAAA,IACJ,GAAA;AAAA,IACA,UAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,4BAAA,CAA6B,GAAA,EAAK,YAAA,EAAc,OAAO,CAAA;AAC7D,EAAA,OAAO,EAAE,aAAA,EAAe,MAAA,CAAO,aAAA,EAAc;AAC/C","file":"chunk-BPYZUJX5.cjs","sourcesContent":["/**\n * What claims a node of a given kind owes, before its props are known.\n *\n * This is the DECLARATION-level half of the claim set, and it is deliberately\n * separate from the props-level half: the same list answers \"which claim rows\n * does this kind write?\" (the entries, once a row's props select the applying\n * constraints and supply their keys) and \"does a write of this kind need the\n * per-graph lock?\" (the projection in `../constraints.ts`). Two consumers, one\n * classification — a second spelling at either of them is what this module\n * exists to prevent.\n *\n * It imports registry, core types and the axis vocabulary only, so the\n * constraint probes can project it without importing the claim seam.\n */\nimport { type UniqueConstraint } from \"../../core/types\";\nimport { type KindRegistry } from \"../../registry/kind-registry\";\nimport {\n DISJOINT_CONSTRAINT_NAME,\n disjointnessClaimAxis,\n uniquenessClaimTarget,\n} from \"./axis\";\nimport { type ConstraintFenceReason } from \"./backing\";\n\n/**\n * WHEN a claim is issued relative to the row write it gates.\n *\n * `\"pre-insert\"` means the claim is the ONLY fence for a violation the row\n * write itself would not surface, so it must precede the row — and a failure\n * between the two leaves a live claim with no row, which is why it is also the\n * subject of the non-transactional refusal. `\"post-insert\"` means the claim\n * follows the row, which is the order those entries ship in today and the order\n * their own primary key already makes sufficient.\n */\nexport type ClaimPlacement = \"pre-insert\" | \"post-insert\";\n\n/**\n * WHICH declared refusal a foreign owner of this claim produces, and the\n * payload that refusal needs.\n *\n * Two constraint families share one claim relation, so the row alone cannot say\n * what refusing it means. Carrying the answer on the site — decided where the\n * site is decided — is what lets the claim seam re-raise the family's own error\n * without re-deriving which family it was from the axis string.\n */\nexport type ClaimRefusal =\n | Readonly<{ kind: \"uniqueness\"; constraint: UniqueConstraint }>\n | Readonly<{ kind: \"disjointness\"; ownKind: string; otherKind: string }>;\n\n/** One claim a node of this kind owes, before its props are known. */\nexport type NodeClaimSite = Readonly<{\n /** The value the claim row's `node_kind` carries — what the PK fences on. */\n axis: string;\n /** The claim row's `constraint_name`. */\n constraintName: string;\n /**\n * Whether this site is ALSO a reason to take the per-graph write lock — i.e.\n * whether its probe reads state the uniques primary key does not already\n * fence. True for a scope spanning more than the node's own kind; false for a\n * single-kind scope, whose own key IS the fence.\n */\n needsLockFence: boolean;\n /**\n * WHEN this site's claim must be issued relative to the row write it gates,\n * for the operation this list was built for. It is DATA, not a caller's\n * choice: the claim seam partitions on it, and the non-transactional refusal\n * asks whether a write owes a `pre-insert` entry.\n */\n placement: ClaimPlacement;\n /**\n * The class a REFUSAL names when this site's claim cannot be undone. A scope\n * spanning more than the node's own kind is `nodeUniquenessScope` — the class\n * the lock path already reports for it; a single-kind scope is\n * `nodeUniquenessClaim`, whose advice is about the reservation row rather\n * than about the scope it does not have.\n */\n refusalReason: ConstraintFenceReason;\n /** Which typed error a foreign owner of this claim produces. */\n refusal: ClaimRefusal;\n}>;\n\n/**\n * The disjointness sites a write BRINGING A NODE INTO EXISTENCE under this kind\n * owes: one per declared partner.\n *\n * `\"create\"` and `\"resurrect\"` only, matching the two places a node comes into\n * existence under a kind — never `\"update\"`, because an in-place update cannot\n * change a node's kind and so re-derives no cross-kind verdict and owes no\n * claim for one. A resurrect owes exactly what a create owes here: reviving a\n * tombstone re-introduces the same live id under the same kind that a fresh\n * insert would, and {@link file://./node-claims.ts deleteUniquenessEntries}\n * released this node's own disjointness reservations at soft-delete time (it\n * reads the `\"create\"` extent precisely because it is the wider of the two), so\n * a resurrect starts from the same \"holds nothing yet\" state a create does and\n * must re-claim from scratch rather than diff.\n *\n * Pairwise rather than per component, because the registry's disjoint pairs are\n * literal unordered pairs: a node disjoint from two partners owes two claims,\n * on two axes, and the two partners are not thereby disjoint from each other.\n *\n * Every one of them is `pre-insert` and `needsLockFence`: the nodes primary key\n * is `(graph_id, kind, id)`, so a disjoint namesake's row does not collide with\n * this node's own insert — the claim is the ONLY fence for the axis, and a\n * fence issued after the write it fences is not a fence. `needsLockFence` is\n * read only by the lock projection (`nodeWriteNeedsConstraintFence`, consulted\n * with `\"create\"` or `\"update\"` alone — never `\"resurrect\"`), so it stays inert\n * for a resurrect: the per-graph lock's trigger set is unchanged by this site\n * applying to a third operation, and the claim's own primary key — the same\n * `INSERT … ON CONFLICT … RETURNING` `insertUnique` already uses for an\n * own-kind uniqueness claim, which needs no lock either — is what fences a\n * resurrect racing a disjoint partner's create.\n */\nfunction disjointnessSites(\n registry: KindRegistry,\n kind: string,\n): readonly NodeClaimSite[] {\n return registry.getDisjointKinds(kind).map((otherKind) => ({\n axis: disjointnessClaimAxis(kind, otherKind, registry),\n constraintName: DISJOINT_CONSTRAINT_NAME,\n needsLockFence: true,\n placement: \"pre-insert\" as const,\n refusalReason: \"nodeDisjointness\" as const,\n refusal: { kind: \"disjointness\" as const, ownKind: kind, otherKind },\n }));\n}\n\n/**\n * The three shapes a node write can take, for claim purposes.\n *\n * `\"create\"` is a fresh id under a kind that has never held it live.\n * `\"update\"` is an in-place change to a row that stays live throughout — it\n * cannot change the node's kind, so it never owes a disjointness claim.\n * `\"resurrect\"` is a tombstoned row coming back to life under its own kind —\n * the SAME cross-kind event a create is, reached through the transition seam\n * instead of the insert seam, which is why its uniqueness claims are placed\n * like an update's (claim-first, {@link file://./node-claims.ts\n * withNodeClaimTransition} is the only correct sequence for a transition) while\n * its disjointness claims are owed like a create's.\n *\n * Two consumers read this vocabulary and each other's classification would be\n * the wrong one to reuse: {@link nodeClaimEntries} (what a ROW owes, given its\n * operation) reaches `\"resurrect\"`; `nodeWriteNeedsConstraintFence` (the lock\n * projection, `../constraints.ts`) and its callers reach only `\"create\"` and\n * `\"update\"`, by design — see {@link disjointnessSites}'s note on why that\n * keeps the per-graph lock's trigger set unchanged.\n */\nexport type NodeClaimOperation = \"create\" | \"update\" | \"resurrect\";\n\n/**\n * THE owner of \"what claims does a node of this kind owe, and when is each\n * due?\".\n *\n * Two families, one list. Disjointness sites come first, so a kind qualifying\n * on both counts reports the class the lock path already reports for it, and so\n * the two families cannot be maintained by two different sets of write paths: a\n * path that remembers uniqueness cannot forget disjointness when both arrive\n * through the same list.\n *\n * Every uniqueness field but `constraintName` is derived from ONE computation —\n * the {@link uniquenessClaimTarget} of this kind and scope — so the four readers\n * of this list (the entries, the claim seam's partition, the non-transactional\n * refusal, and the lock projection in `../constraints.ts`) read one\n * classification rather than four predicates that agree until one is edited.\n * The fact all of them turn on is the same one: does this claim's axis span\n * kinds beyond the writer's own? Disjointness always does; a uniqueness scope\n * does exactly when it covers more than the node's own kind.\n *\n * - `needsLockFence` reads it as \"the probe reads state the uniques primary key\n * does not fence\", which is what the per-graph lock is taken for;\n * - `placement` reads it as \"the claim is the only fence for this axis, so it\n * must precede the row it gates\". On the CREATE path an own-kind claim keeps\n * its shipped position after the row: the uniques primary key at that axis is\n * already the complete fence for it, so moving it would buy no fence and cost\n * a refusal on backends with no transactions. On the UPDATE and RESURRECT\n * paths every claim is pre-insert, because the transition seam claims before\n * its gated write for every scope — see `withNodeClaimTransition`, which\n * explains why that is the only correct sequence for a transition.\n *\n * A future claim family that breaks the coincidence between those two readings\n * must say WHICH it changes; that is why they are two named fields and not one.\n */\nexport function nodeClaimSites(\n registry: KindRegistry,\n kind: string,\n uniqueConstraints: readonly UniqueConstraint[],\n operation: NodeClaimOperation,\n): readonly NodeClaimSite[] {\n const uniqueness = uniqueConstraints.map((constraint) => {\n const target = uniquenessClaimTarget(kind, constraint.scope, registry);\n return {\n axis: target.axis,\n constraintName: constraint.name,\n needsLockFence: target.crossKind,\n placement:\n operation !== \"create\" || target.crossKind ?\n \"pre-insert\"\n : (\"post-insert\" as const),\n refusalReason:\n target.crossKind ?\n (\"nodeUniquenessScope\" as const)\n : (\"nodeUniquenessClaim\" as const),\n refusal: { kind: \"uniqueness\" as const, constraint },\n } satisfies NodeClaimSite;\n });\n\n return operation === \"update\" ? uniqueness : (\n [...disjointnessSites(registry, kind), ...uniqueness]\n );\n}\n","/**\n * Node claims — what a node row reserves, and how each reservation moves.\n *\n * A declared constraint is a CLAIM on an axis (see {@link file://./axis.ts}):\n * the write reserves the row `(graph_id, axis, constraint_name, key)` and is\n * refused when that reservation comes back owned by somebody else. This module\n * decides which claims a row owes, probes them, writes them, releases them, and\n * sequences each of those against the primary row write it gates.\n *\n * Two families reserve in that one relation — a uniqueness constraint at its\n * scope's axis, and a `disjointWith` pair at the pair's axis with the node's id\n * as the key — so every path that already maintained uniqueness reservations\n * maintains disjointness reservations too, by reading one list rather than by\n * being edited twice.\n */\nimport { bindExtraIfReachable } from \"../../backend/capabilities/bind\";\nimport { UNIQUE_SIDECAR_BATCH } from \"../../backend/capabilities/bundle-registry\";\nimport {\n type BundleVerdictOf,\n type ClaimsVerdictThunk,\n} from \"../../backend/capabilities/resolve\";\nimport {\n type GraphBackend,\n type InsertUniqueParams,\n type NodeInsertClaim,\n type TransactionBackend,\n type UniqueConstraintBackend,\n type UniqueRow,\n} from \"../../backend/types\";\nimport { checkWherePredicate, computeUniqueKey } from \"../../constraints\";\nimport { type UniqueConstraint } from \"../../core/types\";\nimport {\n type ConfigurationError,\n DisjointError,\n UniquenessError,\n} from \"../../errors\";\nimport { type KindRegistry } from \"../../registry/kind-registry\";\nimport { requireDefined } from \"../../utils/presence\";\nimport { encodeTupleKey } from \"../../utils/tuple-key\";\nimport { constraintFenceRefusal } from \"../operations/write-transaction\";\nimport { type GraphWriteLock } from \"../recorded-capture/clock\";\nimport {\n type ClaimOwner,\n type ClaimTarget,\n compareClaimTargets,\n isSameClaimOwner,\n uniquenessProbeKinds,\n} from \"./axis\";\nimport { type ConstraintFenceReason } from \"./backing\";\nimport {\n type ClaimPlacement,\n type ClaimRefusal,\n type NodeClaimOperation,\n nodeClaimSites,\n} from \"./sites\";\n\n/**\n * Context for node claim operations.\n */\nexport type UniquenessContext = Readonly<{\n graphId: string;\n registry: KindRegistry;\n backend: GraphBackend | TransactionBackend;\n /** The threaded `uniqueSidecarBatch` verdict — never re-resolved here. */\n uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>;\n}>;\n\n/**\n * Context for the claim PROBE, whose single backend member is the read.\n *\n * Stated separately because the probe runs on handles that cannot write: a\n * write frame's row work holds the read-only `WriteTarget`, and pre-checking a\n * key there is the whole point of the probe. Every {@link UniquenessContext}\n * satisfies this one, so a writer passes its own context unchanged.\n */\nexport type UniquenessProbeContext = Readonly<{\n graphId: string;\n registry: KindRegistry;\n backend: Pick<UniqueConstraintBackend, \"checkUnique\">;\n}>;\n\n/**\n * Builds a claim context — the one constructor every call site shares.\n *\n * Generic in the handle so it yields exactly what it was given: a full backend\n * produces a {@link UniquenessContext} that can also write the claim rows, and\n * a read-only projection produces a {@link UniquenessProbeContext}, which is\n * all the probe needs and all row work can offer.\n */\nexport function createUniquenessContext<\n T extends Pick<UniqueConstraintBackend, \"checkUnique\">,\n>(\n graphId: string,\n registry: KindRegistry,\n backend: T,\n uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>,\n): Readonly<{\n graphId: string;\n registry: KindRegistry;\n backend: T;\n uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>;\n}> {\n return { graphId, registry, backend, uniqueSidecarBatch };\n}\n\n/** One claim a node row owes, decided but not written. */\nexport type NodeClaimEntry = Readonly<{\n /** `uniques.node_kind` — the axis the primary key fences on. */\n axis: string;\n /** `uniques.constraint_name`. */\n constraintName: string;\n /** `uniques.key`. */\n key: string;\n /**\n * WHEN this claim is issued relative to the row write it gates — carried\n * through from the entry's {@link NodeClaimSite}, which is the one owner of\n * the decision. The claim seam issues the two groups on either side of its\n * gated write, and {@link claimFenceRefusal} is keyed on the pre-insert group\n * alone.\n */\n placement: ClaimPlacement;\n /**\n * The class a refusal names when this claim cannot be rolled back — carried\n * through from the site, so no consumer re-derives it.\n */\n refusalReason: ConstraintFenceReason;\n /** Which typed error a foreign owner produces — carried through from the site. */\n refusal: ClaimRefusal;\n}>;\n\n/**\n * The key one site reserves for THIS row, or `undefined` when the site does not\n * apply to it.\n *\n * A uniqueness site applies when its `where` predicate holds, and its key is\n * the constraint's own composite key. A disjointness site always applies, and\n * its key is the node's ID — which is the axis `disjointWith` declares: \"no two\n * live nodes of these two kinds share an id\" is a reservation on the id, taken\n * at the pair.\n */\nfunction claimKeyFor(\n refusal: ClaimRefusal,\n id: string,\n props: Record<string, unknown>,\n): string | undefined {\n if (refusal.kind === \"disjointness\") return id;\n return checkWherePredicate(refusal.constraint, props) ?\n computeUniqueKey(\n props,\n refusal.constraint.fields,\n refusal.constraint.collation,\n )\n : undefined;\n}\n\n/**\n * THE single owner of \"what claims does THIS ROW owe, and when is each due?\":\n * the kind's claim sites ({@link nodeClaimSites}, the declaration-level extent\n * for this operation) filtered to the ones that apply to this row and completed\n * with each one's key. `placement`, `refusalReason` and `refusal` are carried\n * through unchanged; this function decides none of them.\n *\n * Every path that maintains a node's reservations — create, update diff,\n * resurrect, delete, batch, import — reads its work from this one list, so no\n * path can compute a key one way and an axis another, and no path that\n * remembers one family can forget the other.\n *\n * `operation` is threaded rather than assumed because the sites function needs\n * it twice: to place each claim (a transition claims before the row it gates for\n * every scope, while a create only does so for an axis spanning kinds beyond its\n * own) and to decide the disjointness arm, which only a write bringing a node\n * into existence under a kind owes — `\"create\"` and `\"resurrect\"` alike, never\n * `\"update\"`.\n */\nexport function nodeClaimEntries(\n registry: KindRegistry,\n kind: string,\n id: string,\n props: Record<string, unknown>,\n constraints: readonly UniqueConstraint[],\n operation: NodeClaimOperation,\n): readonly NodeClaimEntry[] {\n return nodeClaimSites(registry, kind, constraints, operation).flatMap(\n (site) => {\n const key = claimKeyFor(site.refusal, id, props);\n return key === undefined ?\n []\n : [\n {\n axis: site.axis,\n constraintName: site.constraintName,\n key,\n placement: site.placement,\n refusalReason: site.refusalReason,\n refusal: site.refusal,\n },\n ];\n },\n );\n}\n\n/** An entry whose family is disjointness — the one family that needs mapping. */\ntype DisjointnessClaimEntry = NodeClaimEntry &\n Readonly<{ refusal: Extract<ClaimRefusal, { kind: \"disjointness\" }> }>;\n\n/**\n * THE one place a backend claim refusal becomes the refusal its FAMILY\n * declares.\n *\n * Both families reserve in the `uniques` relation, and `insertUnique` /\n * `insertUniqueBatch` report every foreign owner the same way — as a\n * `UniquenessError` naming the constraint, the holder's concrete kind and the\n * two ids. That contract is deliberately unchanged (a third-party backend\n * implementing it keeps working), so the translation happens here, once, where\n * the entries that produced the claim are still in hand.\n *\n * The reserved `constraintName` alone locates the FAMILY (any entry it matches\n * is a disjointness entry, never a declared constraint's — `assertClaimAxisSafe`\n * makes the name unspellable by one), but not the PAIR: every `disjointWith`\n * pair shares that one literal, so a batch carrying disjointness entries for\n * two different pairs that happen to claim the same id (`Person \"X\"` disjoint\n * with `Company`, `Vehicle \"X\"` disjoint with `Boat`, same batch) would match\n * either indiscriminately on `(constraintName, key)` alone. The entry is\n * additionally required to have written the SAME claim axis the backend\n * reports — the row's actual primary key, and therefore unambiguous — so the\n * one located is provably the one that lost. `error.details.axis` is optional\n * (a third-party backend need not carry it to keep working); when a backend\n * omits it the match falls back to `(constraintName, key)` alone, which is\n * HEAD's behavior and no worse than today's. The payload is built from what\n * the BACKEND reported — the holder's own concrete kind — so the fence's error\n * is identical to the probe's, which is what makes a caller unable to tell\n * which layer refused.\n */\nfunction mapClaimRefusal(\n error: UniquenessError,\n entries: readonly NodeClaimEntry[],\n verdicts: readonly NodeCreateClaimVerdict[] = [],\n): never {\n const verdict = verdicts.find(\n (candidate) =>\n candidate.claim.constraintName === error.details.constraintName &&\n (candidate.refusal.kind === \"uniqueness\" ||\n candidate.claim.key === error.details.newId) &&\n (error.details.axis === undefined ||\n candidate.claim.axis === error.details.axis ||\n (candidate.claim.verdict.kind === \"uniqueness\" &&\n candidate.claim.verdict.probeAxes.includes(error.details.axis))),\n );\n const uniquenessVerdict =\n verdict !== undefined && isNodeCreateUniquenessVerdict(verdict) ?\n verdict\n : undefined;\n if (uniquenessVerdict !== undefined && error.details.fields.length === 0) {\n throw new UniquenessError(\n {\n ...error.details,\n fields: uniquenessVerdict.refusal.constraint.fields,\n },\n { cause: error },\n );\n }\n const owed = entries.find(\n (entry): entry is DisjointnessClaimEntry =>\n entry.refusal.kind === \"disjointness\" &&\n entry.constraintName === error.details.constraintName &&\n entry.key === error.details.newId &&\n (error.details.axis === undefined || entry.axis === error.details.axis),\n );\n if (owed === undefined) throw error;\n throw new DisjointError(\n {\n nodeId: error.details.newId,\n attemptedKind: owed.refusal.ownKind,\n conflictingKind: error.details.kind,\n },\n { cause: error },\n );\n}\n\n/** Re-raises a planned claim failure through the claim family's typed error. */\nexport function refuseNodeCreateClaimError(\n error: unknown,\n plan: NodeCreateClaimPlan,\n): never {\n if (error instanceof UniquenessError) {\n mapClaimRefusal(error, plan.entries, plan.verdicts);\n }\n throw error;\n}\n\n/**\n * Runs a claim statement, re-raising a foreign owner as the declared refusal of\n * whichever family owed the claim.\n *\n * One wrapper around every claim write, rather than a translation at each of\n * them: a claim statement that skipped it would report a `disjointWith`\n * violation as a uniqueness violation on a constraint name no caller ever\n * declared. Both the CREATE seam's `withNodeCreateClaimsIssuedBy` and the\n * transition seam's {@link claimUniqueKeysThen} reuse it — a resurrect's plan\n * can carry a disjointness entry exactly as a create's claim list does (see\n * {@link planNodeClaimReinsert}), so the transition seam needs the same\n * translation the create seam always did. For a plan whose claims are all\n * uniqueness (an in-place update's diff), `mapClaimRefusal` finds no\n * disjointness entry to remap and rethrows the original `UniquenessError`\n * unchanged, so this is a no-op there.\n */\nasync function issuingClaims(\n entries: readonly NodeClaimEntry[],\n issue: () => Promise<void>,\n): Promise<void> {\n try {\n await issue();\n } catch (error) {\n if (error instanceof UniquenessError) mapClaimRefusal(error, entries);\n throw error;\n }\n}\n\n/**\n * THE refusal for \"this write owes a claim it must issue BEFORE the row that\n * claim gates, and this backend cannot roll that pair back together\".\n *\n * A claim row that outlives the write it was taken for is invisible to every\n * read path and blocks its key forever, with no repair path: `deleteUnique` is\n * reached only by a node whose row exists. So a write that would open that\n * window on a backend with no transactions is refused, exactly as a write whose\n * fence is the per-graph lock has been since the lock became the fence. A\n * claim that follows its row opens no such window — a leaked ENTITY row is\n * visible, deletable, and is what that backend already does today — which is\n * why the subject is the pre-insert group and not the claim set.\n *\n * Takes the ENTRIES this write is about to issue rather than the kind's sites:\n * a row whose `where` predicates all fail writes no claim and must not be\n * refused. For a batch, any member's non-empty pre-insert group makes the batch\n * constrained — the same \"any member\" shape the batch lock probe uses.\n *\n * Delegates the error itself to {@link constraintFenceRefusal}, so there is one\n * refusal body, one code and one advice map.\n */\nfunction claimFenceRefusal(\n ctx: Readonly<{ graphId: string }>,\n backend: GraphBackend | TransactionBackend,\n entries: readonly NodeClaimEntry[],\n): ConfigurationError | undefined {\n const gating = entries.find((entry) => entry.placement === \"pre-insert\");\n if (gating === undefined) return undefined;\n return constraintFenceRefusal(ctx, backend, gating.refusalReason);\n}\n\n/** An entry whose family is uniqueness — the only family a claim probe reads. */\nexport type UniquenessClaimEntry = NodeClaimEntry &\n Readonly<{ refusal: Extract<ClaimRefusal, { kind: \"uniqueness\" }> }>;\n\n/**\n * THE narrowing to the uniqueness family, for every path that probes claim rows.\n *\n * Disjointness entries have their own probe (`checkDisjointnessConstraint`,\n * which reads the NODE rows the constraint is declared over) and deliberately\n * do not get a second one here: a claim-row read would be a second spelling of\n * that verdict, and the two would drift.\n *\n * Exported because it is also what \"an ingestion branch defers node UNIQUENESS\n * and nothing else\" means, operationally: the clone's registrations produce\n * claim entries and this predicate is false for every one of them, while the\n * disjointness entries the same list carries are unaffected (see\n * {@link file://../../graph-merge/working-copy.ts graphWithoutNodeUniqueness}).\n */\nexport function isUniquenessClaimEntry(\n entry: NodeClaimEntry,\n): entry is UniquenessClaimEntry {\n return entry.refusal.kind === \"uniqueness\";\n}\n\n/** One set-oriented uniqueness read shared by every batch probe consumer. */\nexport type NodeUniquenessProbeGroup = Readonly<{\n nodeKind: string;\n constraintName: string;\n keys: readonly string[];\n}>;\n\n/**\n * THE owner of grouping node uniqueness entries into backend batch reads.\n *\n * Preparation-cache priming and post-rollback diagnosis consume the same\n * groups, including every canonical and legacy axis covered by a scoped claim.\n * Keeping the grouping here prevents one path from silently probing a narrower\n * hierarchy than the other.\n */\nexport function groupNodeUniquenessProbes(\n registry: KindRegistry,\n items: readonly Readonly<{\n kind: string;\n entries: readonly NodeClaimEntry[];\n }>[],\n): readonly NodeUniquenessProbeGroup[] {\n type MutableProbeGroup = Readonly<{\n nodeKind: string;\n constraintName: string;\n keys: Set<string>;\n }>;\n const groups = new Map<string, MutableProbeGroup>();\n for (const item of items) {\n for (const entry of item.entries) {\n if (!isUniquenessClaimEntry(entry)) continue;\n for (const nodeKind of uniquenessProbeKinds(\n item.kind,\n entry.refusal.constraint.scope,\n registry,\n )) {\n const identity = encodeTupleKey([nodeKind, entry.constraintName]);\n const group = groups.get(identity) ?? {\n nodeKind,\n constraintName: entry.constraintName,\n keys: new Set<string>(),\n };\n group.keys.add(entry.key);\n groups.set(identity, group);\n }\n }\n }\n return [...groups.values()].map((group) => ({\n nodeKind: group.nodeKind,\n constraintName: group.constraintName,\n keys: [...group.keys],\n }));\n}\n\n/**\n * Probes ONE entry's key across every kind its scope covers, the axis first.\n *\n * THE SINGLE OWNER of \"is this key available to this node?\" — the conflict\n * verdict and the ownership reading are one read, so no caller can consult one\n * without the other. {@link checkUniquenessConstraints} is this probe run for\n * its refusal alone; the plan builders below additionally keep what it read.\n *\n * Ownership is the pair `(concrete_kind, node_id)`, never the id alone: ids are\n * unique only per kind, so a namesake under another kind holds a DIFFERENT\n * node's reservation and must be refused — which is exactly what a scope\n * spanning kinds exists to catch. The refusal reports the holder's concrete\n * kind rather than the axis it was found at, because the axis need not be that\n * node's kind and, after this move, usually is not.\n *\n * @returns whether THIS node already holds the key live AT THE AXIS it is about\n * to claim, in which case a claim would be a no-op and a compensating release\n * would strip a reservation the node is entitled to. A row this node owns at\n * a LEGACY axis deliberately does not suppress the claim: the axis row is a\n * genuinely new reservation whose compensation must run.\n * @throws UniquenessError when a DIFFERENT node holds the key under any kind in\n * scope.\n */\nexport async function probeUniqueKey(\n ctx: UniquenessProbeContext,\n kind: string,\n id: string,\n entry: UniquenessClaimEntry,\n lookup: (\n nodeKind: string,\n entry: UniquenessClaimEntry,\n ) => UniqueRow | undefined | Promise<UniqueRow | undefined> = async (\n nodeKind,\n claimEntry,\n ) =>\n ctx.backend.checkUnique({\n graphId: ctx.graphId,\n nodeKind,\n constraintName: claimEntry.constraintName,\n key: claimEntry.key,\n }),\n): Promise<boolean> {\n // `let` earns its place: the loop must visit EVERY kind in scope to reach its\n // refusal, so the ownership reading cannot be an early return.\n let heldByThisNode = false;\n for (const kindToCheck of uniquenessProbeKinds(\n kind,\n entry.refusal.constraint.scope,\n ctx.registry,\n )) {\n const existing = await lookup(kindToCheck, entry);\n\n if (existing === undefined) continue;\n const refusal = uniquenessClaimRefusal(kind, id, entry, existing);\n if (refusal !== undefined) throw refusal;\n if (kindToCheck === entry.axis) heldByThisNode = true;\n }\n return heldByThisNode;\n}\n\n/**\n * THE owner of the conflict verdict for one uniqueness probe result.\n *\n * The scalar probe and post-rollback batch diagnosis both call this function,\n * so owner-pair equality and the public error payload cannot drift between the\n * portable preflight and the native program's exceptional diagnostic path.\n */\nfunction uniquenessClaimRefusal(\n kind: string,\n id: string,\n entry: UniquenessClaimEntry,\n existing: UniqueRow,\n): UniquenessError | undefined {\n const proposedOwner: ClaimOwner = { concreteKind: kind, nodeId: id };\n if (\n isSameClaimOwner(\n { concreteKind: existing.concrete_kind, nodeId: existing.node_id },\n proposedOwner,\n )\n ) {\n return;\n }\n return new UniquenessError({\n constraintName: entry.constraintName,\n kind: existing.concrete_kind,\n existingId: existing.node_id,\n newId: id,\n fields: entry.refusal.constraint.fields,\n });\n}\n\n/**\n * Checks uniqueness constraints for a new or existing node.\n *\n * @throws ValidationError if any constraint is violated\n */\nexport async function checkUniquenessConstraints(\n ctx: UniquenessProbeContext,\n kind: string,\n id: string,\n props: Record<string, unknown>,\n constraints: readonly UniqueConstraint[],\n): Promise<void> {\n // The create extent, which is the wider of the two: a probe wants every claim\n // this row could owe, and placement — the only thing the operation decides\n // for a uniqueness site — says nothing about what is read. The disjointness\n // entries the create extent also carries belong to the other probe, which\n // reads node rows rather than claim rows.\n for (const entry of nodeClaimEntries(\n ctx.registry,\n kind,\n id,\n props,\n constraints,\n \"create\",\n )) {\n if (isUniquenessClaimEntry(entry))\n await probeUniqueKey(ctx, kind, id, entry);\n }\n}\n\n/**\n * What the create claim seam needs from its caller.\n *\n * `lock` is compile-time evidence that the per-graph write-lock discipline was\n * satisfied BEFORE any row work (see {@link GraphWriteLock}); the seam performs\n * no locking of its own, so requiring the token here makes \"claim before lock\"\n * a type error at the call site instead of a lock-order inversion in review.\n *\n * `claimsVerdict` is the `claims` bundle's memoized, at-most-once verdict\n * thunk (ruling B7 refinement 2). This module's own uniqueness/disjointness\n * claims never read it — they are a different fence family, backed by the\n * `uniques` relation — but `node-write-pipeline.ts`'s hard-delete cascade\n * shares this same context and calls `purgeEdgeClaims` (the `claims` bundle's\n * edge-cardinality housekeeping) off it, so the field lives here rather than\n * on a second, parallel context only that one caller would build.\n */\nexport type NodeClaimContext = Readonly<{\n graphId: string;\n registry: KindRegistry;\n lock: GraphWriteLock;\n claimsVerdict: ClaimsVerdictThunk;\n /** Threaded `uniqueSidecarBatch` verdict — never re-resolved here. */\n uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>;\n}>;\n\n/** One row whose claims a create-shaped write is about to issue. */\nexport type NodeClaimItem = Readonly<{\n kind: string;\n id: string;\n props: Record<string, unknown>;\n constraints: readonly UniqueConstraint[];\n}>;\n\n/**\n * The ownership verdict metadata a planned claim would have produced if the\n * store had read the claim relation first.\n *\n * The authoritative insert uses the claim row's primary key instead of these\n * probe coordinates, but carrying the coordinates with the plan keeps the\n * typed refusal complete: uniqueness errors regain their declared fields, and\n * disjoint errors retain the exact partner kind that made the claim apply.\n */\ntype NodeCreateClaimVerdict =\n | Readonly<{\n claim: NodeInsertClaim;\n probeKinds: readonly string[];\n disjointOtherKind: undefined;\n refusal: Extract<ClaimRefusal, { kind: \"uniqueness\" }>;\n }>\n | Readonly<{\n claim: NodeInsertClaim;\n probeKinds: readonly string[];\n disjointOtherKind: string;\n refusal: Extract<ClaimRefusal, { kind: \"disjointness\" }>;\n }>;\n\nfunction isNodeCreateUniquenessVerdict(\n verdict: NodeCreateClaimVerdict,\n): verdict is Extract<\n NodeCreateClaimVerdict,\n { refusal: { kind: \"uniqueness\" } }\n> {\n return verdict.refusal.kind === \"uniqueness\";\n}\n\n/** One row's claim, with the owner it will be written under. */\ntype PlacedClaim = Readonly<{\n item: NodeClaimItem;\n entry: NodeClaimEntry;\n target: ClaimTarget;\n}>;\n\n/** The complete, canonically ordered claim portion of one node insert plan. */\nexport type NodeCreateClaimPlan = Readonly<{\n entries: readonly NodeClaimEntry[];\n claims: readonly NodeInsertClaim[];\n verdicts: readonly NodeCreateClaimVerdict[];\n}>;\n\n/**\n * How one placement group.s statements are issued.\n *\n * `onIssued` reports which claims actually landed, and it is optional because\n * only the pre-insert group has a use for the answer: that group is compensated\n * when its gated write fails, while a post-insert claim belongs to a row that is\n * already written and has nothing to undo.\n */\ntype ClaimIssuer = (\n ctx: UniquenessContext,\n claims: readonly PlacedClaim[],\n onIssued?: (issued: readonly PlacedClaim[]) => void,\n) => Promise<void>;\n\nfunction claimTarget(graphId: string, entry: NodeClaimEntry): ClaimTarget {\n return {\n relation: \"uniques\",\n graphId,\n axis: entry.axis,\n constraintName: entry.constraintName,\n key: entry.key,\n };\n}\n\nfunction claimInsertParams(\n graphId: string,\n claim: PlacedClaim,\n): InsertUniqueParams {\n return {\n graphId,\n nodeKind: claim.entry.axis,\n constraintName: claim.entry.constraintName,\n key: claim.entry.key,\n nodeId: claim.item.id,\n concreteKind: claim.item.kind,\n };\n}\n\nfunction placedNodeCreateClaims(\n ctx: Pick<NodeClaimContext, \"graphId\" | \"registry\">,\n items: readonly NodeClaimItem[],\n): readonly PlacedClaim[] {\n return items.flatMap((item) =>\n nodeClaimEntries(\n ctx.registry,\n item.kind,\n item.id,\n item.props,\n item.constraints,\n \"create\",\n ).map((entry) => ({\n item,\n entry,\n target: claimTarget(ctx.graphId, entry),\n })),\n );\n}\n\n/**\n * Resolves one create's claims once for either the atomic plan or fallback\n * seam. The returned list preserves the claim-site placement decision and the\n * same canonical target order standalone claim statements use.\n */\nexport function planNodeCreateClaims(\n ctx: Pick<NodeClaimContext, \"graphId\" | \"registry\">,\n item: NodeClaimItem,\n): NodeCreateClaimPlan {\n const placed = placedNodeCreateClaims(ctx, [item]).toSorted((left, right) => {\n if (left.entry.placement !== right.entry.placement) {\n return left.entry.placement === \"pre-insert\" ? -1 : 1;\n }\n return compareClaimTargets(left.target, right.target);\n });\n const verdicts = placed.map((claim) => {\n const baseClaim = {\n axis: claim.entry.axis,\n constraintName: claim.entry.constraintName,\n key: claim.entry.key,\n placement: claim.entry.placement,\n };\n if (claim.entry.refusal.kind === \"uniqueness\") {\n const probeKinds = uniquenessProbeKinds(\n claim.item.kind,\n claim.entry.refusal.constraint.scope,\n ctx.registry,\n );\n return {\n claim: {\n ...baseClaim,\n verdict: {\n kind: \"uniqueness\" as const,\n probeAxes: probeKinds,\n fields: claim.entry.refusal.constraint.fields,\n },\n } satisfies NodeInsertClaim,\n probeKinds,\n disjointOtherKind: undefined,\n refusal: claim.entry.refusal,\n } satisfies NodeCreateClaimVerdict;\n }\n return {\n claim: {\n ...baseClaim,\n verdict: {\n kind: \"disjointness\" as const,\n conflictingKinds: [claim.entry.refusal.otherKind],\n },\n } satisfies NodeInsertClaim,\n probeKinds: [],\n disjointOtherKind: claim.entry.refusal.otherKind,\n refusal: claim.entry.refusal,\n } satisfies NodeCreateClaimVerdict;\n });\n return {\n entries: placed.map((claim) => claim.entry),\n claims: verdicts.map((verdict) => verdict.claim),\n verdicts,\n };\n}\n\n/** One statement per claim — the shape the single-row create path ships. */\nasync function issueClaimsIndividually(\n ctx: UniquenessContext,\n claims: readonly PlacedClaim[],\n onIssued?: (issued: readonly PlacedClaim[]) => void,\n): Promise<void> {\n for (const claim of claims) {\n await issuingClaims([claim.entry], () =>\n ctx.backend.insertUnique(claimInsertParams(ctx.graphId, claim)),\n );\n onIssued?.([claim]);\n }\n}\n\n/**\n * ONE statement for the whole group, which is also what makes it deadlock-free\n * against itself: a single multi-row statement takes its row locks in a fixed\n * order. Falls back to the per-claim shape on a backend with no batch\n * primitive.\n */\nasync function issueClaimsBatched(\n ctx: UniquenessContext,\n claims: readonly PlacedClaim[],\n onIssued?: (issued: readonly PlacedClaim[]) => void,\n): Promise<void> {\n if (claims.length === 0) return;\n const bound = bindExtraIfReachable(\n ctx.backend,\n ctx.uniqueSidecarBatch.extras.insertUniqueBatch,\n UNIQUE_SIDECAR_BATCH.id,\n );\n if (bound === undefined) {\n await issueClaimsIndividually(ctx, claims, onIssued);\n return;\n }\n await issuingClaims(\n claims.map((claim) => claim.entry),\n async () => {\n await bound.insertUniqueBatch(\n claims.map((claim) => claimInsertParams(ctx.graphId, claim)),\n );\n },\n );\n onIssued?.(claims);\n}\n\n/**\n * Reserves the gating group, runs the row write it gates, and gives those\n * reservations back if the write does not land.\n *\n * Compensate, not swallow — the same give-back {@link withNodeClaimTransition}\n * makes, for the same reason: the reservations this write took are returned and\n * the original failure is rethrown, so the caller sees the error it would have\n * seen with no reservation attempted at all. Only rows that actually landed are\n * given back, and each is named in full (owner pair and claim axis), so nothing\n * a namesake under another kind or an older axis holds is touched.\n */\nasync function claimGroupThenWrite<T>(\n ctx: UniquenessContext,\n issue: ClaimIssuer,\n gating: readonly PlacedClaim[],\n gatedWrite: () => Promise<T>,\n): Promise<T> {\n const issued: PlacedClaim[] = [];\n try {\n await issue(ctx, gating, (landed) => {\n issued.push(...landed);\n });\n return await gatedWrite();\n } catch (error) {\n for (const claim of issued.toReversed()) {\n await releaseClaimedUniqueKeys(ctx, claim.item.kind, claim.item.id, [\n {\n axis: claim.entry.axis,\n constraintName: claim.entry.constraintName,\n key: claim.entry.key,\n },\n ]);\n }\n throw error;\n }\n}\n\n/**\n * Issues a create's claims on the two sides of the row write they gate, and\n * compensates the PRE-INSERT ones away if that write does not land.\n *\n * The entries are partitioned by their {@link ClaimPlacement} and the two\n * groups are issued around `gatedInsert`:\n *\n * 1. the `pre-insert` group — the create path's twin of\n * {@link withNodeClaimTransition}, with the same claim → gated write →\n * compensate sequence and the same reasoning: the claim is the only fence\n * for that axis, and a fence issued after the write it fences is not a\n * fence. A refusal here therefore happens with zero rows written, and a\n * refusal from the write compensates the reservations away;\n * 2. `gatedInsert()`;\n * 3. the `post-insert` group — the position those entries ship in, unchanged,\n * and with that position's failure behavior: a throw propagates and nothing\n * compensates it, because the row it belongs to is already written and\n * visible.\n *\n * Each group is sorted by {@link compareClaimTargets} and the pre-insert group\n * is always issued first, so every writer of a given row computes the same\n * acquisition order. A row owing claims in both groups therefore emits two\n * claim statements where one placement alone emits one.\n */\nasync function withNodeCreateClaimsIssuedBy<T>(\n ctx: NodeClaimContext,\n items: readonly NodeClaimItem[],\n backend: GraphBackend | TransactionBackend,\n issue: ClaimIssuer,\n gatedInsert: () => Promise<T>,\n): Promise<T> {\n const claimContext = createUniquenessContext(\n ctx.graphId,\n ctx.registry,\n backend,\n ctx.uniqueSidecarBatch,\n );\n const claims = placedNodeCreateClaims(ctx, items);\n\n const refusal = claimFenceRefusal(\n ctx,\n backend,\n claims.map((claim) => claim.entry),\n );\n if (refusal !== undefined) throw refusal;\n\n const inPlacement = (placement: ClaimPlacement): readonly PlacedClaim[] =>\n claims\n .filter((claim) => claim.entry.placement === placement)\n .toSorted((left, right) =>\n compareClaimTargets(left.target, right.target),\n );\n\n const result = await claimGroupThenWrite(\n claimContext,\n issue,\n inPlacement(\"pre-insert\"),\n gatedInsert,\n );\n await issue(claimContext, inPlacement(\"post-insert\"));\n return result;\n}\n\n/**\n * The create claim seam for ONE row: one statement per claim, matching the\n * statement shape the single-row create path ships.\n */\nexport function withNodeCreateClaims<T>(\n ctx: NodeClaimContext,\n item: NodeClaimItem,\n backend: GraphBackend | TransactionBackend,\n gatedInsert: () => Promise<T>,\n): Promise<T> {\n return withNodeCreateClaimsIssuedBy(\n ctx,\n [item],\n backend,\n issueClaimsIndividually,\n gatedInsert,\n );\n}\n\n/**\n * The create claim seam for a BATCH: one statement per placement group across\n * every row, instead of the per-row statement fan.\n */\nexport function withNodeCreateClaimsBatch<T>(\n ctx: NodeClaimContext,\n items: readonly NodeClaimItem[],\n backend: GraphBackend | TransactionBackend,\n gatedInsert: () => Promise<T>,\n): Promise<T> {\n return withNodeCreateClaimsIssuedBy(\n ctx,\n items,\n backend,\n issueClaimsBatched,\n gatedInsert,\n );\n}\n\n/**\n * The gate for a claim set whose row write has ALREADY been applied — a\n * re-claim after a set update, or a test seeding a reservation.\n *\n * Such a write reaches the seam with nothing left to gate, which is exactly why\n * it owes no pre-insert claim: there is no row write left for a claim to\n * precede. Naming it makes that reading explicit at the call site instead of\n * leaving an inline no-op for a reader to interpret.\n */\nexport function alreadyAppliedRowWrite(): Promise<undefined> {\n return Promise.resolve(undefined);\n}\n\n/**\n * Releases the claims a node being deleted holds — the LIFECYCLE shape: every\n * claim this node owns for each applying constraint's key, at whatever axis the\n * claim sits on.\n */\nexport async function deleteUniquenessEntries(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n props: Record<string, unknown>,\n constraints: readonly UniqueConstraint[],\n): Promise<void> {\n // The create extent: a delete gives back everything a create wrote, so the\n // release must be read from the wider of the two lists.\n await releaseOwnedUniqueKeys(\n ctx,\n kind,\n id,\n nodeClaimEntries(ctx.registry, kind, id, props, constraints, \"create\"),\n );\n}\n\n/**\n * Drops EVERY claim a set of nodes holds under one concrete kind, key-blind, so\n * the rebuild that follows can re-claim from the after-images.\n *\n * The key-blind drop is what a set update needs and the per-key\n * {@link deleteUniquenessEntries} cannot give it: the statement rewrote whole\n * rows without reading their before-images, so nobody knows which keys those\n * rows used to hold. It drops BOTH families — every claim the owner pair holds —\n * which is why the rebuild must go back through {@link withNodeCreateClaimsBatch}\n * rather than a uniqueness-only reinsert.\n *\n * Requiring the member rather than probing it: the only caller\n * ({@link file://../operations/node-write-pipeline.ts applyNodeSetUpdate})\n * refuses the write up front when a constrained kind's backend lacks it, with a\n * code that names the operation. A second fallback here would be a quieter\n * answer to a question already asked.\n */\nexport async function hardDeleteClaimsByNodeIds(\n ctx: UniquenessContext,\n concreteKind: string,\n nodeIds: readonly string[],\n): Promise<void> {\n await requireDefined(\n bindExtraIfReachable(\n ctx.backend,\n ctx.uniqueSidecarBatch.extras.hardDeleteUniquesByNodeIds,\n UNIQUE_SIDECAR_BATCH.id,\n )?.hardDeleteUniquesByNodeIds,\n )({\n graphId: ctx.graphId,\n concreteKind,\n nodeIds,\n });\n}\n\n/**\n * A single constraint's sidecar transition, decided by a plan builder and\n * carried out by {@link withNodeClaimTransition}.\n *\n * The two keys move at DIFFERENT times relative to the primary row write, so\n * they are named for when they move rather than for old/new:\n * `claim` is reserved BEFORE the write (it is the write's conflict gate),\n * `release` is given up AFTER it (it is history the write supersedes).\n */\ntype PendingUniqueMutation = Readonly<{\n constraintName: string;\n /** The key to give up once the primary write lands; undefined = none. */\n release: string | undefined;\n /**\n * The entry to reserve before the primary write; undefined = none, either\n * because the constraint stopped applying or because {@link probeUniqueKey}\n * found this node already holding it live. It is the whole entry rather than\n * a bare key so the compensation names the row this transition wrote instead\n * of re-deriving which axis that was, and so the refusal reads the placement\n * and class the entry's site decided.\n */\n claim: NodeClaimEntry | undefined;\n}>;\n\n/**\n * The sidecar transition a node write owes, decided but not yet performed.\n *\n * Opaque to its holder on purpose: the only thing a caller does with a plan is\n * hand it to {@link withNodeClaimTransition} together with the primary row\n * write it belongs to.\n */\nexport type UniquenessUpdatePlan = readonly PendingUniqueMutation[];\n\n/**\n * Decides the claim changes a node's new props require, WITHOUT writing any of\n * them.\n *\n * Preflights EVERY changed constraint before anything is written. A node can\n * carry several unique constraints; probing them one at a time as they are\n * applied would let a later constraint's conflict throw after earlier sidecars\n * already moved. Probing all of them first means a refusal here happens with\n * zero writes, and the probes are independent per `constraintName`, so one\n * constraint's verdict is unaffected by the others' still-unapplied changes.\n *\n * Handles the cases where a constraint starts applying, stops applying, or\n * keeps applying under a different key.\n *\n * @throws UniquenessError if an updated value is already held by another node\n */\nexport async function planNodeClaimUpdate(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n oldProps: Record<string, unknown>,\n newProps: Record<string, unknown>,\n constraints: readonly UniqueConstraint[],\n): Promise<UniquenessUpdatePlan> {\n // Both sides of the diff are read from the one entries function, so the key\n // a release names is computed exactly the way the key a claim names is.\n const oldKeys = new Map(\n nodeClaimEntries(\n ctx.registry,\n kind,\n id,\n oldProps,\n constraints,\n \"update\",\n ).map((entry) => [entry.constraintName, entry.key]),\n );\n const newEntries = new Map(\n nodeClaimEntries(ctx.registry, kind, id, newProps, constraints, \"update\")\n .filter((entry): entry is UniquenessClaimEntry =>\n isUniquenessClaimEntry(entry),\n )\n .map((entry) => [entry.constraintName, entry]),\n );\n\n const pending: PendingUniqueMutation[] = [];\n for (const constraint of constraints) {\n const oldKey = oldKeys.get(constraint.name);\n const newEntry = newEntries.get(constraint.name);\n\n // No change - constraint didn't apply and still doesn't\n if (oldKey === undefined && newEntry === undefined) continue;\n\n // Key is the same and the constraint still applies - nothing to do\n if (oldKey !== undefined && oldKey === newEntry?.key) continue;\n\n // Probe the new key: refuse a value another node holds, and note a value\n // this node somehow holds already so the transition neither re-claims nor\n // releases it.\n const alreadyHeld =\n newEntry === undefined ? false : (\n await probeUniqueKey(ctx, kind, id, newEntry)\n );\n\n pending.push({\n constraintName: constraint.name,\n release: oldKey,\n claim: newEntry === undefined || alreadyHeld ? undefined : newEntry,\n });\n }\n\n return pending;\n}\n\n/**\n * The plan a RESURRECTING write needs: every applying constraint re-reserved\n * from scratch, uniqueness AND disjointness alike.\n *\n * A tombstoned node holds no live reservations — {@link deleteUniquenessEntries}\n * released them at soft-delete time, reading the wider `\"create\"` extent that\n * already covers both families — so the diff-based {@link planNodeClaimUpdate}\n * cannot be used here: it would skip an unchanged key and leave the revived\n * node holding NO reservation, letting a later create (of this node's own key,\n * or of a disjoint partner under this node's id) silently duplicate the value.\n *\n * Reads its entries at `\"resurrect\"`, the {@link NodeClaimOperation} that owes\n * the same disjointness sites a create owes (see `nodeClaimSites`) — a\n * resurrect brings a node back into existence under its kind exactly as a\n * create does, so it owes the same cross-kind claim. A disjointness entry can\n * never already be held by THIS node (its own reservation was released at\n * soft-delete time, and nothing else could have taken it under this node's\n * OWN id/kind pair), so unlike a uniqueness entry it needs no \"already held by\n * myself\" probe — it is claimed fresh, exactly as a create claims it fresh.\n *\n * @throws UniquenessError if a key this node held was taken while it was\n * tombstoned\n * @throws DisjointError if a disjoint partner now holds this id (translated by\n * {@link claimUniqueKeysThen} from the `UniquenessError` `insertUnique`\n * itself reports)\n */\nexport async function planNodeClaimReinsert(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n props: Record<string, unknown>,\n constraints: readonly UniqueConstraint[],\n): Promise<UniquenessUpdatePlan> {\n const pending: PendingUniqueMutation[] = [];\n for (const entry of nodeClaimEntries(\n ctx.registry,\n kind,\n id,\n props,\n constraints,\n \"resurrect\",\n )) {\n const alreadyHeld =\n isUniquenessClaimEntry(entry) ?\n await probeUniqueKey(ctx, kind, id, entry)\n : false;\n\n pending.push({\n constraintName: entry.constraintName,\n release: undefined,\n claim: alreadyHeld ? undefined : entry,\n });\n }\n return pending;\n}\n\n/** One reservation a release names. */\ntype ReleasableKey = Readonly<{ constraintName: string; key: string }>;\n\n/**\n * A reservation a write actually took, remembered together with the claim axis\n * it was written at so the compensation can name the same row rather than\n * re-deriving it.\n */\ntype ClaimedKey = ReleasableKey & Readonly<{ axis: string }>;\n\n/**\n * LIFECYCLE release: gives up every reservation THIS node holds for each\n * `(constraintName, key)`, in plan order, whatever axis the reservation sits\n * on.\n *\n * Scoping to the owner pair `(concreteKind, id)` rather than to the axis is\n * what lets a claim written under an older axis be released by newer code, and\n * what keeps a namesake — same id, different kind — holding its own.\n */\nasync function releaseOwnedUniqueKeys(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n keys: readonly ReleasableKey[],\n): Promise<void> {\n for (const entry of keys) {\n await ctx.backend.deleteUnique({\n graphId: ctx.graphId,\n constraintName: entry.constraintName,\n key: entry.key,\n concreteKind: kind,\n nodeId: id,\n });\n }\n}\n\n/**\n * COMPENSATING release: undoes exactly the rows a failed write just claimed —\n * the owner's reservation AT the axis it claimed on, and nothing else.\n *\n * Deliberately narrower than {@link releaseOwnedUniqueKeys}: a rollback must\n * touch neither a reservation at another axis that predates this write nor one\n * another node holds. Conflating the two would make a refused write strip\n * claims it never took.\n */\nasync function releaseClaimedUniqueKeys(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n keys: readonly ClaimedKey[],\n): Promise<void> {\n for (const entry of keys) {\n await ctx.backend.deleteUnique({\n graphId: ctx.graphId,\n nodeKind: entry.axis,\n constraintName: entry.constraintName,\n key: entry.key,\n concreteKind: kind,\n nodeId: id,\n });\n }\n}\n\n/**\n * Reserves the plan's new keys, runs the primary row write they gate, and undoes\n * the reservations if that write does not land.\n *\n * Each claim statement runs through {@link issuingClaims} — a resurrect's plan\n * can carry a disjointness entry ({@link planNodeClaimReinsert}), and a foreign\n * owner of THAT reservation must surface as `DisjointError`, not the raw\n * `UniquenessError` `insertUnique` reports for every family alike.\n */\nasync function claimUniqueKeysThen<T>(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n plan: UniquenessUpdatePlan,\n gatedWrite: () => Promise<T>,\n): Promise<T> {\n const claimed: ClaimedKey[] = [];\n try {\n for (const mutation of plan) {\n const claim = mutation.claim;\n if (claim === undefined) continue;\n await issuingClaims([claim], () =>\n ctx.backend.insertUnique({\n graphId: ctx.graphId,\n nodeKind: claim.axis,\n constraintName: mutation.constraintName,\n key: claim.key,\n nodeId: id,\n concreteKind: kind,\n }),\n );\n claimed.push({\n axis: claim.axis,\n constraintName: mutation.constraintName,\n key: claim.key,\n });\n }\n return await gatedWrite();\n } catch (error) {\n // Compensate, not swallow: the reservations this transition took are given\n // back and the original failure is rethrown, so the caller sees the SAME\n // error it would have seen with no reservation attempted at all.\n //\n // The give-back names the exact rows this transition wrote — owner pair and\n // claim axis both — so it can strip neither a reservation at another axis\n // that predates this write nor one a namesake under a different kind holds.\n //\n // The give-back is exact because of what a claim can be. `probeUniqueKey`\n // refuses a key another node holds and reports one THIS node already holds\n // (which the plan then does not claim), so every claimed key was free or\n // tombstoned beforehand and releasing it restores precisely that. And no\n // peer can have taken it in between: this transaction holds the row.\n //\n // One detail is restored in kind rather than exactly: a claim that took over\n // a TOMBSTONED reservation rewrites its recorded owner, and the give-back\n // re-tombstones it under THIS node's id instead of the previous holder's.\n // The key reads as free either way — `checkUnique` skips tombstoned rows —\n // and the one reader that looks at them, `getOrCreateByConstraint`'s\n // resurrect-by-key lookup, writes the props it was called with onto whatever\n // row it revives, so the reservation and the row holding the value stay\n // consistent. Which tombstone that lookup revives can differ. If the\n // compensation itself fails the row is genuinely half-written, and the\n // error that then surfaces is a raw backend failure no per-row consumer\n // catches — the enclosing transaction aborts, which is the only honest\n // outcome left.\n await releaseClaimedUniqueKeys(ctx, kind, id, claimed);\n throw error;\n }\n}\n\n/**\n * Runs one node's primary row write with its claim transition wrapped around\n * it, so the pair commits or fails AS ONE UNIT.\n *\n * ## Why the sequence is claim, gate, release\n *\n * A node update is two independently fallible writes — the row itself and its\n * claim rows — with no rollback between them: nothing here is\n * savepoint-protected (see `operations/write-transaction.ts`), and the backends\n * this supports do not all have savepoints to reach for. Sequencing is the only\n * atomicity available, and only ONE sequence makes both failures leave zero net\n * effect:\n *\n * - **Claim first.** `insertUnique` is an upsert that reports the key's final\n * owner, so claiming IS the conflict gate — and once this transaction holds\n * the row, no concurrent writer can take the key from under it. Probing and\n * then claiming later leaves a window (wide open under PostgreSQL READ\n * COMMITTED, where a peer commits between the two) in which the claim fails\n * AFTER the row was already updated.\n * - **Then the row write.** It can legitimately match nothing —\n * `expectedValidFrom`, `deleted_at` — and callers that catch that per row and\n * commit the rest (interchange import) must not be left with reservations for\n * a row that never changed. A refusal here compensates the claims away.\n * - **Release last.** Giving up the old key before the row write would free a\n * value for a write that may never land; giving it up after is safe because\n * nothing can fail on it.\n *\n * The predecessor of this helper ordered the whole sidecar transition after the\n * row write, which closed the second failure and left the first: a caught\n * `UniquenessError` then reported `updated: 0` for a row whose props HAD\n * changed, whose old reservation was gone, and whose new one belonged to someone\n * else.\n *\n * Because that sequence is claim-first for EVERY scope, every claim this seam\n * issues is `pre-insert`, and a backend that cannot roll the pair back together\n * is refused before the first of them — see {@link claimFenceRefusal}. The\n * subject is the plan's claims rather than the kind's constraints: an update\n * that does not move a key issues no reservation and must not be refused.\n */\nexport async function withNodeClaimTransition<T>(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n plan: UniquenessUpdatePlan,\n gatedWrite: () => Promise<T>,\n): Promise<T> {\n const refusal = claimFenceRefusal(\n ctx,\n ctx.backend,\n plan.flatMap((mutation) =>\n mutation.claim === undefined ? [] : [mutation.claim],\n ),\n );\n if (refusal !== undefined) throw refusal;\n\n const result = await claimUniqueKeysThen(ctx, kind, id, plan, gatedWrite);\n await releaseOwnedUniqueKeys(\n ctx,\n kind,\n id,\n plan.flatMap((mutation) =>\n mutation.release === undefined ?\n []\n : [{ constraintName: mutation.constraintName, key: mutation.release }],\n ),\n );\n return result;\n}\n","/**\n * Node claims for a RESOLVED WRITE SET — a whole after-image validated at once,\n * then applied.\n *\n * Every other claim path in this directory decides one row at a time, which is\n * what an ordinary write is. Two callers instead know their complete final state\n * before writing any of it — a graph merge's resolved plan\n * ({@link file://../../graph-merge/merge.ts}) and a set update\n * ({@link file://../operations/node-operations.ts}) — and for them \"one row at a\n * time\" is the wrong verdict: an atomic SWAP of two nodes' keys, or a handoff of\n * one key from a node the set deletes to a node the set writes, is legal in the\n * final state and refused by every intermediate one.\n *\n * So this module reads the set's claims TOGETHER, decides them against each\n * other first and the persisted relation second, and treats every reservation\n * the set itself releases as available. It decides nothing on its own: the\n * entries come from {@link nodeClaimEntries}, the axis fold from\n * {@link uniquenessProbeKinds}, the ownership verdict from\n * {@link isSameClaimOwner} / {@link claimOwnerKey}, and the rebuild from the\n * same claim writer every create-shaped write uses.\n */\nimport { bindExtraIfReachable } from \"../../backend/capabilities/bind\";\nimport { UNIQUE_SIDECAR_BATCH } from \"../../backend/capabilities/bundle-registry\";\nimport { requireExtras } from \"../../backend/capabilities/resolve\";\nimport { type UniqueConstraint } from \"../../core/types\";\nimport { ConfigurationError, UniquenessError } from \"../../errors\";\nimport { encodeTupleKey } from \"../../utils/tuple-key\";\nimport {\n type ClaimOwner,\n claimOwnerKey,\n isSameClaimOwner,\n uniquenessProbeKinds,\n} from \"./axis\";\nimport {\n alreadyAppliedRowWrite,\n isUniquenessClaimEntry,\n type NodeClaimContext,\n nodeClaimEntries,\n type UniquenessClaimEntry,\n type UniquenessContext,\n withNodeCreateClaimsBatch,\n} from \"./node-claims\";\n\n/** A complete node after-image whose claims belong to one resolved write set. */\nexport type ResolvedNodeUpsert = Readonly<{\n kind: string;\n id: string;\n props: Readonly<Record<string, unknown>>;\n constraints: readonly UniqueConstraint[];\n}>;\n\n/** A node whose current claims the resolved write set gives back. */\nexport type ResolvedNodeRelease = Readonly<{\n kind: string;\n id: string;\n}>;\n\n/**\n * One uniqueness claim the set proposes: who takes it, the row it writes, and\n * the rows its probe reads.\n *\n * `probeKinds` is carried rather than recomputed because it is BOTH halves of\n * the conflict test — the persisted probe issues one read per member, and the\n * in-set test asks whether one claim's write lands in another claim's read set.\n */\ntype ProposedClaim = Readonly<{\n owner: ClaimOwner;\n entry: UniquenessClaimEntry;\n probeKinds: readonly string[];\n}>;\n\n/** The claim rows two proposals share a competition for. */\nfunction claimRowKey(entry: UniquenessClaimEntry): string {\n return encodeTupleKey([entry.constraintName, entry.key]);\n}\n\n/**\n * Whether two proposals in one set are competing — one writes a row the other\n * reads.\n *\n * Reachability in EITHER direction, not axis equality: after the axis fold a\n * `kind`-scoped constraint writes under the writer's own kind while a\n * `kindWithSubClasses` constraint of the same name writes under the component's\n * fold, so two claims can compete without sharing an axis. The wider scope's\n * probe is what would have caught the narrower one's row had it been persisted,\n * and inside one set neither row is persisted yet — which is the whole reason\n * this test exists rather than leaving it to the relation.\n */\nfunction claimsCompete(left: ProposedClaim, right: ProposedClaim): boolean {\n return (\n claimRowKey(left.entry) === claimRowKey(right.entry) &&\n (right.probeKinds.includes(left.entry.axis) ||\n left.probeKinds.includes(right.entry.axis))\n );\n}\n\nfunction proposedClaimRefusal(\n incumbent: ProposedClaim,\n challenger: ProposedClaim,\n): UniquenessError {\n return new UniquenessError({\n constraintName: challenger.entry.constraintName,\n kind: incumbent.owner.concreteKind,\n existingId: incumbent.owner.nodeId,\n newId: challenger.owner.nodeId,\n fields: challenger.entry.refusal.constraint.fields,\n });\n}\n\n/**\n * The set's uniqueness claims, with every in-set competition already refused.\n *\n * Reads its work from {@link nodeClaimEntries} at the CREATE extent — the wider\n * of the two, exactly as {@link file://./node-claims.ts checkUniquenessConstraints}\n * does — and narrows to the uniqueness family. The disjointness entries the same\n * list carries are NOT probed here: they have their own probe over node rows,\n * and each write inside the set's `apply()` reaches it. Filtering rather than\n * asking for a narrower list is what keeps that omission a stated decision\n * instead of an absence nobody notices.\n *\n * @throws UniquenessError when two members of the set compete for one claim.\n */\nfunction proposedClaims(\n ctx: UniquenessContext,\n upserts: readonly ResolvedNodeUpsert[],\n): readonly ProposedClaim[] {\n const accepted: ProposedClaim[] = [];\n for (const upsert of upserts) {\n const owner: ClaimOwner = {\n concreteKind: upsert.kind,\n nodeId: upsert.id,\n };\n const entries = nodeClaimEntries(\n ctx.registry,\n upsert.kind,\n upsert.id,\n { ...upsert.props },\n upsert.constraints,\n \"create\",\n );\n for (const entry of entries) {\n if (!isUniquenessClaimEntry(entry)) continue;\n const proposal: ProposedClaim = {\n owner,\n entry,\n probeKinds: uniquenessProbeKinds(\n upsert.kind,\n entry.refusal.constraint.scope,\n ctx.registry,\n ),\n };\n const incumbent = accepted.find(\n (candidate) =>\n !isSameClaimOwner(candidate.owner, proposal.owner) &&\n claimsCompete(candidate, proposal),\n );\n if (incumbent !== undefined) {\n throw proposedClaimRefusal(incumbent, proposal);\n }\n accepted.push(proposal);\n }\n }\n return accepted;\n}\n\n/** One `checkUniqueBatch` round trip: every key this set claims at one axis. */\ntype ClaimProbeGroup = Readonly<{\n probeKind: string;\n constraintName: string;\n claimsByKey: ReadonlyMap<string, ProposedClaim>;\n}>;\n\n/**\n * Folds the proposals into one probe per `(kind in scope, constraint)`.\n *\n * Keyed on {@link uniquenessProbeKinds} rather than on the axis alone for the\n * reason that function documents: rows written before the axis move sit under\n * their own concrete kind, so a probe that read only the axis would not see them\n * and the move would need a data migration.\n */\nfunction groupClaimsForProbe(\n claims: readonly ProposedClaim[],\n): readonly ClaimProbeGroup[] {\n const groups = new Map<\n string,\n {\n probeKind: string;\n constraintName: string;\n claimsByKey: Map<string, ProposedClaim>;\n }\n >();\n for (const claim of claims) {\n for (const probeKind of claim.probeKinds) {\n const groupKey = encodeTupleKey([probeKind, claim.entry.constraintName]);\n const existing = groups.get(groupKey);\n if (existing === undefined) {\n groups.set(groupKey, {\n probeKind,\n constraintName: claim.entry.constraintName,\n claimsByKey: new Map([[claim.entry.key, claim]]),\n });\n continue;\n }\n existing.claimsByKey.set(claim.entry.key, claim);\n }\n }\n return [...groups.values()];\n}\n\n/**\n * The batch probe this validation is defined in terms of, or a typed refusal.\n *\n * Keyed on this ONE extra's own presence, not the operation's full 3-extra\n * `requires` set: widening this to `missingRequiredExtras` would move\n * {@link prepareResolvedNodeClaims}'s refusal earlier for\n * `validateResolvedNodeClaims`'s direct caller\n * ({@link file://../operations/node-write-pipeline.ts applyNodeSetUpdate}),\n * which probes and refuses on the full set itself before reaching this call.\n *\n * Binds through {@link bindExtraIfReachable}, not {@link bindExtra}: this\n * refusal is keyed on \"is the probe reachable at all\" — the verdict says\n * present AND the port (`ctx.backend`, the transaction target the call\n * actually executes on) can serve it — and either failure mode collapses\n * into this SAME typed refusal, preserved byte-for-byte from before the\n * capability model existed\n * (`tests/graph-merge/ingestion-branch.test.ts`'s \"refuses final validation\n * when the target transaction lacks batch uniqueness operations\" pins a\n * transaction target narrower than the verdict it was resolved against, and\n * still expects this exact code). `bindExtra`'s generic\n * `BUNDLE_PORT_SURFACE_MISMATCH` would replace that pinned, operation-specific\n * message with the bundle's own — an acceptable disposition for a call site\n * with no existing refusal to preserve, but not for this one.\n */\nfunction requireBatchProbe(\n ctx: UniquenessContext,\n): NonNullable<UniquenessContext[\"backend\"][\"checkUniqueBatch\"]> {\n const bound = bindExtraIfReachable(\n ctx.backend,\n ctx.uniqueSidecarBatch.extras.checkUniqueBatch,\n UNIQUE_SIDECAR_BATCH.id,\n );\n if (bound === undefined) {\n throw new ConfigurationError(\n \"Resolved node writes require batched uniqueness probes\",\n { code: \"RESOLVED_NODE_UNIQUENESS_UNSUPPORTED\" },\n );\n }\n return bound.checkUniqueBatch;\n}\n\n/**\n * Validates node uniqueness against the FINAL state of a resolved write set.\n *\n * All proposed after-images are compared together before persisted claim rows\n * are consulted. Owners the set itself releases or replaces are ignored, which\n * permits atomic swaps and handoffs while still refusing every owner outside the\n * set. The probe is batch-only by contract: a caller that needs this set\n * semantic must not quietly degrade to sequential checks.\n */\nexport async function validateResolvedNodeClaims(\n ctx: UniquenessContext,\n upserts: readonly ResolvedNodeUpsert[],\n releases: readonly ResolvedNodeRelease[] = [],\n): Promise<void> {\n const checkUniqueBatch = requireBatchProbe(ctx);\n const claims = proposedClaims(ctx, upserts);\n if (claims.length === 0) return;\n\n const affectedOwners = new Set(\n [...upserts, ...releases].map((reference) =>\n claimOwnerKey({ concreteKind: reference.kind, nodeId: reference.id }),\n ),\n );\n for (const group of groupClaimsForProbe(claims)) {\n const existingRows = await checkUniqueBatch({\n graphId: ctx.graphId,\n nodeKind: group.probeKind,\n constraintName: group.constraintName,\n keys: [...group.claimsByKey.keys()],\n });\n for (const existing of existingRows) {\n if (\n affectedOwners.has(\n claimOwnerKey({\n concreteKind: existing.concrete_kind,\n nodeId: existing.node_id,\n }),\n )\n ) {\n continue;\n }\n const claim = group.claimsByKey.get(existing.key);\n if (claim === undefined) continue;\n throw new UniquenessError({\n constraintName: group.constraintName,\n // The holder's own kind, never `group.probeKind`: that is the claim\n // AXIS, which a shared scope folds across kinds and which the caller\n // never wrote. The probe and the fence report the same value.\n kind: existing.concrete_kind,\n existingId: existing.node_id,\n newId: claim.owner.nodeId,\n fields: claim.entry.refusal.constraint.fields,\n });\n }\n }\n}\n\n/**\n * Prepares a transaction to apply a resolved write set row by row.\n *\n * Validation happens before any mutation. Once it succeeds, every affected\n * node's claims are batch-cleared so the later per-node upserts can take the\n * validated final keys in any order (including swaps and handoffs).\n */\nfunction resolvedNodeUniquenessOperationsRefusal(): ConfigurationError {\n return new ConfigurationError(\n \"Resolved node writes require batched uniqueness operations\",\n { code: \"RESOLVED_NODE_UNIQUENESS_UNSUPPORTED\" },\n );\n}\n\nasync function prepareResolvedNodeClaims(\n ctx: UniquenessContext,\n upserts: readonly ResolvedNodeUpsert[],\n releases: readonly ResolvedNodeRelease[],\n): Promise<void> {\n requireExtras(\n UNIQUE_SIDECAR_BATCH,\n ctx.uniqueSidecarBatch,\n \"resolved node write\",\n () => {\n throw resolvedNodeUniquenessOperationsRefusal();\n },\n );\n // The verdict-level check above can pass while the PORT this call actually\n // executes on (`ctx.backend`, a transaction target) still lacks the member —\n // `bindExtraIfReachable` catches that case too, collapsing both into the\n // same pinned refusal rather than the bundle's generic port-mismatch code\n // (see `requireBatchProbe`'s note on the same tradeoff, below).\n const boundHardDelete = bindExtraIfReachable(\n ctx.backend,\n ctx.uniqueSidecarBatch.extras.hardDeleteUniquesByNodeIds,\n UNIQUE_SIDECAR_BATCH.id,\n );\n if (boundHardDelete === undefined) {\n throw resolvedNodeUniquenessOperationsRefusal();\n }\n const { hardDeleteUniquesByNodeIds } = boundHardDelete;\n // Same port re-check for `insertUniqueBatch`, done here rather than left to\n // `applyResolvedNodeClaims`'s later `withNodeCreateClaimsBatch` rebuild: that\n // call reaches the member only through the shared, fallback-dispositioned\n // `issueClaimsBatched` (`node-claims.ts`), which silently degrades to\n // per-row inserts on a port mismatch instead of refusing — the right answer\n // for a plain create, but not for this REFUSE operation. Checked before the\n // hard-delete below runs, so a refusal here still leaves no claim dropped.\n if (\n bindExtraIfReachable(\n ctx.backend,\n ctx.uniqueSidecarBatch.extras.insertUniqueBatch,\n UNIQUE_SIDECAR_BATCH.id,\n ) === undefined\n ) {\n throw resolvedNodeUniquenessOperationsRefusal();\n }\n await validateResolvedNodeClaims(ctx, upserts, releases);\n\n const idsByKind = new Map<string, Set<string>>();\n for (const reference of [...upserts, ...releases]) {\n const ids = idsByKind.get(reference.kind) ?? new Set<string>();\n ids.add(reference.id);\n idsByKind.set(reference.kind, ids);\n }\n for (const [concreteKind, nodeIds] of idsByKind) {\n await hardDeleteUniquesByNodeIds({\n graphId: ctx.graphId,\n concreteKind,\n nodeIds: [...nodeIds],\n });\n }\n}\n\n/**\n * Applies a resolved write set between the set preflight and one final claim\n * rebuild.\n *\n * The rebuild is required even though ordinary upserts take their own claims: an\n * unchanged upsert may be coalesced and skip all of its normal side effects\n * after preparation cleared its reservations. Re-taking every approved claim is\n * idempotent and makes the transition independent of whether individual writes\n * were coalesced.\n *\n * It goes through {@link withNodeCreateClaimsBatch} — the claim writer every\n * create-shaped write uses — and not through a uniqueness-only insert, for a\n * reason the preparation step makes load-bearing: `hardDeleteUniquesByNodeIds`\n * clears every claim the affected nodes OWN, and after WS2 that includes their\n * `disjointWith` reservations. A rebuild that restored only the uniqueness\n * family would leave each merged node unfenced against a disjoint namesake for\n * the rest of the graph's life. The claim writer restores what\n * {@link nodeClaimEntries} says the row owes, both families, so the set's claims\n * cannot fall out of step with an ordinary create's.\n *\n * `lock` is the caller's evidence that the per-graph write lock was taken before\n * any row work; this function performs no locking of its own.\n */\nexport async function applyResolvedNodeClaims<Output>(\n ctx: NodeClaimContext,\n backend: UniquenessContext[\"backend\"],\n upserts: readonly ResolvedNodeUpsert[],\n releases: readonly ResolvedNodeRelease[],\n apply: () => Promise<Output>,\n): Promise<Output> {\n const claimContext: UniquenessContext = {\n graphId: ctx.graphId,\n registry: ctx.registry,\n backend,\n uniqueSidecarBatch: ctx.uniqueSidecarBatch,\n };\n await prepareResolvedNodeClaims(claimContext, upserts, releases);\n const result = await apply();\n await withNodeCreateClaimsBatch(\n ctx,\n upserts.map((upsert) => ({\n kind: upsert.kind,\n id: upsert.id,\n props: { ...upsert.props },\n constraints: upsert.constraints,\n })),\n backend,\n alreadyAppliedRowWrite,\n );\n return result;\n}\n","/**\n * Embedding Sync Utilities\n *\n * Handles automatic synchronization of embedding fields with the embeddings table.\n * When nodes with embedding properties are created, updated, or deleted,\n * these utilities ensure the embeddings table stays in sync.\n */\nimport { type z } from \"zod\";\n\nimport type { AtomicNodeProjection } from \"../backend/capabilities/atomic-mutation-program\";\nimport {\n type GraphBackend,\n type NodeInsertProjection,\n type TransactionBackend,\n} from \"../backend/types\";\nimport {\n type ResolvedEmbeddingField,\n resolveEmbeddingFields,\n} from \"../core/embedding\";\nimport { readOwnProperty } from \"../utils/object\";\n\n// ============================================================\n// Types\n// ============================================================\n\n/**\n * Information about an embedding field in a node schema.\n *\n * Re-exports the canonical {@link ResolvedEmbeddingField} so the backend\n * gets `dimensions` plus the resolved index `(metric, indexType)` — all\n * three needed to address the field's typed per-`(kind, field)` storage\n * slot when upserting.\n */\ntype EmbeddingFieldInfo = ResolvedEmbeddingField;\n\n/**\n * Context for embedding sync operations.\n */\nexport type EmbeddingSyncContext = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n backend: GraphBackend | TransactionBackend;\n}>;\n\ntype EmbeddingProjectionDecision =\n | Readonly<{ kind: \"upsert\"; embedding: readonly number[] }>\n | Readonly<{ kind: \"delete\" }>\n | Readonly<{ kind: \"ignore\" }>;\n\n/** The single owner for how stored embedding values affect projection state. */\nfunction resolveEmbeddingProjectionDecision(\n value: unknown,\n): EmbeddingProjectionDecision {\n if (isValidEmbeddingValue(value)) {\n return { kind: \"upsert\", embedding: value };\n }\n return value === undefined ? { kind: \"delete\" } : { kind: \"ignore\" };\n}\n\n// ============================================================\n// Schema Introspection\n// ============================================================\n\n/**\n * Cache keyed by the Zod schema instance. Schemas are immutable at\n * runtime; the same reference recurs across every CRUD call.\n */\nconst embeddingFieldsCache = new WeakMap<\n z.ZodType,\n readonly EmbeddingFieldInfo[]\n>();\n\n/**\n * Extracts embedding field information from a Zod schema.\n * Returns all embedding fields found at the top level of an object schema.\n *\n * Thin per-schema-instance memoization over the canonical\n * {@link resolveEmbeddingFields}; the same schema reference recurs across\n * every CRUD call, so caching avoids re-walking the shape each time.\n */\nexport function getEmbeddingFields(\n schema: z.ZodType,\n): readonly EmbeddingFieldInfo[] {\n const cached = embeddingFieldsCache.get(schema);\n if (cached) return cached;\n const fields = resolveEmbeddingFields(schema);\n embeddingFieldsCache.set(schema, fields);\n return fields;\n}\n\n// ============================================================\n// Embedding Sync Operations\n// ============================================================\n\n/**\n * Resolves the present embedding sidecar for a fresh generated-id node.\n * Missing optional values are intentionally omitted because no row can exist\n * for a generated id before this insert. Caller-supplied ids use the regular\n * sync path, which retains its delete semantics for missing values.\n */\nexport function resolveNodeEmbeddingProjections(\n schema: z.ZodType,\n props: Record<string, unknown>,\n): readonly NodeInsertProjection[] {\n return getEmbeddingFields(schema).flatMap(\n (field): readonly NodeInsertProjection[] => {\n const value = readOwnProperty(props, field.fieldPath);\n const decision = resolveEmbeddingProjectionDecision(value);\n return decision.kind === \"upsert\" ?\n [\n {\n kind: \"embedding\",\n fieldPath: field.fieldPath,\n embedding: decision.embedding,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n },\n ]\n : [];\n },\n );\n}\n\n/**\n * Resolves every embedding transition owed by a replacement postimage.\n * Unlike fresh generated-id insertion, an absent value is an explicit delete:\n * caller-id resurrection and updates may be replacing an older projection.\n */\nexport function resolveNodeEmbeddingProjectionTransitions(\n schema: z.ZodType,\n props: Record<string, unknown>,\n options?: Readonly<{ omitDeletes?: boolean }>,\n): readonly AtomicNodeProjection[] {\n return getEmbeddingFields(schema).flatMap(\n (field): readonly AtomicNodeProjection[] => {\n const value = readOwnProperty(props, field.fieldPath);\n const common = {\n kind: \"embedding\" as const,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n };\n const decision = resolveEmbeddingProjectionDecision(value);\n if (decision.kind === \"upsert\") {\n return [\n {\n ...common,\n action: \"upsert\" as const,\n embedding: decision.embedding,\n },\n ];\n }\n return decision.kind === \"delete\" && options?.omitDeletes !== true ?\n [{ ...common, action: \"delete\" as const }]\n : [];\n },\n );\n}\n\n/**\n * Syncs embeddings after a node create or update operation.\n *\n * For each embedding field in the schema:\n * - If the props contain an embedding value, upsert it to the embeddings table\n * - If the props don't contain an embedding value (undefined), delete any existing embedding\n */\nexport async function syncEmbeddings(\n ctx: EmbeddingSyncContext,\n schema: z.ZodType,\n props: Record<string, unknown>,\n): Promise<void> {\n const { backend } = ctx;\n\n // Check if backend supports embedding operations\n if (!backend.upsertEmbedding || !backend.deleteEmbedding) {\n return;\n }\n\n const embeddingFields = getEmbeddingFields(schema);\n if (embeddingFields.length === 0) {\n return;\n }\n\n for (const field of embeddingFields) {\n const value = readOwnProperty(props, field.fieldPath);\n\n const decision = resolveEmbeddingProjectionDecision(value);\n if (decision.kind === \"upsert\") {\n // Upsert the embedding\n await backend.upsertEmbedding({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n fieldPath: field.fieldPath,\n embedding: decision.embedding,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n } else if (decision.kind === \"delete\") {\n // Delete any existing embedding for this field\n await backend.deleteEmbedding({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n }\n // If value is null or invalid, skip (validation should have caught this)\n }\n}\n\n/**\n * Syncs embeddings for a batch of same-kind node creates through one\n * `upsertEmbeddingBatch` per field (falling back to per-row\n * `upsertEmbedding` when the backend lacks the batch primitive). Mirrors\n * `syncEmbeddings` per row: present values upsert, `undefined` values\n * delete any existing embedding for the field.\n */\nexport async function syncEmbeddingsBatchForKind(\n args: Readonly<{\n graphId: string;\n nodeKind: string;\n backend: GraphBackend | TransactionBackend;\n }>,\n schema: z.ZodType,\n items: readonly Readonly<{\n nodeId: string;\n props: Record<string, unknown>;\n }>[],\n): Promise<void> {\n const { graphId, nodeKind, backend } = args;\n if (!backend.upsertEmbedding || !backend.deleteEmbedding) {\n return;\n }\n\n const embeddingFields = getEmbeddingFields(schema);\n if (embeddingFields.length === 0) {\n return;\n }\n\n for (const field of embeddingFields) {\n const rows: { nodeId: string; embedding: readonly number[] }[] = [];\n const deletionIds: string[] = [];\n for (const item of items) {\n const value = readOwnProperty(item.props, field.fieldPath);\n const decision = resolveEmbeddingProjectionDecision(value);\n if (decision.kind === \"upsert\") {\n rows.push({ nodeId: item.nodeId, embedding: decision.embedding });\n } else if (decision.kind === \"delete\") {\n deletionIds.push(item.nodeId);\n }\n }\n\n if (rows.length > 0) {\n if (backend.upsertEmbeddingBatch === undefined) {\n for (const row of rows) {\n await backend.upsertEmbedding({\n graphId,\n nodeKind,\n nodeId: row.nodeId,\n fieldPath: field.fieldPath,\n embedding: row.embedding,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n }\n } else {\n await backend.upsertEmbeddingBatch({\n graphId,\n nodeKind,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n rows,\n });\n }\n }\n\n if (deletionIds.length > 0 && backend.deleteEmbeddingBatch !== undefined) {\n await backend.deleteEmbeddingBatch({\n graphId,\n nodeKind,\n nodeIds: deletionIds,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n } else {\n for (const nodeId of deletionIds) {\n await backend.deleteEmbedding({\n graphId,\n nodeKind,\n nodeId,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n }\n }\n }\n}\n\n/**\n * Deletes a node's embeddings for the embedding fields its kind CURRENTLY\n * declares. A field dropped from the schema after the node was written is\n * intentionally NOT swept here — its entire per-field table is reclaimed\n * wholesale by `store.materializeRemovals()` (the deferred-cleanup verb), which\n * also covers live (never-deleted) nodes' rows. So a hard/soft delete can leave\n * a transient orphan row in a removed field's table until the next reclaim pass;\n * that is the deferred-cleanup design, not a leak.\n */\nexport async function deleteNodeEmbeddings(\n ctx: EmbeddingSyncContext,\n schema: z.ZodType,\n): Promise<void> {\n const { backend } = ctx;\n\n // Check if backend supports embedding operations\n if (!backend.deleteEmbedding) {\n return;\n }\n\n const embeddingFields = getEmbeddingFields(schema);\n if (embeddingFields.length === 0) {\n return;\n }\n\n for (const field of embeddingFields) {\n await backend.deleteEmbedding({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n }\n}\n\n// ============================================================\n// Validation Helpers\n// ============================================================\n\n/**\n * Checks if a value is a valid embedding (array of numbers).\n */\nfunction isValidEmbeddingValue(value: unknown): value is readonly number[] {\n if (!Array.isArray(value)) {\n return false;\n }\n return value.every((n) => typeof n === \"number\" && Number.isFinite(n));\n}\n","/**\n * Keeps the fulltext index in sync with node data. One row per node:\n * the values of every `searchable()` field are concatenated (joined by\n * `\\n`) and stored as the indexed `content`, so a single FTS query can\n * match terms spanning multiple source fields — which a per-field\n * layout cannot, since FTS5 / Postgres MATCH require all terms in one\n * indexed document.\n *\n * Sync runs inline in the node-operation call path, so it inherits the\n * caller's transaction context.\n */\nimport { type z } from \"zod\";\n\nimport { resolveBackendFulltext } from \"../backend/capabilities/fulltext\";\nimport {\n type GraphBackend,\n type NodeFulltextSync,\n type NodeInsertProjection,\n type TransactionBackend,\n} from \"../backend/types\";\nimport {\n DEFAULT_SEARCHABLE_LANGUAGE,\n getSearchableFields,\n type SearchableFieldInfo,\n} from \"../core/searchable\";\nimport {\n ConfigurationError,\n UnsupportedBackendCapabilityError,\n} from \"../errors\";\nimport { readOwnProperty } from \"../utils/object\";\n\nexport { getSearchableFields } from \"../core/searchable\";\n\nexport type FulltextSyncContext = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n backend: GraphBackend | TransactionBackend;\n}>;\n\nconst FIELD_SEPARATOR = \"\\n\";\n\n/**\n * Refuses with a typed error, rather than silently dropping the write, when\n * a node kind declares `searchable()` fields but `resolveBackendFulltext`\n * reports the backend has no fulltext support at all (`fulltext: false`).\n * Used by `syncFulltext` / `syncFulltextBatchForKind` on the create/update\n * paths, where an unavailable backend cannot honor the write. Deletes are\n * exempt: a fulltext-off backend maintains no sidecar to remove a row\n * from, so `deleteNodeFulltext` succeeds instead of refusing.\n *\n * Exported for the set-based update paths (`executeNodeSetUpdate` /\n * `applyNodeSetUpdate`), which reach the same \"unavailable\" branch ahead of\n * their own batch-member presence checks, and so need the same refusal\n * without duplicating its error shape.\n */\nexport function refuseFulltextUnavailable(\n backend: GraphBackend | TransactionBackend,\n nodeKind: string,\n): never {\n throw new UnsupportedBackendCapabilityError(\n `Node kind \"${nodeKind}\" declares searchable() fields`,\n \"fulltext\",\n { backend: backend.dialect, nodeKind, reason: \"fulltext_unsupported\" },\n \"This backend declares no fulltext capability. Remove the \" +\n \"searchable() declaration, or use a backend with fulltext support.\",\n );\n}\n\n/**\n * Narrows an optional fulltext member to defined. Called only after\n * `resolveBackendFulltext` has already confirmed the backend declares\n * fulltext support, so a member missing at this point is not an\n * availability decision but a backend contract violation — a bundled\n * backend never reaches this, and a third-party one that declares the\n * capability without the member gets a `ConfigurationError` naming exactly\n * which member is missing, not `refuseFulltextUnavailable`'s\n * capability-absent error.\n */\nexport function assertFulltextMember<T>(\n member: T | undefined,\n memberName: string,\n backend: GraphBackend | TransactionBackend,\n): asserts member is T {\n if (member !== undefined) return;\n throw new ConfigurationError(\n `Backend declares a fulltext capability but is missing the \"${memberName}\" member`,\n {\n backend: backend.dialect,\n capability: \"fulltext\",\n missingMember: memberName,\n },\n );\n}\n\n/**\n * Picks a representative language when a node has searchable fields with\n * different language settings. Users who need true per-field\n * multilingual indexing should split the data across node kinds.\n */\nfunction resolveCombinedLanguage(\n fields: readonly SearchableFieldInfo[],\n): string {\n return fields[0]?.metadata.language ?? DEFAULT_SEARCHABLE_LANGUAGE;\n}\n\n/**\n * Computes the combined fulltext content for a node, or `undefined`\n * if the node has no non-empty searchable fields.\n *\n * Shared between `syncFulltext` (per-write) and `rebuildFulltextIndex`\n * (bulk) so the two never drift.\n */\nexport function computeFulltextContent(\n schema: z.ZodType,\n props: Record<string, unknown>,\n): { content: string; language: string } | undefined {\n const searchableFields = getSearchableFields(schema);\n if (searchableFields.length === 0) return undefined;\n\n const parts: string[] = [];\n for (const field of searchableFields) {\n const value = readOwnProperty(props, field.fieldPath);\n if (typeof value === \"string\" && value.length > 0) {\n parts.push(value);\n }\n }\n if (parts.length === 0) return undefined;\n\n return {\n content: parts.join(FIELD_SEPARATOR),\n language: resolveCombinedLanguage(searchableFields),\n };\n}\n\n/**\n * Resolves the complete fulltext side effect for one node row.\n * `undefined` means the schema has no searchable fields; an explicit delete\n * keeps an all-empty searchable row from being mistaken for no projection.\n */\nexport function resolveNodeFulltextProjection(\n schema: z.ZodType,\n props: Record<string, unknown>,\n): Extract<NodeInsertProjection, { kind: \"fulltext\" }> | undefined {\n if (getSearchableFields(schema).length === 0) return undefined;\n const computed = computeFulltextContent(schema, props);\n return computed === undefined ?\n { kind: \"fulltext\", action: \"delete\" }\n : { kind: \"fulltext\", action: \"upsert\", ...computed };\n}\n\n/** Resolves the ordinary identity-carrying fulltext synchronization input. */\nfunction resolveNodeFulltextSync(\n schema: z.ZodType,\n props: Record<string, unknown>,\n identity: Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n }>,\n): NodeFulltextSync | undefined {\n if (getSearchableFields(schema).length === 0) return undefined;\n const computed = computeFulltextContent(schema, props);\n return computed === undefined ?\n { ...identity, action: \"delete\" }\n : { ...identity, action: \"upsert\", ...computed };\n}\n\n/**\n * Syncs the fulltext index row after a node create or update.\n *\n * Concatenates the values of all searchable fields into a single content\n * string and upserts it. If every field is empty / undefined, deletes\n * any existing row for the node.\n */\nexport async function syncFulltext(\n ctx: FulltextSyncContext,\n schema: z.ZodType,\n props: Record<string, unknown>,\n): Promise<void> {\n const { backend } = ctx;\n\n if (getSearchableFields(schema).length === 0) return;\n\n // `resolveBackendFulltext` is the one decision for \"is fulltext\n // available on this backend\"; a missing member past that point is a\n // contract violation asserted separately below, never re-derived here.\n if (resolveBackendFulltext(backend) === false) {\n refuseFulltextUnavailable(backend, ctx.nodeKind);\n }\n assertFulltextMember(backend.upsertFulltext, \"upsertFulltext\", backend);\n assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n\n const sync = resolveNodeFulltextSync(schema, props, ctx);\n if (sync?.action === \"upsert\") {\n await backend.upsertFulltext({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n content: sync.content,\n language: sync.language,\n });\n return;\n }\n if (sync === undefined) return;\n await backend.deleteFulltext({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n });\n}\n\n/**\n * Syncs the fulltext rows for a batch of same-kind node creates through\n * one `upsertFulltextBatch` call (falling back to per-row `upsertFulltext`\n * when the backend lacks the batch primitive). Mirrors `syncFulltext`\n * per row: computed content upserts, empty content deletes any stale row\n * when the schema declares searchable fields.\n */\nexport async function syncFulltextBatchForKind(\n args: Readonly<{\n graphId: string;\n nodeKind: string;\n backend: GraphBackend | TransactionBackend;\n }>,\n schema: z.ZodType,\n items: readonly Readonly<{\n nodeId: string;\n props: Record<string, unknown>;\n }>[],\n): Promise<void> {\n const { graphId, nodeKind, backend } = args;\n if (getSearchableFields(schema).length === 0) return;\n\n // `resolveBackendFulltext` is the one decision for \"is fulltext\n // available on this backend\"; a missing member past that point is a\n // contract violation asserted separately below, never re-derived here.\n if (resolveBackendFulltext(backend) === false) {\n refuseFulltextUnavailable(backend, nodeKind);\n }\n assertFulltextMember(backend.upsertFulltext, \"upsertFulltext\", backend);\n assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n\n // The bail-out above guarantees the schema has searchable fields for\n // every remaining line, so an item with no computed content always\n // means \"clear its row\" rather than \"not applicable\".\n const rows: { nodeId: string; content: string; language: string }[] = [];\n const emptyContentIds: string[] = [];\n for (const item of items) {\n const computed = computeFulltextContent(schema, item.props);\n if (computed === undefined) {\n emptyContentIds.push(item.nodeId);\n } else {\n rows.push({\n nodeId: item.nodeId,\n content: computed.content,\n language: computed.language,\n });\n }\n }\n\n if (rows.length > 0) {\n if (backend.upsertFulltextBatch === undefined) {\n for (const row of rows) {\n await backend.upsertFulltext({\n graphId,\n nodeKind,\n nodeId: row.nodeId,\n content: row.content,\n language: row.language,\n });\n }\n } else {\n await backend.upsertFulltextBatch({ graphId, nodeKind, rows });\n }\n }\n\n if (emptyContentIds.length > 0) {\n if (backend.deleteFulltextBatch === undefined) {\n for (const nodeId of emptyContentIds) {\n await backend.deleteFulltext({ graphId, nodeKind, nodeId });\n }\n } else {\n await backend.deleteFulltextBatch({\n graphId,\n nodeKind,\n nodeIds: emptyContentIds,\n });\n }\n }\n}\n\n/**\n * Deletes the fulltext row for a node.\n * Called on soft-delete; hard-delete is handled by the backend cascade.\n */\nexport async function deleteNodeFulltext(\n ctx: FulltextSyncContext,\n schema: z.ZodType,\n): Promise<void> {\n const { backend } = ctx;\n\n if (getSearchableFields(schema).length === 0) return;\n\n // Unlike `syncFulltext`, an unavailable backend does not refuse here: a\n // delete removes data rather than accepting a write the backend cannot\n // index, and this backend maintains no fulltext sidecar to issue that\n // removal against, so the delete is a no-op rather than a refusal. If\n // fulltext was active before this backend was reconfigured with\n // `fulltext: false`, an existing row is left in place, unmaintained.\n if (resolveBackendFulltext(backend) === false) return;\n\n assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n\n await backend.deleteFulltext({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n });\n}\n","/**\n * Composable node write steps — the integrity side effects that every node\n * mutation must apply, extracted so there is a single implementation instead of\n * one hand-stitched copy per write path.\n *\n * A node mutation is the core row write plus a fixed set of side effects:\n * uniqueness entries, embedding sync, fulltext sync, and — for deletes —\n * delete-behavior enforcement over connected edges. These steps are shared by\n * the canonical collection operations (create / update / delete) and by\n * provenance retraction, which drives the same close/reopen of a fact node's\n * currency but skips delete-behavior enforcement so every connected edge\n * survives for a later reopen.\n *\n * The steps assume they run inside a write transaction (see\n * {@link runInWriteTransaction}); they perform no transaction management of\n * their own.\n */\nimport { type z } from \"zod\";\n\nimport { bindExtraIfReachable } from \"../../backend/capabilities/bind\";\nimport { UNIQUE_SIDECAR_BATCH } from \"../../backend/capabilities/bundle-registry\";\nimport { resolveBackendFulltext } from \"../../backend/capabilities/fulltext\";\nimport {\n type BundleVerdictOf,\n type ClaimsVerdictThunk,\n missingRequiredExtras,\n} from \"../../backend/capabilities/resolve\";\nimport {\n type GraphBackend,\n type LiveNodeRow,\n type NodePropertyExpectation,\n type NodeRow,\n rowPropsToObject,\n type TombstonedNodeRow,\n type TransactionBackend,\n type UpdateNodeSetResult,\n} from \"../../backend/types\";\nimport {\n type DeleteBehavior,\n type JsonValue,\n type UniqueConstraint,\n} from \"../../core/types\";\nimport {\n ConfigurationError,\n RestrictedDeleteError,\n ValidationError,\n} from \"../../errors\";\nimport { validateNodeProps } from \"../../errors/validation\";\nimport type { CompiledSelectSql } from \"../../query/sql-intent\";\nimport { type KindRegistry } from \"../../registry/kind-registry\";\nimport { canonicalEqual } from \"../../schema/canonical\";\nimport { assertsStoredLowerBound } from \"../../utils/date\";\nimport { purgeEdgeClaims } from \"../claims/edge-claims\";\nimport {\n alreadyAppliedRowWrite,\n createUniquenessContext,\n deleteUniquenessEntries,\n hardDeleteClaimsByNodeIds,\n type NodeClaimContext,\n planNodeClaimReinsert,\n planNodeClaimUpdate,\n type UniquenessUpdatePlan,\n withNodeClaimTransition,\n withNodeCreateClaimsBatch,\n} from \"../claims/node-claims\";\nimport { validateResolvedNodeClaims } from \"../claims/resolved-node-claims\";\nimport {\n deleteNodeEmbeddings,\n getEmbeddingFields,\n syncEmbeddings,\n syncEmbeddingsBatchForKind,\n} from \"../embedding-sync\";\nimport {\n assertFulltextMember,\n deleteNodeFulltext,\n getSearchableFields,\n refuseFulltextUnavailable,\n syncFulltext,\n syncFulltextBatchForKind,\n} from \"../fulltext-sync\";\nimport { type GraphWriteLock } from \"../recorded-capture/clock\";\n\ntype Backend = GraphBackend | TransactionBackend;\n\n/**\n * The graph-scoped state the node write steps need. `lock` is compile-time\n * evidence that the per-graph write-lock discipline was satisfied BEFORE any\n * row work (see {@link GraphWriteLock}): the pipeline performs no locking of\n * its own, so requiring the token here makes \"sidecar write before lock\" a\n * type error at the call site instead of a lock-order inversion in review.\n *\n * It is the claim seam's context by definition rather than by coincidence: a\n * write path hands the same value to {@link withNodeCreateClaims} and to the\n * sync fans, so the two halves of one insert cannot be given different graphs,\n * registries, or lock evidence.\n */\nexport type NodeWriteContext = NodeClaimContext;\n\n/** Builds a {@link NodeWriteContext} — the one constructor every call site shares. */\nexport function createNodeWriteContext(\n graphId: string,\n registry: KindRegistry,\n lock: GraphWriteLock,\n claimsVerdict: ClaimsVerdictThunk,\n uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>,\n): NodeWriteContext {\n return { graphId, registry, lock, claimsVerdict, uniqueSidecarBatch };\n}\n\n/** Whether a delete removes the node (`hard`) or tombstones it (`soft`). */\ntype NodeDeleteMode = \"soft\" | \"hard\";\n\n/**\n * Tunes how a delete treats the node's connected edges.\n *\n * By default delete behavior is enforced: connected edges block a `restrict`\n * node and are removed under `cascade` / `disconnect`. Provenance retraction\n * passes `enforceDeleteBehavior: false` — closing a fact's currency is a\n * belief-status change, not a domain delete, so its edges neither block the\n * close nor get removed; they survive untouched so a later reopen is an exact\n * inverse.\n */\nexport type NodeDeletePolicy = Readonly<{\n enforceDeleteBehavior: boolean;\n}>;\n\nfunction uniquenessContext(ctx: NodeWriteContext, backend: Backend) {\n return createUniquenessContext(\n ctx.graphId,\n ctx.registry,\n backend,\n ctx.uniqueSidecarBatch,\n );\n}\n\n/**\n * The `(graphId, nodeKind, nodeId, backend)` context shared by the embedding and\n * fulltext sync helpers — `EmbeddingSyncContext` and `FulltextSyncContext` are\n * structurally identical, so one builder serves both.\n */\nfunction nodeSyncContext(\n ctx: NodeWriteContext,\n kind: string,\n id: string,\n backend: Backend,\n) {\n return { graphId: ctx.graphId, nodeKind: kind, nodeId: id, backend };\n}\n\n/**\n * Enforces a node's delete behavior against its connected edges: they block\n * the delete (`restrict`) or are removed alongside the node (`cascade` /\n * `disconnect`). Skipped entirely when the caller's {@link NodeDeletePolicy}\n * disables enforcement.\n */\nasync function enforceNodeDeleteBehavior(\n ctx: NodeWriteContext,\n args: Readonly<{\n kind: string;\n id: string;\n mode: NodeDeleteMode;\n onDelete: DeleteBehavior | undefined;\n }>,\n backend: Backend,\n policy?: NodeDeletePolicy,\n): Promise<void> {\n if (policy?.enforceDeleteBehavior === false) return;\n const behavior = args.onDelete ?? \"restrict\";\n const connectedEdges = await backend.findEdgesConnectedTo({\n graphId: ctx.graphId,\n nodeKind: args.kind,\n nodeId: args.id,\n });\n\n if (connectedEdges.length === 0) return;\n\n switch (behavior) {\n case \"restrict\": {\n throw new RestrictedDeleteError({\n nodeKind: args.kind,\n nodeId: args.id,\n edgeCount: connectedEdges.length,\n edgeKinds: [...new Set(connectedEdges.map((edge) => edge.kind))],\n });\n }\n\n case \"cascade\":\n case \"disconnect\": {\n // Both behaviors remove connected edges. \"cascade\" signals intent to\n // remove dependent data; \"disconnect\" signals intent to sever the\n // relationship. The effect is identical because edges cannot exist\n // without both endpoints. One batched statement per bind-budget\n // chunk instead of one statement per edge; the per-edge loop remains\n // for backends without the batch members.\n const connectedEdgeIds = connectedEdges.map((edge) => edge.id);\n const batchDelete =\n args.mode === \"hard\" ?\n backend.hardDeleteEdgesBatch\n : backend.deleteEdgesBatch;\n if (batchDelete === undefined) {\n for (const edge of connectedEdges) {\n await (args.mode === \"hard\" ?\n backend.hardDeleteEdge({ graphId: ctx.graphId, id: edge.id })\n : backend.deleteEdge({ graphId: ctx.graphId, id: edge.id }));\n }\n } else {\n await batchDelete({\n graphId: ctx.graphId,\n ids: connectedEdgeIds,\n });\n }\n // Hard-deleted holders are already takeable through the liveness probe;\n // this is housekeeping so node cascades do not grow edgeClaims forever.\n // Soft-deleted edges retain their rows for resurrection and are not\n // reaped here.\n if (args.mode === \"hard\") {\n await purgeEdgeClaims(\n backend,\n ctx.claimsVerdict(),\n ctx.graphId,\n connectedEdgeIds,\n );\n }\n break;\n }\n }\n}\n\n/** One inserted row, as the post-insert sync fans read it. */\nexport type NodeInsertSyncItem = Readonly<{\n kind: string;\n id: string;\n schema: z.ZodType;\n props: Record<string, unknown>;\n uniqueConstraints: readonly UniqueConstraint[];\n /** True only when the fused node statement wrote every requested projection. */\n projectionsFused?: boolean;\n}>;\n\n/**\n * The sync fans that follow a node insert: embedding and fulltext.\n *\n * The claims this row owes are NOT here. They are issued by\n * {@link withNodeCreateClaims}, on the two sides of the insert their placement\n * names — a claim that is the only fence for its axis has to precede the row it\n * gates, and a function that runs entirely after the insert cannot issue one.\n * The fans have no such constraint: they are derived data, they fence nothing,\n * and they stay where they have always been.\n */\nexport async function applyNodeInsertSyncFans(\n ctx: NodeWriteContext,\n args: NodeInsertSyncItem,\n backend: Backend,\n): Promise<void> {\n const syncContext = nodeSyncContext(ctx, args.kind, args.id, backend);\n if (args.projectionsFused === true) return;\n await Promise.all([\n syncEmbeddings(syncContext, args.schema, args.props),\n syncFulltext(syncContext, args.schema, args.props),\n ]);\n}\n\n/**\n * Batched {@link applyNodeInsertSyncFans}: one embedding batch per (kind,\n * field) and one fulltext batch per kind, instead of the per-row statement fan\n * the single-op path issues.\n */\nexport async function applyNodeInsertSyncFansBatch(\n ctx: NodeWriteContext,\n items: readonly NodeInsertSyncItem[],\n backend: Backend,\n): Promise<void> {\n if (items.length === 0) return;\n\n interface KindGroup {\n schema: z.ZodType;\n rows: { nodeId: string; props: Record<string, unknown> }[];\n }\n const byKind = new Map<string, KindGroup>();\n for (const item of items) {\n const group = byKind.get(item.kind) ?? { schema: item.schema, rows: [] };\n group.rows.push({ nodeId: item.id, props: item.props });\n byKind.set(item.kind, group);\n }\n\n await Promise.all(\n [...byKind.entries()].flatMap(([kind, group]) => {\n const syncArguments = { graphId: ctx.graphId, nodeKind: kind, backend };\n return [\n syncEmbeddingsBatchForKind(syncArguments, group.schema, group.rows),\n syncFulltextBatchForKind(syncArguments, group.schema, group.rows),\n ];\n }),\n );\n}\n\nfunction parseRowProps(row: NodeRow): Record<string, unknown> {\n return rowPropsToObject(row.props);\n}\n\n/**\n * The row a node update targets. A plain update runs live-row side effects\n * (uniqueness diff, embedding/fulltext sync), so it must be handed a\n * {@link LiveNodeRow}; only an explicit `clearDeleted: true` resurrecting\n * upsert may target a possibly-tombstoned row. Encoding the pairing as a\n * union makes \"live-row update pipeline on a tombstoned row\" a type error.\n */\nexport type NodeUpdateTarget =\n | Readonly<{ existing: LiveNodeRow; clearDeleted?: false }>\n | Readonly<{ existing: NodeRow; clearDeleted: true }>;\n\n/**\n * Decides a node update's uniqueness transition, writing nothing.\n *\n * Two shapes behind one seam. A live row diffs its old and new keys; a\n * resurrecting update (`clearDeleted` on a tombstoned row) cannot, because the\n * soft delete already removed its entries — the diff would skip an unchanged\n * key and leave the resurrected node holding NO reservation, so a later create\n * could silently duplicate the value. It re-reserves every applying key\n * instead. Both refuse a conflict before returning, and both hand the caller a\n * plan that only {@link withNodeClaimTransition} may carry out.\n */\nasync function planNodeUpdateUniqueness(\n ctx: NodeWriteContext,\n args: Readonly<{\n existing: NodeRow;\n validatedProps: Record<string, unknown>;\n uniqueConstraints: readonly UniqueConstraint[];\n }>,\n backend: Backend,\n): Promise<UniquenessUpdatePlan> {\n const { kind, id } = args.existing;\n\n if (args.existing.deleted_at !== undefined) {\n return planNodeClaimReinsert(\n uniquenessContext(ctx, backend),\n kind,\n id,\n args.validatedProps,\n args.uniqueConstraints,\n );\n }\n\n return planNodeClaimUpdate(\n uniquenessContext(ctx, backend),\n kind,\n id,\n parseRowProps(args.existing),\n args.validatedProps,\n args.uniqueConstraints,\n );\n}\n\n/**\n * Applies a node update: uniqueness maintenance (diff-based for a live row;\n * check-and-reinsert for a resurrecting update, whose entries the soft delete\n * removed), the core row update, then embedding and fulltext sync. Returns\n * the updated row.\n *\n * ## The row write and its uniqueness transition are ONE unit\n *\n * Both can fail — the row write matches nothing when `expectedValidFrom` or the\n * `deleted_at` fence stopped holding, the uniqueness claim loses a race for a\n * key — and a caller that catches either PER ROW and commits the rest of the\n * transaction (interchange import) must never be left with half of the pair\n * applied. {@link withNodeClaimTransition} owns that sequencing and documents\n * why claim/gate/release is the only order that works; this function just hands\n * it the plan and the write.\n *\n * The embedding and fulltext syncs stay AFTER the gate: they are derived data\n * with no claim to make, so a row write that lands on nothing must not rewrite\n * a fulltext row or re-embed props no row ever received.\n */\nexport async function applyNodeUpdate(\n ctx: NodeWriteContext,\n args: Readonly<{\n schema: z.ZodType;\n validatedProps: Record<string, unknown>;\n uniqueConstraints: readonly UniqueConstraint[];\n validFrom?: string | null;\n validTo?: string;\n clearValidTo?: true;\n /** See {@link UpdateNodeParams.expectedValidFrom}. */\n expectedValidFrom?: string | null;\n }> &\n NodeUpdateTarget,\n backend: Backend,\n): Promise<NodeRow> {\n const { kind, id } = args.existing;\n\n // Read-only phase: decide the sidecar changes, refuse a conflict, write\n // nothing.\n const plan = await planNodeUpdateUniqueness(\n ctx,\n {\n existing: args.existing,\n validatedProps: args.validatedProps,\n uniqueConstraints: args.uniqueConstraints,\n },\n backend,\n );\n\n const updateParams: {\n graphId: string;\n kind: string;\n id: string;\n props: Record<string, unknown>;\n validFrom?: string | null;\n expectedValidFrom?: string | null;\n incrementVersion?: boolean;\n clearDeleted?: boolean;\n } = {\n graphId: ctx.graphId,\n kind,\n id,\n props: args.validatedProps,\n incrementVersion: true,\n };\n if (args.validFrom !== undefined) updateParams.validFrom = args.validFrom;\n // `assertsStoredLowerBound` owns \"does this fence state anything?\" — the same\n // predicate the fence appliers consult, so the step that CARRIES the fence\n // and the seam that VALIDATES it cannot disagree about what an empty fence is.\n if (assertsStoredLowerBound(args)) {\n updateParams.expectedValidFrom = args.expectedValidFrom;\n }\n if (args.clearDeleted) updateParams.clearDeleted = true;\n\n const row = await withNodeClaimTransition(\n uniquenessContext(ctx, backend),\n kind,\n id,\n plan,\n () =>\n backend.updateNode({\n ...updateParams,\n ...(args.clearValidTo === true ? { clearValidTo: true as const }\n : args.validTo === undefined ? {}\n : { validTo: args.validTo }),\n }),\n );\n\n await Promise.all([\n syncEmbeddings(\n nodeSyncContext(ctx, kind, id, backend),\n args.schema,\n args.validatedProps,\n ),\n syncFulltext(\n nodeSyncContext(ctx, kind, id, backend),\n args.schema,\n args.validatedProps,\n ),\n ]);\n\n return row;\n}\n\n/**\n * Applies a node soft delete: delete-behavior enforcement, the tombstone\n * write, then removal of uniqueness entries, embeddings, and fulltext.\n * Requires a {@link LiveNodeRow}: deleting an already-tombstoned row would\n * re-run sidecar cleanup against entries the first delete already removed.\n */\nexport async function applyNodeSoftDelete(\n ctx: NodeWriteContext,\n args: Readonly<{\n existing: LiveNodeRow;\n schema: z.ZodType;\n uniqueConstraints: readonly UniqueConstraint[];\n onDelete: DeleteBehavior | undefined;\n }>,\n backend: Backend,\n policy?: NodeDeletePolicy,\n): Promise<void> {\n const { kind, id } = args.existing;\n await enforceNodeDeleteBehavior(\n ctx,\n { kind, id, mode: \"soft\", onDelete: args.onDelete },\n backend,\n policy,\n );\n await backend.deleteNode({\n graphId: ctx.graphId,\n kind,\n id,\n });\n await deleteUniquenessEntries(\n uniquenessContext(ctx, backend),\n kind,\n id,\n parseRowProps(args.existing),\n args.uniqueConstraints,\n );\n await deleteNodeEmbeddings(\n nodeSyncContext(ctx, kind, id, backend),\n args.schema,\n );\n await deleteNodeFulltext(\n nodeSyncContext(ctx, kind, id, backend),\n args.schema,\n );\n}\n\n/**\n * Applies a node hard delete: delete-behavior enforcement, permanent removal,\n * then embedding cleanup. Uniqueness and fulltext rows are removed by the\n * backend's `hardDeleteNode` cascade; embeddings live in strategy-owned\n * per-`(kind, field)` tables the graph-agnostic cascade cannot reach, so they\n * are cleaned here.\n */\nexport async function applyNodeHardDelete(\n ctx: NodeWriteContext,\n args: Readonly<{\n kind: string;\n id: string;\n schema: z.ZodType;\n onDelete: DeleteBehavior | undefined;\n }>,\n backend: Backend,\n): Promise<void> {\n await enforceNodeDeleteBehavior(\n ctx,\n { kind: args.kind, id: args.id, mode: \"hard\", onDelete: args.onDelete },\n backend,\n );\n await backend.hardDeleteNode({\n graphId: ctx.graphId,\n kind: args.kind,\n id: args.id,\n });\n await deleteNodeEmbeddings(\n nodeSyncContext(ctx, args.kind, args.id, backend),\n args.schema,\n );\n}\n\n/**\n * Reopens a soft-deleted node with its stored props (no merge, no\n * re-validation): re-checks and re-inserts uniqueness entries (the delete\n * removed them), clears the tombstone, then re-syncs embeddings and fulltext.\n * Used by provenance to reinstate a fact whose currency is restored. Returns\n * the reopened row.\n *\n * @throws {UniquenessError} when a unique key the node held was taken by\n * another node while it was tombstoned.\n */\nexport async function applyNodeResurrect(\n ctx: NodeWriteContext,\n args: Readonly<{\n existing: TombstonedNodeRow;\n schema: z.ZodType;\n uniqueConstraints: readonly UniqueConstraint[];\n }>,\n backend: Backend,\n): Promise<NodeRow> {\n const { kind, id } = args.existing;\n const props = parseRowProps(args.existing);\n // One unit, exactly as `applyNodeUpdate`, and for the same reason: the\n // resurrecting UPDATE carries `deleted_at IS NOT NULL`, so a peer that revived\n // this tombstone first makes it match zero rows — and the reservations that\n // revival is entitled to are the peer's, not this caller's.\n // `withNodeClaimTransition` gives them back when the gate refuses.\n const plan = await planNodeClaimReinsert(\n uniquenessContext(ctx, backend),\n kind,\n id,\n props,\n args.uniqueConstraints,\n );\n const row = await withNodeClaimTransition(\n uniquenessContext(ctx, backend),\n kind,\n id,\n plan,\n () =>\n backend.updateNode({\n graphId: ctx.graphId,\n kind,\n id,\n props,\n incrementVersion: true,\n clearDeleted: true,\n }),\n );\n await Promise.all([\n syncEmbeddings(nodeSyncContext(ctx, kind, id, backend), args.schema, props),\n syncFulltext(nodeSyncContext(ctx, kind, id, backend), args.schema, props),\n ]);\n return row;\n}\n\n/**\n * The inputs of one set-based node update: the patch the statement applies and\n * the candidate query that selects the rows it applies to.\n *\n * There is no fence field. `UpdateNodeSetParams` has no `expectedValidFrom`,\n * so a validity lower bound cannot be carried here — it is refused by\n * `NODE_SET_UPDATE_FENCE_APPLIERS` before this step is reached, rather than\n * accepted into a record that would quietly drop it.\n */\ntype NodeSetUpdateCommonWork = Readonly<{\n kind: string;\n schema: z.ZodType<Record<string, unknown>>;\n uniqueConstraints: readonly UniqueConstraint[];\n patch: Readonly<Record<string, JsonValue>>;\n unsetProperties: readonly string[];\n candidateIds: CompiledSelectSql;\n candidateIdColumn: string;\n}>;\n\nexport type NodeSetUpdateWork = NodeSetUpdateCommonWork &\n (\n | Readonly<{ operation: \"updateWhere\" }>\n | Readonly<{\n operation: \"compareAndSet\";\n expected: Readonly<Record<string, NodePropertyExpectation>>;\n }>\n );\n\n/** What a set update reports: how many live rows it rewrote. */\nexport type NodeSetUpdateResult = Readonly<{ affectedCount: number }>;\n\n/**\n * Applies a set-based node update: one UPDATE over every candidate row, then a\n * full rebuild of the sidecars those after-images oblige.\n *\n * ## Why the capability refusals are HERE and not at the entry point\n *\n * The caller probes the backend it was handed before opening the transaction;\n * these four probe the transaction target, which is a different object — a\n * backend may hand out a transaction handle that implements less than the\n * top-level one. They keep the entry point's error codes, so a caller that\n * refuses before the transaction and one that refuses inside it report the\n * same class.\n *\n * ## Why the order is row -> probe -> drop -> re-claim\n *\n * Unlike every other node write, the uniqueness claim happens AFTER the row\n * write: the statement rewrites whole rows without reading their before-images,\n * so the keys to release are not knowable until the after-images come back.\n * The cross-kind re-check below is what makes that safe — it re-probes every\n * changed key across the constraint's scope and refuses the whole transaction\n * before a single entry is dropped. The per-graph write fence (which a\n * shared-scope constraint forces this write to take) is what keeps a concurrent\n * claim from landing between the probe and the reinsert.\n */\nexport async function applyNodeSetUpdate(\n ctx: NodeWriteContext,\n args: NodeSetUpdateWork,\n backend: Backend,\n): Promise<NodeSetUpdateResult> {\n const { kind, schema, uniqueConstraints } = args;\n const commonParams = {\n graphId: ctx.graphId,\n kind,\n patch: args.patch,\n unsetProperties: args.unsetProperties,\n candidateIds: args.candidateIds,\n candidateIdColumn: args.candidateIdColumn,\n } as const;\n let executeNodeSetUpdate: () => Promise<UpdateNodeSetResult>;\n if (args.operation === \"compareAndSet\") {\n const compareAndSetNode = backend.compareAndSetNode;\n if (compareAndSetNode === undefined) {\n throw new ConfigurationError(\n \"The transaction backend does not support node compare-and-set\",\n { code: \"COMPARE_AND_SET_UNSUPPORTED\", kind },\n );\n }\n executeNodeSetUpdate = () =>\n compareAndSetNode({\n ...commonParams,\n operation: \"compareAndSet\",\n expected: args.expected,\n });\n } else {\n const updateNodeSet = backend.updateNodeSet;\n if (updateNodeSet === undefined) {\n throw new ConfigurationError(\n \"The transaction backend does not support set-based node updates\",\n { code: \"SET_UPDATE_UNSUPPORTED\", kind },\n );\n }\n executeNodeSetUpdate = () =>\n updateNodeSet({ ...commonParams, operation: \"updateWhere\" });\n }\n if (\n uniqueConstraints.length > 0 &&\n missingRequiredExtras(\n UNIQUE_SIDECAR_BATCH,\n ctx.uniqueSidecarBatch,\n \"set-based node update\",\n ).length > 0\n ) {\n throw new ConfigurationError(\n \"The transaction backend lacks batched uniqueness operations\",\n { code: \"SET_UPDATE_UNIQUENESS_UNSUPPORTED\", kind },\n );\n }\n if (getSearchableFields(schema).length > 0) {\n // A fulltext-off backend (`resolveBackendFulltext` returns `false`) gets\n // the same typed capability refusal every other fulltext entry point\n // raises, rather than the member-presence assertions below — those are\n // for a backend that DOES have fulltext but lacks one of the four\n // members the write plan calls, mirroring the batched-uniqueness and\n // batched-vector checks around it.\n if (resolveBackendFulltext(backend) === false) {\n refuseFulltextUnavailable(backend, kind);\n }\n // Fulltext is available, so a missing batch member here is not an\n // availability decision but a backend contract violation — the same\n // invariant `syncFulltextBatchForKind` asserts on its own members.\n assertFulltextMember(backend.upsertFulltext, \"upsertFulltext\", backend);\n assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n assertFulltextMember(\n backend.upsertFulltextBatch,\n \"upsertFulltextBatch\",\n backend,\n );\n assertFulltextMember(\n backend.deleteFulltextBatch,\n \"deleteFulltextBatch\",\n backend,\n );\n }\n if (\n getEmbeddingFields(schema).length > 0 &&\n (backend.upsertEmbedding === undefined ||\n backend.deleteEmbedding === undefined ||\n backend.upsertEmbeddingBatch === undefined ||\n backend.deleteEmbeddingBatch === undefined)\n ) {\n throw new ConfigurationError(\n \"The transaction backend lacks batched vector operations\",\n { code: \"SET_UPDATE_VECTOR_UNSUPPORTED\", kind },\n );\n }\n const result = await executeNodeSetUpdate();\n if (result.affectedCount === 0) return { affectedCount: 0 };\n\n const sidecarItems = result.rows.map((row) => {\n const props = rowPropsToObject(row.props);\n const validatedProps = validateNodeProps(schema, props, {\n kind,\n operation: \"update\",\n id: row.id,\n });\n if (!canonicalEqual(validatedProps, props)) {\n throw new ValidationError(\n `Set update would persist a non-canonical ${kind} row`,\n {\n entityType: \"node\",\n kind,\n operation: \"update\",\n id: row.id,\n issues: [\n {\n path: \"props\",\n message: \"The complete row requires schema normalization\",\n },\n ],\n },\n );\n }\n return {\n kind,\n id: row.id,\n schema,\n props: validatedProps,\n uniqueConstraints,\n };\n });\n\n const claimItems = sidecarItems.map((item) => ({\n kind: item.kind,\n id: item.id,\n props: item.props,\n constraints: item.uniqueConstraints,\n }));\n if (uniqueConstraints.length > 0) {\n // The re-claim below (`withNodeCreateClaimsBatch`) reaches `insertUniqueBatch`\n // only through the shared, fallback-dispositioned `issueClaimsBatched`\n // (`../claims/node-claims.ts`), which silently degrades to per-row inserts\n // when the PORT lacks the member — the right answer for a plain create,\n // but not for this REFUSE operation. Re-checking the port here, before the\n // destructive hard-delete below, closes that gap: the later call binds off\n // the same `backend`/verdict pair checked here, so its internal fallback\n // branch can never fire for this call.\n if (\n bindExtraIfReachable(\n backend,\n ctx.uniqueSidecarBatch.extras.insertUniqueBatch,\n UNIQUE_SIDECAR_BATCH.id,\n ) === undefined\n ) {\n throw new ConfigurationError(\n \"The transaction backend lacks batched uniqueness operations\",\n { code: \"SET_UPDATE_UNIQUENESS_UNSUPPORTED\", kind },\n );\n }\n // The RESOLVED-SET verdict, not a row-at-a-time one: the statement rewrote\n // every candidate at once, so a swap or a handoff of one key between two\n // rows it touched is legal in the final state and refused by every\n // intermediate one. One owner of that verdict, shared with the graph merge.\n await validateResolvedNodeClaims(\n createUniquenessContext(\n ctx.graphId,\n ctx.registry,\n backend,\n ctx.uniqueSidecarBatch,\n ),\n claimItems,\n [],\n );\n await hardDeleteClaimsByNodeIds(\n uniquenessContext(ctx, backend),\n kind,\n result.rows.map((row) => row.id),\n );\n }\n // The same claim seam every create-shaped writer uses, with an ALREADY-APPLIED\n // row write as its gate: the rows landed above and the old claims were\n // hard-deleted, so what is left is a re-claim and there is no row write left\n // for a claim to precede. Inverting it would mean reserving keys the update has\n // not written. What covers this site on a backend that cannot fence is stated\n // per kind shape: a kind whose scope spans siblings declares\n // `fencesConstraintProbe` at the entry point and is refused before this body\n // runs; a kind-scoped one is not refused, before or after — its\n // delete-then-rebuild window is unchanged in shape and extent here.\n await withNodeCreateClaimsBatch(\n ctx,\n claimItems,\n backend,\n alreadyAppliedRowWrite,\n );\n await applyNodeInsertSyncFansBatch(ctx, sidecarItems, backend);\n return { affectedCount: result.affectedCount };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/store/claims/sites.ts","../src/store/claims/node-claims.ts","../src/store/claims/resolved-node-claims.ts","../src/store/embedding-sync.ts","../src/store/fulltext-sync.ts","../src/store/operations/node-write-pipeline.ts"],"names":["disjointnessClaimAxis","DISJOINT_CONSTRAINT_NAME","uniquenessClaimTarget","checkWherePredicate","computeUniqueKey","UniquenessError","DisjointError","constraintFenceRefusal","uniquenessProbeKinds","encodeTupleKey","isSameClaimOwner","compareClaimTargets","bindExtraIfReachable","UNIQUE_SIDECAR_BATCH","requireDefined","ConfigurationError","claimOwnerKey","requireExtras","resolveEmbeddingFields","readOwnProperty","UnsupportedBackendCapabilityError","DEFAULT_SEARCHABLE_LANGUAGE","getSearchableFields","resolveBackendFulltext","RestrictedDeleteError","purgeEdgeClaims","rowPropsToObject","assertsStoredLowerBound","missingRequiredExtras","validateNodeProps","canonicalEqual","ValidationError"],"mappings":"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","file":"chunk-MTJAT6UO.cjs","sourcesContent":["/**\n * What claims a node of a given kind owes, before its props are known.\n *\n * This is the DECLARATION-level half of the claim set, and it is deliberately\n * separate from the props-level half: the same list answers \"which claim rows\n * does this kind write?\" (the entries, once a row's props select the applying\n * constraints and supply their keys) and \"does a write of this kind need the\n * per-graph lock?\" (the projection in `../constraints.ts`). Two consumers, one\n * classification — a second spelling at either of them is what this module\n * exists to prevent.\n *\n * It imports registry, core types and the axis vocabulary only, so the\n * constraint probes can project it without importing the claim seam.\n */\nimport { type UniqueConstraint } from \"../../core/types\";\nimport { type KindRegistry } from \"../../registry/kind-registry\";\nimport {\n DISJOINT_CONSTRAINT_NAME,\n disjointnessClaimAxis,\n uniquenessClaimTarget,\n} from \"./axis\";\nimport { type ConstraintFenceReason } from \"./backing\";\n\n/**\n * WHEN a claim is issued relative to the row write it gates.\n *\n * `\"pre-insert\"` means the claim is the ONLY fence for a violation the row\n * write itself would not surface, so it must precede the row — and a failure\n * between the two leaves a live claim with no row, which is why it is also the\n * subject of the non-transactional refusal. `\"post-insert\"` means the claim\n * follows the row, which is the order those entries ship in today and the order\n * their own primary key already makes sufficient.\n */\nexport type ClaimPlacement = \"pre-insert\" | \"post-insert\";\n\n/**\n * WHICH declared refusal a foreign owner of this claim produces, and the\n * payload that refusal needs.\n *\n * Two constraint families share one claim relation, so the row alone cannot say\n * what refusing it means. Carrying the answer on the site — decided where the\n * site is decided — is what lets the claim seam re-raise the family's own error\n * without re-deriving which family it was from the axis string.\n */\nexport type ClaimRefusal =\n | Readonly<{ kind: \"uniqueness\"; constraint: UniqueConstraint }>\n | Readonly<{ kind: \"disjointness\"; ownKind: string; otherKind: string }>;\n\n/** One claim a node of this kind owes, before its props are known. */\nexport type NodeClaimSite = Readonly<{\n /** The value the claim row's `node_kind` carries — what the PK fences on. */\n axis: string;\n /** The claim row's `constraint_name`. */\n constraintName: string;\n /**\n * Whether this site is ALSO a reason to take the per-graph write lock — i.e.\n * whether its probe reads state the uniques primary key does not already\n * fence. True for a scope spanning more than the node's own kind; false for a\n * single-kind scope, whose own key IS the fence.\n */\n needsLockFence: boolean;\n /**\n * WHEN this site's claim must be issued relative to the row write it gates,\n * for the operation this list was built for. It is DATA, not a caller's\n * choice: the claim seam partitions on it, and the non-transactional refusal\n * asks whether a write owes a `pre-insert` entry.\n */\n placement: ClaimPlacement;\n /**\n * The class a REFUSAL names when this site's claim cannot be undone. A scope\n * spanning more than the node's own kind is `nodeUniquenessScope` — the class\n * the lock path already reports for it; a single-kind scope is\n * `nodeUniquenessClaim`, whose advice is about the reservation row rather\n * than about the scope it does not have.\n */\n refusalReason: ConstraintFenceReason;\n /** Which typed error a foreign owner of this claim produces. */\n refusal: ClaimRefusal;\n}>;\n\n/**\n * The disjointness sites a write BRINGING A NODE INTO EXISTENCE under this kind\n * owes: one per declared partner.\n *\n * `\"create\"` and `\"resurrect\"` only, matching the two places a node comes into\n * existence under a kind — never `\"update\"`, because an in-place update cannot\n * change a node's kind and so re-derives no cross-kind verdict and owes no\n * claim for one. A resurrect owes exactly what a create owes here: reviving a\n * tombstone re-introduces the same live id under the same kind that a fresh\n * insert would, and {@link file://./node-claims.ts deleteUniquenessEntries}\n * released this node's own disjointness reservations at soft-delete time (it\n * reads the `\"create\"` extent precisely because it is the wider of the two), so\n * a resurrect starts from the same \"holds nothing yet\" state a create does and\n * must re-claim from scratch rather than diff.\n *\n * Pairwise rather than per component, because the registry's disjoint pairs are\n * literal unordered pairs: a node disjoint from two partners owes two claims,\n * on two axes, and the two partners are not thereby disjoint from each other.\n *\n * Every one of them is `pre-insert` and `needsLockFence`: the nodes primary key\n * is `(graph_id, kind, id)`, so a disjoint namesake's row does not collide with\n * this node's own insert — the claim is the ONLY fence for the axis, and a\n * fence issued after the write it fences is not a fence. `needsLockFence` is\n * read only by the lock projection (`nodeWriteNeedsConstraintFence`, consulted\n * with `\"create\"` or `\"update\"` alone — never `\"resurrect\"`), so it stays inert\n * for a resurrect: the per-graph lock's trigger set is unchanged by this site\n * applying to a third operation, and the claim's own primary key — the same\n * `INSERT … ON CONFLICT … RETURNING` `insertUnique` already uses for an\n * own-kind uniqueness claim, which needs no lock either — is what fences a\n * resurrect racing a disjoint partner's create.\n */\nfunction disjointnessSites(\n registry: KindRegistry,\n kind: string,\n): readonly NodeClaimSite[] {\n return registry.getDisjointKinds(kind).map((otherKind) => ({\n axis: disjointnessClaimAxis(kind, otherKind, registry),\n constraintName: DISJOINT_CONSTRAINT_NAME,\n needsLockFence: true,\n placement: \"pre-insert\" as const,\n refusalReason: \"nodeDisjointness\" as const,\n refusal: { kind: \"disjointness\" as const, ownKind: kind, otherKind },\n }));\n}\n\n/**\n * The three shapes a node write can take, for claim purposes.\n *\n * `\"create\"` is a fresh id under a kind that has never held it live.\n * `\"update\"` is an in-place change to a row that stays live throughout — it\n * cannot change the node's kind, so it never owes a disjointness claim.\n * `\"resurrect\"` is a tombstoned row coming back to life under its own kind —\n * the SAME cross-kind event a create is, reached through the transition seam\n * instead of the insert seam, which is why its uniqueness claims are placed\n * like an update's (claim-first, {@link file://./node-claims.ts\n * withNodeClaimTransition} is the only correct sequence for a transition) while\n * its disjointness claims are owed like a create's.\n *\n * Two consumers read this vocabulary and each other's classification would be\n * the wrong one to reuse: {@link nodeClaimEntries} (what a ROW owes, given its\n * operation) reaches `\"resurrect\"`; `nodeWriteNeedsConstraintFence` (the lock\n * projection, `../constraints.ts`) and its callers reach only `\"create\"` and\n * `\"update\"`, by design — see {@link disjointnessSites}'s note on why that\n * keeps the per-graph lock's trigger set unchanged.\n */\nexport type NodeClaimOperation = \"create\" | \"update\" | \"resurrect\";\n\n/**\n * THE owner of \"what claims does a node of this kind owe, and when is each\n * due?\".\n *\n * Two families, one list. Disjointness sites come first, so a kind qualifying\n * on both counts reports the class the lock path already reports for it, and so\n * the two families cannot be maintained by two different sets of write paths: a\n * path that remembers uniqueness cannot forget disjointness when both arrive\n * through the same list.\n *\n * Every uniqueness field but `constraintName` is derived from ONE computation —\n * the {@link uniquenessClaimTarget} of this kind and scope — so the four readers\n * of this list (the entries, the claim seam's partition, the non-transactional\n * refusal, and the lock projection in `../constraints.ts`) read one\n * classification rather than four predicates that agree until one is edited.\n * The fact all of them turn on is the same one: does this claim's axis span\n * kinds beyond the writer's own? Disjointness always does; a uniqueness scope\n * does exactly when it covers more than the node's own kind.\n *\n * - `needsLockFence` reads it as \"the probe reads state the uniques primary key\n * does not fence\", which is what the per-graph lock is taken for;\n * - `placement` reads it as \"the claim is the only fence for this axis, so it\n * must precede the row it gates\". On the CREATE path an own-kind claim keeps\n * its shipped position after the row: the uniques primary key at that axis is\n * already the complete fence for it, so moving it would buy no fence and cost\n * a refusal on backends with no transactions. On the UPDATE and RESURRECT\n * paths every claim is pre-insert, because the transition seam claims before\n * its gated write for every scope — see `withNodeClaimTransition`, which\n * explains why that is the only correct sequence for a transition.\n *\n * A future claim family that breaks the coincidence between those two readings\n * must say WHICH it changes; that is why they are two named fields and not one.\n */\nexport function nodeClaimSites(\n registry: KindRegistry,\n kind: string,\n uniqueConstraints: readonly UniqueConstraint[],\n operation: NodeClaimOperation,\n): readonly NodeClaimSite[] {\n const uniqueness = uniqueConstraints.map((constraint) => {\n const target = uniquenessClaimTarget(kind, constraint.scope, registry);\n return {\n axis: target.axis,\n constraintName: constraint.name,\n needsLockFence: target.crossKind,\n placement:\n operation !== \"create\" || target.crossKind ?\n \"pre-insert\"\n : (\"post-insert\" as const),\n refusalReason:\n target.crossKind ?\n (\"nodeUniquenessScope\" as const)\n : (\"nodeUniquenessClaim\" as const),\n refusal: { kind: \"uniqueness\" as const, constraint },\n } satisfies NodeClaimSite;\n });\n\n return operation === \"update\" ? uniqueness : (\n [...disjointnessSites(registry, kind), ...uniqueness]\n );\n}\n","/**\n * Node claims — what a node row reserves, and how each reservation moves.\n *\n * A declared constraint is a CLAIM on an axis (see {@link file://./axis.ts}):\n * the write reserves the row `(graph_id, axis, constraint_name, key)` and is\n * refused when that reservation comes back owned by somebody else. This module\n * decides which claims a row owes, probes them, writes them, releases them, and\n * sequences each of those against the primary row write it gates.\n *\n * Two families reserve in that one relation — a uniqueness constraint at its\n * scope's axis, and a `disjointWith` pair at the pair's axis with the node's id\n * as the key — so every path that already maintained uniqueness reservations\n * maintains disjointness reservations too, by reading one list rather than by\n * being edited twice.\n */\nimport { bindExtraIfReachable } from \"../../backend/capabilities/bind\";\nimport { UNIQUE_SIDECAR_BATCH } from \"../../backend/capabilities/bundle-registry\";\nimport {\n type BundleVerdictOf,\n type ClaimsVerdictThunk,\n} from \"../../backend/capabilities/resolve\";\nimport {\n type GraphBackend,\n type InsertUniqueParams,\n type NodeInsertClaim,\n type TransactionBackend,\n type UniqueConstraintBackend,\n type UniqueRow,\n} from \"../../backend/types\";\nimport { checkWherePredicate, computeUniqueKey } from \"../../constraints\";\nimport { type UniqueConstraint } from \"../../core/types\";\nimport {\n type ConfigurationError,\n DisjointError,\n UniquenessError,\n} from \"../../errors\";\nimport { type KindRegistry } from \"../../registry/kind-registry\";\nimport { requireDefined } from \"../../utils/presence\";\nimport { encodeTupleKey } from \"../../utils/tuple-key\";\nimport { constraintFenceRefusal } from \"../operations/write-transaction\";\nimport { type GraphWriteLock } from \"../recorded-capture/clock\";\nimport {\n type ClaimOwner,\n type ClaimTarget,\n compareClaimTargets,\n isSameClaimOwner,\n uniquenessProbeKinds,\n} from \"./axis\";\nimport { type ConstraintFenceReason } from \"./backing\";\nimport {\n type ClaimPlacement,\n type ClaimRefusal,\n type NodeClaimOperation,\n nodeClaimSites,\n} from \"./sites\";\n\n/**\n * Context for node claim operations.\n */\nexport type UniquenessContext = Readonly<{\n graphId: string;\n registry: KindRegistry;\n backend: GraphBackend | TransactionBackend;\n /** The threaded `uniqueSidecarBatch` verdict — never re-resolved here. */\n uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>;\n}>;\n\n/**\n * Context for the claim PROBE, whose single backend member is the read.\n *\n * Stated separately because the probe runs on handles that cannot write: a\n * write frame's row work holds the read-only `WriteTarget`, and pre-checking a\n * key there is the whole point of the probe. Every {@link UniquenessContext}\n * satisfies this one, so a writer passes its own context unchanged.\n */\nexport type UniquenessProbeContext = Readonly<{\n graphId: string;\n registry: KindRegistry;\n backend: Pick<UniqueConstraintBackend, \"checkUnique\">;\n}>;\n\n/**\n * Builds a claim context — the one constructor every call site shares.\n *\n * Generic in the handle so it yields exactly what it was given: a full backend\n * produces a {@link UniquenessContext} that can also write the claim rows, and\n * a read-only projection produces a {@link UniquenessProbeContext}, which is\n * all the probe needs and all row work can offer.\n */\nexport function createUniquenessContext<\n T extends Pick<UniqueConstraintBackend, \"checkUnique\">,\n>(\n graphId: string,\n registry: KindRegistry,\n backend: T,\n uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>,\n): Readonly<{\n graphId: string;\n registry: KindRegistry;\n backend: T;\n uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>;\n}> {\n return { graphId, registry, backend, uniqueSidecarBatch };\n}\n\n/** One claim a node row owes, decided but not written. */\nexport type NodeClaimEntry = Readonly<{\n /** `uniques.node_kind` — the axis the primary key fences on. */\n axis: string;\n /** `uniques.constraint_name`. */\n constraintName: string;\n /** `uniques.key`. */\n key: string;\n /**\n * WHEN this claim is issued relative to the row write it gates — carried\n * through from the entry's {@link NodeClaimSite}, which is the one owner of\n * the decision. The claim seam issues the two groups on either side of its\n * gated write, and {@link claimFenceRefusal} is keyed on the pre-insert group\n * alone.\n */\n placement: ClaimPlacement;\n /**\n * The class a refusal names when this claim cannot be rolled back — carried\n * through from the site, so no consumer re-derives it.\n */\n refusalReason: ConstraintFenceReason;\n /** Which typed error a foreign owner produces — carried through from the site. */\n refusal: ClaimRefusal;\n}>;\n\n/**\n * The key one site reserves for THIS row, or `undefined` when the site does not\n * apply to it.\n *\n * A uniqueness site applies when its `where` predicate holds, and its key is\n * the constraint's own composite key. A disjointness site always applies, and\n * its key is the node's ID — which is the axis `disjointWith` declares: \"no two\n * live nodes of these two kinds share an id\" is a reservation on the id, taken\n * at the pair.\n */\nfunction claimKeyFor(\n refusal: ClaimRefusal,\n id: string,\n props: Record<string, unknown>,\n): string | undefined {\n if (refusal.kind === \"disjointness\") return id;\n return checkWherePredicate(refusal.constraint, props) ?\n computeUniqueKey(\n props,\n refusal.constraint.fields,\n refusal.constraint.collation,\n )\n : undefined;\n}\n\n/**\n * THE single owner of \"what claims does THIS ROW owe, and when is each due?\":\n * the kind's claim sites ({@link nodeClaimSites}, the declaration-level extent\n * for this operation) filtered to the ones that apply to this row and completed\n * with each one's key. `placement`, `refusalReason` and `refusal` are carried\n * through unchanged; this function decides none of them.\n *\n * Every path that maintains a node's reservations — create, update diff,\n * resurrect, delete, batch, import — reads its work from this one list, so no\n * path can compute a key one way and an axis another, and no path that\n * remembers one family can forget the other.\n *\n * `operation` is threaded rather than assumed because the sites function needs\n * it twice: to place each claim (a transition claims before the row it gates for\n * every scope, while a create only does so for an axis spanning kinds beyond its\n * own) and to decide the disjointness arm, which only a write bringing a node\n * into existence under a kind owes — `\"create\"` and `\"resurrect\"` alike, never\n * `\"update\"`.\n */\nexport function nodeClaimEntries(\n registry: KindRegistry,\n kind: string,\n id: string,\n props: Record<string, unknown>,\n constraints: readonly UniqueConstraint[],\n operation: NodeClaimOperation,\n): readonly NodeClaimEntry[] {\n return nodeClaimSites(registry, kind, constraints, operation).flatMap(\n (site) => {\n const key = claimKeyFor(site.refusal, id, props);\n return key === undefined ?\n []\n : [\n {\n axis: site.axis,\n constraintName: site.constraintName,\n key,\n placement: site.placement,\n refusalReason: site.refusalReason,\n refusal: site.refusal,\n },\n ];\n },\n );\n}\n\n/** An entry whose family is disjointness — the one family that needs mapping. */\ntype DisjointnessClaimEntry = NodeClaimEntry &\n Readonly<{ refusal: Extract<ClaimRefusal, { kind: \"disjointness\" }> }>;\n\n/**\n * THE one place a backend claim refusal becomes the refusal its FAMILY\n * declares.\n *\n * Both families reserve in the `uniques` relation, and `insertUnique` /\n * `insertUniqueBatch` report every foreign owner the same way — as a\n * `UniquenessError` naming the constraint, the holder's concrete kind and the\n * two ids. That contract is deliberately unchanged (a third-party backend\n * implementing it keeps working), so the translation happens here, once, where\n * the entries that produced the claim are still in hand.\n *\n * The reserved `constraintName` alone locates the FAMILY (any entry it matches\n * is a disjointness entry, never a declared constraint's — `assertClaimAxisSafe`\n * makes the name unspellable by one), but not the PAIR: every `disjointWith`\n * pair shares that one literal, so a batch carrying disjointness entries for\n * two different pairs that happen to claim the same id (`Person \"X\"` disjoint\n * with `Company`, `Vehicle \"X\"` disjoint with `Boat`, same batch) would match\n * either indiscriminately on `(constraintName, key)` alone. The entry is\n * additionally required to have written the SAME claim axis the backend\n * reports — the row's actual primary key, and therefore unambiguous — so the\n * one located is provably the one that lost. `error.details.axis` is optional\n * (a third-party backend need not carry it to keep working); when a backend\n * omits it the match falls back to `(constraintName, key)` alone, which is\n * HEAD's behavior and no worse than today's. The payload is built from what\n * the BACKEND reported — the holder's own concrete kind — so the fence's error\n * is identical to the probe's, which is what makes a caller unable to tell\n * which layer refused.\n */\nfunction mapClaimRefusal(\n error: UniquenessError,\n entries: readonly NodeClaimEntry[],\n verdicts: readonly NodeCreateClaimVerdict[] = [],\n): never {\n const verdict = verdicts.find(\n (candidate) =>\n candidate.claim.constraintName === error.details.constraintName &&\n (candidate.refusal.kind === \"uniqueness\" ||\n candidate.claim.key === error.details.newId) &&\n (error.details.axis === undefined ||\n candidate.claim.axis === error.details.axis ||\n (candidate.claim.verdict.kind === \"uniqueness\" &&\n candidate.claim.verdict.probeAxes.includes(error.details.axis))),\n );\n const uniquenessVerdict =\n verdict !== undefined && isNodeCreateUniquenessVerdict(verdict) ?\n verdict\n : undefined;\n if (uniquenessVerdict !== undefined && error.details.fields.length === 0) {\n throw new UniquenessError(\n {\n ...error.details,\n fields: uniquenessVerdict.refusal.constraint.fields,\n },\n { cause: error },\n );\n }\n const owed = entries.find(\n (entry): entry is DisjointnessClaimEntry =>\n entry.refusal.kind === \"disjointness\" &&\n entry.constraintName === error.details.constraintName &&\n entry.key === error.details.newId &&\n (error.details.axis === undefined || entry.axis === error.details.axis),\n );\n if (owed === undefined) throw error;\n throw new DisjointError(\n {\n nodeId: error.details.newId,\n attemptedKind: owed.refusal.ownKind,\n conflictingKind: error.details.kind,\n },\n { cause: error },\n );\n}\n\n/** Re-raises a planned claim failure through the claim family's typed error. */\nexport function refuseNodeCreateClaimError(\n error: unknown,\n plan: NodeCreateClaimPlan,\n): never {\n if (error instanceof UniquenessError) {\n mapClaimRefusal(error, plan.entries, plan.verdicts);\n }\n throw error;\n}\n\n/**\n * Runs a claim statement, re-raising a foreign owner as the declared refusal of\n * whichever family owed the claim.\n *\n * One wrapper around every claim write, rather than a translation at each of\n * them: a claim statement that skipped it would report a `disjointWith`\n * violation as a uniqueness violation on a constraint name no caller ever\n * declared. Both the CREATE seam's `withNodeCreateClaimsIssuedBy` and the\n * transition seam's {@link claimUniqueKeysThen} reuse it — a resurrect's plan\n * can carry a disjointness entry exactly as a create's claim list does (see\n * {@link planNodeClaimReinsert}), so the transition seam needs the same\n * translation the create seam always did. For a plan whose claims are all\n * uniqueness (an in-place update's diff), `mapClaimRefusal` finds no\n * disjointness entry to remap and rethrows the original `UniquenessError`\n * unchanged, so this is a no-op there.\n */\nasync function issuingClaims(\n entries: readonly NodeClaimEntry[],\n issue: () => Promise<void>,\n): Promise<void> {\n try {\n await issue();\n } catch (error) {\n if (error instanceof UniquenessError) mapClaimRefusal(error, entries);\n throw error;\n }\n}\n\n/**\n * THE refusal for \"this write owes a claim it must issue BEFORE the row that\n * claim gates, and this backend cannot roll that pair back together\".\n *\n * A claim row that outlives the write it was taken for is invisible to every\n * read path and blocks its key forever, with no repair path: `deleteUnique` is\n * reached only by a node whose row exists. So a write that would open that\n * window on a backend with no transactions is refused, exactly as a write whose\n * fence is the per-graph lock has been since the lock became the fence. A\n * claim that follows its row opens no such window — a leaked ENTITY row is\n * visible, deletable, and is what that backend already does today — which is\n * why the subject is the pre-insert group and not the claim set.\n *\n * Takes the ENTRIES this write is about to issue rather than the kind's sites:\n * a row whose `where` predicates all fail writes no claim and must not be\n * refused. For a batch, any member's non-empty pre-insert group makes the batch\n * constrained — the same \"any member\" shape the batch lock probe uses.\n *\n * Delegates the error itself to {@link constraintFenceRefusal}, so there is one\n * refusal body, one code and one advice map.\n */\nfunction claimFenceRefusal(\n ctx: Readonly<{ graphId: string }>,\n backend: GraphBackend | TransactionBackend,\n entries: readonly NodeClaimEntry[],\n): ConfigurationError | undefined {\n const gating = entries.find((entry) => entry.placement === \"pre-insert\");\n if (gating === undefined) return undefined;\n return constraintFenceRefusal(ctx, backend, gating.refusalReason);\n}\n\n/** An entry whose family is uniqueness — the only family a claim probe reads. */\nexport type UniquenessClaimEntry = NodeClaimEntry &\n Readonly<{ refusal: Extract<ClaimRefusal, { kind: \"uniqueness\" }> }>;\n\n/**\n * THE narrowing to the uniqueness family, for every path that probes claim rows.\n *\n * Disjointness entries have their own probe (`checkDisjointnessConstraint`,\n * which reads the NODE rows the constraint is declared over) and deliberately\n * do not get a second one here: a claim-row read would be a second spelling of\n * that verdict, and the two would drift.\n *\n * Exported because it is also what \"an ingestion branch defers node UNIQUENESS\n * and nothing else\" means, operationally: the clone's registrations produce\n * claim entries and this predicate is false for every one of them, while the\n * disjointness entries the same list carries are unaffected (see\n * {@link file://../../graph-merge/working-copy.ts graphWithoutNodeUniqueness}).\n */\nexport function isUniquenessClaimEntry(\n entry: NodeClaimEntry,\n): entry is UniquenessClaimEntry {\n return entry.refusal.kind === \"uniqueness\";\n}\n\n/** One set-oriented uniqueness read shared by every batch probe consumer. */\nexport type NodeUniquenessProbeGroup = Readonly<{\n nodeKind: string;\n constraintName: string;\n keys: readonly string[];\n}>;\n\n/**\n * THE owner of grouping node uniqueness entries into backend batch reads.\n *\n * Preparation-cache priming and post-rollback diagnosis consume the same\n * groups, including every canonical and legacy axis covered by a scoped claim.\n * Keeping the grouping here prevents one path from silently probing a narrower\n * hierarchy than the other.\n */\nexport function groupNodeUniquenessProbes(\n registry: KindRegistry,\n items: readonly Readonly<{\n kind: string;\n entries: readonly NodeClaimEntry[];\n }>[],\n): readonly NodeUniquenessProbeGroup[] {\n type MutableProbeGroup = Readonly<{\n nodeKind: string;\n constraintName: string;\n keys: Set<string>;\n }>;\n const groups = new Map<string, MutableProbeGroup>();\n for (const item of items) {\n for (const entry of item.entries) {\n if (!isUniquenessClaimEntry(entry)) continue;\n for (const nodeKind of uniquenessProbeKinds(\n item.kind,\n entry.refusal.constraint.scope,\n registry,\n )) {\n const identity = encodeTupleKey([nodeKind, entry.constraintName]);\n const group = groups.get(identity) ?? {\n nodeKind,\n constraintName: entry.constraintName,\n keys: new Set<string>(),\n };\n group.keys.add(entry.key);\n groups.set(identity, group);\n }\n }\n }\n return [...groups.values()].map((group) => ({\n nodeKind: group.nodeKind,\n constraintName: group.constraintName,\n keys: [...group.keys],\n }));\n}\n\n/**\n * Probes ONE entry's key across every kind its scope covers, the axis first.\n *\n * THE SINGLE OWNER of \"is this key available to this node?\" — the conflict\n * verdict and the ownership reading are one read, so no caller can consult one\n * without the other. {@link checkUniquenessConstraints} is this probe run for\n * its refusal alone; the plan builders below additionally keep what it read.\n *\n * Ownership is the pair `(concrete_kind, node_id)`, never the id alone: ids are\n * unique only per kind, so a namesake under another kind holds a DIFFERENT\n * node's reservation and must be refused — which is exactly what a scope\n * spanning kinds exists to catch. The refusal reports the holder's concrete\n * kind rather than the axis it was found at, because the axis need not be that\n * node's kind and, after this move, usually is not.\n *\n * @returns whether THIS node already holds the key live AT THE AXIS it is about\n * to claim, in which case a claim would be a no-op and a compensating release\n * would strip a reservation the node is entitled to. A row this node owns at\n * a LEGACY axis deliberately does not suppress the claim: the axis row is a\n * genuinely new reservation whose compensation must run.\n * @throws UniquenessError when a DIFFERENT node holds the key under any kind in\n * scope.\n */\nexport async function probeUniqueKey(\n ctx: UniquenessProbeContext,\n kind: string,\n id: string,\n entry: UniquenessClaimEntry,\n lookup: (\n nodeKind: string,\n entry: UniquenessClaimEntry,\n ) => UniqueRow | undefined | Promise<UniqueRow | undefined> = async (\n nodeKind,\n claimEntry,\n ) =>\n ctx.backend.checkUnique({\n graphId: ctx.graphId,\n nodeKind,\n constraintName: claimEntry.constraintName,\n key: claimEntry.key,\n }),\n): Promise<boolean> {\n // `let` earns its place: the loop must visit EVERY kind in scope to reach its\n // refusal, so the ownership reading cannot be an early return.\n let heldByThisNode = false;\n for (const kindToCheck of uniquenessProbeKinds(\n kind,\n entry.refusal.constraint.scope,\n ctx.registry,\n )) {\n const existing = await lookup(kindToCheck, entry);\n\n if (existing === undefined) continue;\n const refusal = uniquenessClaimRefusal(kind, id, entry, existing);\n if (refusal !== undefined) throw refusal;\n if (kindToCheck === entry.axis) heldByThisNode = true;\n }\n return heldByThisNode;\n}\n\n/**\n * THE owner of the conflict verdict for one uniqueness probe result.\n *\n * The scalar probe and post-rollback batch diagnosis both call this function,\n * so owner-pair equality and the public error payload cannot drift between the\n * portable preflight and the native program's exceptional diagnostic path.\n */\nfunction uniquenessClaimRefusal(\n kind: string,\n id: string,\n entry: UniquenessClaimEntry,\n existing: UniqueRow,\n): UniquenessError | undefined {\n const proposedOwner: ClaimOwner = { concreteKind: kind, nodeId: id };\n if (\n isSameClaimOwner(\n { concreteKind: existing.concrete_kind, nodeId: existing.node_id },\n proposedOwner,\n )\n ) {\n return;\n }\n return new UniquenessError({\n constraintName: entry.constraintName,\n kind: existing.concrete_kind,\n existingId: existing.node_id,\n newId: id,\n fields: entry.refusal.constraint.fields,\n });\n}\n\n/**\n * Checks uniqueness constraints for a new or existing node.\n *\n * @throws ValidationError if any constraint is violated\n */\nexport async function checkUniquenessConstraints(\n ctx: UniquenessProbeContext,\n kind: string,\n id: string,\n props: Record<string, unknown>,\n constraints: readonly UniqueConstraint[],\n): Promise<void> {\n // The create extent, which is the wider of the two: a probe wants every claim\n // this row could owe, and placement — the only thing the operation decides\n // for a uniqueness site — says nothing about what is read. The disjointness\n // entries the create extent also carries belong to the other probe, which\n // reads node rows rather than claim rows.\n for (const entry of nodeClaimEntries(\n ctx.registry,\n kind,\n id,\n props,\n constraints,\n \"create\",\n )) {\n if (isUniquenessClaimEntry(entry))\n await probeUniqueKey(ctx, kind, id, entry);\n }\n}\n\n/**\n * What the create claim seam needs from its caller.\n *\n * `lock` is compile-time evidence that the per-graph write-lock discipline was\n * satisfied BEFORE any row work (see {@link GraphWriteLock}); the seam performs\n * no locking of its own, so requiring the token here makes \"claim before lock\"\n * a type error at the call site instead of a lock-order inversion in review.\n *\n * `claimsVerdict` is the `claims` bundle's memoized, at-most-once verdict\n * thunk (ruling B7 refinement 2). This module's own uniqueness/disjointness\n * claims never read it — they are a different fence family, backed by the\n * `uniques` relation — but `node-write-pipeline.ts`'s hard-delete cascade\n * shares this same context and calls `purgeEdgeClaims` (the `claims` bundle's\n * edge-cardinality housekeeping) off it, so the field lives here rather than\n * on a second, parallel context only that one caller would build.\n */\nexport type NodeClaimContext = Readonly<{\n graphId: string;\n registry: KindRegistry;\n lock: GraphWriteLock;\n claimsVerdict: ClaimsVerdictThunk;\n /** Threaded `uniqueSidecarBatch` verdict — never re-resolved here. */\n uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>;\n}>;\n\n/** One row whose claims a create-shaped write is about to issue. */\nexport type NodeClaimItem = Readonly<{\n kind: string;\n id: string;\n props: Record<string, unknown>;\n constraints: readonly UniqueConstraint[];\n}>;\n\n/**\n * The ownership verdict metadata a planned claim would have produced if the\n * store had read the claim relation first.\n *\n * The authoritative insert uses the claim row's primary key instead of these\n * probe coordinates, but carrying the coordinates with the plan keeps the\n * typed refusal complete: uniqueness errors regain their declared fields, and\n * disjoint errors retain the exact partner kind that made the claim apply.\n */\ntype NodeCreateClaimVerdict =\n | Readonly<{\n claim: NodeInsertClaim;\n probeKinds: readonly string[];\n disjointOtherKind: undefined;\n refusal: Extract<ClaimRefusal, { kind: \"uniqueness\" }>;\n }>\n | Readonly<{\n claim: NodeInsertClaim;\n probeKinds: readonly string[];\n disjointOtherKind: string;\n refusal: Extract<ClaimRefusal, { kind: \"disjointness\" }>;\n }>;\n\nfunction isNodeCreateUniquenessVerdict(\n verdict: NodeCreateClaimVerdict,\n): verdict is Extract<\n NodeCreateClaimVerdict,\n { refusal: { kind: \"uniqueness\" } }\n> {\n return verdict.refusal.kind === \"uniqueness\";\n}\n\n/** One row's claim, with the owner it will be written under. */\ntype PlacedClaim = Readonly<{\n item: NodeClaimItem;\n entry: NodeClaimEntry;\n target: ClaimTarget;\n}>;\n\n/** The complete, canonically ordered claim portion of one node insert plan. */\nexport type NodeCreateClaimPlan = Readonly<{\n entries: readonly NodeClaimEntry[];\n claims: readonly NodeInsertClaim[];\n verdicts: readonly NodeCreateClaimVerdict[];\n}>;\n\n/**\n * How one placement group.s statements are issued.\n *\n * `onIssued` reports which claims actually landed, and it is optional because\n * only the pre-insert group has a use for the answer: that group is compensated\n * when its gated write fails, while a post-insert claim belongs to a row that is\n * already written and has nothing to undo.\n */\ntype ClaimIssuer = (\n ctx: UniquenessContext,\n claims: readonly PlacedClaim[],\n onIssued?: (issued: readonly PlacedClaim[]) => void,\n) => Promise<void>;\n\nfunction claimTarget(graphId: string, entry: NodeClaimEntry): ClaimTarget {\n return {\n relation: \"uniques\",\n graphId,\n axis: entry.axis,\n constraintName: entry.constraintName,\n key: entry.key,\n };\n}\n\nfunction claimInsertParams(\n graphId: string,\n claim: PlacedClaim,\n): InsertUniqueParams {\n return {\n graphId,\n nodeKind: claim.entry.axis,\n constraintName: claim.entry.constraintName,\n key: claim.entry.key,\n nodeId: claim.item.id,\n concreteKind: claim.item.kind,\n };\n}\n\nfunction placedNodeCreateClaims(\n ctx: Pick<NodeClaimContext, \"graphId\" | \"registry\">,\n items: readonly NodeClaimItem[],\n): readonly PlacedClaim[] {\n return items.flatMap((item) =>\n nodeClaimEntries(\n ctx.registry,\n item.kind,\n item.id,\n item.props,\n item.constraints,\n \"create\",\n ).map((entry) => ({\n item,\n entry,\n target: claimTarget(ctx.graphId, entry),\n })),\n );\n}\n\n/**\n * Resolves one create's claims once for either the atomic plan or fallback\n * seam. The returned list preserves the claim-site placement decision and the\n * same canonical target order standalone claim statements use.\n */\nexport function planNodeCreateClaims(\n ctx: Pick<NodeClaimContext, \"graphId\" | \"registry\">,\n item: NodeClaimItem,\n): NodeCreateClaimPlan {\n const placed = placedNodeCreateClaims(ctx, [item]).toSorted((left, right) => {\n if (left.entry.placement !== right.entry.placement) {\n return left.entry.placement === \"pre-insert\" ? -1 : 1;\n }\n return compareClaimTargets(left.target, right.target);\n });\n const verdicts = placed.map((claim) => {\n const baseClaim = {\n axis: claim.entry.axis,\n constraintName: claim.entry.constraintName,\n key: claim.entry.key,\n placement: claim.entry.placement,\n };\n if (claim.entry.refusal.kind === \"uniqueness\") {\n const probeKinds = uniquenessProbeKinds(\n claim.item.kind,\n claim.entry.refusal.constraint.scope,\n ctx.registry,\n );\n return {\n claim: {\n ...baseClaim,\n verdict: {\n kind: \"uniqueness\" as const,\n probeAxes: probeKinds,\n fields: claim.entry.refusal.constraint.fields,\n },\n } satisfies NodeInsertClaim,\n probeKinds,\n disjointOtherKind: undefined,\n refusal: claim.entry.refusal,\n } satisfies NodeCreateClaimVerdict;\n }\n return {\n claim: {\n ...baseClaim,\n verdict: {\n kind: \"disjointness\" as const,\n conflictingKinds: [claim.entry.refusal.otherKind],\n },\n } satisfies NodeInsertClaim,\n probeKinds: [],\n disjointOtherKind: claim.entry.refusal.otherKind,\n refusal: claim.entry.refusal,\n } satisfies NodeCreateClaimVerdict;\n });\n return {\n entries: placed.map((claim) => claim.entry),\n claims: verdicts.map((verdict) => verdict.claim),\n verdicts,\n };\n}\n\n/** One statement per claim — the shape the single-row create path ships. */\nasync function issueClaimsIndividually(\n ctx: UniquenessContext,\n claims: readonly PlacedClaim[],\n onIssued?: (issued: readonly PlacedClaim[]) => void,\n): Promise<void> {\n for (const claim of claims) {\n await issuingClaims([claim.entry], () =>\n ctx.backend.insertUnique(claimInsertParams(ctx.graphId, claim)),\n );\n onIssued?.([claim]);\n }\n}\n\n/**\n * ONE statement for the whole group, which is also what makes it deadlock-free\n * against itself: a single multi-row statement takes its row locks in a fixed\n * order. Falls back to the per-claim shape on a backend with no batch\n * primitive.\n */\nasync function issueClaimsBatched(\n ctx: UniquenessContext,\n claims: readonly PlacedClaim[],\n onIssued?: (issued: readonly PlacedClaim[]) => void,\n): Promise<void> {\n if (claims.length === 0) return;\n const bound = bindExtraIfReachable(\n ctx.backend,\n ctx.uniqueSidecarBatch.extras.insertUniqueBatch,\n UNIQUE_SIDECAR_BATCH.id,\n );\n if (bound === undefined) {\n await issueClaimsIndividually(ctx, claims, onIssued);\n return;\n }\n await issuingClaims(\n claims.map((claim) => claim.entry),\n async () => {\n await bound.insertUniqueBatch(\n claims.map((claim) => claimInsertParams(ctx.graphId, claim)),\n );\n },\n );\n onIssued?.(claims);\n}\n\n/**\n * Reserves the gating group, runs the row write it gates, and gives those\n * reservations back if the write does not land.\n *\n * Compensate, not swallow — the same give-back {@link withNodeClaimTransition}\n * makes, for the same reason: the reservations this write took are returned and\n * the original failure is rethrown, so the caller sees the error it would have\n * seen with no reservation attempted at all. Only rows that actually landed are\n * given back, and each is named in full (owner pair and claim axis), so nothing\n * a namesake under another kind or an older axis holds is touched.\n */\nasync function claimGroupThenWrite<T>(\n ctx: UniquenessContext,\n issue: ClaimIssuer,\n gating: readonly PlacedClaim[],\n gatedWrite: () => Promise<T>,\n): Promise<T> {\n const issued: PlacedClaim[] = [];\n try {\n await issue(ctx, gating, (landed) => {\n issued.push(...landed);\n });\n return await gatedWrite();\n } catch (error) {\n for (const claim of issued.toReversed()) {\n await releaseClaimedUniqueKeys(ctx, claim.item.kind, claim.item.id, [\n {\n axis: claim.entry.axis,\n constraintName: claim.entry.constraintName,\n key: claim.entry.key,\n },\n ]);\n }\n throw error;\n }\n}\n\n/**\n * Issues a create's claims on the two sides of the row write they gate, and\n * compensates the PRE-INSERT ones away if that write does not land.\n *\n * The entries are partitioned by their {@link ClaimPlacement} and the two\n * groups are issued around `gatedInsert`:\n *\n * 1. the `pre-insert` group — the create path's twin of\n * {@link withNodeClaimTransition}, with the same claim → gated write →\n * compensate sequence and the same reasoning: the claim is the only fence\n * for that axis, and a fence issued after the write it fences is not a\n * fence. A refusal here therefore happens with zero rows written, and a\n * refusal from the write compensates the reservations away;\n * 2. `gatedInsert()`;\n * 3. the `post-insert` group — the position those entries ship in, unchanged,\n * and with that position's failure behavior: a throw propagates and nothing\n * compensates it, because the row it belongs to is already written and\n * visible.\n *\n * Each group is sorted by {@link compareClaimTargets} and the pre-insert group\n * is always issued first, so every writer of a given row computes the same\n * acquisition order. A row owing claims in both groups therefore emits two\n * claim statements where one placement alone emits one.\n */\nasync function withNodeCreateClaimsIssuedBy<T>(\n ctx: NodeClaimContext,\n items: readonly NodeClaimItem[],\n backend: GraphBackend | TransactionBackend,\n issue: ClaimIssuer,\n gatedInsert: () => Promise<T>,\n): Promise<T> {\n const claimContext = createUniquenessContext(\n ctx.graphId,\n ctx.registry,\n backend,\n ctx.uniqueSidecarBatch,\n );\n const claims = placedNodeCreateClaims(ctx, items);\n\n const refusal = claimFenceRefusal(\n ctx,\n backend,\n claims.map((claim) => claim.entry),\n );\n if (refusal !== undefined) throw refusal;\n\n const inPlacement = (placement: ClaimPlacement): readonly PlacedClaim[] =>\n claims\n .filter((claim) => claim.entry.placement === placement)\n .toSorted((left, right) =>\n compareClaimTargets(left.target, right.target),\n );\n\n const result = await claimGroupThenWrite(\n claimContext,\n issue,\n inPlacement(\"pre-insert\"),\n gatedInsert,\n );\n await issue(claimContext, inPlacement(\"post-insert\"));\n return result;\n}\n\n/**\n * The create claim seam for ONE row: one statement per claim, matching the\n * statement shape the single-row create path ships.\n */\nexport function withNodeCreateClaims<T>(\n ctx: NodeClaimContext,\n item: NodeClaimItem,\n backend: GraphBackend | TransactionBackend,\n gatedInsert: () => Promise<T>,\n): Promise<T> {\n return withNodeCreateClaimsIssuedBy(\n ctx,\n [item],\n backend,\n issueClaimsIndividually,\n gatedInsert,\n );\n}\n\n/**\n * The create claim seam for a BATCH: one statement per placement group across\n * every row, instead of the per-row statement fan.\n */\nexport function withNodeCreateClaimsBatch<T>(\n ctx: NodeClaimContext,\n items: readonly NodeClaimItem[],\n backend: GraphBackend | TransactionBackend,\n gatedInsert: () => Promise<T>,\n): Promise<T> {\n return withNodeCreateClaimsIssuedBy(\n ctx,\n items,\n backend,\n issueClaimsBatched,\n gatedInsert,\n );\n}\n\n/**\n * The gate for a claim set whose row write has ALREADY been applied — a\n * re-claim after a set update, or a test seeding a reservation.\n *\n * Such a write reaches the seam with nothing left to gate, which is exactly why\n * it owes no pre-insert claim: there is no row write left for a claim to\n * precede. Naming it makes that reading explicit at the call site instead of\n * leaving an inline no-op for a reader to interpret.\n */\nexport function alreadyAppliedRowWrite(): Promise<undefined> {\n return Promise.resolve(undefined);\n}\n\n/**\n * Releases the claims a node being deleted holds — the LIFECYCLE shape: every\n * claim this node owns for each applying constraint's key, at whatever axis the\n * claim sits on.\n */\nexport async function deleteUniquenessEntries(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n props: Record<string, unknown>,\n constraints: readonly UniqueConstraint[],\n): Promise<void> {\n // The create extent: a delete gives back everything a create wrote, so the\n // release must be read from the wider of the two lists.\n await releaseOwnedUniqueKeys(\n ctx,\n kind,\n id,\n nodeClaimEntries(ctx.registry, kind, id, props, constraints, \"create\"),\n );\n}\n\n/**\n * Drops EVERY claim a set of nodes holds under one concrete kind, key-blind, so\n * the rebuild that follows can re-claim from the after-images.\n *\n * The key-blind drop is what a set update needs and the per-key\n * {@link deleteUniquenessEntries} cannot give it: the statement rewrote whole\n * rows without reading their before-images, so nobody knows which keys those\n * rows used to hold. It drops BOTH families — every claim the owner pair holds —\n * which is why the rebuild must go back through {@link withNodeCreateClaimsBatch}\n * rather than a uniqueness-only reinsert.\n *\n * Requiring the member rather than probing it: the only caller\n * ({@link file://../operations/node-write-pipeline.ts applyNodeSetUpdate})\n * refuses the write up front when a constrained kind's backend lacks it, with a\n * code that names the operation. A second fallback here would be a quieter\n * answer to a question already asked.\n */\nexport async function hardDeleteClaimsByNodeIds(\n ctx: UniquenessContext,\n concreteKind: string,\n nodeIds: readonly string[],\n): Promise<void> {\n await requireDefined(\n bindExtraIfReachable(\n ctx.backend,\n ctx.uniqueSidecarBatch.extras.hardDeleteUniquesByNodeIds,\n UNIQUE_SIDECAR_BATCH.id,\n )?.hardDeleteUniquesByNodeIds,\n )({\n graphId: ctx.graphId,\n concreteKind,\n nodeIds,\n });\n}\n\n/**\n * A single constraint's sidecar transition, decided by a plan builder and\n * carried out by {@link withNodeClaimTransition}.\n *\n * The two keys move at DIFFERENT times relative to the primary row write, so\n * they are named for when they move rather than for old/new:\n * `claim` is reserved BEFORE the write (it is the write's conflict gate),\n * `release` is given up AFTER it (it is history the write supersedes).\n */\ntype PendingUniqueMutation = Readonly<{\n constraintName: string;\n /** The key to give up once the primary write lands; undefined = none. */\n release: string | undefined;\n /**\n * The entry to reserve before the primary write; undefined = none, either\n * because the constraint stopped applying or because {@link probeUniqueKey}\n * found this node already holding it live. It is the whole entry rather than\n * a bare key so the compensation names the row this transition wrote instead\n * of re-deriving which axis that was, and so the refusal reads the placement\n * and class the entry's site decided.\n */\n claim: NodeClaimEntry | undefined;\n}>;\n\n/**\n * The sidecar transition a node write owes, decided but not yet performed.\n *\n * Opaque to its holder on purpose: the only thing a caller does with a plan is\n * hand it to {@link withNodeClaimTransition} together with the primary row\n * write it belongs to.\n */\nexport type UniquenessUpdatePlan = readonly PendingUniqueMutation[];\n\n/**\n * Decides the claim changes a node's new props require, WITHOUT writing any of\n * them.\n *\n * Preflights EVERY changed constraint before anything is written. A node can\n * carry several unique constraints; probing them one at a time as they are\n * applied would let a later constraint's conflict throw after earlier sidecars\n * already moved. Probing all of them first means a refusal here happens with\n * zero writes, and the probes are independent per `constraintName`, so one\n * constraint's verdict is unaffected by the others' still-unapplied changes.\n *\n * Handles the cases where a constraint starts applying, stops applying, or\n * keeps applying under a different key.\n *\n * @throws UniquenessError if an updated value is already held by another node\n */\nexport async function planNodeClaimUpdate(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n oldProps: Record<string, unknown>,\n newProps: Record<string, unknown>,\n constraints: readonly UniqueConstraint[],\n): Promise<UniquenessUpdatePlan> {\n // Both sides of the diff are read from the one entries function, so the key\n // a release names is computed exactly the way the key a claim names is.\n const oldKeys = new Map(\n nodeClaimEntries(\n ctx.registry,\n kind,\n id,\n oldProps,\n constraints,\n \"update\",\n ).map((entry) => [entry.constraintName, entry.key]),\n );\n const newEntries = new Map(\n nodeClaimEntries(ctx.registry, kind, id, newProps, constraints, \"update\")\n .filter((entry): entry is UniquenessClaimEntry =>\n isUniquenessClaimEntry(entry),\n )\n .map((entry) => [entry.constraintName, entry]),\n );\n\n const pending: PendingUniqueMutation[] = [];\n for (const constraint of constraints) {\n const oldKey = oldKeys.get(constraint.name);\n const newEntry = newEntries.get(constraint.name);\n\n // No change - constraint didn't apply and still doesn't\n if (oldKey === undefined && newEntry === undefined) continue;\n\n // Key is the same and the constraint still applies - nothing to do\n if (oldKey !== undefined && oldKey === newEntry?.key) continue;\n\n // Probe the new key: refuse a value another node holds, and note a value\n // this node somehow holds already so the transition neither re-claims nor\n // releases it.\n const alreadyHeld =\n newEntry === undefined ? false : (\n await probeUniqueKey(ctx, kind, id, newEntry)\n );\n\n pending.push({\n constraintName: constraint.name,\n release: oldKey,\n claim: newEntry === undefined || alreadyHeld ? undefined : newEntry,\n });\n }\n\n return pending;\n}\n\n/**\n * The plan a RESURRECTING write needs: every applying constraint re-reserved\n * from scratch, uniqueness AND disjointness alike.\n *\n * A tombstoned node holds no live reservations — {@link deleteUniquenessEntries}\n * released them at soft-delete time, reading the wider `\"create\"` extent that\n * already covers both families — so the diff-based {@link planNodeClaimUpdate}\n * cannot be used here: it would skip an unchanged key and leave the revived\n * node holding NO reservation, letting a later create (of this node's own key,\n * or of a disjoint partner under this node's id) silently duplicate the value.\n *\n * Reads its entries at `\"resurrect\"`, the {@link NodeClaimOperation} that owes\n * the same disjointness sites a create owes (see `nodeClaimSites`) — a\n * resurrect brings a node back into existence under its kind exactly as a\n * create does, so it owes the same cross-kind claim. A disjointness entry can\n * never already be held by THIS node (its own reservation was released at\n * soft-delete time, and nothing else could have taken it under this node's\n * OWN id/kind pair), so unlike a uniqueness entry it needs no \"already held by\n * myself\" probe — it is claimed fresh, exactly as a create claims it fresh.\n *\n * @throws UniquenessError if a key this node held was taken while it was\n * tombstoned\n * @throws DisjointError if a disjoint partner now holds this id (translated by\n * {@link claimUniqueKeysThen} from the `UniquenessError` `insertUnique`\n * itself reports)\n */\nexport async function planNodeClaimReinsert(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n props: Record<string, unknown>,\n constraints: readonly UniqueConstraint[],\n): Promise<UniquenessUpdatePlan> {\n const pending: PendingUniqueMutation[] = [];\n for (const entry of nodeClaimEntries(\n ctx.registry,\n kind,\n id,\n props,\n constraints,\n \"resurrect\",\n )) {\n const alreadyHeld =\n isUniquenessClaimEntry(entry) ?\n await probeUniqueKey(ctx, kind, id, entry)\n : false;\n\n pending.push({\n constraintName: entry.constraintName,\n release: undefined,\n claim: alreadyHeld ? undefined : entry,\n });\n }\n return pending;\n}\n\n/** One reservation a release names. */\ntype ReleasableKey = Readonly<{ constraintName: string; key: string }>;\n\n/**\n * A reservation a write actually took, remembered together with the claim axis\n * it was written at so the compensation can name the same row rather than\n * re-deriving it.\n */\ntype ClaimedKey = ReleasableKey & Readonly<{ axis: string }>;\n\n/**\n * LIFECYCLE release: gives up every reservation THIS node holds for each\n * `(constraintName, key)`, in plan order, whatever axis the reservation sits\n * on.\n *\n * Scoping to the owner pair `(concreteKind, id)` rather than to the axis is\n * what lets a claim written under an older axis be released by newer code, and\n * what keeps a namesake — same id, different kind — holding its own.\n */\nasync function releaseOwnedUniqueKeys(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n keys: readonly ReleasableKey[],\n): Promise<void> {\n for (const entry of keys) {\n await ctx.backend.deleteUnique({\n graphId: ctx.graphId,\n constraintName: entry.constraintName,\n key: entry.key,\n concreteKind: kind,\n nodeId: id,\n });\n }\n}\n\n/**\n * COMPENSATING release: undoes exactly the rows a failed write just claimed —\n * the owner's reservation AT the axis it claimed on, and nothing else.\n *\n * Deliberately narrower than {@link releaseOwnedUniqueKeys}: a rollback must\n * touch neither a reservation at another axis that predates this write nor one\n * another node holds. Conflating the two would make a refused write strip\n * claims it never took.\n */\nasync function releaseClaimedUniqueKeys(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n keys: readonly ClaimedKey[],\n): Promise<void> {\n for (const entry of keys) {\n await ctx.backend.deleteUnique({\n graphId: ctx.graphId,\n nodeKind: entry.axis,\n constraintName: entry.constraintName,\n key: entry.key,\n concreteKind: kind,\n nodeId: id,\n });\n }\n}\n\n/**\n * Reserves the plan's new keys, runs the primary row write they gate, and undoes\n * the reservations if that write does not land.\n *\n * Each claim statement runs through {@link issuingClaims} — a resurrect's plan\n * can carry a disjointness entry ({@link planNodeClaimReinsert}), and a foreign\n * owner of THAT reservation must surface as `DisjointError`, not the raw\n * `UniquenessError` `insertUnique` reports for every family alike.\n */\nasync function claimUniqueKeysThen<T>(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n plan: UniquenessUpdatePlan,\n gatedWrite: () => Promise<T>,\n): Promise<T> {\n const claimed: ClaimedKey[] = [];\n try {\n for (const mutation of plan) {\n const claim = mutation.claim;\n if (claim === undefined) continue;\n await issuingClaims([claim], () =>\n ctx.backend.insertUnique({\n graphId: ctx.graphId,\n nodeKind: claim.axis,\n constraintName: mutation.constraintName,\n key: claim.key,\n nodeId: id,\n concreteKind: kind,\n }),\n );\n claimed.push({\n axis: claim.axis,\n constraintName: mutation.constraintName,\n key: claim.key,\n });\n }\n return await gatedWrite();\n } catch (error) {\n // Compensate, not swallow: the reservations this transition took are given\n // back and the original failure is rethrown, so the caller sees the SAME\n // error it would have seen with no reservation attempted at all.\n //\n // The give-back names the exact rows this transition wrote — owner pair and\n // claim axis both — so it can strip neither a reservation at another axis\n // that predates this write nor one a namesake under a different kind holds.\n //\n // The give-back is exact because of what a claim can be. `probeUniqueKey`\n // refuses a key another node holds and reports one THIS node already holds\n // (which the plan then does not claim), so every claimed key was free or\n // tombstoned beforehand and releasing it restores precisely that. And no\n // peer can have taken it in between: this transaction holds the row.\n //\n // One detail is restored in kind rather than exactly: a claim that took over\n // a TOMBSTONED reservation rewrites its recorded owner, and the give-back\n // re-tombstones it under THIS node's id instead of the previous holder's.\n // The key reads as free either way — `checkUnique` skips tombstoned rows —\n // and the one reader that looks at them, `getOrCreateByConstraint`'s\n // resurrect-by-key lookup, writes the props it was called with onto whatever\n // row it revives, so the reservation and the row holding the value stay\n // consistent. Which tombstone that lookup revives can differ. If the\n // compensation itself fails the row is genuinely half-written, and the\n // error that then surfaces is a raw backend failure no per-row consumer\n // catches — the enclosing transaction aborts, which is the only honest\n // outcome left.\n await releaseClaimedUniqueKeys(ctx, kind, id, claimed);\n throw error;\n }\n}\n\n/**\n * Runs one node's primary row write with its claim transition wrapped around\n * it, so the pair commits or fails AS ONE UNIT.\n *\n * ## Why the sequence is claim, gate, release\n *\n * A node update is two independently fallible writes — the row itself and its\n * claim rows — with no rollback between them: nothing here is\n * savepoint-protected (see `operations/write-transaction.ts`), and the backends\n * this supports do not all have savepoints to reach for. Sequencing is the only\n * atomicity available, and only ONE sequence makes both failures leave zero net\n * effect:\n *\n * - **Claim first.** `insertUnique` is an upsert that reports the key's final\n * owner, so claiming IS the conflict gate — and once this transaction holds\n * the row, no concurrent writer can take the key from under it. Probing and\n * then claiming later leaves a window (wide open under PostgreSQL READ\n * COMMITTED, where a peer commits between the two) in which the claim fails\n * AFTER the row was already updated.\n * - **Then the row write.** It can legitimately match nothing —\n * `expectedValidFrom`, `deleted_at` — and callers that catch that per row and\n * commit the rest (interchange import) must not be left with reservations for\n * a row that never changed. A refusal here compensates the claims away.\n * - **Release last.** Giving up the old key before the row write would free a\n * value for a write that may never land; giving it up after is safe because\n * nothing can fail on it.\n *\n * The predecessor of this helper ordered the whole sidecar transition after the\n * row write, which closed the second failure and left the first: a caught\n * `UniquenessError` then reported `updated: 0` for a row whose props HAD\n * changed, whose old reservation was gone, and whose new one belonged to someone\n * else.\n *\n * Because that sequence is claim-first for EVERY scope, every claim this seam\n * issues is `pre-insert`, and a backend that cannot roll the pair back together\n * is refused before the first of them — see {@link claimFenceRefusal}. The\n * subject is the plan's claims rather than the kind's constraints: an update\n * that does not move a key issues no reservation and must not be refused.\n */\nexport async function withNodeClaimTransition<T>(\n ctx: UniquenessContext,\n kind: string,\n id: string,\n plan: UniquenessUpdatePlan,\n gatedWrite: () => Promise<T>,\n): Promise<T> {\n const refusal = claimFenceRefusal(\n ctx,\n ctx.backend,\n plan.flatMap((mutation) =>\n mutation.claim === undefined ? [] : [mutation.claim],\n ),\n );\n if (refusal !== undefined) throw refusal;\n\n const result = await claimUniqueKeysThen(ctx, kind, id, plan, gatedWrite);\n await releaseOwnedUniqueKeys(\n ctx,\n kind,\n id,\n plan.flatMap((mutation) =>\n mutation.release === undefined ?\n []\n : [{ constraintName: mutation.constraintName, key: mutation.release }],\n ),\n );\n return result;\n}\n","/**\n * Node claims for a RESOLVED WRITE SET — a whole after-image validated at once,\n * then applied.\n *\n * Every other claim path in this directory decides one row at a time, which is\n * what an ordinary write is. Two callers instead know their complete final state\n * before writing any of it — a graph merge's resolved plan\n * ({@link file://../../graph-merge/merge.ts}) and a set update\n * ({@link file://../operations/node-operations.ts}) — and for them \"one row at a\n * time\" is the wrong verdict: an atomic SWAP of two nodes' keys, or a handoff of\n * one key from a node the set deletes to a node the set writes, is legal in the\n * final state and refused by every intermediate one.\n *\n * So this module reads the set's claims TOGETHER, decides them against each\n * other first and the persisted relation second, and treats every reservation\n * the set itself releases as available. It decides nothing on its own: the\n * entries come from {@link nodeClaimEntries}, the axis fold from\n * {@link uniquenessProbeKinds}, the ownership verdict from\n * {@link isSameClaimOwner} / {@link claimOwnerKey}, and the rebuild from the\n * same claim writer every create-shaped write uses.\n */\nimport { bindExtraIfReachable } from \"../../backend/capabilities/bind\";\nimport { UNIQUE_SIDECAR_BATCH } from \"../../backend/capabilities/bundle-registry\";\nimport { requireExtras } from \"../../backend/capabilities/resolve\";\nimport { type UniqueConstraint } from \"../../core/types\";\nimport { ConfigurationError, UniquenessError } from \"../../errors\";\nimport { encodeTupleKey } from \"../../utils/tuple-key\";\nimport {\n type ClaimOwner,\n claimOwnerKey,\n isSameClaimOwner,\n uniquenessProbeKinds,\n} from \"./axis\";\nimport {\n alreadyAppliedRowWrite,\n isUniquenessClaimEntry,\n type NodeClaimContext,\n nodeClaimEntries,\n type UniquenessClaimEntry,\n type UniquenessContext,\n withNodeCreateClaimsBatch,\n} from \"./node-claims\";\n\n/** A complete node after-image whose claims belong to one resolved write set. */\nexport type ResolvedNodeUpsert = Readonly<{\n kind: string;\n id: string;\n props: Readonly<Record<string, unknown>>;\n constraints: readonly UniqueConstraint[];\n}>;\n\n/** A node whose current claims the resolved write set gives back. */\nexport type ResolvedNodeRelease = Readonly<{\n kind: string;\n id: string;\n}>;\n\n/**\n * One uniqueness claim the set proposes: who takes it, the row it writes, and\n * the rows its probe reads.\n *\n * `probeKinds` is carried rather than recomputed because it is BOTH halves of\n * the conflict test — the persisted probe issues one read per member, and the\n * in-set test asks whether one claim's write lands in another claim's read set.\n */\ntype ProposedClaim = Readonly<{\n owner: ClaimOwner;\n entry: UniquenessClaimEntry;\n probeKinds: readonly string[];\n}>;\n\n/** The claim rows two proposals share a competition for. */\nfunction claimRowKey(entry: UniquenessClaimEntry): string {\n return encodeTupleKey([entry.constraintName, entry.key]);\n}\n\n/**\n * Whether two proposals in one set are competing — one writes a row the other\n * reads.\n *\n * Reachability in EITHER direction, not axis equality: after the axis fold a\n * `kind`-scoped constraint writes under the writer's own kind while a\n * `kindWithSubClasses` constraint of the same name writes under the component's\n * fold, so two claims can compete without sharing an axis. The wider scope's\n * probe is what would have caught the narrower one's row had it been persisted,\n * and inside one set neither row is persisted yet — which is the whole reason\n * this test exists rather than leaving it to the relation.\n */\nfunction claimsCompete(left: ProposedClaim, right: ProposedClaim): boolean {\n return (\n claimRowKey(left.entry) === claimRowKey(right.entry) &&\n (right.probeKinds.includes(left.entry.axis) ||\n left.probeKinds.includes(right.entry.axis))\n );\n}\n\nfunction proposedClaimRefusal(\n incumbent: ProposedClaim,\n challenger: ProposedClaim,\n): UniquenessError {\n return new UniquenessError({\n constraintName: challenger.entry.constraintName,\n kind: incumbent.owner.concreteKind,\n existingId: incumbent.owner.nodeId,\n newId: challenger.owner.nodeId,\n fields: challenger.entry.refusal.constraint.fields,\n });\n}\n\n/**\n * The set's uniqueness claims, with every in-set competition already refused.\n *\n * Reads its work from {@link nodeClaimEntries} at the CREATE extent — the wider\n * of the two, exactly as {@link file://./node-claims.ts checkUniquenessConstraints}\n * does — and narrows to the uniqueness family. The disjointness entries the same\n * list carries are NOT probed here: they have their own probe over node rows,\n * and each write inside the set's `apply()` reaches it. Filtering rather than\n * asking for a narrower list is what keeps that omission a stated decision\n * instead of an absence nobody notices.\n *\n * @throws UniquenessError when two members of the set compete for one claim.\n */\nfunction proposedClaims(\n ctx: UniquenessContext,\n upserts: readonly ResolvedNodeUpsert[],\n): readonly ProposedClaim[] {\n const accepted: ProposedClaim[] = [];\n for (const upsert of upserts) {\n const owner: ClaimOwner = {\n concreteKind: upsert.kind,\n nodeId: upsert.id,\n };\n const entries = nodeClaimEntries(\n ctx.registry,\n upsert.kind,\n upsert.id,\n { ...upsert.props },\n upsert.constraints,\n \"create\",\n );\n for (const entry of entries) {\n if (!isUniquenessClaimEntry(entry)) continue;\n const proposal: ProposedClaim = {\n owner,\n entry,\n probeKinds: uniquenessProbeKinds(\n upsert.kind,\n entry.refusal.constraint.scope,\n ctx.registry,\n ),\n };\n const incumbent = accepted.find(\n (candidate) =>\n !isSameClaimOwner(candidate.owner, proposal.owner) &&\n claimsCompete(candidate, proposal),\n );\n if (incumbent !== undefined) {\n throw proposedClaimRefusal(incumbent, proposal);\n }\n accepted.push(proposal);\n }\n }\n return accepted;\n}\n\n/** One `checkUniqueBatch` round trip: every key this set claims at one axis. */\ntype ClaimProbeGroup = Readonly<{\n probeKind: string;\n constraintName: string;\n claimsByKey: ReadonlyMap<string, ProposedClaim>;\n}>;\n\n/**\n * Folds the proposals into one probe per `(kind in scope, constraint)`.\n *\n * Keyed on {@link uniquenessProbeKinds} rather than on the axis alone for the\n * reason that function documents: rows written before the axis move sit under\n * their own concrete kind, so a probe that read only the axis would not see them\n * and the move would need a data migration.\n */\nfunction groupClaimsForProbe(\n claims: readonly ProposedClaim[],\n): readonly ClaimProbeGroup[] {\n const groups = new Map<\n string,\n {\n probeKind: string;\n constraintName: string;\n claimsByKey: Map<string, ProposedClaim>;\n }\n >();\n for (const claim of claims) {\n for (const probeKind of claim.probeKinds) {\n const groupKey = encodeTupleKey([probeKind, claim.entry.constraintName]);\n const existing = groups.get(groupKey);\n if (existing === undefined) {\n groups.set(groupKey, {\n probeKind,\n constraintName: claim.entry.constraintName,\n claimsByKey: new Map([[claim.entry.key, claim]]),\n });\n continue;\n }\n existing.claimsByKey.set(claim.entry.key, claim);\n }\n }\n return [...groups.values()];\n}\n\n/**\n * The batch probe this validation is defined in terms of, or a typed refusal.\n *\n * Keyed on this ONE extra's own presence, not the operation's full 3-extra\n * `requires` set: widening this to `missingRequiredExtras` would move\n * {@link prepareResolvedNodeClaims}'s refusal earlier for\n * `validateResolvedNodeClaims`'s direct caller\n * ({@link file://../operations/node-write-pipeline.ts applyNodeSetUpdate}),\n * which probes and refuses on the full set itself before reaching this call.\n *\n * Binds through {@link bindExtraIfReachable}, not {@link bindExtra}: this\n * refusal is keyed on \"is the probe reachable at all\" — the verdict says\n * present AND the port (`ctx.backend`, the transaction target the call\n * actually executes on) can serve it — and either failure mode collapses\n * into this SAME typed refusal, preserved byte-for-byte from before the\n * capability model existed\n * (`tests/graph-merge/ingestion-branch.test.ts`'s \"refuses final validation\n * when the target transaction lacks batch uniqueness operations\" pins a\n * transaction target narrower than the verdict it was resolved against, and\n * still expects this exact code). `bindExtra`'s generic\n * `BUNDLE_PORT_SURFACE_MISMATCH` would replace that pinned, operation-specific\n * message with the bundle's own — an acceptable disposition for a call site\n * with no existing refusal to preserve, but not for this one.\n */\nfunction requireBatchProbe(\n ctx: UniquenessContext,\n): NonNullable<UniquenessContext[\"backend\"][\"checkUniqueBatch\"]> {\n const bound = bindExtraIfReachable(\n ctx.backend,\n ctx.uniqueSidecarBatch.extras.checkUniqueBatch,\n UNIQUE_SIDECAR_BATCH.id,\n );\n if (bound === undefined) {\n throw new ConfigurationError(\n \"Resolved node writes require batched uniqueness probes\",\n { code: \"RESOLVED_NODE_UNIQUENESS_UNSUPPORTED\" },\n );\n }\n return bound.checkUniqueBatch;\n}\n\n/**\n * Validates node uniqueness against the FINAL state of a resolved write set.\n *\n * All proposed after-images are compared together before persisted claim rows\n * are consulted. Owners the set itself releases or replaces are ignored, which\n * permits atomic swaps and handoffs while still refusing every owner outside the\n * set. The probe is batch-only by contract: a caller that needs this set\n * semantic must not quietly degrade to sequential checks.\n */\nexport async function validateResolvedNodeClaims(\n ctx: UniquenessContext,\n upserts: readonly ResolvedNodeUpsert[],\n releases: readonly ResolvedNodeRelease[] = [],\n): Promise<void> {\n const checkUniqueBatch = requireBatchProbe(ctx);\n const claims = proposedClaims(ctx, upserts);\n if (claims.length === 0) return;\n\n const affectedOwners = new Set(\n [...upserts, ...releases].map((reference) =>\n claimOwnerKey({ concreteKind: reference.kind, nodeId: reference.id }),\n ),\n );\n for (const group of groupClaimsForProbe(claims)) {\n const existingRows = await checkUniqueBatch({\n graphId: ctx.graphId,\n nodeKind: group.probeKind,\n constraintName: group.constraintName,\n keys: [...group.claimsByKey.keys()],\n });\n for (const existing of existingRows) {\n if (\n affectedOwners.has(\n claimOwnerKey({\n concreteKind: existing.concrete_kind,\n nodeId: existing.node_id,\n }),\n )\n ) {\n continue;\n }\n const claim = group.claimsByKey.get(existing.key);\n if (claim === undefined) continue;\n throw new UniquenessError({\n constraintName: group.constraintName,\n // The holder's own kind, never `group.probeKind`: that is the claim\n // AXIS, which a shared scope folds across kinds and which the caller\n // never wrote. The probe and the fence report the same value.\n kind: existing.concrete_kind,\n existingId: existing.node_id,\n newId: claim.owner.nodeId,\n fields: claim.entry.refusal.constraint.fields,\n });\n }\n }\n}\n\n/**\n * Prepares a transaction to apply a resolved write set row by row.\n *\n * Validation happens before any mutation. Once it succeeds, every affected\n * node's claims are batch-cleared so the later per-node upserts can take the\n * validated final keys in any order (including swaps and handoffs).\n */\nfunction resolvedNodeUniquenessOperationsRefusal(): ConfigurationError {\n return new ConfigurationError(\n \"Resolved node writes require batched uniqueness operations\",\n { code: \"RESOLVED_NODE_UNIQUENESS_UNSUPPORTED\" },\n );\n}\n\nasync function prepareResolvedNodeClaims(\n ctx: UniquenessContext,\n upserts: readonly ResolvedNodeUpsert[],\n releases: readonly ResolvedNodeRelease[],\n): Promise<void> {\n requireExtras(\n UNIQUE_SIDECAR_BATCH,\n ctx.uniqueSidecarBatch,\n \"resolved node write\",\n () => {\n throw resolvedNodeUniquenessOperationsRefusal();\n },\n );\n // The verdict-level check above can pass while the PORT this call actually\n // executes on (`ctx.backend`, a transaction target) still lacks the member —\n // `bindExtraIfReachable` catches that case too, collapsing both into the\n // same pinned refusal rather than the bundle's generic port-mismatch code\n // (see `requireBatchProbe`'s note on the same tradeoff, below).\n const boundHardDelete = bindExtraIfReachable(\n ctx.backend,\n ctx.uniqueSidecarBatch.extras.hardDeleteUniquesByNodeIds,\n UNIQUE_SIDECAR_BATCH.id,\n );\n if (boundHardDelete === undefined) {\n throw resolvedNodeUniquenessOperationsRefusal();\n }\n const { hardDeleteUniquesByNodeIds } = boundHardDelete;\n // Same port re-check for `insertUniqueBatch`, done here rather than left to\n // `applyResolvedNodeClaims`'s later `withNodeCreateClaimsBatch` rebuild: that\n // call reaches the member only through the shared, fallback-dispositioned\n // `issueClaimsBatched` (`node-claims.ts`), which silently degrades to\n // per-row inserts on a port mismatch instead of refusing — the right answer\n // for a plain create, but not for this REFUSE operation. Checked before the\n // hard-delete below runs, so a refusal here still leaves no claim dropped.\n if (\n bindExtraIfReachable(\n ctx.backend,\n ctx.uniqueSidecarBatch.extras.insertUniqueBatch,\n UNIQUE_SIDECAR_BATCH.id,\n ) === undefined\n ) {\n throw resolvedNodeUniquenessOperationsRefusal();\n }\n await validateResolvedNodeClaims(ctx, upserts, releases);\n\n const idsByKind = new Map<string, Set<string>>();\n for (const reference of [...upserts, ...releases]) {\n const ids = idsByKind.get(reference.kind) ?? new Set<string>();\n ids.add(reference.id);\n idsByKind.set(reference.kind, ids);\n }\n for (const [concreteKind, nodeIds] of idsByKind) {\n await hardDeleteUniquesByNodeIds({\n graphId: ctx.graphId,\n concreteKind,\n nodeIds: [...nodeIds],\n });\n }\n}\n\n/**\n * Applies a resolved write set between the set preflight and one final claim\n * rebuild.\n *\n * The rebuild is required even though ordinary upserts take their own claims: an\n * unchanged upsert may be coalesced and skip all of its normal side effects\n * after preparation cleared its reservations. Re-taking every approved claim is\n * idempotent and makes the transition independent of whether individual writes\n * were coalesced.\n *\n * It goes through {@link withNodeCreateClaimsBatch} — the claim writer every\n * create-shaped write uses — and not through a uniqueness-only insert, for a\n * reason the preparation step makes load-bearing: `hardDeleteUniquesByNodeIds`\n * clears every claim the affected nodes OWN, and after WS2 that includes their\n * `disjointWith` reservations. A rebuild that restored only the uniqueness\n * family would leave each merged node unfenced against a disjoint namesake for\n * the rest of the graph's life. The claim writer restores what\n * {@link nodeClaimEntries} says the row owes, both families, so the set's claims\n * cannot fall out of step with an ordinary create's.\n *\n * `lock` is the caller's evidence that the per-graph write lock was taken before\n * any row work; this function performs no locking of its own.\n */\nexport async function applyResolvedNodeClaims<Output>(\n ctx: NodeClaimContext,\n backend: UniquenessContext[\"backend\"],\n upserts: readonly ResolvedNodeUpsert[],\n releases: readonly ResolvedNodeRelease[],\n apply: () => Promise<Output>,\n): Promise<Output> {\n const claimContext: UniquenessContext = {\n graphId: ctx.graphId,\n registry: ctx.registry,\n backend,\n uniqueSidecarBatch: ctx.uniqueSidecarBatch,\n };\n await prepareResolvedNodeClaims(claimContext, upserts, releases);\n const result = await apply();\n await withNodeCreateClaimsBatch(\n ctx,\n upserts.map((upsert) => ({\n kind: upsert.kind,\n id: upsert.id,\n props: { ...upsert.props },\n constraints: upsert.constraints,\n })),\n backend,\n alreadyAppliedRowWrite,\n );\n return result;\n}\n","/**\n * Embedding Sync Utilities\n *\n * Handles automatic synchronization of embedding fields with the embeddings table.\n * When nodes with embedding properties are created, updated, or deleted,\n * these utilities ensure the embeddings table stays in sync.\n */\nimport { type z } from \"zod\";\n\nimport type { AtomicNodeProjection } from \"../backend/capabilities/atomic-mutation-program\";\nimport {\n type GraphBackend,\n type NodeInsertProjection,\n type TransactionBackend,\n} from \"../backend/types\";\nimport {\n type ResolvedEmbeddingField,\n resolveEmbeddingFields,\n} from \"../core/embedding\";\nimport { readOwnProperty } from \"../utils/object\";\n\n// ============================================================\n// Types\n// ============================================================\n\n/**\n * Information about an embedding field in a node schema.\n *\n * Re-exports the canonical {@link ResolvedEmbeddingField} so the backend\n * gets `dimensions` plus the resolved index `(metric, indexType)` — all\n * three needed to address the field's typed per-`(kind, field)` storage\n * slot when upserting.\n */\ntype EmbeddingFieldInfo = ResolvedEmbeddingField;\n\n/**\n * Context for embedding sync operations.\n */\nexport type EmbeddingSyncContext = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n backend: GraphBackend | TransactionBackend;\n}>;\n\ntype EmbeddingProjectionDecision =\n | Readonly<{ kind: \"upsert\"; embedding: readonly number[] }>\n | Readonly<{ kind: \"delete\" }>\n | Readonly<{ kind: \"ignore\" }>;\n\n/** The single owner for how stored embedding values affect projection state. */\nfunction resolveEmbeddingProjectionDecision(\n value: unknown,\n): EmbeddingProjectionDecision {\n if (isValidEmbeddingValue(value)) {\n return { kind: \"upsert\", embedding: value };\n }\n return value === undefined ? { kind: \"delete\" } : { kind: \"ignore\" };\n}\n\n// ============================================================\n// Schema Introspection\n// ============================================================\n\n/**\n * Cache keyed by the Zod schema instance. Schemas are immutable at\n * runtime; the same reference recurs across every CRUD call.\n */\nconst embeddingFieldsCache = new WeakMap<\n z.ZodType,\n readonly EmbeddingFieldInfo[]\n>();\n\n/**\n * Extracts embedding field information from a Zod schema.\n * Returns all embedding fields found at the top level of an object schema.\n *\n * Thin per-schema-instance memoization over the canonical\n * {@link resolveEmbeddingFields}; the same schema reference recurs across\n * every CRUD call, so caching avoids re-walking the shape each time.\n */\nexport function getEmbeddingFields(\n schema: z.ZodType,\n): readonly EmbeddingFieldInfo[] {\n const cached = embeddingFieldsCache.get(schema);\n if (cached) return cached;\n const fields = resolveEmbeddingFields(schema);\n embeddingFieldsCache.set(schema, fields);\n return fields;\n}\n\n// ============================================================\n// Embedding Sync Operations\n// ============================================================\n\n/**\n * Resolves the present embedding sidecar for a fresh generated-id node.\n * Missing optional values are intentionally omitted because no row can exist\n * for a generated id before this insert. Caller-supplied ids use the regular\n * sync path, which retains its delete semantics for missing values.\n */\nexport function resolveNodeEmbeddingProjections(\n schema: z.ZodType,\n props: Record<string, unknown>,\n): readonly NodeInsertProjection[] {\n return getEmbeddingFields(schema).flatMap(\n (field): readonly NodeInsertProjection[] => {\n const value = readOwnProperty(props, field.fieldPath);\n const decision = resolveEmbeddingProjectionDecision(value);\n return decision.kind === \"upsert\" ?\n [\n {\n kind: \"embedding\",\n fieldPath: field.fieldPath,\n embedding: decision.embedding,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n },\n ]\n : [];\n },\n );\n}\n\n/**\n * Resolves every embedding transition owed by a replacement postimage.\n * Unlike fresh generated-id insertion, an absent value is an explicit delete:\n * caller-id resurrection and updates may be replacing an older projection.\n */\nexport function resolveNodeEmbeddingProjectionTransitions(\n schema: z.ZodType,\n props: Record<string, unknown>,\n options?: Readonly<{ omitDeletes?: boolean }>,\n): readonly AtomicNodeProjection[] {\n return getEmbeddingFields(schema).flatMap(\n (field): readonly AtomicNodeProjection[] => {\n const value = readOwnProperty(props, field.fieldPath);\n const common = {\n kind: \"embedding\" as const,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n };\n const decision = resolveEmbeddingProjectionDecision(value);\n if (decision.kind === \"upsert\") {\n return [\n {\n ...common,\n action: \"upsert\" as const,\n embedding: decision.embedding,\n },\n ];\n }\n return decision.kind === \"delete\" && options?.omitDeletes !== true ?\n [{ ...common, action: \"delete\" as const }]\n : [];\n },\n );\n}\n\n/**\n * Syncs embeddings after a node create or update operation.\n *\n * For each embedding field in the schema:\n * - If the props contain an embedding value, upsert it to the embeddings table\n * - If the props don't contain an embedding value (undefined), delete any existing embedding\n */\nexport async function syncEmbeddings(\n ctx: EmbeddingSyncContext,\n schema: z.ZodType,\n props: Record<string, unknown>,\n): Promise<void> {\n const { backend } = ctx;\n\n // Check if backend supports embedding operations\n if (!backend.upsertEmbedding || !backend.deleteEmbedding) {\n return;\n }\n\n const embeddingFields = getEmbeddingFields(schema);\n if (embeddingFields.length === 0) {\n return;\n }\n\n for (const field of embeddingFields) {\n const value = readOwnProperty(props, field.fieldPath);\n\n const decision = resolveEmbeddingProjectionDecision(value);\n if (decision.kind === \"upsert\") {\n // Upsert the embedding\n await backend.upsertEmbedding({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n fieldPath: field.fieldPath,\n embedding: decision.embedding,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n } else if (decision.kind === \"delete\") {\n // Delete any existing embedding for this field\n await backend.deleteEmbedding({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n }\n // If value is null or invalid, skip (validation should have caught this)\n }\n}\n\n/**\n * Syncs embeddings for a batch of same-kind node creates through one\n * `upsertEmbeddingBatch` per field (falling back to per-row\n * `upsertEmbedding` when the backend lacks the batch primitive). Mirrors\n * `syncEmbeddings` per row: present values upsert, `undefined` values\n * delete any existing embedding for the field.\n */\nexport async function syncEmbeddingsBatchForKind(\n args: Readonly<{\n graphId: string;\n nodeKind: string;\n backend: GraphBackend | TransactionBackend;\n }>,\n schema: z.ZodType,\n items: readonly Readonly<{\n nodeId: string;\n props: Record<string, unknown>;\n }>[],\n): Promise<void> {\n const { graphId, nodeKind, backend } = args;\n if (!backend.upsertEmbedding || !backend.deleteEmbedding) {\n return;\n }\n\n const embeddingFields = getEmbeddingFields(schema);\n if (embeddingFields.length === 0) {\n return;\n }\n\n for (const field of embeddingFields) {\n const rows: { nodeId: string; embedding: readonly number[] }[] = [];\n const deletionIds: string[] = [];\n for (const item of items) {\n const value = readOwnProperty(item.props, field.fieldPath);\n const decision = resolveEmbeddingProjectionDecision(value);\n if (decision.kind === \"upsert\") {\n rows.push({ nodeId: item.nodeId, embedding: decision.embedding });\n } else if (decision.kind === \"delete\") {\n deletionIds.push(item.nodeId);\n }\n }\n\n if (rows.length > 0) {\n if (backend.upsertEmbeddingBatch === undefined) {\n for (const row of rows) {\n await backend.upsertEmbedding({\n graphId,\n nodeKind,\n nodeId: row.nodeId,\n fieldPath: field.fieldPath,\n embedding: row.embedding,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n }\n } else {\n await backend.upsertEmbeddingBatch({\n graphId,\n nodeKind,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n rows,\n });\n }\n }\n\n if (deletionIds.length > 0 && backend.deleteEmbeddingBatch !== undefined) {\n await backend.deleteEmbeddingBatch({\n graphId,\n nodeKind,\n nodeIds: deletionIds,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n } else {\n for (const nodeId of deletionIds) {\n await backend.deleteEmbedding({\n graphId,\n nodeKind,\n nodeId,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n }\n }\n }\n}\n\n/**\n * Deletes a node's embeddings for the embedding fields its kind CURRENTLY\n * declares. A field dropped from the schema after the node was written is\n * intentionally NOT swept here — its entire per-field table is reclaimed\n * wholesale by `store.materializeRemovals()` (the deferred-cleanup verb), which\n * also covers live (never-deleted) nodes' rows. So a hard/soft delete can leave\n * a transient orphan row in a removed field's table until the next reclaim pass;\n * that is the deferred-cleanup design, not a leak.\n */\nexport async function deleteNodeEmbeddings(\n ctx: EmbeddingSyncContext,\n schema: z.ZodType,\n): Promise<void> {\n const { backend } = ctx;\n\n // Check if backend supports embedding operations\n if (!backend.deleteEmbedding) {\n return;\n }\n\n const embeddingFields = getEmbeddingFields(schema);\n if (embeddingFields.length === 0) {\n return;\n }\n\n for (const field of embeddingFields) {\n await backend.deleteEmbedding({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n fieldPath: field.fieldPath,\n dimensions: field.dimensions,\n metric: field.metric,\n indexType: field.indexType,\n });\n }\n}\n\n// ============================================================\n// Validation Helpers\n// ============================================================\n\n/**\n * Checks if a value is a valid embedding (array of numbers).\n */\nfunction isValidEmbeddingValue(value: unknown): value is readonly number[] {\n if (!Array.isArray(value)) {\n return false;\n }\n return value.every((n) => typeof n === \"number\" && Number.isFinite(n));\n}\n","/**\n * Keeps the fulltext index in sync with node data. One row per node:\n * the values of every `searchable()` field are concatenated (joined by\n * `\\n`) and stored as the indexed `content`, so a single FTS query can\n * match terms spanning multiple source fields — which a per-field\n * layout cannot, since FTS5 / Postgres MATCH require all terms in one\n * indexed document.\n *\n * Sync runs inline in the node-operation call path, so it inherits the\n * caller's transaction context.\n */\nimport { type z } from \"zod\";\n\nimport { resolveBackendFulltext } from \"../backend/capabilities/fulltext\";\nimport {\n type GraphBackend,\n type NodeFulltextSync,\n type NodeInsertProjection,\n type TransactionBackend,\n} from \"../backend/types\";\nimport {\n DEFAULT_SEARCHABLE_LANGUAGE,\n getSearchableFields,\n type SearchableFieldInfo,\n} from \"../core/searchable\";\nimport {\n ConfigurationError,\n UnsupportedBackendCapabilityError,\n} from \"../errors\";\nimport { readOwnProperty } from \"../utils/object\";\n\nexport { getSearchableFields } from \"../core/searchable\";\n\nexport type FulltextSyncContext = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n backend: GraphBackend | TransactionBackend;\n}>;\n\nconst FIELD_SEPARATOR = \"\\n\";\n\n/**\n * Refuses with a typed error, rather than silently dropping the write, when\n * a node kind declares `searchable()` fields but `resolveBackendFulltext`\n * reports the backend has no fulltext support at all (`fulltext: false`).\n * Used by `syncFulltext` / `syncFulltextBatchForKind` on the create/update\n * paths, where an unavailable backend cannot honor the write. Deletes are\n * exempt: a fulltext-off backend maintains no sidecar to remove a row\n * from, so `deleteNodeFulltext` succeeds instead of refusing.\n *\n * Exported for the set-based update paths (`executeNodeSetUpdate` /\n * `applyNodeSetUpdate`), which reach the same \"unavailable\" branch ahead of\n * their own batch-member presence checks, and so need the same refusal\n * without duplicating its error shape.\n */\nexport function refuseFulltextUnavailable(\n backend: GraphBackend | TransactionBackend,\n nodeKind: string,\n): never {\n throw new UnsupportedBackendCapabilityError(\n `Node kind \"${nodeKind}\" declares searchable() fields`,\n \"fulltext\",\n { backend: backend.dialect, nodeKind, reason: \"fulltext_unsupported\" },\n \"This backend declares no fulltext capability. Remove the \" +\n \"searchable() declaration, or use a backend with fulltext support.\",\n );\n}\n\n/**\n * Narrows an optional fulltext member to defined. Called only after\n * `resolveBackendFulltext` has already confirmed the backend declares\n * fulltext support, so a member missing at this point is not an\n * availability decision but a backend contract violation — a bundled\n * backend never reaches this, and a third-party one that declares the\n * capability without the member gets a `ConfigurationError` naming exactly\n * which member is missing, not `refuseFulltextUnavailable`'s\n * capability-absent error.\n */\nexport function assertFulltextMember<T>(\n member: T | undefined,\n memberName: string,\n backend: GraphBackend | TransactionBackend,\n): asserts member is T {\n if (member !== undefined) return;\n throw new ConfigurationError(\n `Backend declares a fulltext capability but is missing the \"${memberName}\" member`,\n {\n backend: backend.dialect,\n capability: \"fulltext\",\n missingMember: memberName,\n },\n );\n}\n\n/**\n * Picks a representative language when a node has searchable fields with\n * different language settings. Users who need true per-field\n * multilingual indexing should split the data across node kinds.\n */\nfunction resolveCombinedLanguage(\n fields: readonly SearchableFieldInfo[],\n): string {\n return fields[0]?.metadata.language ?? DEFAULT_SEARCHABLE_LANGUAGE;\n}\n\n/**\n * Computes the combined fulltext content for a node, or `undefined`\n * if the node has no non-empty searchable fields.\n *\n * Shared between `syncFulltext` (per-write) and `rebuildFulltextIndex`\n * (bulk) so the two never drift.\n */\nexport function computeFulltextContent(\n schema: z.ZodType,\n props: Record<string, unknown>,\n): { content: string; language: string } | undefined {\n const searchableFields = getSearchableFields(schema);\n if (searchableFields.length === 0) return undefined;\n\n const parts: string[] = [];\n for (const field of searchableFields) {\n const value = readOwnProperty(props, field.fieldPath);\n if (typeof value === \"string\" && value.length > 0) {\n parts.push(value);\n }\n }\n if (parts.length === 0) return undefined;\n\n return {\n content: parts.join(FIELD_SEPARATOR),\n language: resolveCombinedLanguage(searchableFields),\n };\n}\n\n/**\n * Resolves the complete fulltext side effect for one node row.\n * `undefined` means the schema has no searchable fields; an explicit delete\n * keeps an all-empty searchable row from being mistaken for no projection.\n */\nexport function resolveNodeFulltextProjection(\n schema: z.ZodType,\n props: Record<string, unknown>,\n): Extract<NodeInsertProjection, { kind: \"fulltext\" }> | undefined {\n if (getSearchableFields(schema).length === 0) return undefined;\n const computed = computeFulltextContent(schema, props);\n return computed === undefined ?\n { kind: \"fulltext\", action: \"delete\" }\n : { kind: \"fulltext\", action: \"upsert\", ...computed };\n}\n\n/** Resolves the ordinary identity-carrying fulltext synchronization input. */\nfunction resolveNodeFulltextSync(\n schema: z.ZodType,\n props: Record<string, unknown>,\n identity: Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n }>,\n): NodeFulltextSync | undefined {\n if (getSearchableFields(schema).length === 0) return undefined;\n const computed = computeFulltextContent(schema, props);\n return computed === undefined ?\n { ...identity, action: \"delete\" }\n : { ...identity, action: \"upsert\", ...computed };\n}\n\n/**\n * Syncs the fulltext index row after a node create or update.\n *\n * Concatenates the values of all searchable fields into a single content\n * string and upserts it. If every field is empty / undefined, deletes\n * any existing row for the node.\n */\nexport async function syncFulltext(\n ctx: FulltextSyncContext,\n schema: z.ZodType,\n props: Record<string, unknown>,\n): Promise<void> {\n const { backend } = ctx;\n\n if (getSearchableFields(schema).length === 0) return;\n\n // `resolveBackendFulltext` is the one decision for \"is fulltext\n // available on this backend\"; a missing member past that point is a\n // contract violation asserted separately below, never re-derived here.\n if (resolveBackendFulltext(backend) === false) {\n refuseFulltextUnavailable(backend, ctx.nodeKind);\n }\n assertFulltextMember(backend.upsertFulltext, \"upsertFulltext\", backend);\n assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n\n const sync = resolveNodeFulltextSync(schema, props, ctx);\n if (sync?.action === \"upsert\") {\n await backend.upsertFulltext({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n content: sync.content,\n language: sync.language,\n });\n return;\n }\n if (sync === undefined) return;\n await backend.deleteFulltext({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n });\n}\n\n/**\n * Syncs the fulltext rows for a batch of same-kind node creates through\n * one `upsertFulltextBatch` call (falling back to per-row `upsertFulltext`\n * when the backend lacks the batch primitive). Mirrors `syncFulltext`\n * per row: computed content upserts, empty content deletes any stale row\n * when the schema declares searchable fields.\n */\nexport async function syncFulltextBatchForKind(\n args: Readonly<{\n graphId: string;\n nodeKind: string;\n backend: GraphBackend | TransactionBackend;\n }>,\n schema: z.ZodType,\n items: readonly Readonly<{\n nodeId: string;\n props: Record<string, unknown>;\n }>[],\n): Promise<void> {\n const { graphId, nodeKind, backend } = args;\n if (getSearchableFields(schema).length === 0) return;\n\n // `resolveBackendFulltext` is the one decision for \"is fulltext\n // available on this backend\"; a missing member past that point is a\n // contract violation asserted separately below, never re-derived here.\n if (resolveBackendFulltext(backend) === false) {\n refuseFulltextUnavailable(backend, nodeKind);\n }\n assertFulltextMember(backend.upsertFulltext, \"upsertFulltext\", backend);\n assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n\n // The bail-out above guarantees the schema has searchable fields for\n // every remaining line, so an item with no computed content always\n // means \"clear its row\" rather than \"not applicable\".\n const rows: { nodeId: string; content: string; language: string }[] = [];\n const emptyContentIds: string[] = [];\n for (const item of items) {\n const computed = computeFulltextContent(schema, item.props);\n if (computed === undefined) {\n emptyContentIds.push(item.nodeId);\n } else {\n rows.push({\n nodeId: item.nodeId,\n content: computed.content,\n language: computed.language,\n });\n }\n }\n\n if (rows.length > 0) {\n if (backend.upsertFulltextBatch === undefined) {\n for (const row of rows) {\n await backend.upsertFulltext({\n graphId,\n nodeKind,\n nodeId: row.nodeId,\n content: row.content,\n language: row.language,\n });\n }\n } else {\n await backend.upsertFulltextBatch({ graphId, nodeKind, rows });\n }\n }\n\n if (emptyContentIds.length > 0) {\n if (backend.deleteFulltextBatch === undefined) {\n for (const nodeId of emptyContentIds) {\n await backend.deleteFulltext({ graphId, nodeKind, nodeId });\n }\n } else {\n await backend.deleteFulltextBatch({\n graphId,\n nodeKind,\n nodeIds: emptyContentIds,\n });\n }\n }\n}\n\n/**\n * Deletes the fulltext row for a node.\n * Called on soft-delete; hard-delete is handled by the backend cascade.\n */\nexport async function deleteNodeFulltext(\n ctx: FulltextSyncContext,\n schema: z.ZodType,\n): Promise<void> {\n const { backend } = ctx;\n\n if (getSearchableFields(schema).length === 0) return;\n\n // Unlike `syncFulltext`, an unavailable backend does not refuse here: a\n // delete removes data rather than accepting a write the backend cannot\n // index, and this backend maintains no fulltext sidecar to issue that\n // removal against, so the delete is a no-op rather than a refusal. If\n // fulltext was active before this backend was reconfigured with\n // `fulltext: false`, an existing row is left in place, unmaintained.\n if (resolveBackendFulltext(backend) === false) return;\n\n assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n\n await backend.deleteFulltext({\n graphId: ctx.graphId,\n nodeKind: ctx.nodeKind,\n nodeId: ctx.nodeId,\n });\n}\n","/**\n * Composable node write steps — the integrity side effects that every node\n * mutation must apply, extracted so there is a single implementation instead of\n * one hand-stitched copy per write path.\n *\n * A node mutation is the core row write plus a fixed set of side effects:\n * uniqueness entries, embedding sync, fulltext sync, and — for deletes —\n * delete-behavior enforcement over connected edges. These steps are shared by\n * the canonical collection operations (create / update / delete) and by\n * provenance retraction, which drives the same close/reopen of a fact node's\n * currency but skips delete-behavior enforcement so every connected edge\n * survives for a later reopen.\n *\n * The steps assume they run inside a write transaction (see\n * {@link runInWriteTransaction}); they perform no transaction management of\n * their own.\n */\nimport { type z } from \"zod\";\n\nimport { bindExtraIfReachable } from \"../../backend/capabilities/bind\";\nimport { UNIQUE_SIDECAR_BATCH } from \"../../backend/capabilities/bundle-registry\";\nimport { resolveBackendFulltext } from \"../../backend/capabilities/fulltext\";\nimport {\n type BundleVerdictOf,\n type ClaimsVerdictThunk,\n missingRequiredExtras,\n} from \"../../backend/capabilities/resolve\";\nimport {\n type GraphBackend,\n type LiveNodeRow,\n type NodePropertyExpectation,\n type NodeRow,\n rowPropsToObject,\n type TombstonedNodeRow,\n type TransactionBackend,\n type UpdateNodeSetResult,\n} from \"../../backend/types\";\nimport {\n type DeleteBehavior,\n type JsonValue,\n type UniqueConstraint,\n} from \"../../core/types\";\nimport {\n ConfigurationError,\n RestrictedDeleteError,\n ValidationError,\n} from \"../../errors\";\nimport { validateNodeProps } from \"../../errors/validation\";\nimport type { CompiledSelectSql } from \"../../query/sql-intent\";\nimport { type KindRegistry } from \"../../registry/kind-registry\";\nimport { canonicalEqual } from \"../../schema/canonical\";\nimport { assertsStoredLowerBound } from \"../../utils/date\";\nimport { purgeEdgeClaims } from \"../claims/edge-claims\";\nimport {\n alreadyAppliedRowWrite,\n createUniquenessContext,\n deleteUniquenessEntries,\n hardDeleteClaimsByNodeIds,\n type NodeClaimContext,\n planNodeClaimReinsert,\n planNodeClaimUpdate,\n type UniquenessUpdatePlan,\n withNodeClaimTransition,\n withNodeCreateClaimsBatch,\n} from \"../claims/node-claims\";\nimport { validateResolvedNodeClaims } from \"../claims/resolved-node-claims\";\nimport {\n deleteNodeEmbeddings,\n getEmbeddingFields,\n syncEmbeddings,\n syncEmbeddingsBatchForKind,\n} from \"../embedding-sync\";\nimport {\n assertFulltextMember,\n deleteNodeFulltext,\n getSearchableFields,\n refuseFulltextUnavailable,\n syncFulltext,\n syncFulltextBatchForKind,\n} from \"../fulltext-sync\";\nimport { type GraphWriteLock } from \"../recorded-capture/clock\";\n\ntype Backend = GraphBackend | TransactionBackend;\n\n/**\n * The graph-scoped state the node write steps need. `lock` is compile-time\n * evidence that the per-graph write-lock discipline was satisfied BEFORE any\n * row work (see {@link GraphWriteLock}): the pipeline performs no locking of\n * its own, so requiring the token here makes \"sidecar write before lock\" a\n * type error at the call site instead of a lock-order inversion in review.\n *\n * It is the claim seam's context by definition rather than by coincidence: a\n * write path hands the same value to {@link withNodeCreateClaims} and to the\n * sync fans, so the two halves of one insert cannot be given different graphs,\n * registries, or lock evidence.\n */\nexport type NodeWriteContext = NodeClaimContext;\n\n/** Builds a {@link NodeWriteContext} — the one constructor every call site shares. */\nexport function createNodeWriteContext(\n graphId: string,\n registry: KindRegistry,\n lock: GraphWriteLock,\n claimsVerdict: ClaimsVerdictThunk,\n uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>,\n): NodeWriteContext {\n return { graphId, registry, lock, claimsVerdict, uniqueSidecarBatch };\n}\n\n/** Whether a delete removes the node (`hard`) or tombstones it (`soft`). */\ntype NodeDeleteMode = \"soft\" | \"hard\";\n\n/**\n * Tunes how a delete treats the node's connected edges.\n *\n * By default delete behavior is enforced: connected edges block a `restrict`\n * node and are removed under `cascade` / `disconnect`. Provenance retraction\n * passes `enforceDeleteBehavior: false` — closing a fact's currency is a\n * belief-status change, not a domain delete, so its edges neither block the\n * close nor get removed; they survive untouched so a later reopen is an exact\n * inverse.\n */\nexport type NodeDeletePolicy = Readonly<{\n enforceDeleteBehavior: boolean;\n}>;\n\nfunction uniquenessContext(ctx: NodeWriteContext, backend: Backend) {\n return createUniquenessContext(\n ctx.graphId,\n ctx.registry,\n backend,\n ctx.uniqueSidecarBatch,\n );\n}\n\n/**\n * The `(graphId, nodeKind, nodeId, backend)` context shared by the embedding and\n * fulltext sync helpers — `EmbeddingSyncContext` and `FulltextSyncContext` are\n * structurally identical, so one builder serves both.\n */\nfunction nodeSyncContext(\n ctx: NodeWriteContext,\n kind: string,\n id: string,\n backend: Backend,\n) {\n return { graphId: ctx.graphId, nodeKind: kind, nodeId: id, backend };\n}\n\n/**\n * Enforces a node's delete behavior against its connected edges: they block\n * the delete (`restrict`) or are removed alongside the node (`cascade` /\n * `disconnect`). Skipped entirely when the caller's {@link NodeDeletePolicy}\n * disables enforcement.\n */\nasync function enforceNodeDeleteBehavior(\n ctx: NodeWriteContext,\n args: Readonly<{\n kind: string;\n id: string;\n mode: NodeDeleteMode;\n onDelete: DeleteBehavior | undefined;\n }>,\n backend: Backend,\n policy?: NodeDeletePolicy,\n): Promise<void> {\n if (policy?.enforceDeleteBehavior === false) return;\n const behavior = args.onDelete ?? \"restrict\";\n const connectedEdges = await backend.findEdgesConnectedTo({\n graphId: ctx.graphId,\n nodeKind: args.kind,\n nodeId: args.id,\n });\n\n if (connectedEdges.length === 0) return;\n\n switch (behavior) {\n case \"restrict\": {\n throw new RestrictedDeleteError({\n nodeKind: args.kind,\n nodeId: args.id,\n edgeCount: connectedEdges.length,\n edgeKinds: [...new Set(connectedEdges.map((edge) => edge.kind))],\n });\n }\n\n case \"cascade\":\n case \"disconnect\": {\n // Both behaviors remove connected edges. \"cascade\" signals intent to\n // remove dependent data; \"disconnect\" signals intent to sever the\n // relationship. The effect is identical because edges cannot exist\n // without both endpoints. One batched statement per bind-budget\n // chunk instead of one statement per edge; the per-edge loop remains\n // for backends without the batch members.\n const connectedEdgeIds = connectedEdges.map((edge) => edge.id);\n const batchDelete =\n args.mode === \"hard\" ?\n backend.hardDeleteEdgesBatch\n : backend.deleteEdgesBatch;\n if (batchDelete === undefined) {\n for (const edge of connectedEdges) {\n await (args.mode === \"hard\" ?\n backend.hardDeleteEdge({ graphId: ctx.graphId, id: edge.id })\n : backend.deleteEdge({ graphId: ctx.graphId, id: edge.id }));\n }\n } else {\n await batchDelete({\n graphId: ctx.graphId,\n ids: connectedEdgeIds,\n });\n }\n // Hard-deleted holders are already takeable through the liveness probe;\n // this is housekeeping so node cascades do not grow edgeClaims forever.\n // Soft-deleted edges retain their rows for resurrection and are not\n // reaped here.\n if (args.mode === \"hard\") {\n await purgeEdgeClaims(\n backend,\n ctx.claimsVerdict(),\n ctx.graphId,\n connectedEdgeIds,\n );\n }\n break;\n }\n }\n}\n\n/** One inserted row, as the post-insert sync fans read it. */\nexport type NodeInsertSyncItem = Readonly<{\n kind: string;\n id: string;\n schema: z.ZodType;\n props: Record<string, unknown>;\n uniqueConstraints: readonly UniqueConstraint[];\n /** True only when the fused node statement wrote every requested projection. */\n projectionsFused?: boolean;\n}>;\n\n/**\n * The sync fans that follow a node insert: embedding and fulltext.\n *\n * The claims this row owes are NOT here. They are issued by\n * {@link withNodeCreateClaims}, on the two sides of the insert their placement\n * names — a claim that is the only fence for its axis has to precede the row it\n * gates, and a function that runs entirely after the insert cannot issue one.\n * The fans have no such constraint: they are derived data, they fence nothing,\n * and they stay where they have always been.\n */\nexport async function applyNodeInsertSyncFans(\n ctx: NodeWriteContext,\n args: NodeInsertSyncItem,\n backend: Backend,\n): Promise<void> {\n const syncContext = nodeSyncContext(ctx, args.kind, args.id, backend);\n if (args.projectionsFused === true) return;\n await Promise.all([\n syncEmbeddings(syncContext, args.schema, args.props),\n syncFulltext(syncContext, args.schema, args.props),\n ]);\n}\n\n/**\n * Batched {@link applyNodeInsertSyncFans}: one embedding batch per (kind,\n * field) and one fulltext batch per kind, instead of the per-row statement fan\n * the single-op path issues.\n */\nexport async function applyNodeInsertSyncFansBatch(\n ctx: NodeWriteContext,\n items: readonly NodeInsertSyncItem[],\n backend: Backend,\n): Promise<void> {\n if (items.length === 0) return;\n\n interface KindGroup {\n schema: z.ZodType;\n rows: { nodeId: string; props: Record<string, unknown> }[];\n }\n const byKind = new Map<string, KindGroup>();\n for (const item of items) {\n const group = byKind.get(item.kind) ?? { schema: item.schema, rows: [] };\n group.rows.push({ nodeId: item.id, props: item.props });\n byKind.set(item.kind, group);\n }\n\n await Promise.all(\n [...byKind.entries()].flatMap(([kind, group]) => {\n const syncArguments = { graphId: ctx.graphId, nodeKind: kind, backend };\n return [\n syncEmbeddingsBatchForKind(syncArguments, group.schema, group.rows),\n syncFulltextBatchForKind(syncArguments, group.schema, group.rows),\n ];\n }),\n );\n}\n\nfunction parseRowProps(row: NodeRow): Record<string, unknown> {\n return rowPropsToObject(row.props);\n}\n\n/**\n * The row a node update targets. A plain update runs live-row side effects\n * (uniqueness diff, embedding/fulltext sync), so it must be handed a\n * {@link LiveNodeRow}; only an explicit `clearDeleted: true` resurrecting\n * upsert may target a possibly-tombstoned row. Encoding the pairing as a\n * union makes \"live-row update pipeline on a tombstoned row\" a type error.\n */\nexport type NodeUpdateTarget =\n | Readonly<{ existing: LiveNodeRow; clearDeleted?: false }>\n | Readonly<{ existing: NodeRow; clearDeleted: true }>;\n\n/**\n * Decides a node update's uniqueness transition, writing nothing.\n *\n * Two shapes behind one seam. A live row diffs its old and new keys; a\n * resurrecting update (`clearDeleted` on a tombstoned row) cannot, because the\n * soft delete already removed its entries — the diff would skip an unchanged\n * key and leave the resurrected node holding NO reservation, so a later create\n * could silently duplicate the value. It re-reserves every applying key\n * instead. Both refuse a conflict before returning, and both hand the caller a\n * plan that only {@link withNodeClaimTransition} may carry out.\n */\nasync function planNodeUpdateUniqueness(\n ctx: NodeWriteContext,\n args: Readonly<{\n existing: NodeRow;\n validatedProps: Record<string, unknown>;\n uniqueConstraints: readonly UniqueConstraint[];\n }>,\n backend: Backend,\n): Promise<UniquenessUpdatePlan> {\n const { kind, id } = args.existing;\n\n if (args.existing.deleted_at !== undefined) {\n return planNodeClaimReinsert(\n uniquenessContext(ctx, backend),\n kind,\n id,\n args.validatedProps,\n args.uniqueConstraints,\n );\n }\n\n return planNodeClaimUpdate(\n uniquenessContext(ctx, backend),\n kind,\n id,\n parseRowProps(args.existing),\n args.validatedProps,\n args.uniqueConstraints,\n );\n}\n\n/**\n * Applies a node update: uniqueness maintenance (diff-based for a live row;\n * check-and-reinsert for a resurrecting update, whose entries the soft delete\n * removed), the core row update, then embedding and fulltext sync. Returns\n * the updated row.\n *\n * ## The row write and its uniqueness transition are ONE unit\n *\n * Both can fail — the row write matches nothing when `expectedValidFrom` or the\n * `deleted_at` fence stopped holding, the uniqueness claim loses a race for a\n * key — and a caller that catches either PER ROW and commits the rest of the\n * transaction (interchange import) must never be left with half of the pair\n * applied. {@link withNodeClaimTransition} owns that sequencing and documents\n * why claim/gate/release is the only order that works; this function just hands\n * it the plan and the write.\n *\n * The embedding and fulltext syncs stay AFTER the gate: they are derived data\n * with no claim to make, so a row write that lands on nothing must not rewrite\n * a fulltext row or re-embed props no row ever received.\n */\nexport async function applyNodeUpdate(\n ctx: NodeWriteContext,\n args: Readonly<{\n schema: z.ZodType;\n validatedProps: Record<string, unknown>;\n uniqueConstraints: readonly UniqueConstraint[];\n validFrom?: string | null;\n validTo?: string;\n clearValidTo?: true;\n /** See {@link UpdateNodeParams.expectedValidFrom}. */\n expectedValidFrom?: string | null;\n }> &\n NodeUpdateTarget,\n backend: Backend,\n): Promise<NodeRow> {\n const { kind, id } = args.existing;\n\n // Read-only phase: decide the sidecar changes, refuse a conflict, write\n // nothing.\n const plan = await planNodeUpdateUniqueness(\n ctx,\n {\n existing: args.existing,\n validatedProps: args.validatedProps,\n uniqueConstraints: args.uniqueConstraints,\n },\n backend,\n );\n\n const updateParams: {\n graphId: string;\n kind: string;\n id: string;\n props: Record<string, unknown>;\n validFrom?: string | null;\n expectedValidFrom?: string | null;\n incrementVersion?: boolean;\n clearDeleted?: boolean;\n } = {\n graphId: ctx.graphId,\n kind,\n id,\n props: args.validatedProps,\n incrementVersion: true,\n };\n if (args.validFrom !== undefined) updateParams.validFrom = args.validFrom;\n // `assertsStoredLowerBound` owns \"does this fence state anything?\" — the same\n // predicate the fence appliers consult, so the step that CARRIES the fence\n // and the seam that VALIDATES it cannot disagree about what an empty fence is.\n if (assertsStoredLowerBound(args)) {\n updateParams.expectedValidFrom = args.expectedValidFrom;\n }\n if (args.clearDeleted) updateParams.clearDeleted = true;\n\n const row = await withNodeClaimTransition(\n uniquenessContext(ctx, backend),\n kind,\n id,\n plan,\n () =>\n backend.updateNode({\n ...updateParams,\n ...(args.clearValidTo === true ? { clearValidTo: true as const }\n : args.validTo === undefined ? {}\n : { validTo: args.validTo }),\n }),\n );\n\n await Promise.all([\n syncEmbeddings(\n nodeSyncContext(ctx, kind, id, backend),\n args.schema,\n args.validatedProps,\n ),\n syncFulltext(\n nodeSyncContext(ctx, kind, id, backend),\n args.schema,\n args.validatedProps,\n ),\n ]);\n\n return row;\n}\n\n/**\n * Applies a node soft delete: delete-behavior enforcement, the tombstone\n * write, then removal of uniqueness entries, embeddings, and fulltext.\n * Requires a {@link LiveNodeRow}: deleting an already-tombstoned row would\n * re-run sidecar cleanup against entries the first delete already removed.\n */\nexport async function applyNodeSoftDelete(\n ctx: NodeWriteContext,\n args: Readonly<{\n existing: LiveNodeRow;\n schema: z.ZodType;\n uniqueConstraints: readonly UniqueConstraint[];\n onDelete: DeleteBehavior | undefined;\n }>,\n backend: Backend,\n policy?: NodeDeletePolicy,\n): Promise<void> {\n const { kind, id } = args.existing;\n await enforceNodeDeleteBehavior(\n ctx,\n { kind, id, mode: \"soft\", onDelete: args.onDelete },\n backend,\n policy,\n );\n await backend.deleteNode({\n graphId: ctx.graphId,\n kind,\n id,\n });\n await deleteUniquenessEntries(\n uniquenessContext(ctx, backend),\n kind,\n id,\n parseRowProps(args.existing),\n args.uniqueConstraints,\n );\n await deleteNodeEmbeddings(\n nodeSyncContext(ctx, kind, id, backend),\n args.schema,\n );\n await deleteNodeFulltext(\n nodeSyncContext(ctx, kind, id, backend),\n args.schema,\n );\n}\n\n/**\n * Applies a node hard delete: delete-behavior enforcement, permanent removal,\n * then embedding cleanup. Uniqueness and fulltext rows are removed by the\n * backend's `hardDeleteNode` cascade; embeddings live in strategy-owned\n * per-`(kind, field)` tables the graph-agnostic cascade cannot reach, so they\n * are cleaned here.\n */\nexport async function applyNodeHardDelete(\n ctx: NodeWriteContext,\n args: Readonly<{\n kind: string;\n id: string;\n schema: z.ZodType;\n onDelete: DeleteBehavior | undefined;\n }>,\n backend: Backend,\n): Promise<void> {\n await enforceNodeDeleteBehavior(\n ctx,\n { kind: args.kind, id: args.id, mode: \"hard\", onDelete: args.onDelete },\n backend,\n );\n await backend.hardDeleteNode({\n graphId: ctx.graphId,\n kind: args.kind,\n id: args.id,\n });\n await deleteNodeEmbeddings(\n nodeSyncContext(ctx, args.kind, args.id, backend),\n args.schema,\n );\n}\n\n/**\n * Reopens a soft-deleted node with its stored props (no merge, no\n * re-validation): re-checks and re-inserts uniqueness entries (the delete\n * removed them), clears the tombstone, then re-syncs embeddings and fulltext.\n * Used by provenance to reinstate a fact whose currency is restored. Returns\n * the reopened row.\n *\n * @throws {UniquenessError} when a unique key the node held was taken by\n * another node while it was tombstoned.\n */\nexport async function applyNodeResurrect(\n ctx: NodeWriteContext,\n args: Readonly<{\n existing: TombstonedNodeRow;\n schema: z.ZodType;\n uniqueConstraints: readonly UniqueConstraint[];\n }>,\n backend: Backend,\n): Promise<NodeRow> {\n const { kind, id } = args.existing;\n const props = parseRowProps(args.existing);\n // One unit, exactly as `applyNodeUpdate`, and for the same reason: the\n // resurrecting UPDATE carries `deleted_at IS NOT NULL`, so a peer that revived\n // this tombstone first makes it match zero rows — and the reservations that\n // revival is entitled to are the peer's, not this caller's.\n // `withNodeClaimTransition` gives them back when the gate refuses.\n const plan = await planNodeClaimReinsert(\n uniquenessContext(ctx, backend),\n kind,\n id,\n props,\n args.uniqueConstraints,\n );\n const row = await withNodeClaimTransition(\n uniquenessContext(ctx, backend),\n kind,\n id,\n plan,\n () =>\n backend.updateNode({\n graphId: ctx.graphId,\n kind,\n id,\n props,\n incrementVersion: true,\n clearDeleted: true,\n }),\n );\n await Promise.all([\n syncEmbeddings(nodeSyncContext(ctx, kind, id, backend), args.schema, props),\n syncFulltext(nodeSyncContext(ctx, kind, id, backend), args.schema, props),\n ]);\n return row;\n}\n\n/**\n * The inputs of one set-based node update: the patch the statement applies and\n * the candidate query that selects the rows it applies to.\n *\n * There is no fence field. `UpdateNodeSetParams` has no `expectedValidFrom`,\n * so a validity lower bound cannot be carried here — it is refused by\n * `NODE_SET_UPDATE_FENCE_APPLIERS` before this step is reached, rather than\n * accepted into a record that would quietly drop it.\n */\ntype NodeSetUpdateCommonWork = Readonly<{\n kind: string;\n schema: z.ZodType<Record<string, unknown>>;\n uniqueConstraints: readonly UniqueConstraint[];\n patch: Readonly<Record<string, JsonValue>>;\n unsetProperties: readonly string[];\n candidateIds: CompiledSelectSql;\n candidateIdColumn: string;\n}>;\n\nexport type NodeSetUpdateWork = NodeSetUpdateCommonWork &\n (\n | Readonly<{ operation: \"updateWhere\" }>\n | Readonly<{\n operation: \"compareAndSet\";\n expected: Readonly<Record<string, NodePropertyExpectation>>;\n }>\n );\n\n/** What a set update reports: how many live rows it rewrote. */\nexport type NodeSetUpdateResult = Readonly<{ affectedCount: number }>;\n\n/**\n * Applies a set-based node update: one UPDATE over every candidate row, then a\n * full rebuild of the sidecars those after-images oblige.\n *\n * ## Why the capability refusals are HERE and not at the entry point\n *\n * The caller probes the backend it was handed before opening the transaction;\n * these four probe the transaction target, which is a different object — a\n * backend may hand out a transaction handle that implements less than the\n * top-level one. They keep the entry point's error codes, so a caller that\n * refuses before the transaction and one that refuses inside it report the\n * same class.\n *\n * ## Why the order is row -> probe -> drop -> re-claim\n *\n * Unlike every other node write, the uniqueness claim happens AFTER the row\n * write: the statement rewrites whole rows without reading their before-images,\n * so the keys to release are not knowable until the after-images come back.\n * The cross-kind re-check below is what makes that safe — it re-probes every\n * changed key across the constraint's scope and refuses the whole transaction\n * before a single entry is dropped. The per-graph write fence (which a\n * shared-scope constraint forces this write to take) is what keeps a concurrent\n * claim from landing between the probe and the reinsert.\n */\nexport async function applyNodeSetUpdate(\n ctx: NodeWriteContext,\n args: NodeSetUpdateWork,\n backend: Backend,\n): Promise<NodeSetUpdateResult> {\n const { kind, schema, uniqueConstraints } = args;\n const commonParams = {\n graphId: ctx.graphId,\n kind,\n patch: args.patch,\n unsetProperties: args.unsetProperties,\n candidateIds: args.candidateIds,\n candidateIdColumn: args.candidateIdColumn,\n } as const;\n let executeNodeSetUpdate: () => Promise<UpdateNodeSetResult>;\n if (args.operation === \"compareAndSet\") {\n const compareAndSetNode = backend.compareAndSetNode;\n if (compareAndSetNode === undefined) {\n throw new ConfigurationError(\n \"The transaction backend does not support node compare-and-set\",\n { code: \"COMPARE_AND_SET_UNSUPPORTED\", kind },\n );\n }\n executeNodeSetUpdate = () =>\n compareAndSetNode({\n ...commonParams,\n operation: \"compareAndSet\",\n expected: args.expected,\n });\n } else {\n const updateNodeSet = backend.updateNodeSet;\n if (updateNodeSet === undefined) {\n throw new ConfigurationError(\n \"The transaction backend does not support set-based node updates\",\n { code: \"SET_UPDATE_UNSUPPORTED\", kind },\n );\n }\n executeNodeSetUpdate = () =>\n updateNodeSet({ ...commonParams, operation: \"updateWhere\" });\n }\n if (\n uniqueConstraints.length > 0 &&\n missingRequiredExtras(\n UNIQUE_SIDECAR_BATCH,\n ctx.uniqueSidecarBatch,\n \"set-based node update\",\n ).length > 0\n ) {\n throw new ConfigurationError(\n \"The transaction backend lacks batched uniqueness operations\",\n { code: \"SET_UPDATE_UNIQUENESS_UNSUPPORTED\", kind },\n );\n }\n if (getSearchableFields(schema).length > 0) {\n // A fulltext-off backend (`resolveBackendFulltext` returns `false`) gets\n // the same typed capability refusal every other fulltext entry point\n // raises, rather than the member-presence assertions below — those are\n // for a backend that DOES have fulltext but lacks one of the four\n // members the write plan calls, mirroring the batched-uniqueness and\n // batched-vector checks around it.\n if (resolveBackendFulltext(backend) === false) {\n refuseFulltextUnavailable(backend, kind);\n }\n // Fulltext is available, so a missing batch member here is not an\n // availability decision but a backend contract violation — the same\n // invariant `syncFulltextBatchForKind` asserts on its own members.\n assertFulltextMember(backend.upsertFulltext, \"upsertFulltext\", backend);\n assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n assertFulltextMember(\n backend.upsertFulltextBatch,\n \"upsertFulltextBatch\",\n backend,\n );\n assertFulltextMember(\n backend.deleteFulltextBatch,\n \"deleteFulltextBatch\",\n backend,\n );\n }\n if (\n getEmbeddingFields(schema).length > 0 &&\n (backend.upsertEmbedding === undefined ||\n backend.deleteEmbedding === undefined ||\n backend.upsertEmbeddingBatch === undefined ||\n backend.deleteEmbeddingBatch === undefined)\n ) {\n throw new ConfigurationError(\n \"The transaction backend lacks batched vector operations\",\n { code: \"SET_UPDATE_VECTOR_UNSUPPORTED\", kind },\n );\n }\n const result = await executeNodeSetUpdate();\n if (result.affectedCount === 0) return { affectedCount: 0 };\n\n const sidecarItems = result.rows.map((row) => {\n const props = rowPropsToObject(row.props);\n const validatedProps = validateNodeProps(schema, props, {\n kind,\n operation: \"update\",\n id: row.id,\n });\n if (!canonicalEqual(validatedProps, props)) {\n throw new ValidationError(\n `Set update would persist a non-canonical ${kind} row`,\n {\n entityType: \"node\",\n kind,\n operation: \"update\",\n id: row.id,\n issues: [\n {\n path: \"props\",\n message: \"The complete row requires schema normalization\",\n },\n ],\n },\n );\n }\n return {\n kind,\n id: row.id,\n schema,\n props: validatedProps,\n uniqueConstraints,\n };\n });\n\n const claimItems = sidecarItems.map((item) => ({\n kind: item.kind,\n id: item.id,\n props: item.props,\n constraints: item.uniqueConstraints,\n }));\n if (uniqueConstraints.length > 0) {\n // The re-claim below (`withNodeCreateClaimsBatch`) reaches `insertUniqueBatch`\n // only through the shared, fallback-dispositioned `issueClaimsBatched`\n // (`../claims/node-claims.ts`), which silently degrades to per-row inserts\n // when the PORT lacks the member — the right answer for a plain create,\n // but not for this REFUSE operation. Re-checking the port here, before the\n // destructive hard-delete below, closes that gap: the later call binds off\n // the same `backend`/verdict pair checked here, so its internal fallback\n // branch can never fire for this call.\n if (\n bindExtraIfReachable(\n backend,\n ctx.uniqueSidecarBatch.extras.insertUniqueBatch,\n UNIQUE_SIDECAR_BATCH.id,\n ) === undefined\n ) {\n throw new ConfigurationError(\n \"The transaction backend lacks batched uniqueness operations\",\n { code: \"SET_UPDATE_UNIQUENESS_UNSUPPORTED\", kind },\n );\n }\n // The RESOLVED-SET verdict, not a row-at-a-time one: the statement rewrote\n // every candidate at once, so a swap or a handoff of one key between two\n // rows it touched is legal in the final state and refused by every\n // intermediate one. One owner of that verdict, shared with the graph merge.\n await validateResolvedNodeClaims(\n createUniquenessContext(\n ctx.graphId,\n ctx.registry,\n backend,\n ctx.uniqueSidecarBatch,\n ),\n claimItems,\n [],\n );\n await hardDeleteClaimsByNodeIds(\n uniquenessContext(ctx, backend),\n kind,\n result.rows.map((row) => row.id),\n );\n }\n // The same claim seam every create-shaped writer uses, with an ALREADY-APPLIED\n // row write as its gate: the rows landed above and the old claims were\n // hard-deleted, so what is left is a re-claim and there is no row write left\n // for a claim to precede. Inverting it would mean reserving keys the update has\n // not written. What covers this site on a backend that cannot fence is stated\n // per kind shape: a kind whose scope spans siblings declares\n // `fencesConstraintProbe` at the entry point and is refused before this body\n // runs; a kind-scoped one is not refused, before or after — its\n // delete-then-rebuild window is unchanged in shape and extent here.\n await withNodeCreateClaimsBatch(\n ctx,\n claimItems,\n backend,\n alreadyAppliedRowWrite,\n );\n await applyNodeInsertSyncFansBatch(ctx, sidecarItems, backend);\n return { affectedCount: result.affectedCount };\n}\n"]}
|