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

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 (376) 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/retrieve/linkTraversalRetriever.js +1 -1
  7. package/dist/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
  8. package/dist/packlets/retrieve/recencyRetriever.js +1 -1
  9. package/dist/packlets/retrieve/recencyRetriever.js.map +1 -1
  10. package/dist/packlets/retrieve/retriever.js +11 -5
  11. package/dist/packlets/retrieve/retriever.js.map +1 -1
  12. package/dist/packlets/retrieve/structuredFilterRetriever.js +27 -5
  13. package/dist/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
  14. package/dist/packlets/retrieve/tagRetriever.js +1 -1
  15. package/dist/packlets/retrieve/tagRetriever.js.map +1 -1
  16. package/dist/packlets/retrieve/temporalRetrievers.js +1 -1
  17. package/dist/packlets/retrieve/temporalRetrievers.js.map +1 -1
  18. package/dist/packlets/store/fileTreeMemoryStore.js +152 -132
  19. package/dist/packlets/store/fileTreeMemoryStore.js.map +1 -1
  20. package/dist/packlets/store/vectorMaintenance.js +251 -0
  21. package/dist/packlets/store/vectorMaintenance.js.map +1 -0
  22. package/dist/packlets/types/envelope.js.map +1 -1
  23. package/dist/packlets/vector/inMemoryCosineIndex.js +81 -18
  24. package/dist/packlets/vector/inMemoryCosineIndex.js.map +1 -1
  25. package/dist/packlets/vector/inMemoryFragmentCosineIndex.js +7 -0
  26. package/dist/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
  27. package/dist/packlets/vector/vectorIndex.js.map +1 -1
  28. package/dist/ts-agent-memory.d.ts +431 -79
  29. package/lib/packlets/ingest/orchestrator.d.ts.map +1 -1
  30. package/lib/packlets/ingest/orchestrator.js +11 -1
  31. package/lib/packlets/ingest/orchestrator.js.map +1 -1
  32. package/lib/packlets/observe/memoryObservationStore.d.ts.map +1 -1
  33. package/lib/packlets/observe/memoryObservationStore.js +6 -0
  34. package/lib/packlets/observe/memoryObservationStore.js.map +1 -1
  35. package/lib/packlets/observe/observer.d.ts +61 -0
  36. package/lib/packlets/observe/observer.d.ts.map +1 -1
  37. package/lib/packlets/observe/observer.js.map +1 -1
  38. package/lib/packlets/retrieve/linkTraversalRetriever.d.ts +1 -1
  39. package/lib/packlets/retrieve/linkTraversalRetriever.js +1 -1
  40. package/lib/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
  41. package/lib/packlets/retrieve/recencyRetriever.d.ts +1 -1
  42. package/lib/packlets/retrieve/recencyRetriever.js +1 -1
  43. package/lib/packlets/retrieve/recencyRetriever.js.map +1 -1
  44. package/lib/packlets/retrieve/retriever.d.ts +26 -7
  45. package/lib/packlets/retrieve/retriever.d.ts.map +1 -1
  46. package/lib/packlets/retrieve/retriever.js +11 -5
  47. package/lib/packlets/retrieve/retriever.js.map +1 -1
  48. package/lib/packlets/retrieve/structuredFilterRetriever.d.ts +26 -4
  49. package/lib/packlets/retrieve/structuredFilterRetriever.d.ts.map +1 -1
  50. package/lib/packlets/retrieve/structuredFilterRetriever.js +27 -5
  51. package/lib/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
  52. package/lib/packlets/retrieve/tagRetriever.d.ts +1 -1
  53. package/lib/packlets/retrieve/tagRetriever.js +1 -1
  54. package/lib/packlets/retrieve/tagRetriever.js.map +1 -1
  55. package/lib/packlets/retrieve/temporalRetrievers.js +1 -1
  56. package/lib/packlets/retrieve/temporalRetrievers.js.map +1 -1
  57. package/lib/packlets/store/fileTreeMemoryStore.d.ts +135 -59
  58. package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
  59. package/lib/packlets/store/fileTreeMemoryStore.js +151 -131
  60. package/lib/packlets/store/fileTreeMemoryStore.js.map +1 -1
  61. package/lib/packlets/store/vectorMaintenance.d.ts +149 -0
  62. package/lib/packlets/store/vectorMaintenance.d.ts.map +1 -0
  63. package/lib/packlets/store/vectorMaintenance.js +255 -0
  64. package/lib/packlets/store/vectorMaintenance.js.map +1 -0
  65. package/lib/packlets/types/envelope.d.ts +11 -0
  66. package/lib/packlets/types/envelope.d.ts.map +1 -1
  67. package/lib/packlets/types/envelope.js.map +1 -1
  68. package/lib/packlets/vector/inMemoryCosineIndex.d.ts +30 -7
  69. package/lib/packlets/vector/inMemoryCosineIndex.d.ts.map +1 -1
  70. package/lib/packlets/vector/inMemoryCosineIndex.js +80 -17
  71. package/lib/packlets/vector/inMemoryCosineIndex.js.map +1 -1
  72. package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts +7 -0
  73. package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts.map +1 -1
  74. package/lib/packlets/vector/inMemoryFragmentCosineIndex.js +7 -0
  75. package/lib/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
  76. package/lib/packlets/vector/vectorIndex.d.ts +129 -1
  77. package/lib/packlets/vector/vectorIndex.d.ts.map +1 -1
  78. package/lib/packlets/vector/vectorIndex.js.map +1 -1
  79. package/package.json +17 -7
  80. package/.rush/temp/5667e36f1c0cc503a5c20a3ebff76e7b9a702d41.tar.log +0 -468
  81. package/.rush/temp/chunked-rush-logs/ts-agent-memory.build.chunks.jsonl +0 -9
  82. package/.rush/temp/operation/build/all.log +0 -9
  83. package/.rush/temp/operation/build/log-chunks.jsonl +0 -9
  84. package/.rush/temp/operation/build/state.json +0 -3
  85. package/.rush/temp/shrinkwrap-deps.json +0 -689
  86. package/config/api-extractor.json +0 -343
  87. package/config/jest.config.json +0 -14
  88. package/config/rig.json +0 -4
  89. package/dist/test/unit/converters/antagonistRoundTrip.test.js +0 -95
  90. package/dist/test/unit/converters/antagonistRoundTrip.test.js.map +0 -1
  91. package/dist/test/unit/converters/bodyConverterRegistry.test.js +0 -72
  92. package/dist/test/unit/converters/bodyConverterRegistry.test.js.map +0 -1
  93. package/dist/test/unit/converters/envelopeConverter.test.js +0 -313
  94. package/dist/test/unit/converters/envelopeConverter.test.js.map +0 -1
  95. package/dist/test/unit/index/memoryIndex.test.js +0 -214
  96. package/dist/test/unit/index/memoryIndex.test.js.map +0 -1
  97. package/dist/test/unit/ingest/antagonistCycleAndParity.test.js +0 -277
  98. package/dist/test/unit/ingest/antagonistCycleAndParity.test.js.map +0 -1
  99. package/dist/test/unit/ingest/cycleGuard.test.js +0 -81
  100. package/dist/test/unit/ingest/cycleGuard.test.js.map +0 -1
  101. package/dist/test/unit/ingest/dedupScope.test.js +0 -434
  102. package/dist/test/unit/ingest/dedupScope.test.js.map +0 -1
  103. package/dist/test/unit/ingest/orchestrator.test.js +0 -1058
  104. package/dist/test/unit/ingest/orchestrator.test.js.map +0 -1
  105. package/dist/test/unit/observe/memoryObservationStore.test.js +0 -118
  106. package/dist/test/unit/observe/memoryObservationStore.test.js.map +0 -1
  107. package/dist/test/unit/retrieve/fragmentSemanticRetriever.test.js +0 -116
  108. package/dist/test/unit/retrieve/fragmentSemanticRetriever.test.js.map +0 -1
  109. package/dist/test/unit/retrieve/linkTraversalRetriever.test.js +0 -257
  110. package/dist/test/unit/retrieve/linkTraversalRetriever.test.js.map +0 -1
  111. package/dist/test/unit/retrieve/retrievers.test.js +0 -768
  112. package/dist/test/unit/retrieve/retrievers.test.js.map +0 -1
  113. package/dist/test/unit/retrieve/temporalRetrievers.test.js +0 -182
  114. package/dist/test/unit/retrieve/temporalRetrievers.test.js.map +0 -1
  115. package/dist/test/unit/store/antagonistTemporalBoundary.test.js +0 -120
  116. package/dist/test/unit/store/antagonistTemporalBoundary.test.js.map +0 -1
  117. package/dist/test/unit/store/embedOnWrite.test.js +0 -317
  118. package/dist/test/unit/store/embedOnWrite.test.js.map +0 -1
  119. package/dist/test/unit/store/fileTreeMemoryStore.test.js +0 -778
  120. package/dist/test/unit/store/fileTreeMemoryStore.test.js.map +0 -1
  121. package/dist/test/unit/store/fragmentEmbedOnWrite.test.js +0 -255
  122. package/dist/test/unit/store/fragmentEmbedOnWrite.test.js.map +0 -1
  123. package/dist/test/unit/store/indexInjection.test.js +0 -432
  124. package/dist/test/unit/store/indexInjection.test.js.map +0 -1
  125. package/dist/test/unit/store/lenientOpen.test.js +0 -248
  126. package/dist/test/unit/store/lenientOpen.test.js.map +0 -1
  127. package/dist/test/unit/store/listScoped.test.js +0 -109
  128. package/dist/test/unit/store/listScoped.test.js.map +0 -1
  129. package/dist/test/unit/store/observations.test.js +0 -239
  130. package/dist/test/unit/store/observations.test.js.map +0 -1
  131. package/dist/test/unit/store/rankAxis.test.js +0 -254
  132. package/dist/test/unit/store/rankAxis.test.js.map +0 -1
  133. package/dist/test/unit/store/scopeEncoding.test.js +0 -24
  134. package/dist/test/unit/store/scopeEncoding.test.js.map +0 -1
  135. package/dist/test/unit/store/temporalStore.test.js +0 -398
  136. package/dist/test/unit/store/temporalStore.test.js.map +0 -1
  137. package/dist/test/unit/tools/memoryTools.test.js +0 -842
  138. package/dist/test/unit/tools/memoryTools.test.js.map +0 -1
  139. package/dist/test/unit/types/identityCodec.test.js +0 -187
  140. package/dist/test/unit/types/identityCodec.test.js.map +0 -1
  141. package/dist/test/unit/types/ids.test.js +0 -84
  142. package/dist/test/unit/types/ids.test.js.map +0 -1
  143. package/dist/test/unit/types/temporalCodec.test.js +0 -203
  144. package/dist/test/unit/types/temporalCodec.test.js.map +0 -1
  145. package/dist/test/unit/types/temporalPolicy.test.js +0 -83
  146. package/dist/test/unit/types/temporalPolicy.test.js.map +0 -1
  147. package/dist/test/unit/types/writePolicy.test.js +0 -331
  148. package/dist/test/unit/types/writePolicy.test.js.map +0 -1
  149. package/dist/test/unit/vector/fragmentConverters.test.js +0 -58
  150. package/dist/test/unit/vector/fragmentConverters.test.js.map +0 -1
  151. package/dist/test/unit/vector/inMemoryCosineIndex.test.js +0 -252
  152. package/dist/test/unit/vector/inMemoryCosineIndex.test.js.map +0 -1
  153. package/dist/test/unit/vector/inMemoryFragmentCosineIndex.test.js +0 -362
  154. package/dist/test/unit/vector/inMemoryFragmentCosineIndex.test.js.map +0 -1
  155. package/dist/test/unit/vector/vectorIndex.test.js +0 -51
  156. package/dist/test/unit/vector/vectorIndex.test.js.map +0 -1
  157. package/eslint.config.js +0 -15
  158. package/etc/ts-agent-memory.api.md +0 -940
  159. package/lib/test/unit/converters/antagonistRoundTrip.test.d.ts +0 -10
  160. package/lib/test/unit/converters/antagonistRoundTrip.test.d.ts.map +0 -1
  161. package/lib/test/unit/converters/antagonistRoundTrip.test.js +0 -97
  162. package/lib/test/unit/converters/antagonistRoundTrip.test.js.map +0 -1
  163. package/lib/test/unit/converters/bodyConverterRegistry.test.d.ts +0 -2
  164. package/lib/test/unit/converters/bodyConverterRegistry.test.d.ts.map +0 -1
  165. package/lib/test/unit/converters/bodyConverterRegistry.test.js +0 -74
  166. package/lib/test/unit/converters/bodyConverterRegistry.test.js.map +0 -1
  167. package/lib/test/unit/converters/envelopeConverter.test.d.ts +0 -2
  168. package/lib/test/unit/converters/envelopeConverter.test.d.ts.map +0 -1
  169. package/lib/test/unit/converters/envelopeConverter.test.js +0 -315
  170. package/lib/test/unit/converters/envelopeConverter.test.js.map +0 -1
  171. package/lib/test/unit/index/memoryIndex.test.d.ts +0 -2
  172. package/lib/test/unit/index/memoryIndex.test.d.ts.map +0 -1
  173. package/lib/test/unit/index/memoryIndex.test.js +0 -216
  174. package/lib/test/unit/index/memoryIndex.test.js.map +0 -1
  175. package/lib/test/unit/ingest/antagonistCycleAndParity.test.d.ts +0 -9
  176. package/lib/test/unit/ingest/antagonistCycleAndParity.test.d.ts.map +0 -1
  177. package/lib/test/unit/ingest/antagonistCycleAndParity.test.js +0 -279
  178. package/lib/test/unit/ingest/antagonistCycleAndParity.test.js.map +0 -1
  179. package/lib/test/unit/ingest/cycleGuard.test.d.ts +0 -2
  180. package/lib/test/unit/ingest/cycleGuard.test.d.ts.map +0 -1
  181. package/lib/test/unit/ingest/cycleGuard.test.js +0 -83
  182. package/lib/test/unit/ingest/cycleGuard.test.js.map +0 -1
  183. package/lib/test/unit/ingest/dedupScope.test.d.ts +0 -2
  184. package/lib/test/unit/ingest/dedupScope.test.d.ts.map +0 -1
  185. package/lib/test/unit/ingest/dedupScope.test.js +0 -436
  186. package/lib/test/unit/ingest/dedupScope.test.js.map +0 -1
  187. package/lib/test/unit/ingest/orchestrator.test.d.ts +0 -2
  188. package/lib/test/unit/ingest/orchestrator.test.d.ts.map +0 -1
  189. package/lib/test/unit/ingest/orchestrator.test.js +0 -1060
  190. package/lib/test/unit/ingest/orchestrator.test.js.map +0 -1
  191. package/lib/test/unit/observe/memoryObservationStore.test.d.ts +0 -2
  192. package/lib/test/unit/observe/memoryObservationStore.test.d.ts.map +0 -1
  193. package/lib/test/unit/observe/memoryObservationStore.test.js +0 -120
  194. package/lib/test/unit/observe/memoryObservationStore.test.js.map +0 -1
  195. package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.d.ts +0 -2
  196. package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.d.ts.map +0 -1
  197. package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.js +0 -118
  198. package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.js.map +0 -1
  199. package/lib/test/unit/retrieve/linkTraversalRetriever.test.d.ts +0 -2
  200. package/lib/test/unit/retrieve/linkTraversalRetriever.test.d.ts.map +0 -1
  201. package/lib/test/unit/retrieve/linkTraversalRetriever.test.js +0 -259
  202. package/lib/test/unit/retrieve/linkTraversalRetriever.test.js.map +0 -1
  203. package/lib/test/unit/retrieve/retrievers.test.d.ts +0 -2
  204. package/lib/test/unit/retrieve/retrievers.test.d.ts.map +0 -1
  205. package/lib/test/unit/retrieve/retrievers.test.js +0 -770
  206. package/lib/test/unit/retrieve/retrievers.test.js.map +0 -1
  207. package/lib/test/unit/retrieve/temporalRetrievers.test.d.ts +0 -2
  208. package/lib/test/unit/retrieve/temporalRetrievers.test.d.ts.map +0 -1
  209. package/lib/test/unit/retrieve/temporalRetrievers.test.js +0 -184
  210. package/lib/test/unit/retrieve/temporalRetrievers.test.js.map +0 -1
  211. package/lib/test/unit/store/antagonistTemporalBoundary.test.d.ts +0 -9
  212. package/lib/test/unit/store/antagonistTemporalBoundary.test.d.ts.map +0 -1
  213. package/lib/test/unit/store/antagonistTemporalBoundary.test.js +0 -122
  214. package/lib/test/unit/store/antagonistTemporalBoundary.test.js.map +0 -1
  215. package/lib/test/unit/store/embedOnWrite.test.d.ts +0 -2
  216. package/lib/test/unit/store/embedOnWrite.test.d.ts.map +0 -1
  217. package/lib/test/unit/store/embedOnWrite.test.js +0 -319
  218. package/lib/test/unit/store/embedOnWrite.test.js.map +0 -1
  219. package/lib/test/unit/store/fileTreeMemoryStore.test.d.ts +0 -2
  220. package/lib/test/unit/store/fileTreeMemoryStore.test.d.ts.map +0 -1
  221. package/lib/test/unit/store/fileTreeMemoryStore.test.js +0 -780
  222. package/lib/test/unit/store/fileTreeMemoryStore.test.js.map +0 -1
  223. package/lib/test/unit/store/fragmentEmbedOnWrite.test.d.ts +0 -2
  224. package/lib/test/unit/store/fragmentEmbedOnWrite.test.d.ts.map +0 -1
  225. package/lib/test/unit/store/fragmentEmbedOnWrite.test.js +0 -257
  226. package/lib/test/unit/store/fragmentEmbedOnWrite.test.js.map +0 -1
  227. package/lib/test/unit/store/indexInjection.test.d.ts +0 -2
  228. package/lib/test/unit/store/indexInjection.test.d.ts.map +0 -1
  229. package/lib/test/unit/store/indexInjection.test.js +0 -434
  230. package/lib/test/unit/store/indexInjection.test.js.map +0 -1
  231. package/lib/test/unit/store/lenientOpen.test.d.ts +0 -2
  232. package/lib/test/unit/store/lenientOpen.test.d.ts.map +0 -1
  233. package/lib/test/unit/store/lenientOpen.test.js +0 -250
  234. package/lib/test/unit/store/lenientOpen.test.js.map +0 -1
  235. package/lib/test/unit/store/listScoped.test.d.ts +0 -2
  236. package/lib/test/unit/store/listScoped.test.d.ts.map +0 -1
  237. package/lib/test/unit/store/listScoped.test.js +0 -111
  238. package/lib/test/unit/store/listScoped.test.js.map +0 -1
  239. package/lib/test/unit/store/observations.test.d.ts +0 -2
  240. package/lib/test/unit/store/observations.test.d.ts.map +0 -1
  241. package/lib/test/unit/store/observations.test.js +0 -241
  242. package/lib/test/unit/store/observations.test.js.map +0 -1
  243. package/lib/test/unit/store/rankAxis.test.d.ts +0 -2
  244. package/lib/test/unit/store/rankAxis.test.d.ts.map +0 -1
  245. package/lib/test/unit/store/rankAxis.test.js +0 -256
  246. package/lib/test/unit/store/rankAxis.test.js.map +0 -1
  247. package/lib/test/unit/store/scopeEncoding.test.d.ts +0 -2
  248. package/lib/test/unit/store/scopeEncoding.test.d.ts.map +0 -1
  249. package/lib/test/unit/store/scopeEncoding.test.js +0 -26
  250. package/lib/test/unit/store/scopeEncoding.test.js.map +0 -1
  251. package/lib/test/unit/store/temporalStore.test.d.ts +0 -2
  252. package/lib/test/unit/store/temporalStore.test.d.ts.map +0 -1
  253. package/lib/test/unit/store/temporalStore.test.js +0 -400
  254. package/lib/test/unit/store/temporalStore.test.js.map +0 -1
  255. package/lib/test/unit/tools/memoryTools.test.d.ts +0 -2
  256. package/lib/test/unit/tools/memoryTools.test.d.ts.map +0 -1
  257. package/lib/test/unit/tools/memoryTools.test.js +0 -844
  258. package/lib/test/unit/tools/memoryTools.test.js.map +0 -1
  259. package/lib/test/unit/types/identityCodec.test.d.ts +0 -2
  260. package/lib/test/unit/types/identityCodec.test.d.ts.map +0 -1
  261. package/lib/test/unit/types/identityCodec.test.js +0 -189
  262. package/lib/test/unit/types/identityCodec.test.js.map +0 -1
  263. package/lib/test/unit/types/ids.test.d.ts +0 -2
  264. package/lib/test/unit/types/ids.test.d.ts.map +0 -1
  265. package/lib/test/unit/types/ids.test.js +0 -86
  266. package/lib/test/unit/types/ids.test.js.map +0 -1
  267. package/lib/test/unit/types/temporalCodec.test.d.ts +0 -2
  268. package/lib/test/unit/types/temporalCodec.test.d.ts.map +0 -1
  269. package/lib/test/unit/types/temporalCodec.test.js +0 -205
  270. package/lib/test/unit/types/temporalCodec.test.js.map +0 -1
  271. package/lib/test/unit/types/temporalPolicy.test.d.ts +0 -2
  272. package/lib/test/unit/types/temporalPolicy.test.d.ts.map +0 -1
  273. package/lib/test/unit/types/temporalPolicy.test.js +0 -85
  274. package/lib/test/unit/types/temporalPolicy.test.js.map +0 -1
  275. package/lib/test/unit/types/writePolicy.test.d.ts +0 -2
  276. package/lib/test/unit/types/writePolicy.test.d.ts.map +0 -1
  277. package/lib/test/unit/types/writePolicy.test.js +0 -333
  278. package/lib/test/unit/types/writePolicy.test.js.map +0 -1
  279. package/lib/test/unit/vector/fragmentConverters.test.d.ts +0 -2
  280. package/lib/test/unit/vector/fragmentConverters.test.d.ts.map +0 -1
  281. package/lib/test/unit/vector/fragmentConverters.test.js +0 -60
  282. package/lib/test/unit/vector/fragmentConverters.test.js.map +0 -1
  283. package/lib/test/unit/vector/inMemoryCosineIndex.test.d.ts +0 -2
  284. package/lib/test/unit/vector/inMemoryCosineIndex.test.d.ts.map +0 -1
  285. package/lib/test/unit/vector/inMemoryCosineIndex.test.js +0 -254
  286. package/lib/test/unit/vector/inMemoryCosineIndex.test.js.map +0 -1
  287. package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.d.ts +0 -2
  288. package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.d.ts.map +0 -1
  289. package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.js +0 -364
  290. package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.js.map +0 -1
  291. package/lib/test/unit/vector/vectorIndex.test.d.ts +0 -2
  292. package/lib/test/unit/vector/vectorIndex.test.d.ts.map +0 -1
  293. package/lib/test/unit/vector/vectorIndex.test.js +0 -53
  294. package/lib/test/unit/vector/vectorIndex.test.js.map +0 -1
  295. package/rush-logs/ts-agent-memory.build.cache.log +0 -3
  296. package/rush-logs/ts-agent-memory.build.log +0 -9
  297. package/src/index.ts +0 -14
  298. package/src/packlets/converters/bodyConverterRegistry.ts +0 -105
  299. package/src/packlets/converters/envelopeConverter.ts +0 -233
  300. package/src/packlets/converters/index.ts +0 -7
  301. package/src/packlets/index/index.ts +0 -6
  302. package/src/packlets/index/memoryIndex.ts +0 -332
  303. package/src/packlets/ingest/cycleGuard.ts +0 -153
  304. package/src/packlets/ingest/hostStages.ts +0 -111
  305. package/src/packlets/ingest/index.ts +0 -9
  306. package/src/packlets/ingest/model.ts +0 -195
  307. package/src/packlets/ingest/orchestrator.ts +0 -968
  308. package/src/packlets/observe/index.ts +0 -7
  309. package/src/packlets/observe/memoryObservationStore.ts +0 -153
  310. package/src/packlets/observe/observer.ts +0 -119
  311. package/src/packlets/retrieve/fragmentSemanticRetriever.ts +0 -138
  312. package/src/packlets/retrieve/hybridRetriever.ts +0 -194
  313. package/src/packlets/retrieve/index.ts +0 -14
  314. package/src/packlets/retrieve/linkTraversalRetriever.ts +0 -158
  315. package/src/packlets/retrieve/recencyRetriever.ts +0 -54
  316. package/src/packlets/retrieve/retriever.ts +0 -291
  317. package/src/packlets/retrieve/semanticRetriever.ts +0 -152
  318. package/src/packlets/retrieve/structuredFilterRetriever.ts +0 -58
  319. package/src/packlets/retrieve/tagRetriever.ts +0 -58
  320. package/src/packlets/retrieve/temporalRetrievers.ts +0 -210
  321. package/src/packlets/store/fileTreeMemoryStore.ts +0 -1872
  322. package/src/packlets/store/index.ts +0 -7
  323. package/src/packlets/store/scopeEncoding.ts +0 -36
  324. package/src/packlets/tools/index.ts +0 -6
  325. package/src/packlets/tools/memoryTools.ts +0 -706
  326. package/src/packlets/types/envelope.ts +0 -196
  327. package/src/packlets/types/filenameSafety.ts +0 -57
  328. package/src/packlets/types/identityCodec.ts +0 -447
  329. package/src/packlets/types/ids.ts +0 -124
  330. package/src/packlets/types/index.ts +0 -11
  331. package/src/packlets/types/temporal.ts +0 -96
  332. package/src/packlets/types/writePolicy.ts +0 -612
  333. package/src/packlets/vector/fragmentConverters.ts +0 -55
  334. package/src/packlets/vector/inMemoryCosineIndex.ts +0 -196
  335. package/src/packlets/vector/inMemoryFragmentCosineIndex.ts +0 -289
  336. package/src/packlets/vector/index.ts +0 -9
  337. package/src/packlets/vector/vectorIndex.ts +0 -273
  338. package/src/test/unit/converters/antagonistRoundTrip.test.ts +0 -110
  339. package/src/test/unit/converters/bodyConverterRegistry.test.ts +0 -89
  340. package/src/test/unit/converters/envelopeConverter.test.ts +0 -418
  341. package/src/test/unit/index/memoryIndex.test.ts +0 -272
  342. package/src/test/unit/ingest/antagonistCycleAndParity.test.ts +0 -367
  343. package/src/test/unit/ingest/cycleGuard.test.ts +0 -110
  344. package/src/test/unit/ingest/dedupScope.test.ts +0 -542
  345. package/src/test/unit/ingest/orchestrator.test.ts +0 -1355
  346. package/src/test/unit/observe/memoryObservationStore.test.ts +0 -158
  347. package/src/test/unit/retrieve/fragmentSemanticRetriever.test.ts +0 -163
  348. package/src/test/unit/retrieve/linkTraversalRetriever.test.ts +0 -329
  349. package/src/test/unit/retrieve/retrievers.test.ts +0 -1018
  350. package/src/test/unit/retrieve/temporalRetrievers.test.ts +0 -226
  351. package/src/test/unit/store/antagonistTemporalBoundary.test.ts +0 -158
  352. package/src/test/unit/store/embedOnWrite.test.ts +0 -418
  353. package/src/test/unit/store/fileTreeMemoryStore.test.ts +0 -1041
  354. package/src/test/unit/store/fragmentEmbedOnWrite.test.ts +0 -349
  355. package/src/test/unit/store/indexInjection.test.ts +0 -550
  356. package/src/test/unit/store/lenientOpen.test.ts +0 -292
  357. package/src/test/unit/store/listScoped.test.ts +0 -138
  358. package/src/test/unit/store/observations.test.ts +0 -290
  359. package/src/test/unit/store/rankAxis.test.ts +0 -349
  360. package/src/test/unit/store/scopeEncoding.test.ts +0 -37
  361. package/src/test/unit/store/temporalStore.test.ts +0 -469
  362. package/src/test/unit/tools/memoryTools.test.ts +0 -1121
  363. package/src/test/unit/types/identityCodec.test.ts +0 -266
  364. package/src/test/unit/types/ids.test.ts +0 -94
  365. package/src/test/unit/types/temporalCodec.test.ts +0 -259
  366. package/src/test/unit/types/temporalPolicy.test.ts +0 -124
  367. package/src/test/unit/types/writePolicy.test.ts +0 -446
  368. package/src/test/unit/vector/fragmentConverters.test.ts +0 -80
  369. package/src/test/unit/vector/inMemoryCosineIndex.test.ts +0 -318
  370. package/src/test/unit/vector/inMemoryFragmentCosineIndex.test.ts +0 -477
  371. package/src/test/unit/vector/vectorIndex.test.ts +0 -64
  372. package/temp/build/lint/_eslint-5eVG3S6w.json +0 -306
  373. package/temp/build/typescript/ts_8nwakTlr.json +0 -1
  374. package/temp/ts-agent-memory.api.json +0 -21030
  375. package/temp/ts-agent-memory.api.md +0 -940
  376. package/tsconfig.json +0 -8
