@nicia-ai/typegraph 0.47.0 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/dist/backend/drizzle/indexes.d.cts +1 -1
  2. package/dist/backend/drizzle/indexes.d.ts +1 -1
  3. package/dist/backend/index.cjs +27 -19
  4. package/dist/backend/index.d.cts +37 -55
  5. package/dist/backend/index.d.ts +37 -55
  6. package/dist/backend/index.js +4 -4
  7. package/dist/backend/postgres/index.cjs +7 -7
  8. package/dist/backend/postgres/index.d.cts +21 -7
  9. package/dist/backend/postgres/index.d.ts +21 -7
  10. package/dist/backend/postgres/index.js +6 -6
  11. package/dist/backend/postgres/pglite-store.cjs +17 -17
  12. package/dist/backend/postgres/pglite-store.d.cts +8 -8
  13. package/dist/backend/postgres/pglite-store.d.ts +8 -8
  14. package/dist/backend/postgres/pglite-store.js +14 -14
  15. package/dist/backend/postgres/pglite.cjs +8 -8
  16. package/dist/backend/postgres/pglite.d.cts +3 -3
  17. package/dist/backend/postgres/pglite.d.ts +3 -3
  18. package/dist/backend/postgres/pglite.js +7 -7
  19. package/dist/backend/sqlite/index.cjs +7 -7
  20. package/dist/backend/sqlite/index.d.cts +20 -7
  21. package/dist/backend/sqlite/index.d.ts +20 -7
  22. package/dist/backend/sqlite/index.js +6 -6
  23. package/dist/backend/sqlite/libsql.cjs +8 -8
  24. package/dist/backend/sqlite/libsql.d.cts +3 -3
  25. package/dist/backend/sqlite/libsql.d.ts +3 -3
  26. package/dist/backend/sqlite/libsql.js +6 -6
  27. package/dist/backend/sqlite/local-store.cjs +18 -18
  28. package/dist/backend/sqlite/local-store.d.cts +8 -8
  29. package/dist/backend/sqlite/local-store.d.ts +8 -8
  30. package/dist/backend/sqlite/local-store.js +15 -15
  31. package/dist/backend/sqlite/local.cjs +9 -9
  32. package/dist/backend/sqlite/local.d.cts +3 -3
  33. package/dist/backend/sqlite/local.d.ts +3 -3
  34. package/dist/backend/sqlite/local.js +7 -7
  35. package/dist/{chunk-5FBRVORR.cjs → chunk-2O4PCIZ6.cjs} +8 -7
  36. package/dist/chunk-2O4PCIZ6.cjs.map +1 -0
  37. package/dist/{chunk-6KFLYYOC.cjs → chunk-2QGYQBS2.cjs} +5 -5
  38. package/dist/{chunk-6KFLYYOC.cjs.map → chunk-2QGYQBS2.cjs.map} +1 -1
  39. package/dist/{chunk-XYBQI6LE.js → chunk-2TYSSBU5.js} +6 -6
  40. package/dist/{chunk-XYBQI6LE.js.map → chunk-2TYSSBU5.js.map} +1 -1
  41. package/dist/{chunk-6JVZSOHQ.cjs → chunk-3FPR224C.cjs} +26 -26
  42. package/dist/{chunk-6JVZSOHQ.cjs.map → chunk-3FPR224C.cjs.map} +1 -1
  43. package/dist/{chunk-U5EDAVOJ.cjs → chunk-3G5W2U2L.cjs} +82 -51
  44. package/dist/chunk-3G5W2U2L.cjs.map +1 -0
  45. package/dist/{chunk-MFZR4QKM.cjs → chunk-3KOY4FH3.cjs} +181 -4
  46. package/dist/chunk-3KOY4FH3.cjs.map +1 -0
  47. package/dist/{chunk-UPAJHMW3.cjs → chunk-3QNZ5SAJ.cjs} +55 -58
  48. package/dist/chunk-3QNZ5SAJ.cjs.map +1 -0
  49. package/dist/{chunk-NG2RB5WL.js → chunk-5K2BKEBD.js} +18 -3
  50. package/dist/chunk-5K2BKEBD.js.map +1 -0
  51. package/dist/chunk-5PRKMB24.cjs +124 -0
  52. package/dist/chunk-5PRKMB24.cjs.map +1 -0
  53. package/dist/chunk-6LN7FIVU.js +107 -0
  54. package/dist/chunk-6LN7FIVU.js.map +1 -0
  55. package/dist/{chunk-M35DF33T.js → chunk-7LZJNLA5.js} +29 -16
  56. package/dist/chunk-7LZJNLA5.js.map +1 -0
  57. package/dist/{chunk-I4G3SQPF.cjs → chunk-7UOLHNWC.cjs} +7 -7
  58. package/dist/chunk-7UOLHNWC.cjs.map +1 -0
  59. package/dist/{chunk-DJZTXBWY.js → chunk-BRRP76WO.js} +71 -30
  60. package/dist/chunk-BRRP76WO.js.map +1 -0
  61. package/dist/{chunk-5FT3TLPK.js → chunk-D4QLTJSM.js} +16 -13
  62. package/dist/chunk-D4QLTJSM.js.map +1 -0
  63. package/dist/{chunk-XY5OMOJD.js → chunk-DZAICA5J.js} +3 -3
  64. package/dist/{chunk-XY5OMOJD.js.map → chunk-DZAICA5J.js.map} +1 -1
  65. package/dist/{chunk-OIFSOPSR.cjs → chunk-EZEEWCFJ.cjs} +38 -156
  66. package/dist/chunk-EZEEWCFJ.cjs.map +1 -0
  67. package/dist/{chunk-AMMWA76F.cjs → chunk-FA2AFWLP.cjs} +6 -6
  68. package/dist/{chunk-AMMWA76F.cjs.map → chunk-FA2AFWLP.cjs.map} +1 -1
  69. package/dist/{chunk-FNOMT74T.js → chunk-I4GAZH5Z.js} +180 -5
  70. package/dist/chunk-I4GAZH5Z.js.map +1 -0
  71. package/dist/{chunk-WGX7JH7E.cjs → chunk-JB6T4GLL.cjs} +106 -134
  72. package/dist/chunk-JB6T4GLL.cjs.map +1 -0
  73. package/dist/{chunk-MX4DHSQP.cjs → chunk-JFRT7S3B.cjs} +92 -98
  74. package/dist/chunk-JFRT7S3B.cjs.map +1 -0
  75. package/dist/{chunk-5UMTUOM5.js → chunk-JPD2CTC3.js} +5 -4
  76. package/dist/chunk-JPD2CTC3.js.map +1 -0
  77. package/dist/{chunk-SE6EGQSD.js → chunk-KF6K7TGH.js} +38 -66
  78. package/dist/chunk-KF6K7TGH.js.map +1 -0
  79. package/dist/{chunk-QS3NQZVC.js → chunk-LTXQOEIC.js} +44 -14
  80. package/dist/chunk-LTXQOEIC.js.map +1 -0
  81. package/dist/{chunk-ZHNXLS3C.js → chunk-NACVVDWB.js} +208 -8
  82. package/dist/chunk-NACVVDWB.js.map +1 -0
  83. package/dist/{chunk-AVGUJWVX.js → chunk-S5TERQVW.js} +15 -132
  84. package/dist/chunk-S5TERQVW.js.map +1 -0
  85. package/dist/chunk-SIT26LAZ.cjs +614 -0
  86. package/dist/chunk-SIT26LAZ.cjs.map +1 -0
  87. package/dist/{chunk-BR7SHKGM.cjs → chunk-SR725PWF.cjs} +548 -507
  88. package/dist/chunk-SR725PWF.cjs.map +1 -0
  89. package/dist/{chunk-425IZOQ5.cjs → chunk-TQHGE7UC.cjs} +20 -2
  90. package/dist/chunk-TQHGE7UC.cjs.map +1 -0
  91. package/dist/{chunk-GYUJZARH.cjs → chunk-TUNPBZY3.cjs} +4 -4
  92. package/dist/{chunk-GYUJZARH.cjs.map → chunk-TUNPBZY3.cjs.map} +1 -1
  93. package/dist/chunk-UGHG7PGX.js +592 -0
  94. package/dist/chunk-UGHG7PGX.js.map +1 -0
  95. package/dist/{chunk-BCQ76AXA.cjs → chunk-UGHQV7MP.cjs} +107 -94
  96. package/dist/chunk-UGHQV7MP.cjs.map +1 -0
  97. package/dist/{chunk-KABFHAL7.cjs → chunk-UMGZDVOA.cjs} +213 -12
  98. package/dist/chunk-UMGZDVOA.cjs.map +1 -0
  99. package/dist/{chunk-6FWSNSRE.js → chunk-WIC7DRXW.js} +4 -4
  100. package/dist/chunk-WIC7DRXW.js.map +1 -0
  101. package/dist/{chunk-LEWHMOUY.js → chunk-YIURNGXI.js} +4 -4
  102. package/dist/{chunk-LEWHMOUY.js.map → chunk-YIURNGXI.js.map} +1 -1
  103. package/dist/{chunk-EP4RUYD6.js → chunk-YVF2EM7B.js} +3 -3
  104. package/dist/{chunk-EP4RUYD6.js.map → chunk-YVF2EM7B.js.map} +1 -1
  105. package/dist/{chunk-EMIB2RXD.cjs → chunk-YYUHLYM2.cjs} +99 -96
  106. package/dist/chunk-YYUHLYM2.cjs.map +1 -0
  107. package/dist/{chunk-KH7XW7VV.js → chunk-Z2JCLZFJ.js} +25 -28
  108. package/dist/chunk-Z2JCLZFJ.js.map +1 -0
  109. package/dist/{chunk-NNQ6A3RM.js → chunk-ZFMCDJGB.js} +7 -12
  110. package/dist/chunk-ZFMCDJGB.js.map +1 -0
  111. package/dist/core/index.cjs +6 -6
  112. package/dist/core/index.d.cts +4 -4
  113. package/dist/core/index.d.ts +4 -4
  114. package/dist/core/index.js +2 -2
  115. package/dist/ddl-BL1NZLMY.d.cts +78 -0
  116. package/dist/ddl-D_oW-EVO.d.ts +78 -0
  117. package/dist/graph-extension/index.d.cts +4 -4
  118. package/dist/graph-extension/index.d.ts +4 -4
  119. package/dist/graph-merge/index.cjs +357 -191
  120. package/dist/graph-merge/index.cjs.map +1 -1
  121. package/dist/graph-merge/index.d.cts +68 -15
  122. package/dist/graph-merge/index.d.ts +68 -15
  123. package/dist/graph-merge/index.js +197 -32
  124. package/dist/graph-merge/index.js.map +1 -1
  125. package/dist/{index-CHTv4XMZ.d.cts → index-COs_z6nV.d.cts} +2 -2
  126. package/dist/{index-CzoJ3MUw.d.ts → index-D7d1u2gr.d.ts} +2 -2
  127. package/dist/index.cjs +90 -86
  128. package/dist/index.cjs.map +1 -1
  129. package/dist/index.d.cts +12 -12
  130. package/dist/index.d.ts +12 -12
  131. package/dist/index.js +13 -13
  132. package/dist/index.js.map +1 -1
  133. package/dist/indexes/index.d.cts +4 -4
  134. package/dist/indexes/index.d.ts +4 -4
  135. package/dist/ingestion-import-target-XPxZYw89.d.cts +17 -0
  136. package/dist/ingestion-import-target-dNeL7iAv.d.ts +17 -0
  137. package/dist/interchange/index.cjs +38 -38
  138. package/dist/interchange/index.d.cts +15 -12
  139. package/dist/interchange/index.d.ts +15 -12
  140. package/dist/interchange/index.js +10 -10
  141. package/dist/{manager-DlY1vlla.d.cts → manager-CYaff3n3.d.cts} +2 -2
  142. package/dist/{manager-B6sOQzcQ.d.ts → manager-D9eRT_ns.d.ts} +2 -2
  143. package/dist/{materialize-indexes-DQL4xcpf.d.ts → materialize-indexes-DJ3ykH59.d.ts} +1 -1
  144. package/dist/{materialize-indexes-sskhp-c_.d.cts → materialize-indexes-DTtAnvfY.d.cts} +1 -1
  145. package/dist/{postgres-BXy_nyMs.d.cts → postgres-CcL4bAHS.d.ts} +1 -1
  146. package/dist/{postgres-B6YOUcaK.d.ts → postgres-DMj39MEu.d.cts} +1 -1
  147. package/dist/profiler/index.d.cts +9 -9
  148. package/dist/profiler/index.d.ts +9 -9
  149. package/dist/provenance/index.cjs +25 -26
  150. package/dist/provenance/index.cjs.map +1 -1
  151. package/dist/provenance/index.d.cts +7 -7
  152. package/dist/provenance/index.d.ts +7 -7
  153. package/dist/provenance/index.js +9 -10
  154. package/dist/provenance/index.js.map +1 -1
  155. package/dist/repair-validity-windows-BFNZvd_H.d.cts +166 -0
  156. package/dist/repair-validity-windows-DlUSqwCg.d.ts +166 -0
  157. package/dist/schema/index.cjs +35 -35
  158. package/dist/schema/index.d.cts +6 -6
  159. package/dist/schema/index.d.ts +6 -6
  160. package/dist/schema/index.js +8 -8
  161. package/dist/{searchable-D9gMiwcS.d.ts → searchable-DHJMh_nj.d.cts} +1 -1
  162. package/dist/{searchable-0Cn_lY8U.d.cts → searchable-bpE1bBfc.d.ts} +1 -1
  163. package/dist/{sqlite-DioSxaPe.d.cts → sqlite-D7Oz0SQh.d.ts} +1 -1
  164. package/dist/{sqlite-ClXuBYAj.d.ts → sqlite-YppHrNFb.d.cts} +1 -1
  165. package/dist/{store-5j-w5onJ.d.ts → store-DRrFCx5x.d.ts} +122 -27
  166. package/dist/{store-CFedKGU5.d.cts → store-bphCSo7z.d.cts} +122 -27
  167. package/dist/{temporal-CjO9FH1l.d.ts → temporal-5GqpYCk2.d.cts} +1 -1
  168. package/dist/{temporal-Ce1pG0S1.d.cts → temporal-CbnLzTmM.d.ts} +1 -1
  169. package/dist/{types-DKkMJZjR.d.cts → types-BqFZTQmV.d.cts} +29 -4
  170. package/dist/{types-DKkMJZjR.d.ts → types-BqFZTQmV.d.ts} +29 -4
  171. package/dist/{types-BrdOFu48.d.ts → types-Bx74kaTt.d.ts} +1 -1
  172. package/dist/{types-oj_OGAaZ.d.cts → types-CXAhpW-c.d.cts} +1 -1
  173. package/dist/{where-D1wKCJ4Q.d.cts → where-DI_Fqz-X.d.cts} +1 -1
  174. package/dist/{where-C8w2627G.d.ts → where-O-k2wgYm.d.ts} +1 -1
  175. package/package.json +2 -3
  176. package/dist/chunk-3HGRTCDU.cjs +0 -269
  177. package/dist/chunk-3HGRTCDU.cjs.map +0 -1
  178. package/dist/chunk-425IZOQ5.cjs.map +0 -1
  179. package/dist/chunk-5FBRVORR.cjs.map +0 -1
  180. package/dist/chunk-5FT3TLPK.js.map +0 -1
  181. package/dist/chunk-5UMTUOM5.js.map +0 -1
  182. package/dist/chunk-6FWSNSRE.js.map +0 -1
  183. package/dist/chunk-AVGUJWVX.js.map +0 -1
  184. package/dist/chunk-BCQ76AXA.cjs.map +0 -1
  185. package/dist/chunk-BR7SHKGM.cjs.map +0 -1
  186. package/dist/chunk-DJZTXBWY.js.map +0 -1
  187. package/dist/chunk-EMIB2RXD.cjs.map +0 -1
  188. package/dist/chunk-FNOMT74T.js.map +0 -1
  189. package/dist/chunk-I4G3SQPF.cjs.map +0 -1
  190. package/dist/chunk-JR6SX5RH.cjs +0 -268
  191. package/dist/chunk-JR6SX5RH.cjs.map +0 -1
  192. package/dist/chunk-KABFHAL7.cjs.map +0 -1
  193. package/dist/chunk-KH7XW7VV.js.map +0 -1
  194. package/dist/chunk-M35DF33T.js.map +0 -1
  195. package/dist/chunk-MFZR4QKM.cjs.map +0 -1
  196. package/dist/chunk-MX4DHSQP.cjs.map +0 -1
  197. package/dist/chunk-NAZ2RA4L.js +0 -254
  198. package/dist/chunk-NAZ2RA4L.js.map +0 -1
  199. package/dist/chunk-NG2RB5WL.js.map +0 -1
  200. package/dist/chunk-NNQ6A3RM.js.map +0 -1
  201. package/dist/chunk-OIFSOPSR.cjs.map +0 -1
  202. package/dist/chunk-QS3NQZVC.js.map +0 -1
  203. package/dist/chunk-SE6EGQSD.js.map +0 -1
  204. package/dist/chunk-SHSSRCFR.js +0 -246
  205. package/dist/chunk-SHSSRCFR.js.map +0 -1
  206. package/dist/chunk-U5EDAVOJ.cjs.map +0 -1
  207. package/dist/chunk-UPAJHMW3.cjs.map +0 -1
  208. package/dist/chunk-WGX7JH7E.cjs.map +0 -1
  209. package/dist/chunk-ZHNXLS3C.js.map +0 -1
  210. package/dist/ddl-CprnMXJ-.d.ts +0 -38
  211. package/dist/ddl-DJA7Lci5.d.cts +0 -38
