@fgv/ts-agent-memory 5.1.0-47 → 5.1.0-48

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 (341) hide show
  1. package/dist/packlets/ingest/orchestrator.js +11 -1
  2. package/dist/packlets/ingest/orchestrator.js.map +1 -1
  3. package/dist/packlets/observe/memoryObservationStore.js +6 -0
  4. package/dist/packlets/observe/memoryObservationStore.js.map +1 -1
  5. package/dist/packlets/observe/observer.js.map +1 -1
  6. package/dist/packlets/store/fileTreeMemoryStore.js +52 -131
  7. package/dist/packlets/store/fileTreeMemoryStore.js.map +1 -1
  8. package/dist/packlets/store/vectorMaintenance.js +251 -0
  9. package/dist/packlets/store/vectorMaintenance.js.map +1 -0
  10. package/dist/packlets/vector/inMemoryCosineIndex.js +81 -18
  11. package/dist/packlets/vector/inMemoryCosineIndex.js.map +1 -1
  12. package/dist/packlets/vector/inMemoryFragmentCosineIndex.js +7 -0
  13. package/dist/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
  14. package/dist/packlets/vector/vectorIndex.js.map +1 -1
  15. package/dist/ts-agent-memory.d.ts +297 -66
  16. package/lib/packlets/ingest/orchestrator.d.ts.map +1 -1
  17. package/lib/packlets/ingest/orchestrator.js +11 -1
  18. package/lib/packlets/ingest/orchestrator.js.map +1 -1
  19. package/lib/packlets/observe/memoryObservationStore.d.ts.map +1 -1
  20. package/lib/packlets/observe/memoryObservationStore.js +6 -0
  21. package/lib/packlets/observe/memoryObservationStore.js.map +1 -1
  22. package/lib/packlets/observe/observer.d.ts +61 -0
  23. package/lib/packlets/observe/observer.d.ts.map +1 -1
  24. package/lib/packlets/observe/observer.js.map +1 -1
  25. package/lib/packlets/store/fileTreeMemoryStore.d.ts +66 -59
  26. package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
  27. package/lib/packlets/store/fileTreeMemoryStore.js +52 -131
  28. package/lib/packlets/store/fileTreeMemoryStore.js.map +1 -1
  29. package/lib/packlets/store/vectorMaintenance.d.ts +149 -0
  30. package/lib/packlets/store/vectorMaintenance.d.ts.map +1 -0
  31. package/lib/packlets/store/vectorMaintenance.js +255 -0
  32. package/lib/packlets/store/vectorMaintenance.js.map +1 -0
  33. package/lib/packlets/vector/inMemoryCosineIndex.d.ts +30 -7
  34. package/lib/packlets/vector/inMemoryCosineIndex.d.ts.map +1 -1
  35. package/lib/packlets/vector/inMemoryCosineIndex.js +80 -17
  36. package/lib/packlets/vector/inMemoryCosineIndex.js.map +1 -1
  37. package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts +7 -0
  38. package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts.map +1 -1
  39. package/lib/packlets/vector/inMemoryFragmentCosineIndex.js +7 -0
  40. package/lib/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
  41. package/lib/packlets/vector/vectorIndex.d.ts +129 -1
  42. package/lib/packlets/vector/vectorIndex.d.ts.map +1 -1
  43. package/lib/packlets/vector/vectorIndex.js.map +1 -1
  44. package/package.json +17 -7
  45. package/.rush/temp/5667e36f1c0cc503a5c20a3ebff76e7b9a702d41.tar.log +0 -468
  46. package/.rush/temp/chunked-rush-logs/ts-agent-memory.build.chunks.jsonl +0 -9
  47. package/.rush/temp/operation/build/all.log +0 -9
  48. package/.rush/temp/operation/build/log-chunks.jsonl +0 -9
  49. package/.rush/temp/operation/build/state.json +0 -3
  50. package/.rush/temp/shrinkwrap-deps.json +0 -689
  51. package/config/api-extractor.json +0 -343
  52. package/config/jest.config.json +0 -14
  53. package/config/rig.json +0 -4
  54. package/dist/test/unit/converters/antagonistRoundTrip.test.js +0 -95
  55. package/dist/test/unit/converters/antagonistRoundTrip.test.js.map +0 -1
  56. package/dist/test/unit/converters/bodyConverterRegistry.test.js +0 -72
  57. package/dist/test/unit/converters/bodyConverterRegistry.test.js.map +0 -1
  58. package/dist/test/unit/converters/envelopeConverter.test.js +0 -313
  59. package/dist/test/unit/converters/envelopeConverter.test.js.map +0 -1
  60. package/dist/test/unit/index/memoryIndex.test.js +0 -214
  61. package/dist/test/unit/index/memoryIndex.test.js.map +0 -1
  62. package/dist/test/unit/ingest/antagonistCycleAndParity.test.js +0 -277
  63. package/dist/test/unit/ingest/antagonistCycleAndParity.test.js.map +0 -1
  64. package/dist/test/unit/ingest/cycleGuard.test.js +0 -81
  65. package/dist/test/unit/ingest/cycleGuard.test.js.map +0 -1
  66. package/dist/test/unit/ingest/dedupScope.test.js +0 -434
  67. package/dist/test/unit/ingest/dedupScope.test.js.map +0 -1
  68. package/dist/test/unit/ingest/orchestrator.test.js +0 -1058
  69. package/dist/test/unit/ingest/orchestrator.test.js.map +0 -1
  70. package/dist/test/unit/observe/memoryObservationStore.test.js +0 -118
  71. package/dist/test/unit/observe/memoryObservationStore.test.js.map +0 -1
  72. package/dist/test/unit/retrieve/fragmentSemanticRetriever.test.js +0 -116
  73. package/dist/test/unit/retrieve/fragmentSemanticRetriever.test.js.map +0 -1
  74. package/dist/test/unit/retrieve/linkTraversalRetriever.test.js +0 -257
  75. package/dist/test/unit/retrieve/linkTraversalRetriever.test.js.map +0 -1
  76. package/dist/test/unit/retrieve/retrievers.test.js +0 -768
  77. package/dist/test/unit/retrieve/retrievers.test.js.map +0 -1
  78. package/dist/test/unit/retrieve/temporalRetrievers.test.js +0 -182
  79. package/dist/test/unit/retrieve/temporalRetrievers.test.js.map +0 -1
  80. package/dist/test/unit/store/antagonistTemporalBoundary.test.js +0 -120
  81. package/dist/test/unit/store/antagonistTemporalBoundary.test.js.map +0 -1
  82. package/dist/test/unit/store/embedOnWrite.test.js +0 -317
  83. package/dist/test/unit/store/embedOnWrite.test.js.map +0 -1
  84. package/dist/test/unit/store/fileTreeMemoryStore.test.js +0 -778
  85. package/dist/test/unit/store/fileTreeMemoryStore.test.js.map +0 -1
  86. package/dist/test/unit/store/fragmentEmbedOnWrite.test.js +0 -255
  87. package/dist/test/unit/store/fragmentEmbedOnWrite.test.js.map +0 -1
  88. package/dist/test/unit/store/indexInjection.test.js +0 -432
  89. package/dist/test/unit/store/indexInjection.test.js.map +0 -1
  90. package/dist/test/unit/store/lenientOpen.test.js +0 -248
  91. package/dist/test/unit/store/lenientOpen.test.js.map +0 -1
  92. package/dist/test/unit/store/listScoped.test.js +0 -109
  93. package/dist/test/unit/store/listScoped.test.js.map +0 -1
  94. package/dist/test/unit/store/observations.test.js +0 -239
  95. package/dist/test/unit/store/observations.test.js.map +0 -1
  96. package/dist/test/unit/store/rankAxis.test.js +0 -254
  97. package/dist/test/unit/store/rankAxis.test.js.map +0 -1
  98. package/dist/test/unit/store/scopeEncoding.test.js +0 -24
  99. package/dist/test/unit/store/scopeEncoding.test.js.map +0 -1
  100. package/dist/test/unit/store/temporalStore.test.js +0 -398
  101. package/dist/test/unit/store/temporalStore.test.js.map +0 -1
  102. package/dist/test/unit/tools/memoryTools.test.js +0 -842
  103. package/dist/test/unit/tools/memoryTools.test.js.map +0 -1
  104. package/dist/test/unit/types/identityCodec.test.js +0 -187
  105. package/dist/test/unit/types/identityCodec.test.js.map +0 -1
  106. package/dist/test/unit/types/ids.test.js +0 -84
  107. package/dist/test/unit/types/ids.test.js.map +0 -1
  108. package/dist/test/unit/types/temporalCodec.test.js +0 -203
  109. package/dist/test/unit/types/temporalCodec.test.js.map +0 -1
  110. package/dist/test/unit/types/temporalPolicy.test.js +0 -83
  111. package/dist/test/unit/types/temporalPolicy.test.js.map +0 -1
  112. package/dist/test/unit/types/writePolicy.test.js +0 -331
  113. package/dist/test/unit/types/writePolicy.test.js.map +0 -1
  114. package/dist/test/unit/vector/fragmentConverters.test.js +0 -58
  115. package/dist/test/unit/vector/fragmentConverters.test.js.map +0 -1
  116. package/dist/test/unit/vector/inMemoryCosineIndex.test.js +0 -252
  117. package/dist/test/unit/vector/inMemoryCosineIndex.test.js.map +0 -1
  118. package/dist/test/unit/vector/inMemoryFragmentCosineIndex.test.js +0 -362
  119. package/dist/test/unit/vector/inMemoryFragmentCosineIndex.test.js.map +0 -1
  120. package/dist/test/unit/vector/vectorIndex.test.js +0 -51
  121. package/dist/test/unit/vector/vectorIndex.test.js.map +0 -1
  122. package/eslint.config.js +0 -15
  123. package/etc/ts-agent-memory.api.md +0 -940
  124. package/lib/test/unit/converters/antagonistRoundTrip.test.d.ts +0 -10
  125. package/lib/test/unit/converters/antagonistRoundTrip.test.d.ts.map +0 -1
  126. package/lib/test/unit/converters/antagonistRoundTrip.test.js +0 -97
  127. package/lib/test/unit/converters/antagonistRoundTrip.test.js.map +0 -1
  128. package/lib/test/unit/converters/bodyConverterRegistry.test.d.ts +0 -2
  129. package/lib/test/unit/converters/bodyConverterRegistry.test.d.ts.map +0 -1
  130. package/lib/test/unit/converters/bodyConverterRegistry.test.js +0 -74
  131. package/lib/test/unit/converters/bodyConverterRegistry.test.js.map +0 -1
  132. package/lib/test/unit/converters/envelopeConverter.test.d.ts +0 -2
  133. package/lib/test/unit/converters/envelopeConverter.test.d.ts.map +0 -1
  134. package/lib/test/unit/converters/envelopeConverter.test.js +0 -315
  135. package/lib/test/unit/converters/envelopeConverter.test.js.map +0 -1
  136. package/lib/test/unit/index/memoryIndex.test.d.ts +0 -2
  137. package/lib/test/unit/index/memoryIndex.test.d.ts.map +0 -1
  138. package/lib/test/unit/index/memoryIndex.test.js +0 -216
  139. package/lib/test/unit/index/memoryIndex.test.js.map +0 -1
  140. package/lib/test/unit/ingest/antagonistCycleAndParity.test.d.ts +0 -9
  141. package/lib/test/unit/ingest/antagonistCycleAndParity.test.d.ts.map +0 -1
  142. package/lib/test/unit/ingest/antagonistCycleAndParity.test.js +0 -279
  143. package/lib/test/unit/ingest/antagonistCycleAndParity.test.js.map +0 -1
  144. package/lib/test/unit/ingest/cycleGuard.test.d.ts +0 -2
  145. package/lib/test/unit/ingest/cycleGuard.test.d.ts.map +0 -1
  146. package/lib/test/unit/ingest/cycleGuard.test.js +0 -83
  147. package/lib/test/unit/ingest/cycleGuard.test.js.map +0 -1
  148. package/lib/test/unit/ingest/dedupScope.test.d.ts +0 -2
  149. package/lib/test/unit/ingest/dedupScope.test.d.ts.map +0 -1
  150. package/lib/test/unit/ingest/dedupScope.test.js +0 -436
  151. package/lib/test/unit/ingest/dedupScope.test.js.map +0 -1
  152. package/lib/test/unit/ingest/orchestrator.test.d.ts +0 -2
  153. package/lib/test/unit/ingest/orchestrator.test.d.ts.map +0 -1
  154. package/lib/test/unit/ingest/orchestrator.test.js +0 -1060
  155. package/lib/test/unit/ingest/orchestrator.test.js.map +0 -1
  156. package/lib/test/unit/observe/memoryObservationStore.test.d.ts +0 -2
  157. package/lib/test/unit/observe/memoryObservationStore.test.d.ts.map +0 -1
  158. package/lib/test/unit/observe/memoryObservationStore.test.js +0 -120
  159. package/lib/test/unit/observe/memoryObservationStore.test.js.map +0 -1
  160. package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.d.ts +0 -2
  161. package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.d.ts.map +0 -1
  162. package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.js +0 -118
  163. package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.js.map +0 -1
  164. package/lib/test/unit/retrieve/linkTraversalRetriever.test.d.ts +0 -2
  165. package/lib/test/unit/retrieve/linkTraversalRetriever.test.d.ts.map +0 -1
  166. package/lib/test/unit/retrieve/linkTraversalRetriever.test.js +0 -259
  167. package/lib/test/unit/retrieve/linkTraversalRetriever.test.js.map +0 -1
  168. package/lib/test/unit/retrieve/retrievers.test.d.ts +0 -2
  169. package/lib/test/unit/retrieve/retrievers.test.d.ts.map +0 -1
  170. package/lib/test/unit/retrieve/retrievers.test.js +0 -770
  171. package/lib/test/unit/retrieve/retrievers.test.js.map +0 -1
  172. package/lib/test/unit/retrieve/temporalRetrievers.test.d.ts +0 -2
  173. package/lib/test/unit/retrieve/temporalRetrievers.test.d.ts.map +0 -1
  174. package/lib/test/unit/retrieve/temporalRetrievers.test.js +0 -184
  175. package/lib/test/unit/retrieve/temporalRetrievers.test.js.map +0 -1
  176. package/lib/test/unit/store/antagonistTemporalBoundary.test.d.ts +0 -9
  177. package/lib/test/unit/store/antagonistTemporalBoundary.test.d.ts.map +0 -1
  178. package/lib/test/unit/store/antagonistTemporalBoundary.test.js +0 -122
  179. package/lib/test/unit/store/antagonistTemporalBoundary.test.js.map +0 -1
  180. package/lib/test/unit/store/embedOnWrite.test.d.ts +0 -2
  181. package/lib/test/unit/store/embedOnWrite.test.d.ts.map +0 -1
  182. package/lib/test/unit/store/embedOnWrite.test.js +0 -319
  183. package/lib/test/unit/store/embedOnWrite.test.js.map +0 -1
  184. package/lib/test/unit/store/fileTreeMemoryStore.test.d.ts +0 -2
  185. package/lib/test/unit/store/fileTreeMemoryStore.test.d.ts.map +0 -1
  186. package/lib/test/unit/store/fileTreeMemoryStore.test.js +0 -780
  187. package/lib/test/unit/store/fileTreeMemoryStore.test.js.map +0 -1
  188. package/lib/test/unit/store/fragmentEmbedOnWrite.test.d.ts +0 -2
  189. package/lib/test/unit/store/fragmentEmbedOnWrite.test.d.ts.map +0 -1
  190. package/lib/test/unit/store/fragmentEmbedOnWrite.test.js +0 -257
  191. package/lib/test/unit/store/fragmentEmbedOnWrite.test.js.map +0 -1
  192. package/lib/test/unit/store/indexInjection.test.d.ts +0 -2
  193. package/lib/test/unit/store/indexInjection.test.d.ts.map +0 -1
  194. package/lib/test/unit/store/indexInjection.test.js +0 -434
  195. package/lib/test/unit/store/indexInjection.test.js.map +0 -1
  196. package/lib/test/unit/store/lenientOpen.test.d.ts +0 -2
  197. package/lib/test/unit/store/lenientOpen.test.d.ts.map +0 -1
  198. package/lib/test/unit/store/lenientOpen.test.js +0 -250
  199. package/lib/test/unit/store/lenientOpen.test.js.map +0 -1
  200. package/lib/test/unit/store/listScoped.test.d.ts +0 -2
  201. package/lib/test/unit/store/listScoped.test.d.ts.map +0 -1
  202. package/lib/test/unit/store/listScoped.test.js +0 -111
  203. package/lib/test/unit/store/listScoped.test.js.map +0 -1
  204. package/lib/test/unit/store/observations.test.d.ts +0 -2
  205. package/lib/test/unit/store/observations.test.d.ts.map +0 -1
  206. package/lib/test/unit/store/observations.test.js +0 -241
  207. package/lib/test/unit/store/observations.test.js.map +0 -1
  208. package/lib/test/unit/store/rankAxis.test.d.ts +0 -2
  209. package/lib/test/unit/store/rankAxis.test.d.ts.map +0 -1
  210. package/lib/test/unit/store/rankAxis.test.js +0 -256
  211. package/lib/test/unit/store/rankAxis.test.js.map +0 -1
  212. package/lib/test/unit/store/scopeEncoding.test.d.ts +0 -2
  213. package/lib/test/unit/store/scopeEncoding.test.d.ts.map +0 -1
  214. package/lib/test/unit/store/scopeEncoding.test.js +0 -26
  215. package/lib/test/unit/store/scopeEncoding.test.js.map +0 -1
  216. package/lib/test/unit/store/temporalStore.test.d.ts +0 -2
  217. package/lib/test/unit/store/temporalStore.test.d.ts.map +0 -1
  218. package/lib/test/unit/store/temporalStore.test.js +0 -400
  219. package/lib/test/unit/store/temporalStore.test.js.map +0 -1
  220. package/lib/test/unit/tools/memoryTools.test.d.ts +0 -2
  221. package/lib/test/unit/tools/memoryTools.test.d.ts.map +0 -1
  222. package/lib/test/unit/tools/memoryTools.test.js +0 -844
  223. package/lib/test/unit/tools/memoryTools.test.js.map +0 -1
  224. package/lib/test/unit/types/identityCodec.test.d.ts +0 -2
  225. package/lib/test/unit/types/identityCodec.test.d.ts.map +0 -1
  226. package/lib/test/unit/types/identityCodec.test.js +0 -189
  227. package/lib/test/unit/types/identityCodec.test.js.map +0 -1
  228. package/lib/test/unit/types/ids.test.d.ts +0 -2
  229. package/lib/test/unit/types/ids.test.d.ts.map +0 -1
  230. package/lib/test/unit/types/ids.test.js +0 -86
  231. package/lib/test/unit/types/ids.test.js.map +0 -1
  232. package/lib/test/unit/types/temporalCodec.test.d.ts +0 -2
  233. package/lib/test/unit/types/temporalCodec.test.d.ts.map +0 -1
  234. package/lib/test/unit/types/temporalCodec.test.js +0 -205
  235. package/lib/test/unit/types/temporalCodec.test.js.map +0 -1
  236. package/lib/test/unit/types/temporalPolicy.test.d.ts +0 -2
  237. package/lib/test/unit/types/temporalPolicy.test.d.ts.map +0 -1
  238. package/lib/test/unit/types/temporalPolicy.test.js +0 -85
  239. package/lib/test/unit/types/temporalPolicy.test.js.map +0 -1
  240. package/lib/test/unit/types/writePolicy.test.d.ts +0 -2
  241. package/lib/test/unit/types/writePolicy.test.d.ts.map +0 -1
  242. package/lib/test/unit/types/writePolicy.test.js +0 -333
  243. package/lib/test/unit/types/writePolicy.test.js.map +0 -1
  244. package/lib/test/unit/vector/fragmentConverters.test.d.ts +0 -2
  245. package/lib/test/unit/vector/fragmentConverters.test.d.ts.map +0 -1
  246. package/lib/test/unit/vector/fragmentConverters.test.js +0 -60
  247. package/lib/test/unit/vector/fragmentConverters.test.js.map +0 -1
  248. package/lib/test/unit/vector/inMemoryCosineIndex.test.d.ts +0 -2
  249. package/lib/test/unit/vector/inMemoryCosineIndex.test.d.ts.map +0 -1
  250. package/lib/test/unit/vector/inMemoryCosineIndex.test.js +0 -254
  251. package/lib/test/unit/vector/inMemoryCosineIndex.test.js.map +0 -1
  252. package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.d.ts +0 -2
  253. package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.d.ts.map +0 -1
  254. package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.js +0 -364
  255. package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.js.map +0 -1
  256. package/lib/test/unit/vector/vectorIndex.test.d.ts +0 -2
  257. package/lib/test/unit/vector/vectorIndex.test.d.ts.map +0 -1
  258. package/lib/test/unit/vector/vectorIndex.test.js +0 -53
  259. package/lib/test/unit/vector/vectorIndex.test.js.map +0 -1
  260. package/rush-logs/ts-agent-memory.build.cache.log +0 -3
  261. package/rush-logs/ts-agent-memory.build.log +0 -9
  262. package/src/index.ts +0 -14
  263. package/src/packlets/converters/bodyConverterRegistry.ts +0 -105
  264. package/src/packlets/converters/envelopeConverter.ts +0 -233
  265. package/src/packlets/converters/index.ts +0 -7
  266. package/src/packlets/index/index.ts +0 -6
  267. package/src/packlets/index/memoryIndex.ts +0 -332
  268. package/src/packlets/ingest/cycleGuard.ts +0 -153
  269. package/src/packlets/ingest/hostStages.ts +0 -111
  270. package/src/packlets/ingest/index.ts +0 -9
  271. package/src/packlets/ingest/model.ts +0 -195
  272. package/src/packlets/ingest/orchestrator.ts +0 -968
  273. package/src/packlets/observe/index.ts +0 -7
  274. package/src/packlets/observe/memoryObservationStore.ts +0 -153
  275. package/src/packlets/observe/observer.ts +0 -119
  276. package/src/packlets/retrieve/fragmentSemanticRetriever.ts +0 -138
  277. package/src/packlets/retrieve/hybridRetriever.ts +0 -194
  278. package/src/packlets/retrieve/index.ts +0 -14
  279. package/src/packlets/retrieve/linkTraversalRetriever.ts +0 -158
  280. package/src/packlets/retrieve/recencyRetriever.ts +0 -54
  281. package/src/packlets/retrieve/retriever.ts +0 -291
  282. package/src/packlets/retrieve/semanticRetriever.ts +0 -152
  283. package/src/packlets/retrieve/structuredFilterRetriever.ts +0 -58
  284. package/src/packlets/retrieve/tagRetriever.ts +0 -58
  285. package/src/packlets/retrieve/temporalRetrievers.ts +0 -210
  286. package/src/packlets/store/fileTreeMemoryStore.ts +0 -1872
  287. package/src/packlets/store/index.ts +0 -7
  288. package/src/packlets/store/scopeEncoding.ts +0 -36
  289. package/src/packlets/tools/index.ts +0 -6
  290. package/src/packlets/tools/memoryTools.ts +0 -706
  291. package/src/packlets/types/envelope.ts +0 -196
  292. package/src/packlets/types/filenameSafety.ts +0 -57
  293. package/src/packlets/types/identityCodec.ts +0 -447
  294. package/src/packlets/types/ids.ts +0 -124
  295. package/src/packlets/types/index.ts +0 -11
  296. package/src/packlets/types/temporal.ts +0 -96
  297. package/src/packlets/types/writePolicy.ts +0 -612
  298. package/src/packlets/vector/fragmentConverters.ts +0 -55
  299. package/src/packlets/vector/inMemoryCosineIndex.ts +0 -196
  300. package/src/packlets/vector/inMemoryFragmentCosineIndex.ts +0 -289
  301. package/src/packlets/vector/index.ts +0 -9
  302. package/src/packlets/vector/vectorIndex.ts +0 -273
  303. package/src/test/unit/converters/antagonistRoundTrip.test.ts +0 -110
  304. package/src/test/unit/converters/bodyConverterRegistry.test.ts +0 -89
  305. package/src/test/unit/converters/envelopeConverter.test.ts +0 -418
  306. package/src/test/unit/index/memoryIndex.test.ts +0 -272
  307. package/src/test/unit/ingest/antagonistCycleAndParity.test.ts +0 -367
  308. package/src/test/unit/ingest/cycleGuard.test.ts +0 -110
  309. package/src/test/unit/ingest/dedupScope.test.ts +0 -542
  310. package/src/test/unit/ingest/orchestrator.test.ts +0 -1355
  311. package/src/test/unit/observe/memoryObservationStore.test.ts +0 -158
  312. package/src/test/unit/retrieve/fragmentSemanticRetriever.test.ts +0 -163
  313. package/src/test/unit/retrieve/linkTraversalRetriever.test.ts +0 -329
  314. package/src/test/unit/retrieve/retrievers.test.ts +0 -1018
  315. package/src/test/unit/retrieve/temporalRetrievers.test.ts +0 -226
  316. package/src/test/unit/store/antagonistTemporalBoundary.test.ts +0 -158
  317. package/src/test/unit/store/embedOnWrite.test.ts +0 -418
  318. package/src/test/unit/store/fileTreeMemoryStore.test.ts +0 -1041
  319. package/src/test/unit/store/fragmentEmbedOnWrite.test.ts +0 -349
  320. package/src/test/unit/store/indexInjection.test.ts +0 -550
  321. package/src/test/unit/store/lenientOpen.test.ts +0 -292
  322. package/src/test/unit/store/listScoped.test.ts +0 -138
  323. package/src/test/unit/store/observations.test.ts +0 -290
  324. package/src/test/unit/store/rankAxis.test.ts +0 -349
  325. package/src/test/unit/store/scopeEncoding.test.ts +0 -37
  326. package/src/test/unit/store/temporalStore.test.ts +0 -469
  327. package/src/test/unit/tools/memoryTools.test.ts +0 -1121
  328. package/src/test/unit/types/identityCodec.test.ts +0 -266
  329. package/src/test/unit/types/ids.test.ts +0 -94
  330. package/src/test/unit/types/temporalCodec.test.ts +0 -259
  331. package/src/test/unit/types/temporalPolicy.test.ts +0 -124
  332. package/src/test/unit/types/writePolicy.test.ts +0 -446
  333. package/src/test/unit/vector/fragmentConverters.test.ts +0 -80
  334. package/src/test/unit/vector/inMemoryCosineIndex.test.ts +0 -318
  335. package/src/test/unit/vector/inMemoryFragmentCosineIndex.test.ts +0 -477
  336. package/src/test/unit/vector/vectorIndex.test.ts +0 -64
  337. package/temp/build/lint/_eslint-5eVG3S6w.json +0 -306
  338. package/temp/build/typescript/ts_8nwakTlr.json +0 -1
  339. package/temp/ts-agent-memory.api.json +0 -21030
  340. package/temp/ts-agent-memory.api.md +0 -940
  341. package/tsconfig.json +0 -8