@@ -1,432 +0,0 @@
1
- /*
2
- * Copyright (c) 2026 Erik Fortune
3
- * SPDX-License-Identifier: MIT
4
- */
5
- import '@fgv/ts-utils-jest';
6
- import { Converters, succeed } from '@fgv/ts-utils';
7
- import { FileTree } from '@fgv/ts-json-base';
8
- import { BodyConverterRegistry, FileTreeMemoryStore, KnowledgeIdentityCodec, MemoryCapCullPolicy, MemoryIndex, MtmIdentityCodec, RecencyRetriever, TemporalIdentityCodec, TemporalVersionedPolicy, envelopeConverter } from '../../../index';
9
- const knowledgeKind = 'knowledge';
10
- const knowledgeScope = 'knowledge';
11
- function mutableRoot() {
12
- const tree = FileTree.inMemory([], { mutable: true }).orThrow();
13
- const root = tree.getDirectory('/').orThrow();
14
- if (!FileTree.isMutableDirectoryItem(root)) {
15
- throw new Error('expected a mutable root directory');
16
- }
17
- return root;
18
- }
19
- function knowledgeRecord(id, body, tags = []) {
20
- return {
21
- envelope: envelopeConverter
22
- .convert({
23
- id,
24
- entityId: id,
25
- kind: 'knowledge',
26
- tags: [...tags],
27
- links: [],
28
- created: 0,
29
- updated: 0,
30
- seq: 0,
31
- contentHash: '',
32
- provenance: { source: 'agent' }
33
- })
34
- .orThrow(),
35
- body
36
- };
37
- }
38
- function storeWith(index, root) {
39
- const registry = BodyConverterRegistry.create().orThrow();
40
- registry.register(knowledgeKind, Converters.string);
41
- return FileTreeMemoryStore.create({
42
- root: root !== null && root !== void 0 ? root : mutableRoot(),
43
- registry,
44
- codecs: new Map([[knowledgeKind, new KnowledgeIdentityCodec()]]),
45
- index
46
- }).orThrow();
47
- }
48
- /**
49
- * A counting/timing decorator over the shipped `MemoryIndex` — the exact shape
50
- * the injection seam exists to enable. Every call is delegated verbatim, so a
51
- * store wired with one behaves identically to a store using the default index;
52
- * the recorded counts are the measurement the consumer is after.
53
- */
54
- class RecordingMemoryIndex {
55
- constructor(inner) {
56
- this.rebuildSizes = [];
57
- this.patchCalls = [];
58
- this.entriesCalls = 0;
59
- this._inner = inner;
60
- }
61
- static create() {
62
- return MemoryIndex.create().onSuccess((inner) => succeed(new RecordingMemoryIndex(inner)));
63
- }
64
- rebuild(entries) {
65
- this.rebuildSizes.push(entries.length);
66
- return this._inner.rebuild(entries);
67
- }
68
- patch(op, entry) {
69
- this.patchCalls.push({ op, scope: entry.scope, id: entry.record.envelope.id });
70
- return this._inner.patch(op, entry);
71
- }
72
- entries() {
73
- this.entriesCalls += 1;
74
- return this._inner.entries();
75
- }
76
- byKind(kind) {
77
- return this._inner.byKind(kind);
78
- }
79
- byTag(tag) {
80
- return this._inner.byTag(tag);
81
- }
82
- byRecency() {
83
- return this._inner.byRecency();
84
- }
85
- byRank() {
86
- return this._inner.byRank();
87
- }
88
- backlinks(target) {
89
- return this._inner.backlinks(target);
90
- }
91
- }
92
- /**
93
- * An index that hides every record whose body contains `hidden` from the
94
- * `entries()` read surface. Not a realistic index — it exists to prove the store
95
- * reads from the INJECTED index rather than one it built for itself. A store
96
- * with a private index could not produce these results.
97
- */
98
- class HidingMemoryIndex {
99
- constructor(inner) {
100
- this._inner = inner;
101
- }
102
- static create() {
103
- return MemoryIndex.create().onSuccess((inner) => succeed(new HidingMemoryIndex(inner)));
104
- }
105
- rebuild(entries) {
106
- return this._inner.rebuild(entries);
107
- }
108
- patch(op, entry) {
109
- return this._inner.patch(op, entry);
110
- }
111
- entries() {
112
- return this._inner.entries().filter((e) => !String(e.record.body).includes('hidden'));
113
- }
114
- byKind(kind) {
115
- return this._inner.byKind(kind);
116
- }
117
- byTag(tag) {
118
- return this._inner.byTag(tag);
119
- }
120
- byRecency() {
121
- return this._inner.byRecency();
122
- }
123
- byRank() {
124
- return this._inner.byRank();
125
- }
126
- backlinks(target) {
127
- return this._inner.backlinks(target);
128
- }
129
- }
130
- // ---------------------------------------------------------------------------
131
- // Temporal (versioned) and cap-cull fixtures.
132
- //
133
- // The `index` param's TSDoc claims that an injected index decides which version a
134
- // versioned `put` supersedes, which versions a `delete` tombstones, and what a
135
- // cap-cull policy evicts — because all three derive their working set from
136
- // `entries()` rather than from the FileTree. These fixtures exist so those claims
137
- // are evidenced by test rather than only reasoned about from the implementation.
138
- // ---------------------------------------------------------------------------
139
- const factKind = 'fact';
140
- const factScope = 'facts/entities/fact-1';
141
- const mtmKind = 'mtm';
142
- let clockValue = 1000;
143
- const clock = () => clockValue;
144
- function factRecord(body) {
145
- return {
146
- envelope: envelopeConverter
147
- .convert({
148
- id: 'fact-1',
149
- entityId: 'fact-1',
150
- kind: 'fact',
151
- tags: [],
152
- links: [],
153
- created: 0,
154
- updated: 0,
155
- seq: 0,
156
- contentHash: '',
157
- provenance: { source: 'agent' }
158
- })
159
- .orThrow(),
160
- body
161
- };
162
- }
163
- function versionedStore(index) {
164
- const registry = BodyConverterRegistry.create().orThrow();
165
- registry.register(factKind, Converters.string);
166
- return FileTreeMemoryStore.create({
167
- root: mutableRoot(),
168
- registry,
169
- codecs: new Map([[factKind, TemporalIdentityCodec.create('facts').orThrow()]]),
170
- writePolicies: new Map([[factKind, TemporalVersionedPolicy.create().orThrow()]]),
171
- clock,
172
- index
173
- }).orThrow();
174
- }
175
- function turnRecord(turn, body) {
176
- return {
177
- envelope: envelopeConverter
178
- .convert({
179
- id: `turn-${turn}`,
180
- entityId: `conv-1:${turn}`,
181
- kind: 'mtm',
182
- tags: [],
183
- links: [],
184
- created: 0,
185
- updated: 0,
186
- seq: 0,
187
- contentHash: '',
188
- provenance: { source: 'agent' }
189
- })
190
- .orThrow(),
191
- body
192
- };
193
- }
194
- function cappedStore(index, maxRecords = 2) {
195
- const registry = BodyConverterRegistry.create().orThrow();
196
- registry.register(mtmKind, Converters.string);
197
- return FileTreeMemoryStore.create({
198
- root: mutableRoot(),
199
- registry,
200
- codecs: new Map([[mtmKind, new MtmIdentityCodec()]]),
201
- writePolicies: new Map([
202
- [
203
- mtmKind,
204
- MemoryCapCullPolicy.create({
205
- maxRecords,
206
- mutableFields: ['body', 'tags', 'links', 'provenance']
207
- }).orThrow()
208
- ]
209
- ]),
210
- clock,
211
- index
212
- }).orThrow();
213
- }
214
- describe('FileTreeMemoryStore index injection', () => {
215
- describe('default (index omitted)', () => {
216
- test('creates and serves reads from a default MemoryIndex', async () => {
217
- const store = storeWith();
218
- (await store.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();
219
- (await store.put(knowledgeRecord('doc-b', 'beta'))).orThrow();
220
- expect(await store.list()).toSucceedAndSatisfy((records) => {
221
- expect(records.map((r) => r.envelope.id).sort()).toEqual(['doc-a', 'doc-b']);
222
- });
223
- expect(await store.get(knowledgeKind, 'doc-a')).toSucceedAndSatisfy((record) => {
224
- expect(record === null || record === void 0 ? void 0 : record.body).toBe('alpha');
225
- });
226
- expect(await store.listScoped()).toSucceedAndSatisfy((scoped) => {
227
- expect(scoped).toHaveLength(2);
228
- });
229
- });
230
- test('reopening an existing vault re-indexes it and resumes seq', async () => {
231
- const root = mutableRoot();
232
- const first = storeWith(undefined, root);
233
- (await first.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();
234
- const reopened = storeWith(undefined, root);
235
- expect(await reopened.list()).toSucceedAndSatisfy((records) => {
236
- expect(records).toHaveLength(1);
237
- expect(records[0].envelope.id).toBe('doc-a');
238
- });
239
- // seq resumes past the persisted high-water mark rather than restarting at 1.
240
- expect(await reopened.put(knowledgeRecord('doc-b', 'beta'))).toSucceedAndSatisfy((record) => {
241
- expect(record.envelope.seq).toBe(2);
242
- });
243
- });
244
- });
245
- describe('absent index', () => {
246
- test('a null index is treated as absent, matching every sibling optional param', async () => {
247
- // `create()`'s other optional params all absorb absence with `??`, which takes
248
- // null and undefined alike. A JS caller (or a TS caller through an `unknown`
249
- // hatch) passing `null` here must get the default index too — installing
250
- // `null` would instead fail later inside `entries()`, naming neither the param
251
- // nor the cause.
252
- const store = storeWith(null);
253
- (await store.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();
254
- expect(await store.list()).toSucceedAndSatisfy((records) => {
255
- expect(records.map((r) => r.envelope.id)).toEqual(['doc-a']);
256
- });
257
- });
258
- });
259
- describe('injected index', () => {
260
- test('receives the create() rebuild of an existing vault', async () => {
261
- const root = mutableRoot();
262
- const seeded = storeWith(undefined, root);
263
- (await seeded.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();
264
- (await seeded.put(knowledgeRecord('doc-b', 'beta'))).orThrow();
265
- const recording = RecordingMemoryIndex.create().orThrow();
266
- const reopened = storeWith(recording, root);
267
- // create() rebuilt the injected index exactly once, with both persisted records.
268
- expect(recording.rebuildSizes).toEqual([2]);
269
- expect(recording.patchCalls).toEqual([]);
270
- expect(await reopened.list()).toSucceedAndSatisfy((records) => {
271
- expect(records.map((r) => r.envelope.id).sort()).toEqual(['doc-a', 'doc-b']);
272
- });
273
- });
274
- test('receives a put patch and a delete patch', async () => {
275
- const recording = RecordingMemoryIndex.create().orThrow();
276
- const store = storeWith(recording);
277
- // The empty-vault open still rebuilds (with zero entries) and patches nothing.
278
- expect(recording.rebuildSizes).toEqual([0]);
279
- expect(recording.patchCalls).toEqual([]);
280
- (await store.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();
281
- expect(recording.patchCalls).toEqual([{ op: 'put', scope: knowledgeScope, id: 'doc-a' }]);
282
- // A content revision of the same id is another 'put' patch, not a second entry.
283
- (await store.put(knowledgeRecord('doc-a', 'alpha revised'))).orThrow();
284
- expect(recording.patchCalls).toHaveLength(2);
285
- expect(recording.patchCalls[1]).toEqual({ op: 'put', scope: knowledgeScope, id: 'doc-a' });
286
- expect(await store.delete(knowledgeKind, 'doc-a')).toSucceedWith('doc-a');
287
- expect(recording.patchCalls[2]).toEqual({ op: 'delete', scope: knowledgeScope, id: 'doc-a' });
288
- });
289
- test('serves the store read surface — no second index is built', async () => {
290
- const recording = RecordingMemoryIndex.create().orThrow();
291
- const store = storeWith(recording);
292
- (await store.put(knowledgeRecord('doc-a', 'alpha', ['topic']))).orThrow();
293
- const before = recording.entriesCalls;
294
- expect(await store.list()).toSucceed();
295
- expect(await store.listScoped()).toSucceed();
296
- expect(recording.entriesCalls).toBeGreaterThan(before);
297
- // The injected index really holds the store's records: its projection views
298
- // (never touched by the store itself) answer from the patched state.
299
- expect(recording.byKind(knowledgeKind).map((r) => r.envelope.id)).toEqual(['doc-a']);
300
- expect(recording.byTag('topic').map((r) => r.envelope.id)).toEqual(['doc-a']);
301
- expect(recording.byRecency().map((r) => r.envelope.id)).toEqual(['doc-a']);
302
- expect(recording.byRank().map((r) => r.envelope.id)).toEqual(['doc-a']);
303
- expect(recording.backlinks({ scope: knowledgeScope, id: 'doc-a' })).toEqual([]);
304
- });
305
- test('shares one index with a retriever built over the same instance', async () => {
306
- const recording = RecordingMemoryIndex.create().orThrow();
307
- const store = storeWith(recording);
308
- (await store.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();
309
- (await store.put(knowledgeRecord('doc-b', 'beta'))).orThrow();
310
- // The consumer's real pattern: the store maintains the index, retrievers read it.
311
- const retriever = RecencyRetriever.create(recording).orThrow();
312
- expect(await retriever.retrieve({ kind: knowledgeKind })).toSucceedAndSatisfy((records) => {
313
- expect(records.map((r) => r.envelope.id).sort()).toEqual(['doc-a', 'doc-b']);
314
- });
315
- });
316
- test('the injected index — not a private one — determines what the store returns', async () => {
317
- const hiding = HidingMemoryIndex.create().orThrow();
318
- const store = storeWith(hiding);
319
- (await store.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();
320
- (await store.put(knowledgeRecord('doc-b', 'hidden beta'))).orThrow();
321
- // Both records persisted, but the injected index hides one from `entries()`,
322
- // and every store read that goes through the index reflects exactly that.
323
- expect(await store.list()).toSucceedAndSatisfy((records) => {
324
- expect(records.map((r) => r.envelope.id)).toEqual(['doc-a']);
325
- });
326
- expect(await store.listScoped()).toSucceedAndSatisfy((scoped) => {
327
- expect(scoped.map((s) => s.target.id)).toEqual(['doc-a']);
328
- });
329
- // The file is still on disk — `getById` reads through to the FileTree, which
330
- // remains the source of truth regardless of what the derived index projects.
331
- expect(await store.getById(knowledgeScope, 'doc-b')).toSucceedAndSatisfy((record) => {
332
- expect(record === null || record === void 0 ? void 0 : record.body).toBe('hidden beta');
333
- });
334
- });
335
- test('an index that reshapes entries() changes write semantics, not just reads', async () => {
336
- // The store's content-hash dedup and write-policy admission cohort both read
337
- // the index's `entries()`, so an index that hides a record hides it from dedup
338
- // too. This is the documented caveat on the `index` param — the reason to
339
- // inject only a faithful delegating decorator.
340
- const control = storeWith();
341
- (await control.put(knowledgeRecord('doc-b', 'hidden beta'))).orThrow();
342
- // Default index: an identical body under a NEW id collapses onto the existing
343
- // record (knowledge declares `dedupScope: 'content'`).
344
- expect(await control.put(knowledgeRecord('doc-c', 'hidden beta'))).toSucceedAndSatisfy((record) => {
345
- expect(record.envelope.id).toBe('doc-b');
346
- });
347
- const hiding = storeWith(HidingMemoryIndex.create().orThrow());
348
- (await hiding.put(knowledgeRecord('doc-b', 'hidden beta'))).orThrow();
349
- // Hiding index: doc-b is invisible to `entries()`, so the content-hash lookup
350
- // finds no duplicate and doc-c is written as a distinct record.
351
- expect(await hiding.put(knowledgeRecord('doc-c', 'hidden beta'))).toSucceedAndSatisfy((record) => {
352
- expect(record.envelope.id).toBe('doc-c');
353
- });
354
- });
355
- });
356
- describe('injected index — temporal and cap-cull write paths', () => {
357
- beforeEach(() => {
358
- clockValue = 1000;
359
- });
360
- test('the injected index decides which version a versioned put supersedes and a delete tombstones', async () => {
361
- // Both the versioned put and the versioned delete resolve an entity's version
362
- // history through `_versionsForEntity`, which is a scope filter over the
363
- // index's `entries()`. A version the injected index hides is therefore
364
- // invisible to both — it stays on disk, but the store will not supersede,
365
- // invalidate, or tombstone it. That is the documented caveat, and the reason
366
- // only a faithful delegating decorator is safe to inject.
367
- const control = versionedStore();
368
- (await control.put(factRecord('hidden blue'))).orThrow();
369
- clockValue = 2000;
370
- (await control.put(factRecord('grey'))).orThrow();
371
- // Default index: v1 is visible, so the second put closes its world-truth
372
- // interval at the new version's `valid_at`.
373
- expect(await control.getById(factScope, 'fact-1-v1')).toSucceedAndSatisfy((v1) => {
374
- var _a;
375
- expect((_a = v1 === null || v1 === void 0 ? void 0 : v1.envelope.temporal) === null || _a === void 0 ? void 0 : _a.invalid_at).toBe(2000);
376
- });
377
- const hiding = versionedStore(HidingMemoryIndex.create().orThrow());
378
- clockValue = 1000;
379
- (await hiding.put(factRecord('hidden blue'))).orThrow();
380
- clockValue = 2000;
381
- (await hiding.put(factRecord('grey'))).orThrow();
382
- // Hiding index: v1 is invisible to the version walk, so the second put sees no
383
- // current version, is built as a FIRST version, and invalidates nothing. v1 is
384
- // still on disk and still carries no `invalid_at` — two live currents.
385
- expect(await hiding.getById(factScope, 'fact-1-v1')).toSucceedAndSatisfy((v1) => {
386
- var _a;
387
- expect(v1 === null || v1 === void 0 ? void 0 : v1.body).toBe('hidden blue');
388
- expect((_a = v1 === null || v1 === void 0 ? void 0 : v1.envelope.temporal) === null || _a === void 0 ? void 0 : _a.invalid_at).toBeUndefined();
389
- });
390
- // The delete half of the same claim: a soft delete tombstones every version the
391
- // index shows as current, so the hidden v1 survives it untouched.
392
- clockValue = 3000;
393
- expect(await hiding.delete(factKind, 'fact-1')).toSucceed();
394
- expect(await hiding.getById(factScope, 'fact-1-v2')).toSucceedAndSatisfy((v2) => {
395
- var _a;
396
- expect((_a = v2 === null || v2 === void 0 ? void 0 : v2.envelope.temporal) === null || _a === void 0 ? void 0 : _a.invalid_at).toBe(3000);
397
- });
398
- expect(await hiding.getById(factScope, 'fact-1-v1')).toSucceedAndSatisfy((v1) => {
399
- var _a;
400
- expect((_a = v1 === null || v1 === void 0 ? void 0 : v1.envelope.temporal) === null || _a === void 0 ? void 0 : _a.invalid_at).toBeUndefined();
401
- });
402
- });
403
- test('cap-cull patches the injected index, and a reshaped cohort changes what is evicted', async () => {
404
- // `maxRecords: 2` over the shared conversations/conv-1 MTM scope. The third
405
- // write's admission cohort is the two prior records, so it culls the oldest.
406
- const recording = RecordingMemoryIndex.create().orThrow();
407
- const recorded = cappedStore(recording);
408
- for (let turn = 0; turn < 3; turn++) {
409
- clockValue = 1000 + turn; // distinct `created`, so "oldest" is unambiguous
410
- (await recorded.put(turnRecord(turn, turn === 0 ? 'hidden zero' : `turn ${turn}`))).orThrow();
411
- }
412
- // The eviction reaches the INJECTED index as a `delete` patch — the store keeps
413
- // no private index it could have patched instead.
414
- expect(recording.patchCalls.filter((c) => c.op === 'delete')).toEqual([
415
- { op: 'delete', scope: 'conversations/conv-1', id: 'turn-0' }
416
- ]);
417
- expect(await recorded.get(mtmKind, 'conv-1:0')).toSucceedWith(undefined);
418
- // Same writes, but an index that hides turn-0 shrinks the admission cohort to
419
- // one, which is under the cap — so nothing is evicted and turn-0 survives.
420
- // The cohort the policy sees is the index's projection, not the vault's.
421
- const hidden = cappedStore(HidingMemoryIndex.create().orThrow());
422
- for (let turn = 0; turn < 3; turn++) {
423
- clockValue = 1000 + turn;
424
- (await hidden.put(turnRecord(turn, turn === 0 ? 'hidden zero' : `turn ${turn}`))).orThrow();
425
- }
426
- expect(await hidden.get(mtmKind, 'conv-1:0')).toSucceedAndSatisfy((record) => {
427
- expect(record === null || record === void 0 ? void 0 : record.body).toBe('hidden zero');
428
- });
429
- });
430
- });
431
- });
432
- //# sourceMappingURL=indexInjection.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"indexInjection.test.js","sourceRoot":"","sources":["../../../../src/test/unit/store/indexInjection.test.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport '@fgv/ts-utils-jest';\nimport { Converters, Result, succeed } from '@fgv/ts-utils';\nimport { FileTree } from '@fgv/ts-json-base';\nimport {\n BodyConverterRegistry,\n EntityId,\n FileTreeMemoryStore,\n IBodyConverterRegistry,\n IEdgeTarget,\n IIdentityCodec,\n IIndexedMemoryRecord,\n IMemoryIndex,\n IMemoryRecord,\n IWritePolicy,\n Kind,\n KnowledgeIdentityCodec,\n MemoryCapCullPolicy,\n MemoryId,\n MemoryIndex,\n MemoryIndexPatchOp,\n MemoryScopeKey,\n MtmIdentityCodec,\n RecencyRetriever,\n Tag,\n TemporalIdentityCodec,\n TemporalVersionedPolicy,\n envelopeConverter\n} from '../../../index';\n\nconst knowledgeKind: Kind = 'knowledge' as Kind;\nconst knowledgeScope: MemoryScopeKey = 'knowledge' as MemoryScopeKey;\n\nfunction mutableRoot(): FileTree.IMutableFileTreeDirectoryItem {\n const tree = FileTree.inMemory([], { mutable: true }).orThrow();\n const root = tree.getDirectory('/').orThrow();\n if (!FileTree.isMutableDirectoryItem(root)) {\n throw new Error('expected a mutable root directory');\n }\n return root;\n}\n\nfunction knowledgeRecord(id: string, body: string, tags: ReadonlyArray<string> = []): IMemoryRecord<unknown> {\n return {\n envelope: envelopeConverter\n .convert({\n id,\n entityId: id,\n kind: 'knowledge',\n tags: [...tags],\n links: [],\n created: 0,\n updated: 0,\n seq: 0,\n contentHash: '',\n provenance: { source: 'agent' }\n })\n .orThrow(),\n body\n };\n}\n\nfunction storeWith(index?: IMemoryIndex, root?: FileTree.IMutableFileTreeDirectoryItem): FileTreeMemoryStore {\n const registry: IBodyConverterRegistry = BodyConverterRegistry.create().orThrow();\n registry.register(knowledgeKind, Converters.string);\n return FileTreeMemoryStore.create({\n root: root ?? mutableRoot(),\n registry,\n codecs: new Map<Kind, IIdentityCodec>([[knowledgeKind, new KnowledgeIdentityCodec()]]),\n index\n }).orThrow();\n}\n\n/** One recorded {@link IMemoryIndex.patch} call. */\ninterface IPatchCall {\n readonly op: MemoryIndexPatchOp;\n readonly scope: MemoryScopeKey;\n readonly id: string;\n}\n\n/**\n * A counting/timing decorator over the shipped `MemoryIndex` — the exact shape\n * the injection seam exists to enable. Every call is delegated verbatim, so a\n * store wired with one behaves identically to a store using the default index;\n * the recorded counts are the measurement the consumer is after.\n */\nclass RecordingMemoryIndex implements IMemoryIndex {\n public readonly rebuildSizes: number[] = [];\n public readonly patchCalls: IPatchCall[] = [];\n public entriesCalls: number = 0;\n\n private readonly _inner: IMemoryIndex;\n\n private constructor(inner: IMemoryIndex) {\n this._inner = inner;\n }\n\n public static create(): Result<RecordingMemoryIndex> {\n return MemoryIndex.create().onSuccess((inner) => succeed(new RecordingMemoryIndex(inner)));\n }\n\n public rebuild(entries: ReadonlyArray<IIndexedMemoryRecord>): Result<number> {\n this.rebuildSizes.push(entries.length);\n return this._inner.rebuild(entries);\n }\n\n public patch(op: MemoryIndexPatchOp, entry: IIndexedMemoryRecord): Result<IIndexedMemoryRecord> {\n this.patchCalls.push({ op, scope: entry.scope, id: entry.record.envelope.id });\n return this._inner.patch(op, entry);\n }\n\n public entries(): ReadonlyArray<IIndexedMemoryRecord> {\n this.entriesCalls += 1;\n return this._inner.entries();\n }\n\n public byKind(kind: Kind): ReadonlyArray<IMemoryRecord<unknown>> {\n return this._inner.byKind(kind);\n }\n\n public byTag(tag: Tag): ReadonlyArray<IMemoryRecord<unknown>> {\n return this._inner.byTag(tag);\n }\n\n public byRecency(): ReadonlyArray<IMemoryRecord<unknown>> {\n return this._inner.byRecency();\n }\n\n public byRank(): ReadonlyArray<IMemoryRecord<unknown>> {\n return this._inner.byRank();\n }\n\n public backlinks(target: IEdgeTarget): ReadonlyArray<IEdgeTarget> {\n return this._inner.backlinks(target);\n }\n}\n\n/**\n * An index that hides every record whose body contains `hidden` from the\n * `entries()` read surface. Not a realistic index — it exists to prove the store\n * reads from the INJECTED index rather than one it built for itself. A store\n * with a private index could not produce these results.\n */\nclass HidingMemoryIndex implements IMemoryIndex {\n private readonly _inner: IMemoryIndex;\n\n private constructor(inner: IMemoryIndex) {\n this._inner = inner;\n }\n\n public static create(): Result<HidingMemoryIndex> {\n return MemoryIndex.create().onSuccess((inner) => succeed(new HidingMemoryIndex(inner)));\n }\n\n public rebuild(entries: ReadonlyArray<IIndexedMemoryRecord>): Result<number> {\n return this._inner.rebuild(entries);\n }\n\n public patch(op: MemoryIndexPatchOp, entry: IIndexedMemoryRecord): Result<IIndexedMemoryRecord> {\n return this._inner.patch(op, entry);\n }\n\n public entries(): ReadonlyArray<IIndexedMemoryRecord> {\n return this._inner.entries().filter((e) => !String(e.record.body).includes('hidden'));\n }\n\n public byKind(kind: Kind): ReadonlyArray<IMemoryRecord<unknown>> {\n return this._inner.byKind(kind);\n }\n\n public byTag(tag: Tag): ReadonlyArray<IMemoryRecord<unknown>> {\n return this._inner.byTag(tag);\n }\n\n public byRecency(): ReadonlyArray<IMemoryRecord<unknown>> {\n return this._inner.byRecency();\n }\n\n public byRank(): ReadonlyArray<IMemoryRecord<unknown>> {\n return this._inner.byRank();\n }\n\n public backlinks(target: IEdgeTarget): ReadonlyArray<IEdgeTarget> {\n return this._inner.backlinks(target);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Temporal (versioned) and cap-cull fixtures.\n//\n// The `index` param's TSDoc claims that an injected index decides which version a\n// versioned `put` supersedes, which versions a `delete` tombstones, and what a\n// cap-cull policy evicts — because all three derive their working set from\n// `entries()` rather than from the FileTree. These fixtures exist so those claims\n// are evidenced by test rather than only reasoned about from the implementation.\n// ---------------------------------------------------------------------------\n\nconst factKind: Kind = 'fact' as Kind;\nconst factScope: MemoryScopeKey = 'facts/entities/fact-1' as MemoryScopeKey;\nconst mtmKind: Kind = 'mtm' as Kind;\n\nlet clockValue: number = 1000;\nconst clock = (): number => clockValue;\n\nfunction factRecord(body: string): IMemoryRecord<unknown> {\n return {\n envelope: envelopeConverter\n .convert({\n id: 'fact-1',\n entityId: 'fact-1',\n kind: 'fact',\n tags: [],\n links: [],\n created: 0,\n updated: 0,\n seq: 0,\n contentHash: '',\n provenance: { source: 'agent' }\n })\n .orThrow(),\n body\n };\n}\n\nfunction versionedStore(index?: IMemoryIndex): FileTreeMemoryStore {\n const registry: IBodyConverterRegistry = BodyConverterRegistry.create().orThrow();\n registry.register(factKind, Converters.string);\n return FileTreeMemoryStore.create({\n root: mutableRoot(),\n registry,\n codecs: new Map<Kind, IIdentityCodec>([[factKind, TemporalIdentityCodec.create('facts').orThrow()]]),\n writePolicies: new Map<Kind, IWritePolicy>([[factKind, TemporalVersionedPolicy.create().orThrow()]]),\n clock,\n index\n }).orThrow();\n}\n\nfunction turnRecord(turn: number, body: string): IMemoryRecord<unknown> {\n return {\n envelope: envelopeConverter\n .convert({\n id: `turn-${turn}`,\n entityId: `conv-1:${turn}`,\n kind: 'mtm',\n tags: [],\n links: [],\n created: 0,\n updated: 0,\n seq: 0,\n contentHash: '',\n provenance: { source: 'agent' }\n })\n .orThrow(),\n body\n };\n}\n\nfunction cappedStore(index?: IMemoryIndex, maxRecords: number = 2): FileTreeMemoryStore {\n const registry: IBodyConverterRegistry = BodyConverterRegistry.create().orThrow();\n registry.register(mtmKind, Converters.string);\n return FileTreeMemoryStore.create({\n root: mutableRoot(),\n registry,\n codecs: new Map<Kind, IIdentityCodec>([[mtmKind, new MtmIdentityCodec()]]),\n writePolicies: new Map<Kind, IWritePolicy>([\n [\n mtmKind,\n MemoryCapCullPolicy.create({\n maxRecords,\n mutableFields: ['body', 'tags', 'links', 'provenance']\n }).orThrow()\n ]\n ]),\n clock,\n index\n }).orThrow();\n}\n\ndescribe('FileTreeMemoryStore index injection', () => {\n describe('default (index omitted)', () => {\n test('creates and serves reads from a default MemoryIndex', async () => {\n const store = storeWith();\n (await store.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();\n (await store.put(knowledgeRecord('doc-b', 'beta'))).orThrow();\n\n expect(await store.list()).toSucceedAndSatisfy((records: ReadonlyArray<IMemoryRecord<unknown>>) => {\n expect(records.map((r) => r.envelope.id).sort()).toEqual(['doc-a', 'doc-b']);\n });\n expect(await store.get(knowledgeKind, 'doc-a' as EntityId)).toSucceedAndSatisfy(\n (record: IMemoryRecord<unknown> | undefined) => {\n expect(record?.body).toBe('alpha');\n }\n );\n expect(await store.listScoped()).toSucceedAndSatisfy((scoped) => {\n expect(scoped).toHaveLength(2);\n });\n });\n\n test('reopening an existing vault re-indexes it and resumes seq', async () => {\n const root = mutableRoot();\n const first = storeWith(undefined, root);\n (await first.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();\n\n const reopened = storeWith(undefined, root);\n expect(await reopened.list()).toSucceedAndSatisfy((records: ReadonlyArray<IMemoryRecord<unknown>>) => {\n expect(records).toHaveLength(1);\n expect(records[0].envelope.id).toBe('doc-a');\n });\n // seq resumes past the persisted high-water mark rather than restarting at 1.\n expect(await reopened.put(knowledgeRecord('doc-b', 'beta'))).toSucceedAndSatisfy(\n (record: IMemoryRecord<unknown>) => {\n expect(record.envelope.seq).toBe(2);\n }\n );\n });\n });\n\n describe('absent index', () => {\n test('a null index is treated as absent, matching every sibling optional param', async () => {\n // `create()`'s other optional params all absorb absence with `??`, which takes\n // null and undefined alike. A JS caller (or a TS caller through an `unknown`\n // hatch) passing `null` here must get the default index too — installing\n // `null` would instead fail later inside `entries()`, naming neither the param\n // nor the cause.\n const store = storeWith(null as unknown as IMemoryIndex);\n (await store.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();\n\n expect(await store.list()).toSucceedAndSatisfy((records: ReadonlyArray<IMemoryRecord<unknown>>) => {\n expect(records.map((r) => r.envelope.id)).toEqual(['doc-a']);\n });\n });\n });\n\n describe('injected index', () => {\n test('receives the create() rebuild of an existing vault', async () => {\n const root = mutableRoot();\n const seeded = storeWith(undefined, root);\n (await seeded.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();\n (await seeded.put(knowledgeRecord('doc-b', 'beta'))).orThrow();\n\n const recording = RecordingMemoryIndex.create().orThrow();\n const reopened = storeWith(recording, root);\n\n // create() rebuilt the injected index exactly once, with both persisted records.\n expect(recording.rebuildSizes).toEqual([2]);\n expect(recording.patchCalls).toEqual([]);\n expect(await reopened.list()).toSucceedAndSatisfy((records: ReadonlyArray<IMemoryRecord<unknown>>) => {\n expect(records.map((r) => r.envelope.id).sort()).toEqual(['doc-a', 'doc-b']);\n });\n });\n\n test('receives a put patch and a delete patch', async () => {\n const recording = RecordingMemoryIndex.create().orThrow();\n const store = storeWith(recording);\n\n // The empty-vault open still rebuilds (with zero entries) and patches nothing.\n expect(recording.rebuildSizes).toEqual([0]);\n expect(recording.patchCalls).toEqual([]);\n\n (await store.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();\n expect(recording.patchCalls).toEqual([{ op: 'put', scope: knowledgeScope, id: 'doc-a' }]);\n\n // A content revision of the same id is another 'put' patch, not a second entry.\n (await store.put(knowledgeRecord('doc-a', 'alpha revised'))).orThrow();\n expect(recording.patchCalls).toHaveLength(2);\n expect(recording.patchCalls[1]).toEqual({ op: 'put', scope: knowledgeScope, id: 'doc-a' });\n\n expect(await store.delete(knowledgeKind, 'doc-a' as EntityId)).toSucceedWith('doc-a' as MemoryId);\n expect(recording.patchCalls[2]).toEqual({ op: 'delete', scope: knowledgeScope, id: 'doc-a' });\n });\n\n test('serves the store read surface — no second index is built', async () => {\n const recording = RecordingMemoryIndex.create().orThrow();\n const store = storeWith(recording);\n (await store.put(knowledgeRecord('doc-a', 'alpha', ['topic']))).orThrow();\n\n const before: number = recording.entriesCalls;\n expect(await store.list()).toSucceed();\n expect(await store.listScoped()).toSucceed();\n expect(recording.entriesCalls).toBeGreaterThan(before);\n\n // The injected index really holds the store's records: its projection views\n // (never touched by the store itself) answer from the patched state.\n expect(recording.byKind(knowledgeKind).map((r) => r.envelope.id)).toEqual(['doc-a']);\n expect(recording.byTag('topic' as Tag).map((r) => r.envelope.id)).toEqual(['doc-a']);\n expect(recording.byRecency().map((r) => r.envelope.id)).toEqual(['doc-a']);\n expect(recording.byRank().map((r) => r.envelope.id)).toEqual(['doc-a']);\n expect(recording.backlinks({ scope: knowledgeScope, id: 'doc-a' as MemoryId })).toEqual([]);\n });\n\n test('shares one index with a retriever built over the same instance', async () => {\n const recording = RecordingMemoryIndex.create().orThrow();\n const store = storeWith(recording);\n (await store.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();\n (await store.put(knowledgeRecord('doc-b', 'beta'))).orThrow();\n\n // The consumer's real pattern: the store maintains the index, retrievers read it.\n const retriever = RecencyRetriever.create(recording).orThrow();\n expect(await retriever.retrieve({ kind: knowledgeKind })).toSucceedAndSatisfy(\n (records: ReadonlyArray<IMemoryRecord<unknown>>) => {\n expect(records.map((r) => r.envelope.id).sort()).toEqual(['doc-a', 'doc-b']);\n }\n );\n });\n\n test('the injected index — not a private one — determines what the store returns', async () => {\n const hiding = HidingMemoryIndex.create().orThrow();\n const store = storeWith(hiding);\n (await store.put(knowledgeRecord('doc-a', 'alpha'))).orThrow();\n (await store.put(knowledgeRecord('doc-b', 'hidden beta'))).orThrow();\n\n // Both records persisted, but the injected index hides one from `entries()`,\n // and every store read that goes through the index reflects exactly that.\n expect(await store.list()).toSucceedAndSatisfy((records: ReadonlyArray<IMemoryRecord<unknown>>) => {\n expect(records.map((r) => r.envelope.id)).toEqual(['doc-a']);\n });\n expect(await store.listScoped()).toSucceedAndSatisfy((scoped) => {\n expect(scoped.map((s) => s.target.id)).toEqual(['doc-a']);\n });\n // The file is still on disk — `getById` reads through to the FileTree, which\n // remains the source of truth regardless of what the derived index projects.\n expect(await store.getById(knowledgeScope, 'doc-b' as MemoryId)).toSucceedAndSatisfy(\n (record: IMemoryRecord<unknown> | undefined) => {\n expect(record?.body).toBe('hidden beta');\n }\n );\n });\n\n test('an index that reshapes entries() changes write semantics, not just reads', async () => {\n // The store's content-hash dedup and write-policy admission cohort both read\n // the index's `entries()`, so an index that hides a record hides it from dedup\n // too. This is the documented caveat on the `index` param — the reason to\n // inject only a faithful delegating decorator.\n const control = storeWith();\n (await control.put(knowledgeRecord('doc-b', 'hidden beta'))).orThrow();\n // Default index: an identical body under a NEW id collapses onto the existing\n // record (knowledge declares `dedupScope: 'content'`).\n expect(await control.put(knowledgeRecord('doc-c', 'hidden beta'))).toSucceedAndSatisfy(\n (record: IMemoryRecord<unknown>) => {\n expect(record.envelope.id).toBe('doc-b');\n }\n );\n\n const hiding = storeWith(HidingMemoryIndex.create().orThrow());\n (await hiding.put(knowledgeRecord('doc-b', 'hidden beta'))).orThrow();\n // Hiding index: doc-b is invisible to `entries()`, so the content-hash lookup\n // finds no duplicate and doc-c is written as a distinct record.\n expect(await hiding.put(knowledgeRecord('doc-c', 'hidden beta'))).toSucceedAndSatisfy(\n (record: IMemoryRecord<unknown>) => {\n expect(record.envelope.id).toBe('doc-c');\n }\n );\n });\n });\n\n describe('injected index — temporal and cap-cull write paths', () => {\n beforeEach(() => {\n clockValue = 1000;\n });\n\n test('the injected index decides which version a versioned put supersedes and a delete tombstones', async () => {\n // Both the versioned put and the versioned delete resolve an entity's version\n // history through `_versionsForEntity`, which is a scope filter over the\n // index's `entries()`. A version the injected index hides is therefore\n // invisible to both — it stays on disk, but the store will not supersede,\n // invalidate, or tombstone it. That is the documented caveat, and the reason\n // only a faithful delegating decorator is safe to inject.\n const control = versionedStore();\n (await control.put(factRecord('hidden blue'))).orThrow();\n clockValue = 2000;\n (await control.put(factRecord('grey'))).orThrow();\n\n // Default index: v1 is visible, so the second put closes its world-truth\n // interval at the new version's `valid_at`.\n expect(await control.getById(factScope, 'fact-1-v1' as MemoryId)).toSucceedAndSatisfy(\n (v1: IMemoryRecord<unknown> | undefined) => {\n expect(v1?.envelope.temporal?.invalid_at).toBe(2000);\n }\n );\n\n const hiding = versionedStore(HidingMemoryIndex.create().orThrow());\n clockValue = 1000;\n (await hiding.put(factRecord('hidden blue'))).orThrow();\n clockValue = 2000;\n (await hiding.put(factRecord('grey'))).orThrow();\n\n // Hiding index: v1 is invisible to the version walk, so the second put sees no\n // current version, is built as a FIRST version, and invalidates nothing. v1 is\n // still on disk and still carries no `invalid_at` — two live currents.\n expect(await hiding.getById(factScope, 'fact-1-v1' as MemoryId)).toSucceedAndSatisfy(\n (v1: IMemoryRecord<unknown> | undefined) => {\n expect(v1?.body).toBe('hidden blue');\n expect(v1?.envelope.temporal?.invalid_at).toBeUndefined();\n }\n );\n\n // The delete half of the same claim: a soft delete tombstones every version the\n // index shows as current, so the hidden v1 survives it untouched.\n clockValue = 3000;\n expect(await hiding.delete(factKind, 'fact-1' as EntityId)).toSucceed();\n expect(await hiding.getById(factScope, 'fact-1-v2' as MemoryId)).toSucceedAndSatisfy(\n (v2: IMemoryRecord<unknown> | undefined) => {\n expect(v2?.envelope.temporal?.invalid_at).toBe(3000);\n }\n );\n expect(await hiding.getById(factScope, 'fact-1-v1' as MemoryId)).toSucceedAndSatisfy(\n (v1: IMemoryRecord<unknown> | undefined) => {\n expect(v1?.envelope.temporal?.invalid_at).toBeUndefined();\n }\n );\n });\n\n test('cap-cull patches the injected index, and a reshaped cohort changes what is evicted', async () => {\n // `maxRecords: 2` over the shared conversations/conv-1 MTM scope. The third\n // write's admission cohort is the two prior records, so it culls the oldest.\n const recording = RecordingMemoryIndex.create().orThrow();\n const recorded = cappedStore(recording);\n for (let turn = 0; turn < 3; turn++) {\n clockValue = 1000 + turn; // distinct `created`, so \"oldest\" is unambiguous\n (await recorded.put(turnRecord(turn, turn === 0 ? 'hidden zero' : `turn ${turn}`))).orThrow();\n }\n\n // The eviction reaches the INJECTED index as a `delete` patch — the store keeps\n // no private index it could have patched instead.\n expect(recording.patchCalls.filter((c) => c.op === 'delete')).toEqual([\n { op: 'delete', scope: 'conversations/conv-1', id: 'turn-0' }\n ]);\n expect(await recorded.get(mtmKind, 'conv-1:0' as EntityId)).toSucceedWith(undefined);\n\n // Same writes, but an index that hides turn-0 shrinks the admission cohort to\n // one, which is under the cap — so nothing is evicted and turn-0 survives.\n // The cohort the policy sees is the index's projection, not the vault's.\n const hidden = cappedStore(HidingMemoryIndex.create().orThrow());\n for (let turn = 0; turn < 3; turn++) {\n clockValue = 1000 + turn;\n (await hidden.put(turnRecord(turn, turn === 0 ? 'hidden zero' : `turn ${turn}`))).orThrow();\n }\n\n expect(await hidden.get(mtmKind, 'conv-1:0' as EntityId)).toSucceedAndSatisfy(\n (record: IMemoryRecord<unknown> | undefined) => {\n expect(record?.body).toBe('hidden zero');\n }\n );\n });\n });\n});\n"]}