@@ -1,5 +1,5 @@
1
- import { K as KindEntity } from './types-DKkMJZjR.cjs';
2
- import { M as MaterializeIndexesResult, S as SchemaDiff } from './materialize-indexes-sskhp-c_.cjs';
1
+ import { bj as KindEntity } from './types-BqFZTQmV.cjs';
2
+ import { M as MaterializeIndexesResult, S as SchemaDiff } from './materialize-indexes-DTtAnvfY.cjs';
3
3
 
4
4
  /**
5
5
  * TypeGraph Error Hierarchy
@@ -1,5 +1,5 @@
1
- import { K as KindEntity } from './types-DKkMJZjR.js';
2
- import { M as MaterializeIndexesResult, S as SchemaDiff } from './materialize-indexes-DQL4xcpf.js';
1
+ import { bj as KindEntity } from './types-BqFZTQmV.js';
2
+ import { M as MaterializeIndexesResult, S as SchemaDiff } from './materialize-indexes-DJ3ykH59.js';
3
3
 
4
4
  /**
5
5
  * TypeGraph Error Hierarchy
package/dist/index.cjs CHANGED
@@ -1,30 +1,30 @@
1
1
  'use strict';
2
2
 
3
- var chunkBR7SHKGM_cjs = require('./chunk-BR7SHKGM.cjs');
3
+ var chunkSR725PWF_cjs = require('./chunk-SR725PWF.cjs');
4
4
  var chunkOORXGFL5_cjs = require('./chunk-OORXGFL5.cjs');
5
5
  var chunkDO7SAMEK_cjs = require('./chunk-DO7SAMEK.cjs');
6
6
  var chunkROR5ZR6A_cjs = require('./chunk-ROR5ZR6A.cjs');
7
7
  require('./chunk-CICO5GXD.cjs');
8
- require('./chunk-AMMWA76F.cjs');
9
- var chunkKABFHAL7_cjs = require('./chunk-KABFHAL7.cjs');
8
+ require('./chunk-FA2AFWLP.cjs');
9
+ var chunkUMGZDVOA_cjs = require('./chunk-UMGZDVOA.cjs');
10
10
  var chunkHDL2ARHX_cjs = require('./chunk-HDL2ARHX.cjs');
11
11
  require('./chunk-WODMN3Q2.cjs');
12
12
  var chunkTZEGUG6D_cjs = require('./chunk-TZEGUG6D.cjs');
13
- require('./chunk-WGX7JH7E.cjs');
14
- var chunkMFZR4QKM_cjs = require('./chunk-MFZR4QKM.cjs');
15
- require('./chunk-GYUJZARH.cjs');
16
- var chunk6JVZSOHQ_cjs = require('./chunk-6JVZSOHQ.cjs');
13
+ require('./chunk-JB6T4GLL.cjs');
14
+ var chunk3KOY4FH3_cjs = require('./chunk-3KOY4FH3.cjs');
15
+ require('./chunk-TUNPBZY3.cjs');
16
+ var chunk3FPR224C_cjs = require('./chunk-3FPR224C.cjs');
17
17
  var chunk26YKDNUD_cjs = require('./chunk-26YKDNUD.cjs');
18
- require('./chunk-MX4DHSQP.cjs');
19
- var chunkOIFSOPSR_cjs = require('./chunk-OIFSOPSR.cjs');
18
+ require('./chunk-JFRT7S3B.cjs');
19
+ var chunkEZEEWCFJ_cjs = require('./chunk-EZEEWCFJ.cjs');
20
20
  require('./chunk-PWLJ77UV.cjs');
21
- var chunkJR6SX5RH_cjs = require('./chunk-JR6SX5RH.cjs');
21
+ var chunkSIT26LAZ_cjs = require('./chunk-SIT26LAZ.cjs');
22
22
  var chunk3U5ABFDW_cjs = require('./chunk-3U5ABFDW.cjs');
23
- var chunk3HGRTCDU_cjs = require('./chunk-3HGRTCDU.cjs');
23
+ var chunk5PRKMB24_cjs = require('./chunk-5PRKMB24.cjs');
24
24
  var chunkBFUOME67_cjs = require('./chunk-BFUOME67.cjs');
25
25
  require('./chunk-FQPEMEWX.cjs');
26
- var chunk6KFLYYOC_cjs = require('./chunk-6KFLYYOC.cjs');
27
- require('./chunk-425IZOQ5.cjs');
26
+ var chunk2QGYQBS2_cjs = require('./chunk-2QGYQBS2.cjs');
27
+ require('./chunk-TQHGE7UC.cjs');
28
28
  var chunkUWG5GX6E_cjs = require('./chunk-UWG5GX6E.cjs');
29
29
  require('./chunk-AOSSQDVO.cjs');
30
30
  var chunkOI2GQ25X_cjs = require('./chunk-OI2GQ25X.cjs');
@@ -46,7 +46,7 @@ var chunkN66HCGCY_cjs = require('./chunk-N66HCGCY.cjs');
46
46
 
47
47
  // src/identity/rebuild.ts
48
48
  async function rebuildIdentityClosure(store) {
49
- await chunkMFZR4QKM_cjs.storeRuntime(store).rebuildIdentityClosure();
49
+ await chunk3KOY4FH3_cjs.storeRuntime(store).rebuildIdentityClosure();
50
50
  }
51
51
 
52
52
  // src/identity/types.ts
@@ -110,7 +110,7 @@ async function migrateLegacyEmbeddings(options) {
110
110
  after: cursor
111
111
  });
112
112
  } catch (error) {
113
- if (cursor === void 0 && chunkJR6SX5RH_cjs.isMissingTableError(error)) {
113
+ if (cursor === void 0 && chunkSIT26LAZ_cjs.isMissingTableError(error)) {
114
114
  return {
115
115
  migrated: 0,
116
116
  perField: {},
@@ -265,155 +265,155 @@ function decodeEmbeddingJson(row) {
265
265
 
266
266
  Object.defineProperty(exports, "ExecutableAggregateQuery", {
267
267
  enumerable: true,
268
- get: function () { return chunkBR7SHKGM_cjs.ExecutableAggregateQuery; }
268
+ get: function () { return chunkSR725PWF_cjs.ExecutableAggregateQuery; }
269
269
  });
270
270
  Object.defineProperty(exports, "ExecutableQuery", {
271
271
  enumerable: true,
272
- get: function () { return chunkBR7SHKGM_cjs.ExecutableQuery; }
272
+ get: function () { return chunkSR725PWF_cjs.ExecutableQuery; }
273
273
  });
274
274
  Object.defineProperty(exports, "MAX_EXPLICIT_RECURSIVE_DEPTH", {
275
275
  enumerable: true,
276
- get: function () { return chunkBR7SHKGM_cjs.MAX_EXPLICIT_RECURSIVE_DEPTH; }
276
+ get: function () { return chunkSR725PWF_cjs.MAX_EXPLICIT_RECURSIVE_DEPTH; }
277
277
  });
278
278
  Object.defineProperty(exports, "MAX_RECURSIVE_DEPTH", {
279
279
  enumerable: true,
280
- get: function () { return chunkBR7SHKGM_cjs.MAX_RECURSIVE_DEPTH; }
280
+ get: function () { return chunkSR725PWF_cjs.MAX_RECURSIVE_DEPTH; }
281
281
  });
282
282
  Object.defineProperty(exports, "PreparedQuery", {
283
283
  enumerable: true,
284
- get: function () { return chunkBR7SHKGM_cjs.PreparedQuery; }
284
+ get: function () { return chunkSR725PWF_cjs.PreparedQuery; }
285
285
  });
286
286
  Object.defineProperty(exports, "QueryBuilder", {
287
287
  enumerable: true,
288
- get: function () { return chunkBR7SHKGM_cjs.QueryBuilder; }
288
+ get: function () { return chunkSR725PWF_cjs.QueryBuilder; }
289
289
  });
290
290
  Object.defineProperty(exports, "RecordedStoreView", {
291
291
  enumerable: true,
292
- get: function () { return chunkBR7SHKGM_cjs.RecordedStoreView; }
292
+ get: function () { return chunkSR725PWF_cjs.RecordedStoreView; }
293
293
  });
294
294
  Object.defineProperty(exports, "StoreSearch", {
295
295
  enumerable: true,
296
- get: function () { return chunkBR7SHKGM_cjs.StoreSearch; }
296
+ get: function () { return chunkSR725PWF_cjs.StoreSearch; }
297
297
  });
298
298
  Object.defineProperty(exports, "StoreView", {
299
299
  enumerable: true,
300
- get: function () { return chunkBR7SHKGM_cjs.StoreView; }
300
+ get: function () { return chunkSR725PWF_cjs.StoreView; }
301
301
  });
302
302
  Object.defineProperty(exports, "UnionableQuery", {
303
303
  enumerable: true,
304
- get: function () { return chunkBR7SHKGM_cjs.UnionableQuery; }
304
+ get: function () { return chunkSR725PWF_cjs.UnionableQuery; }
305
305
  });
306
306
  Object.defineProperty(exports, "avg", {
307
307
  enumerable: true,
308
- get: function () { return chunkBR7SHKGM_cjs.avg; }
308
+ get: function () { return chunkSR725PWF_cjs.avg; }
309
309
  });
310
310
  Object.defineProperty(exports, "composeFragments", {
311
311
  enumerable: true,
312
- get: function () { return chunkBR7SHKGM_cjs.composeFragments; }
312
+ get: function () { return chunkSR725PWF_cjs.composeFragments; }
313
313
  });
314
314
  Object.defineProperty(exports, "count", {
315
315
  enumerable: true,
316
- get: function () { return chunkBR7SHKGM_cjs.count; }
316
+ get: function () { return chunkSR725PWF_cjs.count; }
317
317
  });
318
318
  Object.defineProperty(exports, "countDistinct", {
319
319
  enumerable: true,
320
- get: function () { return chunkBR7SHKGM_cjs.countDistinct; }
320
+ get: function () { return chunkSR725PWF_cjs.countDistinct; }
321
321
  });
322
322
  Object.defineProperty(exports, "countDistinctEdges", {
323
323
  enumerable: true,
324
- get: function () { return chunkBR7SHKGM_cjs.countDistinctEdges; }
324
+ get: function () { return chunkSR725PWF_cjs.countDistinctEdges; }
325
325
  });
326
326
  Object.defineProperty(exports, "countEdges", {
327
327
  enumerable: true,
328
- get: function () { return chunkBR7SHKGM_cjs.countEdges; }
328
+ get: function () { return chunkSR725PWF_cjs.countEdges; }
329
329
  });
330
330
  Object.defineProperty(exports, "createAdapterStore", {
331
331
  enumerable: true,
332
- get: function () { return chunkBR7SHKGM_cjs.createAdapterStore; }
332
+ get: function () { return chunkSR725PWF_cjs.createAdapterStore; }
333
333
  });
334
334
  Object.defineProperty(exports, "createAdapterStoreWithSchema", {
335
335
  enumerable: true,
336
- get: function () { return chunkBR7SHKGM_cjs.createAdapterStoreWithSchema; }
336
+ get: function () { return chunkSR725PWF_cjs.createAdapterStoreWithSchema; }
337
337
  });
338
338
  Object.defineProperty(exports, "createFragment", {
339
339
  enumerable: true,
340
- get: function () { return chunkBR7SHKGM_cjs.createFragment; }
340
+ get: function () { return chunkSR725PWF_cjs.createFragment; }
341
341
  });
342
342
  Object.defineProperty(exports, "createQueryBuilder", {
343
343
  enumerable: true,
344
- get: function () { return chunkBR7SHKGM_cjs.createQueryBuilder; }
344
+ get: function () { return chunkSR725PWF_cjs.createQueryBuilder; }
345
345
  });
346
346
  Object.defineProperty(exports, "createStore", {
347
347
  enumerable: true,
348
- get: function () { return chunkBR7SHKGM_cjs.createStore; }
348
+ get: function () { return chunkSR725PWF_cjs.createStore; }
349
349
  });
350
350
  Object.defineProperty(exports, "createStoreWithSchema", {
351
351
  enumerable: true,
352
- get: function () { return chunkBR7SHKGM_cjs.createStoreWithSchema; }
352
+ get: function () { return chunkSR725PWF_cjs.createStoreWithSchema; }
353
353
  });
354
354
  Object.defineProperty(exports, "createVerifiedAdapterStore", {
355
355
  enumerable: true,
356
- get: function () { return chunkBR7SHKGM_cjs.createVerifiedAdapterStore; }
356
+ get: function () { return chunkSR725PWF_cjs.createVerifiedAdapterStore; }
357
357
  });
358
358
  Object.defineProperty(exports, "createVerifiedStore", {
359
359
  enumerable: true,
360
- get: function () { return chunkBR7SHKGM_cjs.createVerifiedStore; }
360
+ get: function () { return chunkSR725PWF_cjs.createVerifiedStore; }
361
361
  });
362
362
  Object.defineProperty(exports, "defineSubgraphProject", {
363
363
  enumerable: true,
364
- get: function () { return chunkBR7SHKGM_cjs.defineSubgraphProject; }
364
+ get: function () { return chunkSR725PWF_cjs.defineSubgraphProject; }
365
365
  });
366
366
  Object.defineProperty(exports, "field", {
367
367
  enumerable: true,
368
- get: function () { return chunkBR7SHKGM_cjs.field; }
368
+ get: function () { return chunkSR725PWF_cjs.field; }
369
369
  });
370
370
  Object.defineProperty(exports, "having", {
371
371
  enumerable: true,
372
- get: function () { return chunkBR7SHKGM_cjs.having; }
372
+ get: function () { return chunkSR725PWF_cjs.having; }
373
373
  });
374
374
  Object.defineProperty(exports, "havingEq", {
375
375
  enumerable: true,
376
- get: function () { return chunkBR7SHKGM_cjs.havingEq; }
376
+ get: function () { return chunkSR725PWF_cjs.havingEq; }
377
377
  });
378
378
  Object.defineProperty(exports, "havingGt", {
379
379
  enumerable: true,
380
- get: function () { return chunkBR7SHKGM_cjs.havingGt; }
380
+ get: function () { return chunkSR725PWF_cjs.havingGt; }
381
381
  });
382
382
  Object.defineProperty(exports, "havingGte", {
383
383
  enumerable: true,
384
- get: function () { return chunkBR7SHKGM_cjs.havingGte; }
384
+ get: function () { return chunkSR725PWF_cjs.havingGte; }
385
385
  });
386
386
  Object.defineProperty(exports, "havingLt", {
387
387
  enumerable: true,
388
- get: function () { return chunkBR7SHKGM_cjs.havingLt; }
388
+ get: function () { return chunkSR725PWF_cjs.havingLt; }
389
389
  });
390
390
  Object.defineProperty(exports, "havingLte", {
391
391
  enumerable: true,
392
- get: function () { return chunkBR7SHKGM_cjs.havingLte; }
392
+ get: function () { return chunkSR725PWF_cjs.havingLte; }
393
393
  });
394
394
  Object.defineProperty(exports, "limitFragment", {
395
395
  enumerable: true,
396
- get: function () { return chunkBR7SHKGM_cjs.limitFragment; }
396
+ get: function () { return chunkSR725PWF_cjs.limitFragment; }
397
397
  });
398
398
  Object.defineProperty(exports, "max", {
399
399
  enumerable: true,
400
- get: function () { return chunkBR7SHKGM_cjs.max; }
400
+ get: function () { return chunkSR725PWF_cjs.max; }
401
401
  });
402
402
  Object.defineProperty(exports, "min", {
403
403
  enumerable: true,
404
- get: function () { return chunkBR7SHKGM_cjs.min; }
404
+ get: function () { return chunkSR725PWF_cjs.min; }
405
405
  });
406
406
  Object.defineProperty(exports, "offsetFragment", {
407
407
  enumerable: true,
408
- get: function () { return chunkBR7SHKGM_cjs.offsetFragment; }
408
+ get: function () { return chunkSR725PWF_cjs.offsetFragment; }
409
409
  });
410
410
  Object.defineProperty(exports, "orderByFragment", {
411
411
  enumerable: true,
412
- get: function () { return chunkBR7SHKGM_cjs.orderByFragment; }
412
+ get: function () { return chunkSR725PWF_cjs.orderByFragment; }
413
413
  });
414
414
  Object.defineProperty(exports, "sum", {
415
415
  enumerable: true,
416
- get: function () { return chunkBR7SHKGM_cjs.sum; }
416
+ get: function () { return chunkSR725PWF_cjs.sum; }
417
417
  });
418
418
  Object.defineProperty(exports, "sqliteVecStrategy", {
419
419
  enumerable: true,
@@ -429,15 +429,19 @@ Object.defineProperty(exports, "pgvectorStrategy", {
429
429
  });
430
430
  Object.defineProperty(exports, "deleteLegacyRecordedAnchorMap", {
431
431
  enumerable: true,
432
- get: function () { return chunkKABFHAL7_cjs.deleteLegacyRecordedAnchorMap; }
432
+ get: function () { return chunkUMGZDVOA_cjs.deleteLegacyRecordedAnchorMap; }
433
433
  });
434
434
  Object.defineProperty(exports, "migrateLegacyRecordedTime", {
435
435
  enumerable: true,
436
- get: function () { return chunkKABFHAL7_cjs.migrateLegacyRecordedTime; }
436
+ get: function () { return chunkUMGZDVOA_cjs.migrateLegacyRecordedTime; }
437
437
  });
438
438
  Object.defineProperty(exports, "migrateRecordedAnchor", {
439
439
  enumerable: true,
440
- get: function () { return chunkKABFHAL7_cjs.migrateRecordedAnchor; }
440
+ get: function () { return chunkUMGZDVOA_cjs.migrateRecordedAnchor; }
441
+ });
442
+ Object.defineProperty(exports, "repairInvertedValidityWindows", {
443
+ enumerable: true,
444
+ get: function () { return chunkUMGZDVOA_cjs.repairInvertedValidityWindows; }
441
445
  });
442
446
  Object.defineProperty(exports, "createExternalRef", {
443
447
  enumerable: true,
@@ -461,67 +465,67 @@ Object.defineProperty(exports, "metaEdge", {
461
465
  });
462
466
  Object.defineProperty(exports, "broader", {
463
467
  enumerable: true,
464
- get: function () { return chunk6JVZSOHQ_cjs.broader; }
468
+ get: function () { return chunk3FPR224C_cjs.broader; }
465
469
  });
466
470
  Object.defineProperty(exports, "core", {
467
471
  enumerable: true,
468
- get: function () { return chunk6JVZSOHQ_cjs.core; }
472
+ get: function () { return chunk3FPR224C_cjs.core; }
469
473
  });
470
474
  Object.defineProperty(exports, "differentFrom", {
471
475
  enumerable: true,
472
- get: function () { return chunk6JVZSOHQ_cjs.differentFrom; }
476
+ get: function () { return chunk3FPR224C_cjs.differentFrom; }
473
477
  });
474
478
  Object.defineProperty(exports, "disjointWith", {
475
479
  enumerable: true,
476
- get: function () { return chunk6JVZSOHQ_cjs.disjointWith; }
480
+ get: function () { return chunk3FPR224C_cjs.disjointWith; }
477
481
  });
478
482
  Object.defineProperty(exports, "equivalentTo", {
479
483
  enumerable: true,
480
- get: function () { return chunk6JVZSOHQ_cjs.equivalentTo; }
484
+ get: function () { return chunk3FPR224C_cjs.equivalentTo; }
481
485
  });
482
486
  Object.defineProperty(exports, "getActiveSchema", {
483
487
  enumerable: true,
484
- get: function () { return chunk6JVZSOHQ_cjs.getActiveSchema; }
488
+ get: function () { return chunk3FPR224C_cjs.getActiveSchema; }
485
489
  });
486
490
  Object.defineProperty(exports, "getCommittedSchemaVersion", {
487
491
  enumerable: true,
488
- get: function () { return chunk6JVZSOHQ_cjs.getCommittedSchemaVersion; }
492
+ get: function () { return chunk3FPR224C_cjs.getCommittedSchemaVersion; }
489
493
  });
490
494
  Object.defineProperty(exports, "hasPart", {
491
495
  enumerable: true,
492
- get: function () { return chunk6JVZSOHQ_cjs.hasPart; }
496
+ get: function () { return chunk3FPR224C_cjs.hasPart; }
493
497
  });
494
498
  Object.defineProperty(exports, "implies", {
495
499
  enumerable: true,
496
- get: function () { return chunk6JVZSOHQ_cjs.implies; }
500
+ get: function () { return chunk3FPR224C_cjs.implies; }
497
501
  });
498
502
  Object.defineProperty(exports, "inverseOf", {
499
503
  enumerable: true,
500
- get: function () { return chunk6JVZSOHQ_cjs.inverseOf; }
504
+ get: function () { return chunk3FPR224C_cjs.inverseOf; }
501
505
  });
502
506
  Object.defineProperty(exports, "isSchemaInitialized", {
503
507
  enumerable: true,
504
- get: function () { return chunk6JVZSOHQ_cjs.isSchemaInitialized; }
508
+ get: function () { return chunk3FPR224C_cjs.isSchemaInitialized; }
505
509
  });
506
510
  Object.defineProperty(exports, "narrower", {
507
511
  enumerable: true,
508
- get: function () { return chunk6JVZSOHQ_cjs.narrower; }
512
+ get: function () { return chunk3FPR224C_cjs.narrower; }
509
513
  });
510
514
  Object.defineProperty(exports, "partOf", {
511
515
  enumerable: true,
512
- get: function () { return chunk6JVZSOHQ_cjs.partOf; }
516
+ get: function () { return chunk3FPR224C_cjs.partOf; }
513
517
  });
514
518
  Object.defineProperty(exports, "relatedTo", {
515
519
  enumerable: true,
516
- get: function () { return chunk6JVZSOHQ_cjs.relatedTo; }
520
+ get: function () { return chunk3FPR224C_cjs.relatedTo; }
517
521
  });
518
522
  Object.defineProperty(exports, "sameAs", {
519
523
  enumerable: true,
520
- get: function () { return chunk6JVZSOHQ_cjs.sameAs; }
524
+ get: function () { return chunk3FPR224C_cjs.sameAs; }
521
525
  });
522
526
  Object.defineProperty(exports, "subClassOf", {
523
527
  enumerable: true,
524
- get: function () { return chunk6JVZSOHQ_cjs.subClassOf; }
528
+ get: function () { return chunk3FPR224C_cjs.subClassOf; }
525
529
  });
526
530
  Object.defineProperty(exports, "defineEdge", {
527
531
  enumerable: true,
@@ -537,35 +541,35 @@ Object.defineProperty(exports, "isMetaEdge", {
537
541
  });
538
542
  Object.defineProperty(exports, "exists", {
539
543
  enumerable: true,
540
- get: function () { return chunkOIFSOPSR_cjs.exists; }
544
+ get: function () { return chunkEZEEWCFJ_cjs.exists; }
541
545
  });
542
546
  Object.defineProperty(exports, "fieldRef", {
543
547
  enumerable: true,
544
- get: function () { return chunkOIFSOPSR_cjs.fieldRef; }
548
+ get: function () { return chunkEZEEWCFJ_cjs.fieldRef; }
545
549
  });
546
550
  Object.defineProperty(exports, "generateId", {
547
551
  enumerable: true,
548
- get: function () { return chunkOIFSOPSR_cjs.generateId; }
552
+ get: function () { return chunkEZEEWCFJ_cjs.generateId; }
549
553
  });
550
554
  Object.defineProperty(exports, "inSubquery", {
551
555
  enumerable: true,
552
- get: function () { return chunkOIFSOPSR_cjs.inSubquery; }
556
+ get: function () { return chunkEZEEWCFJ_cjs.inSubquery; }
553
557
  });
554
558
  Object.defineProperty(exports, "isParameterRef", {
555
559
  enumerable: true,
556
- get: function () { return chunkOIFSOPSR_cjs.isParameterRef; }
560
+ get: function () { return chunkEZEEWCFJ_cjs.isParameterRef; }
557
561
  });
558
562
  Object.defineProperty(exports, "notExists", {
559
563
  enumerable: true,
560
- get: function () { return chunkOIFSOPSR_cjs.notExists; }
564
+ get: function () { return chunkEZEEWCFJ_cjs.notExists; }
561
565
  });
562
566
  Object.defineProperty(exports, "notInSubquery", {
563
567
  enumerable: true,
564
- get: function () { return chunkOIFSOPSR_cjs.notInSubquery; }
568
+ get: function () { return chunkEZEEWCFJ_cjs.notInSubquery; }
565
569
  });
566
570
  Object.defineProperty(exports, "param", {
567
571
  enumerable: true,
568
- get: function () { return chunkOIFSOPSR_cjs.param; }
572
+ get: function () { return chunkEZEEWCFJ_cjs.param; }
569
573
  });
570
574
  Object.defineProperty(exports, "DEFAULT_SQL_SCHEMA", {
571
575
  enumerable: true,
@@ -581,11 +585,11 @@ Object.defineProperty(exports, "recordedRelation", {
581
585
  });
582
586
  Object.defineProperty(exports, "rowPropsToJsonText", {
583
587
  enumerable: true,
584
- get: function () { return chunk3HGRTCDU_cjs.rowPropsToJsonText; }
588
+ get: function () { return chunk5PRKMB24_cjs.rowPropsToJsonText; }
585
589
  });
586
590
  Object.defineProperty(exports, "rowPropsToObject", {
587
591
  enumerable: true,
588
- get: function () { return chunk3HGRTCDU_cjs.rowPropsToObject; }
592
+ get: function () { return chunk5PRKMB24_cjs.rowPropsToObject; }
589
593
  });
590
594
  Object.defineProperty(exports, "asEdgeId", {
591
595
  enumerable: true,
@@ -625,19 +629,19 @@ Object.defineProperty(exports, "isNodeType", {
625
629
  });
626
630
  Object.defineProperty(exports, "asRecordedInstant", {
627
631
  enumerable: true,
628
- get: function () { return chunk6KFLYYOC_cjs.asRecordedInstant; }
632
+ get: function () { return chunk2QGYQBS2_cjs.asRecordedInstant; }
629
633
  });
630
634
  Object.defineProperty(exports, "compareRecordedInstants", {
631
635
  enumerable: true,
632
- get: function () { return chunk6KFLYYOC_cjs.compareRecordedInstants; }
636
+ get: function () { return chunk2QGYQBS2_cjs.compareRecordedInstants; }
633
637
  });
634
638
  Object.defineProperty(exports, "recordedInstantRevision", {
635
639
  enumerable: true,
636
- get: function () { return chunk6KFLYYOC_cjs.recordedInstantRevision; }
640
+ get: function () { return chunk2QGYQBS2_cjs.recordedInstantRevision; }
637
641
  });
638
642
  Object.defineProperty(exports, "recordedInstantWallTime", {
639
643
  enumerable: true,
640
- get: function () { return chunk6KFLYYOC_cjs.recordedInstantWallTime; }
644
+ get: function () { return chunk2QGYQBS2_cjs.recordedInstantWallTime; }
641
645
  });
642
646
  Object.defineProperty(exports, "andWhere", {
643
647
  enumerable: true,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/identity/rebuild.ts","../src/identity/types.ts","../src/backend/migrate-vectors.ts"],"names":["storeRuntime","ValidationError","DEFAULT_EMBEDDING_METRIC","DEFAULT_EMBEDDING_INDEX_TYPE","LEGACY_EMBEDDINGS_TABLE_NAME","createDataKeyedBag","isMissingTableError","embedding","EmbeddingDimensionChangedError","requireDefined","sql","asCompiledRowsSql"],"mappings":"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","file":"index.cjs","sourcesContent":["import { type GraphDef, type GraphIdentityConfig } from \"../core/define-graph\";\nimport { storeRuntime } from \"../store/runtime-port\";\nimport { type Store } from \"../store/store\";\n\n/**\n * Rebuilds the derived current identity closure for an identity-enabled store.\n * This is a repair operation: it does not change graph revision or assertions.\n */\nexport async function rebuildIdentityClosure<\n G extends GraphDef & Readonly<{ identity: GraphIdentityConfig }>,\n>(store: Store<G>): Promise<void> {\n await storeRuntime(store).rebuildIdentityClosure();\n}\n","import {\n type AllNodeTypes,\n type GraphDef,\n type NodeKinds,\n} from \"../core/define-graph\";\nimport { ValidationError } from \"../errors\";\nimport {\n type DynamicNode,\n type DynamicNodeReference,\n type GraphNodeReference,\n type Node,\n type NodeRef,\n} from \"../store/types\";\n\n/**\n * The accepted *input* form for every identity facade method: a whole node or\n * a `{ kind, id }` pair for any compile-time graph kind, plus a proof-bearing\n * node or reference produced through the runtime collection lane. Runtime\n * values stay nominal so accepting them does not make an arbitrary\n * `{ kind: string, id: string }` object type-safe.\n *\n * Identity results use {@link IdentityNodeReference}, which honestly includes\n * runtime kinds because an evolved kind can belong to a class reached from a\n * compile-time node.\n */\nexport type IdentityNodeRefInput<G extends GraphDef> =\n NodeRef<AllNodeTypes<G>> | DynamicNode | DynamicNodeReference;\n\n/**\n * A node reference returned by Operational Identity.\n *\n * Identity classes can contain runtime-evolved kinds even when a read starts\n * from a compile-time node, so results honestly include both lanes.\n */\nexport type IdentityNodeReference<G extends GraphDef> =\n GraphNodeReference<G> | DynamicNodeReference;\n\n/** A hydrated compile-time or runtime identity member. */\nexport type IdentityNode<G extends GraphDef> =\n | {\n [K in NodeKinds<G>]: Node<G[\"nodes\"][K][\"type\"]>;\n }[NodeKinds<G>]\n | DynamicNode;\n\ndeclare const __identityAssertionId: unique symbol;\n\nexport type IdentityAssertionId = string &\n Readonly<{ [__identityAssertionId]: true }>;\n\n/**\n * Brands a non-empty string as an {@link IdentityAssertionId}.\n *\n * Use this when a persisted identity assertion id has round-tripped through\n * untyped storage or an external boundary and must be passed back to a\n * retraction surface such as `retractAssertion` or `bulkRetractAssertions`.\n * Mirrors the `asNodeId` / `asEdgeId` precedent.\n *\n * @throws {ValidationError} when `value` is empty.\n */\nexport function asIdentityAssertionId(value: string): IdentityAssertionId {\n if (value.length === 0) {\n throw new ValidationError(\n \"asIdentityAssertionId must be a non-empty string.\",\n {\n issues: [\n {\n path: \"asIdentityAssertionId\",\n message: \"Expected a non-empty string.\",\n },\n ],\n },\n {\n suggestion: \"Use a persisted identity assertion id value.\",\n },\n );\n }\n return value as IdentityAssertionId;\n}\n\n/**\n * What one assertion claims about a pair of nodes: `\"same\"` merges them into\n * one equivalence set, `\"different\"` records a disjointness that a later\n * `\"same\"` claim must not contradict.\n */\nexport type IdentityRelation = \"same\" | \"different\";\n\n/**\n * One persisted identity claim about an ordered pair of nodes. Returned by the\n * assertion writers and by `identity.assertionsOf(...)`; `validTo` is set when\n * the assertion has been retracted, so a historical read can still see it.\n */\nexport type IdentityAssertion<G extends GraphDef> = Readonly<{\n id: IdentityAssertionId;\n relation: IdentityRelation;\n a: IdentityNodeReference<G>;\n b: IdentityNodeReference<G>;\n validFrom: string;\n validTo?: string;\n}>;\n\n/** Result of an idempotent assertion write. */\nexport type IdentityAssertionResult<G extends GraphDef> = Readonly<{\n assertion: IdentityAssertion<G>;\n action: \"created\" | \"existing\";\n}>;\n\n/** The half-open effective-time window of an identity assertion. */\nexport type IdentityValidityWindow = Readonly<{\n validFrom?: string;\n validTo?: string;\n}>;\n\n/** One ordered node pair handed to `bulkAssertSame` / `bulkAssertDifferent`. */\nexport type IdentityPair<G extends GraphDef> = Readonly<{\n a: IdentityNodeRefInput<G>;\n b: IdentityNodeRefInput<G>;\n}> &\n IdentityValidityWindow;\n\n/**\n * The read half of the identity surface: equivalence-set membership,\n * representative selection, and the assertions behind them.\n *\n * Obtained from a read-only lens — `store.asOf(...).identity`,\n * `store.snapshot().identity` — where it answers at that view's coordinate.\n * The full read+write surface is {@link IdentityFacade}.\n */\nexport type IdentityReadFacade<G extends GraphDef> = Readonly<{\n representativeOf: (\n ref: IdentityNodeRefInput<G>,\n ) => Promise<IdentityNodeReference<G> | undefined>;\n membersOf: (\n ref: IdentityNodeRefInput<G>,\n ) => Promise<readonly IdentityNodeReference<G>[]>;\n nodesOf: (\n ref: IdentityNodeRefInput<G>,\n ) => Promise<readonly IdentityNode<G>[]>;\n areSame: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n ) => Promise<boolean>;\n areDifferent: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n ) => Promise<boolean>;\n assertionsOf: (\n ref: IdentityNodeRefInput<G>,\n ) => Promise<readonly IdentityAssertion<G>[]>;\n}>;\n\n/**\n * The full TypeGraph Identity Profile surface: {@link IdentityReadFacade} plus\n * the assertion writers and retractions.\n *\n * Obtained from `store.identity` or `tx.identity`, and present only on graphs\n * that declared `identity: { ... }` in `defineGraph`. Every writer is\n * idempotent — re-asserting an existing claim returns it with\n * `action: \"existing\"` rather than duplicating it.\n */\nexport type IdentityFacade<G extends GraphDef> = IdentityReadFacade<G> &\n Readonly<{\n assertSame: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n window?: IdentityValidityWindow,\n ) => Promise<IdentityAssertionResult<G>>;\n assertDifferent: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n window?: IdentityValidityWindow,\n ) => Promise<IdentityAssertionResult<G>>;\n bulkAssertSame: (\n pairs: readonly IdentityPair<G>[],\n ) => Promise<readonly IdentityAssertionResult<G>[]>;\n bulkAssertDifferent: (\n pairs: readonly IdentityPair<G>[],\n ) => Promise<readonly IdentityAssertionResult<G>[]>;\n retractAssertion: (\n id: IdentityAssertionId,\n ) => Promise<IdentityAssertion<G> | undefined>;\n retractSameAssertion: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n ) => Promise<IdentityAssertion<G> | undefined>;\n retractDifferentAssertion: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n ) => Promise<IdentityAssertion<G> | undefined>;\n bulkRetractAssertions: (\n ids: readonly IdentityAssertionId[],\n ) => Promise<readonly IdentityAssertion<G>[]>;\n }>;\n\n/**\n * Per-transaction identity write counts carried by a transaction receipt.\n * `total` is the sum of the three preceding counters.\n */\nexport type IdentityWriteSummary = Readonly<{\n sameAssertions: number;\n differentAssertions: number;\n retractions: number;\n total: number;\n}>;\n","/**\n * One-time offline migration: legacy shared embeddings table → per-field\n * strategy storage.\n *\n * ## What this is for\n *\n * The cross-backend vector cutover (#157) dropped the single shared\n * `typegraph_node_embeddings` table. Each\n * `VectorStrategy` now OWNS one typed, fixed-dimension structure per\n * `(nodeKind, fieldPath)` — the only layout that can be ANN-indexed on\n * libSQL and sqlite-vec, not just pgvector.\n *\n * Deployments that wrote embeddings under the old shared table before\n * upgrading still hold those rows. This utility drains them into the new\n * per-field storage **once**, during the upgrade, so existing embedded\n * data survives the cutover without re-embedding from source.\n *\n * It is an explicitly-run, offline step — not wired into `materializeIndexes`\n * or any boot path. Run it once after deploying the new version and before\n * (or alongside) the first `materializeIndexes()`, then drop the legacy\n * table at your leisure.\n *\n * ## How it works\n *\n * - Skips cleanly (returns a zero summary) when the legacy table is absent —\n * a fresh install, or a re-run after the table was dropped.\n * - Reads rows in keyset-paginated batches (never the whole table at once),\n * decoding the engine-native embedding column to a numeric array at the SQL\n * level: sqlite-vec stored a `vec_f32` blob (`vec_to_json` decodes it);\n * pgvector stored a native `vector` (`::text` yields a `[…]` literal).\n * - Re-inserts each row through `backend.upsertEmbedding`, which routes the\n * active strategy's `buildUpsert` and idempotently provisions the per-field\n * storage (the same `(nodeKind, fieldPath)` slot a fresh store write uses).\n * The migration stays graph-agnostic and execution-correct on both the\n * sync (better-sqlite3) and async (libsql / Postgres) backends — it does\n * not re-implement the backend's statement-execution glue.\n *\n * Idempotent and resumable: a partial run followed by a full run converges\n * to the same per-field tables, because every write is an upsert keyed by\n * `(graph_id, node_id)` in the strategy's owned storage.\n */\nimport {\n DEFAULT_EMBEDDING_INDEX_TYPE,\n DEFAULT_EMBEDDING_METRIC,\n type EmbeddingIndexType,\n type EmbeddingMetric,\n} from \"../core/embedding\";\nimport { EmbeddingDimensionChangedError } from \"../errors\";\nimport { sql, type SqlFragment } from \"../query/sql-fragment\";\nimport { asCompiledRowsSql } from \"../query/sql-intent\";\nimport { createDataKeyedBag } from \"../utils/object\";\nimport { requireDefined } from \"../utils/presence\";\nimport { isMissingTableError } from \"../utils/sql-errors\";\nimport { LEGACY_EMBEDDINGS_TABLE_NAME } from \"./drizzle/schema/sqlite\";\nimport { type GraphBackend } from \"./types\";\n\n/**\n * Default rows read per round-trip. Large enough to amortize round-trip\n * latency, small enough to bound peak memory regardless of table size.\n */\nconst DEFAULT_BATCH_SIZE = 500;\n\n/**\n * Metric / index type applied to a migrated field when no\n * {@link MigrateLegacyEmbeddingsOptions.resolveSlotConfig} is supplied (or\n * it returns `undefined`). Matches the defaults `embedding()` and\n * `resolveEmbeddingFields` apply, so a migrated field lands in storage shaped\n * identically to one written fresh through the store. Migrated data is only\n * ever brute-forceable until `materializeIndexes()` builds the ANN index, so\n * the index-type default governs only which ANN structure the per-field\n * storage DDL provisions, not the migration's correctness.\n */\nconst DEFAULT_SLOT_METRIC: EmbeddingMetric = DEFAULT_EMBEDDING_METRIC;\nconst DEFAULT_SLOT_INDEX_TYPE: EmbeddingIndexType =\n DEFAULT_EMBEDDING_INDEX_TYPE;\n\n/**\n * The resolved storage config for one `(nodeKind, fieldPath)` slot that the\n * legacy table did not record. The legacy shared table stored only the\n * vector and its dimension count — not the metric or index type — so a\n * caller that wants migrated fields to match a specific graph's `embedding()`\n * declarations supplies this resolver.\n */\nexport type LegacyEmbeddingSlotConfig = Readonly<{\n metric: EmbeddingMetric;\n indexType: EmbeddingIndexType;\n}>;\n\n/**\n * Options for {@link migrateLegacyEmbeddings}.\n */\nexport type MigrateLegacyEmbeddingsOptions = Readonly<{\n /**\n * The backend to migrate, wired with the destination `VectorStrategy`\n * (i.e. the post-cutover backend). Its `vectorStrategy` owns the per-field\n * storage rows are written into and its `upsertEmbedding` performs the\n * writes.\n */\n backend: GraphBackend;\n\n /**\n * Restrict the migration to a single graph. When omitted, every graph's\n * rows in the legacy table are migrated (the table is graph-scoped by its\n * `graph_id` column).\n */\n graphId?: string;\n\n /**\n * Resolves the metric / index type for a `(nodeKind, fieldPath)` slot the\n * legacy table didn't persist. Return `undefined` to fall back to the\n * cosine / hnsw defaults. Supply this (typically reading the graph's\n * `embedding()` declarations) when migrated fields must match a specific\n * metric — e.g. an `l2` field, which scores incorrectly under the cosine\n * default.\n */\n resolveSlotConfig?: (\n nodeKind: string,\n fieldPath: string,\n ) => LegacyEmbeddingSlotConfig | undefined;\n\n /** Rows read per round-trip. Defaults to {@link DEFAULT_BATCH_SIZE}. */\n batchSize?: number;\n\n /**\n * Physical name of the legacy table to drain. Defaults to\n * {@link LEGACY_EMBEDDINGS_TABLE_NAME}. Override only for a non-default\n * deployment that renamed the embeddings table.\n */\n legacyTableName?: string;\n}>;\n\n/**\n * Summary of a {@link migrateLegacyEmbeddings} run.\n */\nexport type MigrateLegacyEmbeddingsResult = Readonly<{\n /** Total embedding rows re-inserted into per-field storage. */\n migrated: number;\n /**\n * Per-`(nodeKind, fieldPath)` counts, keyed `\"<nodeKind>.<fieldPath>\"`\n * (the strategy's logical-slot key form). Empty when the legacy table was\n * absent or held no rows for the requested scope.\n */\n perField: Readonly<Record<string, number>>;\n /**\n * Rows skipped because their vector length didn't match the per-field\n * table's fixed dimension. The legacy shared column allowed mixed\n * dimensions for one `(nodeKind, fieldPath)` (e.g. an unmigrated model\n * change); the first migrated row fixes the typed table's dimension and\n * any differently-sized rows for that slot are skipped rather than aborting\n * the whole migration. Keyed `\"<nodeKind>.<fieldPath>\"`. Non-empty here\n * means those fields need a deliberate re-embed at a single dimension.\n */\n skippedDimensionMismatch: Readonly<Record<string, number>>;\n /**\n * Rows skipped because their legacy embedding could not be decoded into a\n * finite-number array — a corrupt value (e.g. a pgvector `vector` column\n * permits `NaN`/`Infinity`, which is not valid JSON). Keyed\n * `\"<nodeKind>.<fieldPath>\"`. Skipping + reporting keeps one bad row from\n * aborting the whole migration; non-empty here means those rows need manual\n * repair.\n */\n skippedDecodeError: Readonly<Record<string, number>>;\n /**\n * Whether the legacy table existed. `false` means the run was a clean\n * no-op (fresh install, or already-dropped table on a re-run).\n */\n legacyTablePresent: boolean;\n}>;\n\n/**\n * A single legacy embedding row, with the engine-native vector already\n * decoded to a JSON array string by the dialect-specific SELECT. The\n * legacy `dimensions` column is intentionally not read: the decoded array's\n * length is the authoritative fixed dimension for the destination slot, and\n * relying on it sidesteps the per-driver string/number coercion the legacy\n * integer column would otherwise need.\n */\ntype LegacyEmbeddingRow = Readonly<{\n graph_id: string;\n node_kind: string;\n node_id: string;\n field_path: string;\n /** JSON array text, e.g. `\"[0.1,0.2,0.3]\"` — decoded per dialect. */\n embedding_json: string;\n}>;\n\n/**\n * Re-inserts every embedding from the legacy shared\n * `typegraph_node_embeddings` table into the active\n * `backend.vectorStrategy`'s per-`(nodeKind, fieldPath)` storage.\n *\n * One-time, explicitly-run upgrade step for the shared-table → per-field\n * cutover (#157). Idempotent, batched, and a clean no-op when the legacy\n * table is absent. See the module doc comment for the full contract.\n *\n * @throws Error when the backend exposes no `vectorStrategy` /\n * `upsertEmbedding` (nothing to migrate *into*) — a configuration\n * error the caller must fix by wiring the destination strategy\n * before migrating.\n */\nexport async function migrateLegacyEmbeddings(\n options: MigrateLegacyEmbeddingsOptions,\n): Promise<MigrateLegacyEmbeddingsResult> {\n const {\n backend,\n graphId,\n resolveSlotConfig,\n batchSize = DEFAULT_BATCH_SIZE,\n legacyTableName = LEGACY_EMBEDDINGS_TABLE_NAME,\n } = options;\n\n if (\n backend.vectorStrategy === undefined ||\n backend.upsertEmbedding === undefined\n ) {\n throw new Error(\n \"migrateLegacyEmbeddings requires a backend wired with a vectorStrategy \" +\n \"(the destination per-field storage). Pass the post-cutover backend.\",\n );\n }\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw new RangeError(\n `batchSize must be a positive integer, got: ${batchSize}`,\n );\n }\n const upsertEmbedding = backend.upsertEmbedding;\n const ensureVectorSlotContribution = backend.ensureVectorSlotContribution;\n\n // Data-keyed: slot keys are built from a row's `node_kind` / `field_path`.\n const perField = createDataKeyedBag<number>();\n const skippedDimensionMismatch = createDataKeyedBag<number>();\n const skippedDecodeError = createDataKeyedBag<number>();\n // (kind, field) slots whose per-field table + durable marker this run has\n // already provisioned, mapped to the dimension the table was fixed at.\n // `upsertEmbedding` asserts the marker (#135) and no longer self-creates\n // the table, so this offline migration (privileged) provisions each slot\n // once — at the first row's dimension, which fixes the typed table just as\n // the original lazy write did. Differently-sized later rows for the same\n // slot are detected against this map and skipped BEFORE the upsert: the\n // marker assert would otherwise read the differently-dimensioned slot as\n // stale and abort the whole migration, and the ensure is deliberately not\n // re-run per row (that would trip the marker drift-guard).\n const ensuredSlots = new Map<string, number>();\n let migrated = 0;\n\n let cursor: LegacyRowCursor | undefined;\n for (;;) {\n let batch: readonly LegacyEmbeddingRow[];\n try {\n batch = await readLegacyBatch(backend, {\n legacyTableName,\n graphId,\n batchSize,\n after: cursor,\n });\n } catch (error) {\n // A missing legacy table is the expected \"nothing to migrate\" path on\n // the first read — surface it as a clean no-op, not a failure.\n if (cursor === undefined && isMissingTableError(error)) {\n return {\n migrated: 0,\n perField: {},\n skippedDimensionMismatch: {},\n skippedDecodeError: {},\n legacyTablePresent: false,\n };\n }\n throw error;\n }\n\n if (batch.length === 0) break;\n\n for (const row of batch) {\n const slotKey = `${row.node_kind}.${row.field_path}`;\n\n let embedding: readonly number[];\n try {\n embedding = decodeEmbeddingJson(row);\n } catch {\n // A corrupt legacy value (e.g. a pgvector `vector` column permits\n // NaN/Infinity, which is not valid JSON) is skipped + reported rather\n // than aborting the whole migration on one bad row.\n skippedDecodeError[slotKey] = (skippedDecodeError[slotKey] ?? 0) + 1;\n continue;\n }\n const config = resolveSlotConfig?.(row.node_kind, row.field_path);\n // The decoded length is the authoritative fixed dimension — the\n // strategy provisions its column type (e.g. `F32_BLOB(N)`) from it.\n const slot = {\n graphId: row.graph_id,\n nodeKind: row.node_kind,\n fieldPath: row.field_path,\n dimensions: embedding.length,\n metric: config?.metric ?? DEFAULT_SLOT_METRIC,\n indexType: config?.indexType ?? DEFAULT_SLOT_INDEX_TYPE,\n };\n\n // Provision the per-field table + durable marker before the first\n // write into this slot. Once per (graph, kind, field): the first row's\n // dimension fixes the table. Keyed by graph id too — the legacy table\n // is graph-scoped, so the same `kind.field` can recur across graphs.\n const ensuredKey = JSON.stringify([\n row.graph_id,\n row.node_kind,\n row.field_path,\n ]);\n if (\n ensureVectorSlotContribution !== undefined &&\n !ensuredSlots.has(ensuredKey)\n ) {\n await ensureVectorSlotContribution(slot);\n ensuredSlots.set(ensuredKey, slot.dimensions);\n }\n\n // The legacy shared column allowed mixed dimensions for one\n // (nodeKind, fieldPath); the per-field table is fixed at the first\n // migrated row's dimension. Skip a differently-sized row up front —\n // its slot would fail the marker assert as stale (different\n // signature), aborting the migration instead of skipping the row.\n const provisionedDimensions = ensuredSlots.get(ensuredKey);\n if (\n provisionedDimensions !== undefined &&\n provisionedDimensions !== embedding.length\n ) {\n skippedDimensionMismatch[slotKey] =\n (skippedDimensionMismatch[slotKey] ?? 0) + 1;\n continue;\n }\n\n try {\n await upsertEmbedding({ ...slot, nodeId: row.node_id, embedding });\n } catch (error) {\n // The legacy shared column allowed mixed dimensions for one\n // (nodeKind, fieldPath); the per-field table is fixed at the first\n // migrated row's dimension, so a differently-sized row is skipped and\n // reported rather than aborting the whole migration.\n if (error instanceof EmbeddingDimensionChangedError) {\n skippedDimensionMismatch[slotKey] =\n (skippedDimensionMismatch[slotKey] ?? 0) + 1;\n continue;\n }\n throw error;\n }\n\n migrated += 1;\n perField[slotKey] = (perField[slotKey] ?? 0) + 1;\n }\n\n if (batch.length < batchSize) break;\n const last = requireDefined(batch.at(-1));\n cursor = {\n graphId: last.graph_id,\n nodeKind: last.node_kind,\n nodeId: last.node_id,\n fieldPath: last.field_path,\n };\n }\n\n // SPREAD at the boundary. The three maps are null-prototype accumulators\n // because their keys are slot names built from row data; that protection is\n // internal, and returning the bags as-is handed a caller three maps with no\n // `toString` and `instanceof Object === false` — while the early\n // \"nothing to migrate\" return above hands back `{}` literals, so the same\n // exported function answered with two different kinds of object depending on\n // whether the legacy table existed. Spread copies own properties with\n // CreateDataProperty, so a `__proto__` slot key survives as an own key.\n return {\n migrated,\n perField: { ...perField },\n skippedDimensionMismatch: { ...skippedDimensionMismatch },\n skippedDecodeError: { ...skippedDecodeError },\n legacyTablePresent: true,\n };\n}\n\n/**\n * Composite keyset cursor over the legacy table's primary key\n * `(graph_id, node_kind, node_id, field_path)`. Stable under concurrent\n * writes and immune to OFFSET drift, so a batched walk reads every row once.\n */\ntype LegacyRowCursor = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n fieldPath: string;\n}>;\n\ntype ReadLegacyBatchParams = Readonly<{\n legacyTableName: string;\n graphId: string | undefined;\n batchSize: number;\n after: LegacyRowCursor | undefined;\n}>;\n\n/**\n * Reads one keyset-paginated batch of legacy rows, ordered by the primary\n * key, with the engine-native embedding column decoded to a JSON array\n * string by the dialect.\n */\nasync function readLegacyBatch(\n backend: GraphBackend,\n params: ReadLegacyBatchParams,\n): Promise<readonly LegacyEmbeddingRow[]> {\n const table = sql.identifier(params.legacyTableName);\n const embeddingJson = legacyEmbeddingDecodeExpression(backend);\n\n const conditions: SqlFragment[] = [];\n if (params.graphId !== undefined) {\n conditions.push(sql`\"graph_id\" = ${params.graphId}`);\n }\n if (params.after !== undefined) {\n conditions.push(keysetAfterCondition(params.after));\n }\n\n const whereClause =\n conditions.length === 0 ?\n sql``\n : sql` WHERE ${sql.join(conditions, sql` AND `)}`;\n\n const query = sql`\n SELECT\n \"graph_id\" AS graph_id,\n \"node_kind\" AS node_kind,\n \"node_id\" AS node_id,\n \"field_path\" AS field_path,\n ${embeddingJson} AS embedding_json\n FROM ${table}${whereClause}\n ORDER BY \"graph_id\" ASC, \"node_kind\" ASC, \"node_id\" ASC, \"field_path\" ASC\n LIMIT ${params.batchSize}\n `;\n\n return backend.execute<LegacyEmbeddingRow>(asCompiledRowsSql(query));\n}\n\n/**\n * The strict `>` comparison over the composite primary key, expressed as\n * the standard lexicographic OR-chain so it works on every dialect (SQLite\n * supports row-value comparison, but Postgres + SQLite both accept this\n * portable form).\n */\nfunction keysetAfterCondition(after: LegacyRowCursor): SqlFragment {\n return sql`\n (\n \"graph_id\" > ${after.graphId}\n OR (\"graph_id\" = ${after.graphId} AND \"node_kind\" > ${after.nodeKind})\n OR (\"graph_id\" = ${after.graphId} AND \"node_kind\" = ${after.nodeKind} AND \"node_id\" > ${after.nodeId})\n OR (\n \"graph_id\" = ${after.graphId}\n AND \"node_kind\" = ${after.nodeKind}\n AND \"node_id\" = ${after.nodeId}\n AND \"field_path\" > ${after.fieldPath}\n )\n )\n `;\n}\n\n/**\n * The SQL expression that decodes the legacy engine-native embedding column\n * into a JSON array string `embedding_json`. The single dialect branch in\n * this whole module: the legacy storage formats are genuinely engine-\n * specific, and there is no longer a strategy abstraction over the *legacy*\n * table to delegate to.\n */\nfunction legacyEmbeddingDecodeExpression(backend: GraphBackend): SqlFragment {\n switch (backend.dialect) {\n case \"sqlite\": {\n // Legacy SQLite embeddings were written via `vec_f32('[…]')`\n // (sqlite-vec binary). `vec_to_json` is its inverse, yielding the\n // JSON array text. Requires sqlite-vec on the connection — which the\n // legacy write path also required, so any deployment with legacy rows\n // has it loaded.\n return sql`vec_to_json(\"embedding\")`;\n }\n case \"postgres\": {\n // pgvector's native `vector` casts to its `[…]` text literal, which is\n // valid JSON for `JSON.parse`.\n return sql`\"embedding\"::text`;\n }\n default: {\n const _exhaustive: never = backend.dialect;\n throw new Error(\n `migrateLegacyEmbeddings does not support dialect: ${String(_exhaustive)}`,\n );\n }\n }\n}\n\n/**\n * Parses a decoded `embedding_json` array, asserting it is a non-empty array\n * of finite numbers. A bad decode (wrong type, NaN) names the offending row\n * loudly instead of writing a corrupt vector into per-field storage.\n */\nfunction decodeEmbeddingJson(row: LegacyEmbeddingRow): readonly number[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(row.embedding_json) as unknown;\n } catch (error) {\n throw new Error(\n `Failed to decode legacy embedding for ${row.node_kind}.${row.field_path} ` +\n `(graph ${row.graph_id}, node ${row.node_id}): not valid JSON.`,\n { cause: error },\n );\n }\n if (!Array.isArray(parsed) || parsed.length === 0) {\n throw new Error(\n `Legacy embedding for ${row.node_kind}.${row.field_path} ` +\n `(graph ${row.graph_id}, node ${row.node_id}) decoded to a non-array ` +\n `or empty value.`,\n );\n }\n for (const [index, value] of parsed.entries()) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new TypeError(\n `Legacy embedding for ${row.node_kind}.${row.field_path} ` +\n `(graph ${row.graph_id}, node ${row.node_id}) has a non-finite ` +\n `value at index ${index}: ${String(value)}.`,\n );\n }\n }\n return parsed as readonly number[];\n}\n"]}