@@ -1,542 +0,0 @@
1
- /*
2
- * Copyright (c) 2026 Erik Fortune
3
- * SPDX-License-Identifier: MIT
4
- */
5
-
6
- import '@fgv/ts-utils-jest';
7
- import { Converters, Result, succeed } from '@fgv/ts-utils';
8
- import { FileTree } from '@fgv/ts-json-base';
9
- import {
10
- BodyConverterRegistry,
11
- DedupScope,
12
- EntityId,
13
- FileTreeMemoryStore,
14
- IBodyConverterRegistry,
15
- ICandidateEdge,
16
- ICandidateRecord,
17
- IEdgeTarget,
18
- IEntityResolutionCandidate,
19
- IEntityResolver,
20
- IFactExtractor,
21
- IIdentityCodec,
22
- IIngestItem,
23
- IIngestItemResult,
24
- IMemoryClassification,
25
- IMemoryClassifier,
26
- IMemoryRecord,
27
- IProvenance,
28
- IRelationContext,
29
- IRelationExtractor,
30
- IVectorIndex,
31
- IWritePolicy,
32
- InMemoryCosineIndex,
33
- Kind,
34
- KnowledgeIdentityCodec,
35
- KnowledgeLwwPolicy,
36
- LinkType,
37
- LtmIdentityCodec,
38
- MemoryCapCullPolicy,
39
- MemoryEmbedder,
40
- MemoryId,
41
- MemoryIngestOrchestrator,
42
- MemoryScopeKey,
43
- MtmIdentityCodec,
44
- ResolutionVerdict,
45
- Tag,
46
- TemporalIdentityCodec,
47
- TemporalVersionedPolicy
48
- } from '../../../index';
49
-
50
- // --- kinds --------------------------------------------------------------------
51
- // `mem` is the entity-scoped kind under test: a FLAT (non-versioned) kind whose
52
- // policy declares `dedupScope: 'entity'`. This is the shape the reporter runs —
53
- // an experience family — and the one whose ingest-path behavior this stream fixes.
54
- const memKind: Kind = 'mem' as Kind;
55
- // `doc` is the content-scoped control: cross-id collapse is CORRECT for it and
56
- // must keep working exactly as before.
57
- const docKind: Kind = 'doc' as Kind;
58
- // `claim` is the sibling candidate whose edge points at a collapsed candidate.
59
- // It has no registered policy, so it resolves through the store's DEFAULT policy.
60
- const claimKind: Kind = 'claim' as Kind;
61
- // `turn` is the reporter's LITERAL shape: an MTM kind whose turns share one
62
- // conversation scope and differ only by idStem. This is where the bug bit.
63
- const turnKind: Kind = 'turn' as Kind;
64
- // `evt` is a TEMPORAL entity-scoped kind. TemporalIdentityCodec gives each entity
65
- // its own scope (`<base>/entities/<id>`), so distinct temporal entities were
66
- // already isolated by the scope filter alone — see the test below.
67
- const evtKind: Kind = 'evt' as Kind;
68
-
69
- const memScope: MemoryScopeKey = LtmIdentityCodec.scope;
70
- const docScope: MemoryScopeKey = KnowledgeIdentityCodec.scope;
71
-
72
- // --- fixtures -----------------------------------------------------------------
73
- const clock = (): number => 1000;
74
-
75
- function mutableRoot(): FileTree.IMutableFileTreeDirectoryItem {
76
- const tree = FileTree.inMemory([], { mutable: true }).orThrow();
77
- const root = tree.getDirectory('/').orThrow();
78
- if (!FileTree.isMutableDirectoryItem(root)) {
79
- throw new Error('expected a mutable root directory');
80
- }
81
- return root;
82
- }
83
-
84
- function registry(): IBodyConverterRegistry {
85
- const reg = BodyConverterRegistry.create().orThrow();
86
- reg.register(memKind, Converters.string);
87
- reg.register(docKind, Converters.string);
88
- reg.register(claimKind, Converters.string);
89
- reg.register(turnKind, Converters.string);
90
- reg.register(evtKind, Converters.string);
91
- return reg;
92
- }
93
-
94
- const codecs: ReadonlyMap<Kind, IIdentityCodec> = new Map<Kind, IIdentityCodec>([
95
- [memKind, new LtmIdentityCodec()],
96
- [docKind, new KnowledgeIdentityCodec()],
97
- [claimKind, new KnowledgeIdentityCodec()],
98
- [turnKind, new MtmIdentityCodec()],
99
- [evtKind, TemporalIdentityCodec.create('events').orThrow()]
100
- ]);
101
-
102
- /**
103
- * `mem` declares `'entity'` (the experience family), `doc` declares `'content'`
104
- * (the knowledge family). `claim` is deliberately absent so it exercises the
105
- * store's default-policy fallback.
106
- */
107
- function policies(): ReadonlyMap<Kind, IWritePolicy> {
108
- return new Map<Kind, IWritePolicy>([
109
- [
110
- memKind,
111
- MemoryCapCullPolicy.create({
112
- mutableFields: ['body', 'tags', 'links', 'provenance']
113
- }).orThrow()
114
- ],
115
- [docKind, KnowledgeLwwPolicy.create().orThrow()],
116
- [
117
- turnKind,
118
- MemoryCapCullPolicy.create({
119
- mutableFields: ['body', 'tags', 'links', 'provenance']
120
- }).orThrow()
121
- ],
122
- [evtKind, TemporalVersionedPolicy.create().orThrow()]
123
- ]);
124
- }
125
-
126
- /** A deterministic embedder: identical bodies embed identically (cosine 1.0). */
127
- const embed: MemoryEmbedder = (record) => {
128
- const vec: ReadonlyArray<number> = record.body === 'shared body' ? [1, 0, 0] : [0, 1, 0];
129
- return Promise.resolve(succeed(Float32Array.from(vec)));
130
- };
131
-
132
- function buildStore(vectorIndex?: IVectorIndex): FileTreeMemoryStore {
133
- return FileTreeMemoryStore.create({
134
- root: mutableRoot(),
135
- registry: registry(),
136
- codecs,
137
- writePolicies: policies(),
138
- clock,
139
- vectorIndex,
140
- embed: vectorIndex !== undefined ? embed : undefined
141
- }).orThrow();
142
- }
143
-
144
- /**
145
- * Write a record straight through the store (the direct-put path). The envelope
146
- * `id` is the CODEC-DERIVED stem, which is not always the `entityId` — an MTM
147
- * entity `conv-1:2` addresses to `conversations/conv-1` + stem `turn-2`.
148
- */
149
- async function put(
150
- store: FileTreeMemoryStore,
151
- kind: Kind,
152
- entityId: string,
153
- body: string
154
- ): Promise<Result<IMemoryRecord<unknown>>> {
155
- const idStem: string = codecs
156
- .get(kind)!
157
- .encode(entityId as EntityId)
158
- .orThrow().idStem;
159
- return store.put({
160
- envelope: {
161
- id: idStem as MemoryId,
162
- entityId: entityId as EntityId,
163
- kind,
164
- tags: [] as ReadonlyArray<Tag>,
165
- links: [],
166
- created: 0,
167
- updated: 0,
168
- seq: 0,
169
- contentHash: '',
170
- provenance: { source: 'agent' } as IProvenance
171
- },
172
- body
173
- });
174
- }
175
-
176
- function candidate(kind: Kind, entityId: string, body: string): ICandidateRecord {
177
- return {
178
- envelope: {
179
- entityId: entityId as EntityId,
180
- kind,
181
- tags: [] as ReadonlyArray<Tag>,
182
- links: [],
183
- provenance: { source: 'agent' } as IProvenance
184
- },
185
- body
186
- };
187
- }
188
-
189
- function target(scope: MemoryScopeKey, id: string): IEdgeTarget {
190
- return { scope, id: id as MemoryId };
191
- }
192
-
193
- const classifyMem: IMemoryClassifier = {
194
- classify: () => Promise.resolve(succeed({ kind: memKind } as IMemoryClassification))
195
- };
196
-
197
- function extractorFor(candidates: ReadonlyArray<ICandidateRecord>): IFactExtractor {
198
- return { extract: () => Promise.resolve(succeed(candidates)) };
199
- }
200
-
201
- function relaterFor(edges: ReadonlyArray<ICandidateEdge>): IRelationExtractor {
202
- return { relate: (__ctx: IRelationContext) => Promise.resolve(succeed(edges)) };
203
- }
204
-
205
- const noEdges: IRelationExtractor = relaterFor([]);
206
-
207
- interface IBuildOrchestratorParams {
208
- readonly store: FileTreeMemoryStore;
209
- readonly candidates: ReadonlyArray<ICandidateRecord>;
210
- readonly edges?: ReadonlyArray<ICandidateEdge>;
211
- readonly entityResolver?: IEntityResolver;
212
- readonly vectorIndex?: IVectorIndex;
213
- }
214
-
215
- function buildOrchestrator(params: IBuildOrchestratorParams): MemoryIngestOrchestrator {
216
- return MemoryIngestOrchestrator.create({
217
- store: params.store,
218
- registry: registry(),
219
- codecs,
220
- classifier: classifyMem,
221
- extractor: extractorFor(params.candidates),
222
- relationExtractor: params.edges !== undefined ? relaterFor(params.edges) : noEdges,
223
- entityResolver: params.entityResolver,
224
- vectorIndex: params.vectorIndex,
225
- embed: params.vectorIndex !== undefined ? embed : undefined
226
- }).orThrow();
227
- }
228
-
229
- const item: IIngestItem = { id: 'item-1', content: 'irrelevant' };
230
-
231
- /** The per-candidate outcome for `entityId`, or `undefined` when absent. */
232
- function outcomeFor(
233
- result: IIngestItemResult,
234
- entityId: string
235
- ): IIngestItemResult['records'][number] | undefined {
236
- return result.records.find((r) => r.candidate.envelope.entityId === (entityId as EntityId));
237
- }
238
-
239
- describe('dedupScope on the ingest path', () => {
240
- describe('IMemoryStore.dedupScopeFor (deliverable 1)', () => {
241
- test("reports 'entity' for a kind whose policy declares it", () => {
242
- expect(buildStore().dedupScopeFor(memKind)).toBe('entity');
243
- });
244
-
245
- test("reports 'content' for a kind whose policy declares it", () => {
246
- expect(buildStore().dedupScopeFor(docKind)).toBe('content');
247
- });
248
-
249
- test("reports 'content' for a kind with NO registered policy (the store's default policy is KnowledgeLwwPolicy)", () => {
250
- // Documents the real fallback: the store's default policy is a
251
- // KnowledgeLwwPolicy, which DECLARES 'content'. An unpoliced kind therefore
252
- // resolves to 'content' and never reaches DEFAULT_DEDUP_SCOPE ('entity').
253
- expect(buildStore().dedupScopeFor(claimKind)).toBe('content');
254
- expect(buildStore().dedupScopeFor('never-registered' as Kind)).toBe('content');
255
- });
256
-
257
- test('agrees with what the write path actually does', async () => {
258
- // The accessor is not a parallel declaration — it is the same read the
259
- // store's own dedup branch performs. An 'entity' kind keeps two identical
260
- // bodies; a 'content' kind collapses them.
261
- const store: FileTreeMemoryStore = buildStore();
262
- const scopes: ReadonlyArray<DedupScope> = [store.dedupScopeFor(memKind), store.dedupScopeFor(docKind)];
263
- expect(scopes).toEqual(['entity', 'content']);
264
- });
265
- });
266
-
267
- describe('direct-put path (unchanged, the parity baseline)', () => {
268
- test("an 'entity' kind keeps two distinct entities with byte-identical bodies", async () => {
269
- const store: FileTreeMemoryStore = buildStore();
270
- expect(await put(store, memKind, 'turn-1', 'shared body')).toSucceed();
271
- expect(await put(store, memKind, 'turn-2', 'shared body')).toSucceedAndSatisfy((rec) => {
272
- expect(rec.envelope.id).toBe('turn-2');
273
- });
274
- expect(await store.list({ kind: memKind })).toSucceedAndSatisfy((records) => {
275
- expect(records).toHaveLength(2);
276
- });
277
- });
278
-
279
- test("a 'content' kind collapses two distinct entities with byte-identical bodies", async () => {
280
- const store: FileTreeMemoryStore = buildStore();
281
- expect(await put(store, docKind, 'doc-a', 'shared body')).toSucceed();
282
- expect(await put(store, docKind, 'doc-b', 'shared body')).toSucceedAndSatisfy((rec) => {
283
- // The existing record is returned unchanged — the cross-id collapse.
284
- expect(rec.envelope.id).toBe('doc-a');
285
- });
286
- expect(await store.list({ kind: docKind })).toSucceedAndSatisfy((records) => {
287
- expect(records).toHaveLength(1);
288
- });
289
- });
290
- });
291
-
292
- describe('layer-1 exact match honors dedupScope (deliverable 2)', () => {
293
- test("an 'entity' kind does NOT collapse a cross-id body collision (fails against pre-fix code)", async () => {
294
- const store: FileTreeMemoryStore = buildStore();
295
- expect(await put(store, memKind, 'turn-1', 'shared body')).toSucceed();
296
-
297
- const orchestrator: MemoryIngestOrchestrator = buildOrchestrator({
298
- store,
299
- candidates: [candidate(memKind, 'turn-2', 'shared body')]
300
- });
301
-
302
- expect(await orchestrator.ingestItem(item)).toSucceedAndSatisfy((result) => {
303
- const turn2 = outcomeFor(result, 'turn-2');
304
- // Pre-fix this was `deduped` against turn-1 — layer-1 ignored the
305
- // declaration and always behaved as 'content'.
306
- expect(turn2?.disposition).toBe('written');
307
- expect(turn2?.resolution.verdict).toBe('new');
308
- expect(turn2?.id).toBe('turn-2');
309
- });
310
- expect(await store.list({ kind: memKind })).toSucceedAndSatisfy((records) => {
311
- expect(records).toHaveLength(2);
312
- });
313
- });
314
-
315
- test("a 'content' kind still collapses a cross-id body collision", async () => {
316
- const store: FileTreeMemoryStore = buildStore();
317
- expect(await put(store, docKind, 'doc-a', 'shared body')).toSucceed();
318
-
319
- const orchestrator: MemoryIngestOrchestrator = buildOrchestrator({
320
- store,
321
- candidates: [candidate(docKind, 'doc-b', 'shared body')]
322
- });
323
-
324
- expect(await orchestrator.ingestItem(item)).toSucceedAndSatisfy((result) => {
325
- const docB = outcomeFor(result, 'doc-b');
326
- expect(docB?.disposition).toBe('deduped');
327
- expect(docB?.resolution).toEqual({
328
- verdict: 'duplicate-of',
329
- target: target(docScope, 'doc-a')
330
- });
331
- expect(docB?.id).toBe('doc-a');
332
- });
333
- expect(await store.list({ kind: docKind })).toSucceedAndSatisfy((records) => {
334
- expect(records).toHaveLength(1);
335
- });
336
- });
337
-
338
- test("an 'entity' kind still reports duplicate-of for a SAME-entity identical body (OQ-2)", async () => {
339
- const store: FileTreeMemoryStore = buildStore();
340
- expect(await put(store, memKind, 'turn-1', 'shared body')).toSucceed();
341
-
342
- const orchestrator: MemoryIngestOrchestrator = buildOrchestrator({
343
- store,
344
- candidates: [candidate(memKind, 'turn-1', 'shared body')]
345
- });
346
-
347
- expect(await orchestrator.ingestItem(item)).toSucceedAndSatisfy((result) => {
348
- const turn1 = outcomeFor(result, 'turn-1');
349
- // A genuine no-op the store would also collapse. Emitting the verdict
350
- // keeps it honest, and it is safe because the redirect (deliverable 3)
351
- // keeps the address resolvable for sibling edges.
352
- expect(turn1?.disposition).toBe('deduped');
353
- expect(turn1?.resolution).toEqual({
354
- verdict: 'duplicate-of',
355
- target: target(memScope, 'turn-1')
356
- });
357
- });
358
- });
359
-
360
- test("the reporter's literal shape: two MTM turns in ONE conversation scope with identical bodies", async () => {
361
- // MtmIdentityCodec puts every turn of a conversation in the SAME scope
362
- // (`conversations/<id>`), differing only by idStem (`turn-<n>`). That is
363
- // exactly where the bug bit: same kind, same scope, different entity, and
364
- // a body collision was enough to collapse one turn into the other.
365
- const store: FileTreeMemoryStore = buildStore();
366
- expect(await put(store, turnKind, 'conv-1:1', 'ok, thanks')).toSucceed();
367
-
368
- const orchestrator: MemoryIngestOrchestrator = buildOrchestrator({
369
- store,
370
- candidates: [candidate(turnKind, 'conv-1:2', 'ok, thanks')]
371
- });
372
-
373
- expect(await orchestrator.ingestItem(item)).toSucceedAndSatisfy((result) => {
374
- expect(outcomeFor(result, 'conv-1:2')?.disposition).toBe('written');
375
- });
376
- expect(await store.list({ kind: turnKind })).toSucceedAndSatisfy((records) => {
377
- // Both turns persist. Pre-fix, turn 2 was silently swallowed.
378
- expect(records).toHaveLength(2);
379
- });
380
- });
381
-
382
- test('a TEMPORAL entity kind keeps distinct entities apart (scope isolation, unchanged)', async () => {
383
- // TemporalIdentityCodec addresses each entity to its OWN scope
384
- // (`events/entities/<id>`), so two distinct temporal entities were never
385
- // in one exact-match cohort even before this change — the scope filter
386
- // alone separated them. Guarding it so the entity narrowing (which is a
387
- // no-op within a single entity's scope, where every version shares the
388
- // idStem) is never mistaken for what protects temporal kinds.
389
- const store: FileTreeMemoryStore = buildStore();
390
- expect(await put(store, evtKind, 'evt-1', 'shared body')).toSucceed();
391
-
392
- const orchestrator: MemoryIngestOrchestrator = buildOrchestrator({
393
- store,
394
- candidates: [candidate(evtKind, 'evt-2', 'shared body')]
395
- });
396
-
397
- expect(await orchestrator.ingestItem(item)).toSucceedAndSatisfy((result) => {
398
- expect(outcomeFor(result, 'evt-2')?.disposition).toBe('written');
399
- });
400
- });
401
-
402
- test("an 'entity' kind does not match across scopes", async () => {
403
- // A doc and a mem record can share a body without either seeing the other:
404
- // the cohort is scope-filtered before the entity narrowing applies.
405
- const store: FileTreeMemoryStore = buildStore();
406
- expect(await put(store, docKind, 'doc-a', 'shared body')).toSucceed();
407
-
408
- const orchestrator: MemoryIngestOrchestrator = buildOrchestrator({
409
- store,
410
- candidates: [candidate(memKind, 'turn-1', 'shared body')]
411
- });
412
-
413
- expect(await orchestrator.ingestItem(item)).toSucceedAndSatisfy((result) => {
414
- expect(outcomeFor(result, 'turn-1')?.disposition).toBe('written');
415
- });
416
- });
417
- });
418
-
419
- describe("the reporter's scenario end to end", () => {
420
- test('a cross-id body collision on an entity kind no longer fails the whole item, and the claim is written', async () => {
421
- // Two live records, same kind, same scope, byte-identical bodies, different
422
- // entity ids — plus a sibling edge to the second. Pre-fix: turn-2 collapsed
423
- // to turn-1, its address vanished from `refIds`, and the edge failed
424
- // validation, taking the WHOLE ingest item (claim included) down with it.
425
- const store: FileTreeMemoryStore = buildStore();
426
- expect(await put(store, memKind, 'turn-1', 'shared body')).toSucceed();
427
-
428
- const orchestrator: MemoryIngestOrchestrator = buildOrchestrator({
429
- store,
430
- candidates: [candidate(memKind, 'turn-2', 'shared body'), candidate(claimKind, 'c-1', 'a claim')],
431
- edges: [
432
- {
433
- source: target(docScope, 'c-1'),
434
- edge: { type: 'supports' as LinkType, target: target(memScope, 'turn-2') }
435
- }
436
- ]
437
- });
438
-
439
- expect(await orchestrator.ingestItem(item)).toSucceedAndSatisfy((result) => {
440
- expect(outcomeFor(result, 'turn-2')?.disposition).toBe('written');
441
- const claim = outcomeFor(result, 'c-1');
442
- expect(claim?.disposition).toBe('written');
443
- // The claim's edge survived and still points at turn-2, which was written.
444
- expect(claim?.record?.envelope.links).toEqual([
445
- { type: 'supports', target: target(memScope, 'turn-2') }
446
- ]);
447
- });
448
- expect(await store.list({ kind: memKind })).toSucceedAndSatisfy((records) => {
449
- expect(records).toHaveLength(2);
450
- });
451
- });
452
- });
453
-
454
- describe('duplicate-of edge redirect (deliverable 3)', () => {
455
- test("a 'content' kind's collapse redirects a sibling edge to the collapse target", async () => {
456
- // The collapse is CORRECT here — doc-b really is doc-a. The ingest must
457
- // still not fail: the claim's edge is redirected onto doc-a.
458
- const store: FileTreeMemoryStore = buildStore();
459
- expect(await put(store, docKind, 'doc-a', 'shared body')).toSucceed();
460
-
461
- const orchestrator: MemoryIngestOrchestrator = buildOrchestrator({
462
- store,
463
- candidates: [candidate(docKind, 'doc-b', 'shared body'), candidate(claimKind, 'c-1', 'a claim')],
464
- edges: [
465
- {
466
- source: target(docScope, 'c-1'),
467
- edge: { type: 'supports' as LinkType, target: target(docScope, 'doc-b') }
468
- }
469
- ]
470
- });
471
-
472
- expect(await orchestrator.ingestItem(item)).toSucceedAndSatisfy((result) => {
473
- expect(outcomeFor(result, 'doc-b')?.disposition).toBe('deduped');
474
- const claim = outcomeFor(result, 'c-1');
475
- expect(claim?.disposition).toBe('written');
476
- // Redirected from the collapsed doc-b to the record it collapsed into.
477
- expect(claim?.record?.envelope.links).toEqual([
478
- { type: 'supports', target: target(docScope, 'doc-a') }
479
- ]);
480
- });
481
- });
482
-
483
- test("an 'entity' kind's resolver-driven duplicate-of redirects a sibling edge", async () => {
484
- // Layer-1 no longer collapses cross-id on an entity kind, so the
485
- // duplicate-of here comes from the host resolver (layer 2) — the remaining
486
- // way an entity-scoped candidate legitimately collapses onto another entity.
487
- const vectorIndex: IVectorIndex = InMemoryCosineIndex.create().orThrow();
488
- const store: FileTreeMemoryStore = buildStore(vectorIndex);
489
- expect(await put(store, memKind, 'turn-1', 'shared body')).toSucceed();
490
-
491
- const entityResolver: IEntityResolver = {
492
- resolve: (__candidate: ICandidateRecord, similar: ReadonlyArray<IEntityResolutionCandidate>) =>
493
- Promise.resolve(
494
- succeed({ verdict: 'duplicate-of', target: similar[0].target } as ResolutionVerdict)
495
- )
496
- };
497
-
498
- const orchestrator: MemoryIngestOrchestrator = buildOrchestrator({
499
- store,
500
- candidates: [candidate(memKind, 'turn-2', 'shared body'), candidate(claimKind, 'c-1', 'a claim')],
501
- edges: [
502
- {
503
- source: target(docScope, 'c-1'),
504
- edge: { type: 'supports' as LinkType, target: target(memScope, 'turn-2') }
505
- }
506
- ],
507
- entityResolver,
508
- vectorIndex
509
- });
510
-
511
- expect(await orchestrator.ingestItem(item)).toSucceedAndSatisfy((result) => {
512
- expect(outcomeFor(result, 'turn-2')?.disposition).toBe('deduped');
513
- const claim = outcomeFor(result, 'c-1');
514
- expect(claim?.disposition).toBe('written');
515
- expect(claim?.record?.envelope.links).toEqual([
516
- { type: 'supports', target: target(memScope, 'turn-1') }
517
- ]);
518
- });
519
- });
520
-
521
- test('an edge SOURCED at a collapsed candidate is still rejected loudly', async () => {
522
- // Sources are the records an edge is written ONTO. A collapsed candidate is
523
- // never written, so silently relocating the edge would attribute a link the
524
- // host never asked for. The loud failure is the correct outcome here.
525
- const store: FileTreeMemoryStore = buildStore();
526
- expect(await put(store, docKind, 'doc-a', 'shared body')).toSucceed();
527
-
528
- const orchestrator: MemoryIngestOrchestrator = buildOrchestrator({
529
- store,
530
- candidates: [candidate(docKind, 'doc-b', 'shared body'), candidate(claimKind, 'c-1', 'a claim')],
531
- edges: [
532
- {
533
- source: target(docScope, 'doc-b'),
534
- edge: { type: 'supports' as LinkType, target: target(docScope, 'c-1') }
535
- }
536
- ]
537
- });
538
-
539
- expect(await orchestrator.ingestItem(item)).toFailWith(/is not a candidate being written/i);
540
- });
541
- });
542
- });