1
+ {"version":3,"sources":["../src/identity/rebuild.ts","../src/identity/types.ts","../src/backend/migrate-vectors.ts"],"names":["storeRuntime","ValidationError","DEFAULT_EMBEDDING_METRIC","DEFAULT_EMBEDDING_INDEX_TYPE","LEGACY_EMBEDDINGS_TABLE_NAME","createDataKeyedBag","isMissingTableError","embedding","EmbeddingDimensionChangedError","requireDefined","sql","asCompiledRowsSql"],"mappings":"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","file":"index.cjs","sourcesContent":["import { type GraphDef, type GraphIdentityConfig } from \"../core/define-graph\";\nimport { storeRuntime } from \"../store/runtime-port\";\nimport { type Store } from \"../store/store\";\n\n/**\n * Rebuilds the derived current identity closure for an identity-enabled store.\n * This is a repair operation: it does not change graph revision or assertions.\n */\nexport async function rebuildIdentityClosure<\n G extends GraphDef & Readonly<{ identity: GraphIdentityConfig }>,\n>(store: Store<G>): Promise<void> {\n await storeRuntime(store).rebuildIdentityClosure();\n}\n","import {\n type AllNodeTypes,\n type GraphDef,\n type NodeKinds,\n} from \"../core/define-graph\";\nimport { ValidationError } from \"../errors\";\nimport {\n type DynamicNode,\n type DynamicNodeReference,\n type GraphNodeReference,\n type Node,\n type NodeRef,\n} from \"../store/types\";\n\n/**\n * The accepted *input* form for every identity facade method: a whole node or\n * a `{ kind, id }` pair for any compile-time graph kind, plus a proof-bearing\n * node or reference produced through the runtime collection lane. Runtime\n * values stay nominal so accepting them does not make an arbitrary\n * `{ kind: string, id: string }` object type-safe.\n *\n * Identity results use {@link IdentityNodeReference}, which honestly includes\n * runtime kinds because an evolved kind can belong to a class reached from a\n * compile-time node.\n */\nexport type IdentityNodeRefInput<G extends GraphDef> =\n NodeRef<AllNodeTypes<G>> | DynamicNode | DynamicNodeReference;\n\n/**\n * A node reference returned by Operational Identity.\n *\n * Identity classes can contain runtime-evolved kinds even when a read starts\n * from a compile-time node, so results honestly include both lanes.\n */\nexport type IdentityNodeReference<G extends GraphDef> =\n GraphNodeReference<G> | DynamicNodeReference;\n\n/** A hydrated compile-time or runtime identity member. */\nexport type IdentityNode<G extends GraphDef> =\n | {\n [K in NodeKinds<G>]: Node<G[\"nodes\"][K][\"type\"]>;\n }[NodeKinds<G>]\n | DynamicNode;\n\ndeclare const __identityAssertionId: unique symbol;\n\nexport type IdentityAssertionId = string &\n Readonly<{ [__identityAssertionId]: true }>;\n\n/**\n * Brands a non-empty string as an {@link IdentityAssertionId}.\n *\n * Use this when a persisted identity assertion id has round-tripped through\n * untyped storage or an external boundary and must be passed back to a\n * retraction surface such as `retractAssertion` or `bulkRetractAssertions`.\n * Mirrors the `asNodeId` / `asEdgeId` precedent.\n *\n * @throws {ValidationError} when `value` is empty.\n */\nexport function asIdentityAssertionId(value: string): IdentityAssertionId {\n if (value.length === 0) {\n throw new ValidationError(\n \"asIdentityAssertionId must be a non-empty string.\",\n {\n issues: [\n {\n path: \"asIdentityAssertionId\",\n message: \"Expected a non-empty string.\",\n },\n ],\n },\n {\n suggestion: \"Use a persisted identity assertion id value.\",\n },\n );\n }\n return value as IdentityAssertionId;\n}\n\n/**\n * What one assertion claims about a pair of nodes: `\"same\"` merges them into\n * one equivalence set, `\"different\"` records a disjointness that a later\n * `\"same\"` claim must not contradict.\n */\nexport type IdentityRelation = \"same\" | \"different\";\n\n/**\n * One persisted identity claim about an ordered pair of nodes. Returned by the\n * assertion writers and by `identity.assertionsOf(...)`; `validTo` is set when\n * the assertion has been retracted, so a historical read can still see it.\n */\nexport type IdentityAssertion<G extends GraphDef> = Readonly<{\n id: IdentityAssertionId;\n relation: IdentityRelation;\n a: IdentityNodeReference<G>;\n b: IdentityNodeReference<G>;\n validFrom: string;\n validTo?: string;\n}>;\n\n/** Result of an idempotent assertion write. */\nexport type IdentityAssertionResult<G extends GraphDef> = Readonly<{\n assertion: IdentityAssertion<G>;\n action: \"created\" | \"existing\";\n}>;\n\n/** The half-open effective-time window of an identity assertion. */\nexport type IdentityValidityWindow = Readonly<{\n validFrom?: string;\n validTo?: string;\n}>;\n\n/** One ordered node pair handed to `bulkAssertSame` / `bulkAssertDifferent`. */\nexport type IdentityPair<G extends GraphDef> = Readonly<{\n a: IdentityNodeRefInput<G>;\n b: IdentityNodeRefInput<G>;\n}> &\n IdentityValidityWindow;\n\n/**\n * The read half of the identity surface: equivalence-set membership,\n * representative selection, and the assertions behind them.\n *\n * Obtained from a read-only lens — `store.asOf(...).identity`,\n * `store.snapshot().identity` — where it answers at that view's coordinate.\n * The full read+write surface is {@link IdentityFacade}.\n */\nexport type IdentityReadFacade<G extends GraphDef> = Readonly<{\n representativeOf: (\n ref: IdentityNodeRefInput<G>,\n ) => Promise<IdentityNodeReference<G> | undefined>;\n membersOf: (\n ref: IdentityNodeRefInput<G>,\n ) => Promise<readonly IdentityNodeReference<G>[]>;\n nodesOf: (\n ref: IdentityNodeRefInput<G>,\n ) => Promise<readonly IdentityNode<G>[]>;\n areSame: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n ) => Promise<boolean>;\n areDifferent: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n ) => Promise<boolean>;\n assertionsOf: (\n ref: IdentityNodeRefInput<G>,\n ) => Promise<readonly IdentityAssertion<G>[]>;\n}>;\n\n/**\n * The full TypeGraph Identity Profile surface: {@link IdentityReadFacade} plus\n * the assertion writers and retractions.\n *\n * Obtained from `store.identity` or `tx.identity`, and present only on graphs\n * that declared `identity: { ... }` in `defineGraph`. Every writer is\n * idempotent — re-asserting an existing claim returns it with\n * `action: \"existing\"` rather than duplicating it.\n */\nexport type IdentityFacade<G extends GraphDef> = IdentityReadFacade<G> &\n Readonly<{\n assertSame: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n window?: IdentityValidityWindow,\n ) => Promise<IdentityAssertionResult<G>>;\n assertDifferent: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n window?: IdentityValidityWindow,\n ) => Promise<IdentityAssertionResult<G>>;\n bulkAssertSame: (\n pairs: readonly IdentityPair<G>[],\n ) => Promise<readonly IdentityAssertionResult<G>[]>;\n bulkAssertDifferent: (\n pairs: readonly IdentityPair<G>[],\n ) => Promise<readonly IdentityAssertionResult<G>[]>;\n retractAssertion: (\n id: IdentityAssertionId,\n ) => Promise<IdentityAssertion<G> | undefined>;\n retractSameAssertion: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n ) => Promise<IdentityAssertion<G> | undefined>;\n retractDifferentAssertion: (\n a: IdentityNodeRefInput<G>,\n b: IdentityNodeRefInput<G>,\n ) => Promise<IdentityAssertion<G> | undefined>;\n bulkRetractAssertions: (\n ids: readonly IdentityAssertionId[],\n ) => Promise<readonly IdentityAssertion<G>[]>;\n }>;\n\n/**\n * The assertion-only write surface of the TypeGraph Identity Profile.\n *\n * This deliberately excludes reads and retractions so constrained staging\n * handles can accept incoming identity claims without exposing the broader\n * operational identity surface.\n */\nexport type IdentityAssertionWriteFacade<G extends GraphDef> = Pick<\n IdentityFacade<G>,\n \"assertSame\" | \"assertDifferent\" | \"bulkAssertSame\" | \"bulkAssertDifferent\"\n>;\n\n/**\n * Per-transaction identity write counts carried by a transaction receipt.\n * `total` is the sum of the three preceding counters.\n */\nexport type IdentityWriteSummary = Readonly<{\n sameAssertions: number;\n differentAssertions: number;\n retractions: number;\n total: number;\n}>;\n","/**\n * One-time offline migration: legacy shared embeddings table → per-field\n * strategy storage.\n *\n * ## What this is for\n *\n * The cross-backend vector cutover (#157) dropped the single shared\n * `typegraph_node_embeddings` table. Each\n * `VectorStrategy` now OWNS one typed, fixed-dimension structure per\n * `(nodeKind, fieldPath)` — the only layout that can be ANN-indexed on\n * libSQL and sqlite-vec, not just pgvector.\n *\n * Deployments that wrote embeddings under the old shared table before\n * upgrading still hold those rows. This utility drains them into the new\n * per-field storage **once**, during the upgrade, so existing embedded\n * data survives the cutover without re-embedding from source.\n *\n * It is an explicitly-run, offline step — not wired into `materializeIndexes`\n * or any boot path. Run it once after deploying the new version and before\n * (or alongside) the first `materializeIndexes()`, then drop the legacy\n * table at your leisure.\n *\n * ## How it works\n *\n * - Skips cleanly (returns a zero summary) when the legacy table is absent —\n * a fresh install, or a re-run after the table was dropped.\n * - Reads rows in keyset-paginated batches (never the whole table at once),\n * decoding the engine-native embedding column to a numeric array at the SQL\n * level: sqlite-vec stored a `vec_f32` blob (`vec_to_json` decodes it);\n * pgvector stored a native `vector` (`::text` yields a `[…]` literal).\n * - Re-inserts each row through `backend.upsertEmbedding`, which routes the\n * active strategy's `buildUpsert` and idempotently provisions the per-field\n * storage (the same `(nodeKind, fieldPath)` slot a fresh store write uses).\n * The migration stays graph-agnostic and execution-correct on both the\n * sync (better-sqlite3) and async (libsql / Postgres) backends — it does\n * not re-implement the backend's statement-execution glue.\n *\n * Idempotent and resumable: a partial run followed by a full run converges\n * to the same per-field tables, because every write is an upsert keyed by\n * `(graph_id, node_id)` in the strategy's owned storage.\n */\nimport {\n DEFAULT_EMBEDDING_INDEX_TYPE,\n DEFAULT_EMBEDDING_METRIC,\n type EmbeddingIndexType,\n type EmbeddingMetric,\n} from \"../core/embedding\";\nimport { EmbeddingDimensionChangedError } from \"../errors\";\nimport { sql, type SqlFragment } from \"../query/sql-fragment\";\nimport { asCompiledRowsSql } from \"../query/sql-intent\";\nimport { createDataKeyedBag } from \"../utils/object\";\nimport { requireDefined } from \"../utils/presence\";\nimport { isMissingTableError } from \"../utils/sql-errors\";\nimport { LEGACY_EMBEDDINGS_TABLE_NAME } from \"./drizzle/schema/sqlite\";\nimport { type GraphBackend } from \"./types\";\n\n/**\n * Default rows read per round-trip. Large enough to amortize round-trip\n * latency, small enough to bound peak memory regardless of table size.\n */\nconst DEFAULT_BATCH_SIZE = 500;\n\n/**\n * Metric / index type applied to a migrated field when no\n * {@link MigrateLegacyEmbeddingsOptions.resolveSlotConfig} is supplied (or\n * it returns `undefined`). Matches the defaults `embedding()` and\n * `resolveEmbeddingFields` apply, so a migrated field lands in storage shaped\n * identically to one written fresh through the store. Migrated data is only\n * ever brute-forceable until `materializeIndexes()` builds the ANN index, so\n * the index-type default governs only which ANN structure the per-field\n * storage DDL provisions, not the migration's correctness.\n */\nconst DEFAULT_SLOT_METRIC: EmbeddingMetric = DEFAULT_EMBEDDING_METRIC;\nconst DEFAULT_SLOT_INDEX_TYPE: EmbeddingIndexType =\n DEFAULT_EMBEDDING_INDEX_TYPE;\n\n/**\n * The resolved storage config for one `(nodeKind, fieldPath)` slot that the\n * legacy table did not record. The legacy shared table stored only the\n * vector and its dimension count — not the metric or index type — so a\n * caller that wants migrated fields to match a specific graph's `embedding()`\n * declarations supplies this resolver.\n */\nexport type LegacyEmbeddingSlotConfig = Readonly<{\n metric: EmbeddingMetric;\n indexType: EmbeddingIndexType;\n}>;\n\n/**\n * Options for {@link migrateLegacyEmbeddings}.\n */\nexport type MigrateLegacyEmbeddingsOptions = Readonly<{\n /**\n * The backend to migrate, wired with the destination `VectorStrategy`\n * (i.e. the post-cutover backend). Its `vectorStrategy` owns the per-field\n * storage rows are written into and its `upsertEmbedding` performs the\n * writes.\n */\n backend: GraphBackend;\n\n /**\n * Restrict the migration to a single graph. When omitted, every graph's\n * rows in the legacy table are migrated (the table is graph-scoped by its\n * `graph_id` column).\n */\n graphId?: string;\n\n /**\n * Resolves the metric / index type for a `(nodeKind, fieldPath)` slot the\n * legacy table didn't persist. Return `undefined` to fall back to the\n * cosine / hnsw defaults. Supply this (typically reading the graph's\n * `embedding()` declarations) when migrated fields must match a specific\n * metric — e.g. an `l2` field, which scores incorrectly under the cosine\n * default.\n */\n resolveSlotConfig?: (\n nodeKind: string,\n fieldPath: string,\n ) => LegacyEmbeddingSlotConfig | undefined;\n\n /** Rows read per round-trip. Defaults to {@link DEFAULT_BATCH_SIZE}. */\n batchSize?: number;\n\n /**\n * Physical name of the legacy table to drain. Defaults to\n * {@link LEGACY_EMBEDDINGS_TABLE_NAME}. Override only for a non-default\n * deployment that renamed the embeddings table.\n */\n legacyTableName?: string;\n}>;\n\n/**\n * Summary of a {@link migrateLegacyEmbeddings} run.\n */\nexport type MigrateLegacyEmbeddingsResult = Readonly<{\n /** Total embedding rows re-inserted into per-field storage. */\n migrated: number;\n /**\n * Per-`(nodeKind, fieldPath)` counts, keyed `\"<nodeKind>.<fieldPath>\"`\n * (the strategy's logical-slot key form). Empty when the legacy table was\n * absent or held no rows for the requested scope.\n */\n perField: Readonly<Record<string, number>>;\n /**\n * Rows skipped because their vector length didn't match the per-field\n * table's fixed dimension. The legacy shared column allowed mixed\n * dimensions for one `(nodeKind, fieldPath)` (e.g. an unmigrated model\n * change); the first migrated row fixes the typed table's dimension and\n * any differently-sized rows for that slot are skipped rather than aborting\n * the whole migration. Keyed `\"<nodeKind>.<fieldPath>\"`. Non-empty here\n * means those fields need a deliberate re-embed at a single dimension.\n */\n skippedDimensionMismatch: Readonly<Record<string, number>>;\n /**\n * Rows skipped because their legacy embedding could not be decoded into a\n * finite-number array — a corrupt value (e.g. a pgvector `vector` column\n * permits `NaN`/`Infinity`, which is not valid JSON). Keyed\n * `\"<nodeKind>.<fieldPath>\"`. Skipping + reporting keeps one bad row from\n * aborting the whole migration; non-empty here means those rows need manual\n * repair.\n */\n skippedDecodeError: Readonly<Record<string, number>>;\n /**\n * Whether the legacy table existed. `false` means the run was a clean\n * no-op (fresh install, or already-dropped table on a re-run).\n */\n legacyTablePresent: boolean;\n}>;\n\n/**\n * A single legacy embedding row, with the engine-native vector already\n * decoded to a JSON array string by the dialect-specific SELECT. The\n * legacy `dimensions` column is intentionally not read: the decoded array's\n * length is the authoritative fixed dimension for the destination slot, and\n * relying on it sidesteps the per-driver string/number coercion the legacy\n * integer column would otherwise need.\n */\ntype LegacyEmbeddingRow = Readonly<{\n graph_id: string;\n node_kind: string;\n node_id: string;\n field_path: string;\n /** JSON array text, e.g. `\"[0.1,0.2,0.3]\"` — decoded per dialect. */\n embedding_json: string;\n}>;\n\n/**\n * Re-inserts every embedding from the legacy shared\n * `typegraph_node_embeddings` table into the active\n * `backend.vectorStrategy`'s per-`(nodeKind, fieldPath)` storage.\n *\n * One-time, explicitly-run upgrade step for the shared-table → per-field\n * cutover (#157). Idempotent, batched, and a clean no-op when the legacy\n * table is absent. See the module doc comment for the full contract.\n *\n * @throws Error when the backend exposes no `vectorStrategy` /\n * `upsertEmbedding` (nothing to migrate *into*) — a configuration\n * error the caller must fix by wiring the destination strategy\n * before migrating.\n */\nexport async function migrateLegacyEmbeddings(\n options: MigrateLegacyEmbeddingsOptions,\n): Promise<MigrateLegacyEmbeddingsResult> {\n const {\n backend,\n graphId,\n resolveSlotConfig,\n batchSize = DEFAULT_BATCH_SIZE,\n legacyTableName = LEGACY_EMBEDDINGS_TABLE_NAME,\n } = options;\n\n if (\n backend.vectorStrategy === undefined ||\n backend.upsertEmbedding === undefined\n ) {\n throw new Error(\n \"migrateLegacyEmbeddings requires a backend wired with a vectorStrategy \" +\n \"(the destination per-field storage). Pass the post-cutover backend.\",\n );\n }\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw new RangeError(\n `batchSize must be a positive integer, got: ${batchSize}`,\n );\n }\n const upsertEmbedding = backend.upsertEmbedding;\n const ensureVectorSlotContribution = backend.ensureVectorSlotContribution;\n\n // Data-keyed: slot keys are built from a row's `node_kind` / `field_path`.\n const perField = createDataKeyedBag<number>();\n const skippedDimensionMismatch = createDataKeyedBag<number>();\n const skippedDecodeError = createDataKeyedBag<number>();\n // (kind, field) slots whose per-field table + durable marker this run has\n // already provisioned, mapped to the dimension the table was fixed at.\n // `upsertEmbedding` asserts the marker (#135) and no longer self-creates\n // the table, so this offline migration (privileged) provisions each slot\n // once — at the first row's dimension, which fixes the typed table just as\n // the original lazy write did. Differently-sized later rows for the same\n // slot are detected against this map and skipped BEFORE the upsert: the\n // marker assert would otherwise read the differently-dimensioned slot as\n // stale and abort the whole migration, and the ensure is deliberately not\n // re-run per row (that would trip the marker drift-guard).\n const ensuredSlots = new Map<string, number>();\n let migrated = 0;\n\n let cursor: LegacyRowCursor | undefined;\n for (;;) {\n let batch: readonly LegacyEmbeddingRow[];\n try {\n batch = await readLegacyBatch(backend, {\n legacyTableName,\n graphId,\n batchSize,\n after: cursor,\n });\n } catch (error) {\n // A missing legacy table is the expected \"nothing to migrate\" path on\n // the first read — surface it as a clean no-op, not a failure.\n if (cursor === undefined && isMissingTableError(error)) {\n return {\n migrated: 0,\n perField: {},\n skippedDimensionMismatch: {},\n skippedDecodeError: {},\n legacyTablePresent: false,\n };\n }\n throw error;\n }\n\n if (batch.length === 0) break;\n\n for (const row of batch) {\n const slotKey = `${row.node_kind}.${row.field_path}`;\n\n let embedding: readonly number[];\n try {\n embedding = decodeEmbeddingJson(row);\n } catch {\n // A corrupt legacy value (e.g. a pgvector `vector` column permits\n // NaN/Infinity, which is not valid JSON) is skipped + reported rather\n // than aborting the whole migration on one bad row.\n skippedDecodeError[slotKey] = (skippedDecodeError[slotKey] ?? 0) + 1;\n continue;\n }\n const config = resolveSlotConfig?.(row.node_kind, row.field_path);\n // The decoded length is the authoritative fixed dimension — the\n // strategy provisions its column type (e.g. `F32_BLOB(N)`) from it.\n const slot = {\n graphId: row.graph_id,\n nodeKind: row.node_kind,\n fieldPath: row.field_path,\n dimensions: embedding.length,\n metric: config?.metric ?? DEFAULT_SLOT_METRIC,\n indexType: config?.indexType ?? DEFAULT_SLOT_INDEX_TYPE,\n };\n\n // Provision the per-field table + durable marker before the first\n // write into this slot. Once per (graph, kind, field): the first row's\n // dimension fixes the table. Keyed by graph id too — the legacy table\n // is graph-scoped, so the same `kind.field` can recur across graphs.\n const ensuredKey = JSON.stringify([\n row.graph_id,\n row.node_kind,\n row.field_path,\n ]);\n if (\n ensureVectorSlotContribution !== undefined &&\n !ensuredSlots.has(ensuredKey)\n ) {\n await ensureVectorSlotContribution(slot);\n ensuredSlots.set(ensuredKey, slot.dimensions);\n }\n\n // The legacy shared column allowed mixed dimensions for one\n // (nodeKind, fieldPath); the per-field table is fixed at the first\n // migrated row's dimension. Skip a differently-sized row up front —\n // its slot would fail the marker assert as stale (different\n // signature), aborting the migration instead of skipping the row.\n const provisionedDimensions = ensuredSlots.get(ensuredKey);\n if (\n provisionedDimensions !== undefined &&\n provisionedDimensions !== embedding.length\n ) {\n skippedDimensionMismatch[slotKey] =\n (skippedDimensionMismatch[slotKey] ?? 0) + 1;\n continue;\n }\n\n try {\n await upsertEmbedding({ ...slot, nodeId: row.node_id, embedding });\n } catch (error) {\n // The legacy shared column allowed mixed dimensions for one\n // (nodeKind, fieldPath); the per-field table is fixed at the first\n // migrated row's dimension, so a differently-sized row is skipped and\n // reported rather than aborting the whole migration.\n if (error instanceof EmbeddingDimensionChangedError) {\n skippedDimensionMismatch[slotKey] =\n (skippedDimensionMismatch[slotKey] ?? 0) + 1;\n continue;\n }\n throw error;\n }\n\n migrated += 1;\n perField[slotKey] = (perField[slotKey] ?? 0) + 1;\n }\n\n if (batch.length < batchSize) break;\n const last = requireDefined(batch.at(-1));\n cursor = {\n graphId: last.graph_id,\n nodeKind: last.node_kind,\n nodeId: last.node_id,\n fieldPath: last.field_path,\n };\n }\n\n // SPREAD at the boundary. The three maps are null-prototype accumulators\n // because their keys are slot names built from row data; that protection is\n // internal, and returning the bags as-is handed a caller three maps with no\n // `toString` and `instanceof Object === false` — while the early\n // \"nothing to migrate\" return above hands back `{}` literals, so the same\n // exported function answered with two different kinds of object depending on\n // whether the legacy table existed. Spread copies own properties with\n // CreateDataProperty, so a `__proto__` slot key survives as an own key.\n return {\n migrated,\n perField: { ...perField },\n skippedDimensionMismatch: { ...skippedDimensionMismatch },\n skippedDecodeError: { ...skippedDecodeError },\n legacyTablePresent: true,\n };\n}\n\n/**\n * Composite keyset cursor over the legacy table's primary key\n * `(graph_id, node_kind, node_id, field_path)`. Stable under concurrent\n * writes and immune to OFFSET drift, so a batched walk reads every row once.\n */\ntype LegacyRowCursor = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n fieldPath: string;\n}>;\n\ntype ReadLegacyBatchParams = Readonly<{\n legacyTableName: string;\n graphId: string | undefined;\n batchSize: number;\n after: LegacyRowCursor | undefined;\n}>;\n\n/**\n * Reads one keyset-paginated batch of legacy rows, ordered by the primary\n * key, with the engine-native embedding column decoded to a JSON array\n * string by the dialect.\n */\nasync function readLegacyBatch(\n backend: GraphBackend,\n params: ReadLegacyBatchParams,\n): Promise<readonly LegacyEmbeddingRow[]> {\n const table = sql.identifier(params.legacyTableName);\n const embeddingJson = legacyEmbeddingDecodeExpression(backend);\n\n const conditions: SqlFragment[] = [];\n if (params.graphId !== undefined) {\n conditions.push(sql`\"graph_id\" = ${params.graphId}`);\n }\n if (params.after !== undefined) {\n conditions.push(keysetAfterCondition(params.after));\n }\n\n const whereClause =\n conditions.length === 0 ?\n sql``\n : sql` WHERE ${sql.join(conditions, sql` AND `)}`;\n\n const query = sql`\n SELECT\n \"graph_id\" AS graph_id,\n \"node_kind\" AS node_kind,\n \"node_id\" AS node_id,\n \"field_path\" AS field_path,\n ${embeddingJson} AS embedding_json\n FROM ${table}${whereClause}\n ORDER BY \"graph_id\" ASC, \"node_kind\" ASC, \"node_id\" ASC, \"field_path\" ASC\n LIMIT ${params.batchSize}\n `;\n\n return backend.execute<LegacyEmbeddingRow>(asCompiledRowsSql(query));\n}\n\n/**\n * The strict `>` comparison over the composite primary key, expressed as\n * the standard lexicographic OR-chain so it works on every dialect (SQLite\n * supports row-value comparison, but Postgres + SQLite both accept this\n * portable form).\n */\nfunction keysetAfterCondition(after: LegacyRowCursor): SqlFragment {\n return sql`\n (\n \"graph_id\" > ${after.graphId}\n OR (\"graph_id\" = ${after.graphId} AND \"node_kind\" > ${after.nodeKind})\n OR (\"graph_id\" = ${after.graphId} AND \"node_kind\" = ${after.nodeKind} AND \"node_id\" > ${after.nodeId})\n OR (\n \"graph_id\" = ${after.graphId}\n AND \"node_kind\" = ${after.nodeKind}\n AND \"node_id\" = ${after.nodeId}\n AND \"field_path\" > ${after.fieldPath}\n )\n )\n `;\n}\n\n/**\n * The SQL expression that decodes the legacy engine-native embedding column\n * into a JSON array string `embedding_json`. The single dialect branch in\n * this whole module: the legacy storage formats are genuinely engine-\n * specific, and there is no longer a strategy abstraction over the *legacy*\n * table to delegate to.\n */\nfunction legacyEmbeddingDecodeExpression(backend: GraphBackend): SqlFragment {\n switch (backend.dialect) {\n case \"sqlite\": {\n // Legacy SQLite embeddings were written via `vec_f32('[…]')`\n // (sqlite-vec binary). `vec_to_json` is its inverse, yielding the\n // JSON array text. Requires sqlite-vec on the connection — which the\n // legacy write path also required, so any deployment with legacy rows\n // has it loaded.\n return sql`vec_to_json(\"embedding\")`;\n }\n case \"postgres\": {\n // pgvector's native `vector` casts to its `[…]` text literal, which is\n // valid JSON for `JSON.parse`.\n return sql`\"embedding\"::text`;\n }\n default: {\n const _exhaustive: never = backend.dialect;\n throw new Error(\n `migrateLegacyEmbeddings does not support dialect: ${String(_exhaustive)}`,\n );\n }\n }\n}\n\n/**\n * Parses a decoded `embedding_json` array, asserting it is a non-empty array\n * of finite numbers. A bad decode (wrong type, NaN) names the offending row\n * loudly instead of writing a corrupt vector into per-field storage.\n */\nfunction decodeEmbeddingJson(row: LegacyEmbeddingRow): readonly number[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(row.embedding_json) as unknown;\n } catch (error) {\n throw new Error(\n `Failed to decode legacy embedding for ${row.node_kind}.${row.field_path} ` +\n `(graph ${row.graph_id}, node ${row.node_id}): not valid JSON.`,\n { cause: error },\n );\n }\n if (!Array.isArray(parsed) || parsed.length === 0) {\n throw new Error(\n `Legacy embedding for ${row.node_kind}.${row.field_path} ` +\n `(graph ${row.graph_id}, node ${row.node_id}) decoded to a non-array ` +\n `or empty value.`,\n );\n }\n for (const [index, value] of parsed.entries()) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new TypeError(\n `Legacy embedding for ${row.node_kind}.${row.field_path} ` +\n `(graph ${row.graph_id}, node ${row.node_id}) has a non-finite ` +\n `value at index ${index}: ${String(value)}.`,\n );\n }\n }\n return parsed as readonly number[];\n}\n"]}