@fgv/ts-agent-memory 5.1.0-36

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 (331) hide show
  1. package/.rush/temp/chunked-rush-logs/ts-agent-memory.build.chunks.jsonl +9 -0
  2. package/.rush/temp/f6a88bfdd66517ccb98c2c7ae1be6e6fe9e15d38.tar.log +282 -0
  3. package/.rush/temp/operation/build/all.log +9 -0
  4. package/.rush/temp/operation/build/log-chunks.jsonl +9 -0
  5. package/.rush/temp/operation/build/state.json +3 -0
  6. package/.rush/temp/shrinkwrap-deps.json +688 -0
  7. package/LICENSE +21 -0
  8. package/README.md +45 -0
  9. package/config/api-extractor.json +343 -0
  10. package/config/jest.config.json +14 -0
  11. package/config/rig.json +4 -0
  12. package/dist/index.js +12 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/packlets/converters/bodyConverterRegistry.js +51 -0
  15. package/dist/packlets/converters/bodyConverterRegistry.js.map +1 -0
  16. package/dist/packlets/converters/envelopeConverter.js +159 -0
  17. package/dist/packlets/converters/envelopeConverter.js.map +1 -0
  18. package/dist/packlets/converters/index.js +7 -0
  19. package/dist/packlets/converters/index.js.map +1 -0
  20. package/dist/packlets/index/index.js +6 -0
  21. package/dist/packlets/index/index.js.map +1 -0
  22. package/dist/packlets/index/memoryIndex.js +170 -0
  23. package/dist/packlets/index/memoryIndex.js.map +1 -0
  24. package/dist/packlets/observe/index.js +7 -0
  25. package/dist/packlets/observe/index.js.map +1 -0
  26. package/dist/packlets/observe/memoryObservationStore.js +119 -0
  27. package/dist/packlets/observe/memoryObservationStore.js.map +1 -0
  28. package/dist/packlets/observe/observer.js +6 -0
  29. package/dist/packlets/observe/observer.js.map +1 -0
  30. package/dist/packlets/retrieve/hybridRetriever.js +135 -0
  31. package/dist/packlets/retrieve/hybridRetriever.js.map +1 -0
  32. package/dist/packlets/retrieve/index.js +12 -0
  33. package/dist/packlets/retrieve/index.js.map +1 -0
  34. package/dist/packlets/retrieve/linkTraversalRetriever.js +143 -0
  35. package/dist/packlets/retrieve/linkTraversalRetriever.js.map +1 -0
  36. package/dist/packlets/retrieve/recencyRetriever.js +33 -0
  37. package/dist/packlets/retrieve/recencyRetriever.js.map +1 -0
  38. package/dist/packlets/retrieve/retriever.js +110 -0
  39. package/dist/packlets/retrieve/retriever.js.map +1 -0
  40. package/dist/packlets/retrieve/semanticRetriever.js +86 -0
  41. package/dist/packlets/retrieve/semanticRetriever.js.map +1 -0
  42. package/dist/packlets/retrieve/structuredFilterRetriever.js +37 -0
  43. package/dist/packlets/retrieve/structuredFilterRetriever.js.map +1 -0
  44. package/dist/packlets/retrieve/tagRetriever.js +37 -0
  45. package/dist/packlets/retrieve/tagRetriever.js.map +1 -0
  46. package/dist/packlets/store/fileTreeMemoryStore.js +698 -0
  47. package/dist/packlets/store/fileTreeMemoryStore.js.map +1 -0
  48. package/dist/packlets/store/index.js +7 -0
  49. package/dist/packlets/store/index.js.map +1 -0
  50. package/dist/packlets/store/scopeEncoding.js +31 -0
  51. package/dist/packlets/store/scopeEncoding.js.map +1 -0
  52. package/dist/packlets/types/envelope.js +6 -0
  53. package/dist/packlets/types/envelope.js.map +1 -0
  54. package/dist/packlets/types/filenameSafety.js +52 -0
  55. package/dist/packlets/types/filenameSafety.js.map +1 -0
  56. package/dist/packlets/types/identityCodec.js +184 -0
  57. package/dist/packlets/types/identityCodec.js.map +1 -0
  58. package/dist/packlets/types/ids.js +67 -0
  59. package/dist/packlets/types/ids.js.map +1 -0
  60. package/dist/packlets/types/index.js +10 -0
  61. package/dist/packlets/types/index.js.map +1 -0
  62. package/dist/packlets/types/writePolicy.js +263 -0
  63. package/dist/packlets/types/writePolicy.js.map +1 -0
  64. package/dist/packlets/vector/inMemoryCosineIndex.js +150 -0
  65. package/dist/packlets/vector/inMemoryCosineIndex.js.map +1 -0
  66. package/dist/packlets/vector/index.js +7 -0
  67. package/dist/packlets/vector/index.js.map +1 -0
  68. package/dist/packlets/vector/vectorIndex.js +6 -0
  69. package/dist/packlets/vector/vectorIndex.js.map +1 -0
  70. package/dist/test/unit/converters/bodyConverterRegistry.test.js +72 -0
  71. package/dist/test/unit/converters/bodyConverterRegistry.test.js.map +1 -0
  72. package/dist/test/unit/converters/envelopeConverter.test.js +196 -0
  73. package/dist/test/unit/converters/envelopeConverter.test.js.map +1 -0
  74. package/dist/test/unit/index/memoryIndex.test.js +152 -0
  75. package/dist/test/unit/index/memoryIndex.test.js.map +1 -0
  76. package/dist/test/unit/observe/memoryObservationStore.test.js +118 -0
  77. package/dist/test/unit/observe/memoryObservationStore.test.js.map +1 -0
  78. package/dist/test/unit/retrieve/linkTraversalRetriever.test.js +182 -0
  79. package/dist/test/unit/retrieve/linkTraversalRetriever.test.js.map +1 -0
  80. package/dist/test/unit/retrieve/retrievers.test.js +506 -0
  81. package/dist/test/unit/retrieve/retrievers.test.js.map +1 -0
  82. package/dist/test/unit/store/embedOnWrite.test.js +260 -0
  83. package/dist/test/unit/store/embedOnWrite.test.js.map +1 -0
  84. package/dist/test/unit/store/fileTreeMemoryStore.test.js +647 -0
  85. package/dist/test/unit/store/fileTreeMemoryStore.test.js.map +1 -0
  86. package/dist/test/unit/store/observations.test.js +239 -0
  87. package/dist/test/unit/store/observations.test.js.map +1 -0
  88. package/dist/test/unit/store/scopeEncoding.test.js +24 -0
  89. package/dist/test/unit/store/scopeEncoding.test.js.map +1 -0
  90. package/dist/test/unit/types/identityCodec.test.js +187 -0
  91. package/dist/test/unit/types/identityCodec.test.js.map +1 -0
  92. package/dist/test/unit/types/ids.test.js +84 -0
  93. package/dist/test/unit/types/ids.test.js.map +1 -0
  94. package/dist/test/unit/types/writePolicy.test.js +241 -0
  95. package/dist/test/unit/types/writePolicy.test.js.map +1 -0
  96. package/dist/test/unit/vector/inMemoryCosineIndex.test.js +192 -0
  97. package/dist/test/unit/vector/inMemoryCosineIndex.test.js.map +1 -0
  98. package/dist/test/unit/vector/vectorIndex.test.js +42 -0
  99. package/dist/test/unit/vector/vectorIndex.test.js.map +1 -0
  100. package/dist/ts-agent-memory.d.ts +1901 -0
  101. package/dist/tsdoc-metadata.json +11 -0
  102. package/eslint.config.js +15 -0
  103. package/etc/ts-agent-memory.api.md +525 -0
  104. package/lib/index.d.ts +8 -0
  105. package/lib/index.d.ts.map +1 -0
  106. package/lib/index.js +28 -0
  107. package/lib/index.js.map +1 -0
  108. package/lib/packlets/converters/bodyConverterRegistry.d.ts +64 -0
  109. package/lib/packlets/converters/bodyConverterRegistry.d.ts.map +1 -0
  110. package/lib/packlets/converters/bodyConverterRegistry.js +55 -0
  111. package/lib/packlets/converters/bodyConverterRegistry.js.map +1 -0
  112. package/lib/packlets/converters/envelopeConverter.d.ts +70 -0
  113. package/lib/packlets/converters/envelopeConverter.d.ts.map +1 -0
  114. package/lib/packlets/converters/envelopeConverter.js +166 -0
  115. package/lib/packlets/converters/envelopeConverter.js.map +1 -0
  116. package/lib/packlets/converters/index.d.ts +3 -0
  117. package/lib/packlets/converters/index.d.ts.map +1 -0
  118. package/lib/packlets/converters/index.js +23 -0
  119. package/lib/packlets/converters/index.js.map +1 -0
  120. package/lib/packlets/index/index.d.ts +2 -0
  121. package/lib/packlets/index/index.d.ts.map +1 -0
  122. package/lib/packlets/index/index.js +22 -0
  123. package/lib/packlets/index/index.js.map +1 -0
  124. package/lib/packlets/index/memoryIndex.d.ts +127 -0
  125. package/lib/packlets/index/memoryIndex.d.ts.map +1 -0
  126. package/lib/packlets/index/memoryIndex.js +174 -0
  127. package/lib/packlets/index/memoryIndex.js.map +1 -0
  128. package/lib/packlets/observe/index.d.ts +3 -0
  129. package/lib/packlets/observe/index.d.ts.map +1 -0
  130. package/lib/packlets/observe/index.js +23 -0
  131. package/lib/packlets/observe/index.js.map +1 -0
  132. package/lib/packlets/observe/memoryObservationStore.d.ts +91 -0
  133. package/lib/packlets/observe/memoryObservationStore.d.ts.map +1 -0
  134. package/lib/packlets/observe/memoryObservationStore.js +123 -0
  135. package/lib/packlets/observe/memoryObservationStore.js.map +1 -0
  136. package/lib/packlets/observe/observer.d.ts +110 -0
  137. package/lib/packlets/observe/observer.d.ts.map +1 -0
  138. package/lib/packlets/observe/observer.js +7 -0
  139. package/lib/packlets/observe/observer.js.map +1 -0
  140. package/lib/packlets/retrieve/hybridRetriever.d.ts +79 -0
  141. package/lib/packlets/retrieve/hybridRetriever.d.ts.map +1 -0
  142. package/lib/packlets/retrieve/hybridRetriever.js +140 -0
  143. package/lib/packlets/retrieve/hybridRetriever.js.map +1 -0
  144. package/lib/packlets/retrieve/index.d.ts +8 -0
  145. package/lib/packlets/retrieve/index.d.ts.map +1 -0
  146. package/lib/packlets/retrieve/index.js +28 -0
  147. package/lib/packlets/retrieve/index.js.map +1 -0
  148. package/lib/packlets/retrieve/linkTraversalRetriever.d.ts +61 -0
  149. package/lib/packlets/retrieve/linkTraversalRetriever.d.ts.map +1 -0
  150. package/lib/packlets/retrieve/linkTraversalRetriever.js +147 -0
  151. package/lib/packlets/retrieve/linkTraversalRetriever.js.map +1 -0
  152. package/lib/packlets/retrieve/recencyRetriever.d.ts +21 -0
  153. package/lib/packlets/retrieve/recencyRetriever.d.ts.map +1 -0
  154. package/lib/packlets/retrieve/recencyRetriever.js +37 -0
  155. package/lib/packlets/retrieve/recencyRetriever.js.map +1 -0
  156. package/lib/packlets/retrieve/retriever.d.ts +133 -0
  157. package/lib/packlets/retrieve/retriever.d.ts.map +1 -0
  158. package/lib/packlets/retrieve/retriever.js +119 -0
  159. package/lib/packlets/retrieve/retriever.js.map +1 -0
  160. package/lib/packlets/retrieve/semanticRetriever.d.ts +69 -0
  161. package/lib/packlets/retrieve/semanticRetriever.d.ts.map +1 -0
  162. package/lib/packlets/retrieve/semanticRetriever.js +90 -0
  163. package/lib/packlets/retrieve/semanticRetriever.js.map +1 -0
  164. package/lib/packlets/retrieve/structuredFilterRetriever.d.ts +22 -0
  165. package/lib/packlets/retrieve/structuredFilterRetriever.d.ts.map +1 -0
  166. package/lib/packlets/retrieve/structuredFilterRetriever.js +41 -0
  167. package/lib/packlets/retrieve/structuredFilterRetriever.js.map +1 -0
  168. package/lib/packlets/retrieve/tagRetriever.d.ts +22 -0
  169. package/lib/packlets/retrieve/tagRetriever.d.ts.map +1 -0
  170. package/lib/packlets/retrieve/tagRetriever.js +41 -0
  171. package/lib/packlets/retrieve/tagRetriever.js.map +1 -0
  172. package/lib/packlets/store/fileTreeMemoryStore.d.ts +327 -0
  173. package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -0
  174. package/lib/packlets/store/fileTreeMemoryStore.js +702 -0
  175. package/lib/packlets/store/fileTreeMemoryStore.js.map +1 -0
  176. package/lib/packlets/store/index.d.ts +3 -0
  177. package/lib/packlets/store/index.d.ts.map +1 -0
  178. package/lib/packlets/store/index.js +23 -0
  179. package/lib/packlets/store/index.js.map +1 -0
  180. package/lib/packlets/store/scopeEncoding.d.ts +19 -0
  181. package/lib/packlets/store/scopeEncoding.d.ts.map +1 -0
  182. package/lib/packlets/store/scopeEncoding.js +34 -0
  183. package/lib/packlets/store/scopeEncoding.js.map +1 -0
  184. package/lib/packlets/types/envelope.d.ts +119 -0
  185. package/lib/packlets/types/envelope.d.ts.map +1 -0
  186. package/lib/packlets/types/envelope.js +7 -0
  187. package/lib/packlets/types/envelope.js.map +1 -0
  188. package/lib/packlets/types/filenameSafety.d.ts +16 -0
  189. package/lib/packlets/types/filenameSafety.d.ts.map +1 -0
  190. package/lib/packlets/types/filenameSafety.js +55 -0
  191. package/lib/packlets/types/filenameSafety.js.map +1 -0
  192. package/lib/packlets/types/identityCodec.d.ts +136 -0
  193. package/lib/packlets/types/identityCodec.d.ts.map +1 -0
  194. package/lib/packlets/types/identityCodec.js +190 -0
  195. package/lib/packlets/types/identityCodec.js.map +1 -0
  196. package/lib/packlets/types/ids.d.ts +55 -0
  197. package/lib/packlets/types/ids.d.ts.map +1 -0
  198. package/lib/packlets/types/ids.js +70 -0
  199. package/lib/packlets/types/ids.js.map +1 -0
  200. package/lib/packlets/types/index.d.ts +6 -0
  201. package/lib/packlets/types/index.d.ts.map +1 -0
  202. package/lib/packlets/types/index.js +26 -0
  203. package/lib/packlets/types/index.js.map +1 -0
  204. package/lib/packlets/types/writePolicy.d.ts +213 -0
  205. package/lib/packlets/types/writePolicy.d.ts.map +1 -0
  206. package/lib/packlets/types/writePolicy.js +268 -0
  207. package/lib/packlets/types/writePolicy.js.map +1 -0
  208. package/lib/packlets/vector/inMemoryCosineIndex.d.ts +69 -0
  209. package/lib/packlets/vector/inMemoryCosineIndex.d.ts.map +1 -0
  210. package/lib/packlets/vector/inMemoryCosineIndex.js +154 -0
  211. package/lib/packlets/vector/inMemoryCosineIndex.js.map +1 -0
  212. package/lib/packlets/vector/index.d.ts +3 -0
  213. package/lib/packlets/vector/index.d.ts.map +1 -0
  214. package/lib/packlets/vector/index.js +23 -0
  215. package/lib/packlets/vector/index.js.map +1 -0
  216. package/lib/packlets/vector/vectorIndex.d.ts +68 -0
  217. package/lib/packlets/vector/vectorIndex.d.ts.map +1 -0
  218. package/lib/packlets/vector/vectorIndex.js +7 -0
  219. package/lib/packlets/vector/vectorIndex.js.map +1 -0
  220. package/lib/test/unit/converters/bodyConverterRegistry.test.d.ts +2 -0
  221. package/lib/test/unit/converters/bodyConverterRegistry.test.d.ts.map +1 -0
  222. package/lib/test/unit/converters/bodyConverterRegistry.test.js +74 -0
  223. package/lib/test/unit/converters/bodyConverterRegistry.test.js.map +1 -0
  224. package/lib/test/unit/converters/envelopeConverter.test.d.ts +2 -0
  225. package/lib/test/unit/converters/envelopeConverter.test.d.ts.map +1 -0
  226. package/lib/test/unit/converters/envelopeConverter.test.js +198 -0
  227. package/lib/test/unit/converters/envelopeConverter.test.js.map +1 -0
  228. package/lib/test/unit/index/memoryIndex.test.d.ts +2 -0
  229. package/lib/test/unit/index/memoryIndex.test.d.ts.map +1 -0
  230. package/lib/test/unit/index/memoryIndex.test.js +154 -0
  231. package/lib/test/unit/index/memoryIndex.test.js.map +1 -0
  232. package/lib/test/unit/observe/memoryObservationStore.test.d.ts +2 -0
  233. package/lib/test/unit/observe/memoryObservationStore.test.d.ts.map +1 -0
  234. package/lib/test/unit/observe/memoryObservationStore.test.js +120 -0
  235. package/lib/test/unit/observe/memoryObservationStore.test.js.map +1 -0
  236. package/lib/test/unit/retrieve/linkTraversalRetriever.test.d.ts +2 -0
  237. package/lib/test/unit/retrieve/linkTraversalRetriever.test.d.ts.map +1 -0
  238. package/lib/test/unit/retrieve/linkTraversalRetriever.test.js +184 -0
  239. package/lib/test/unit/retrieve/linkTraversalRetriever.test.js.map +1 -0
  240. package/lib/test/unit/retrieve/retrievers.test.d.ts +2 -0
  241. package/lib/test/unit/retrieve/retrievers.test.d.ts.map +1 -0
  242. package/lib/test/unit/retrieve/retrievers.test.js +508 -0
  243. package/lib/test/unit/retrieve/retrievers.test.js.map +1 -0
  244. package/lib/test/unit/store/embedOnWrite.test.d.ts +2 -0
  245. package/lib/test/unit/store/embedOnWrite.test.d.ts.map +1 -0
  246. package/lib/test/unit/store/embedOnWrite.test.js +262 -0
  247. package/lib/test/unit/store/embedOnWrite.test.js.map +1 -0
  248. package/lib/test/unit/store/fileTreeMemoryStore.test.d.ts +2 -0
  249. package/lib/test/unit/store/fileTreeMemoryStore.test.d.ts.map +1 -0
  250. package/lib/test/unit/store/fileTreeMemoryStore.test.js +649 -0
  251. package/lib/test/unit/store/fileTreeMemoryStore.test.js.map +1 -0
  252. package/lib/test/unit/store/observations.test.d.ts +2 -0
  253. package/lib/test/unit/store/observations.test.d.ts.map +1 -0
  254. package/lib/test/unit/store/observations.test.js +241 -0
  255. package/lib/test/unit/store/observations.test.js.map +1 -0
  256. package/lib/test/unit/store/scopeEncoding.test.d.ts +2 -0
  257. package/lib/test/unit/store/scopeEncoding.test.d.ts.map +1 -0
  258. package/lib/test/unit/store/scopeEncoding.test.js +26 -0
  259. package/lib/test/unit/store/scopeEncoding.test.js.map +1 -0
  260. package/lib/test/unit/types/identityCodec.test.d.ts +2 -0
  261. package/lib/test/unit/types/identityCodec.test.d.ts.map +1 -0
  262. package/lib/test/unit/types/identityCodec.test.js +189 -0
  263. package/lib/test/unit/types/identityCodec.test.js.map +1 -0
  264. package/lib/test/unit/types/ids.test.d.ts +2 -0
  265. package/lib/test/unit/types/ids.test.d.ts.map +1 -0
  266. package/lib/test/unit/types/ids.test.js +86 -0
  267. package/lib/test/unit/types/ids.test.js.map +1 -0
  268. package/lib/test/unit/types/writePolicy.test.d.ts +2 -0
  269. package/lib/test/unit/types/writePolicy.test.d.ts.map +1 -0
  270. package/lib/test/unit/types/writePolicy.test.js +243 -0
  271. package/lib/test/unit/types/writePolicy.test.js.map +1 -0
  272. package/lib/test/unit/vector/inMemoryCosineIndex.test.d.ts +2 -0
  273. package/lib/test/unit/vector/inMemoryCosineIndex.test.d.ts.map +1 -0
  274. package/lib/test/unit/vector/inMemoryCosineIndex.test.js +194 -0
  275. package/lib/test/unit/vector/inMemoryCosineIndex.test.js.map +1 -0
  276. package/lib/test/unit/vector/vectorIndex.test.d.ts +2 -0
  277. package/lib/test/unit/vector/vectorIndex.test.d.ts.map +1 -0
  278. package/lib/test/unit/vector/vectorIndex.test.js +44 -0
  279. package/lib/test/unit/vector/vectorIndex.test.js.map +1 -0
  280. package/package.json +81 -0
  281. package/rush-logs/ts-agent-memory.build.cache.log +3 -0
  282. package/rush-logs/ts-agent-memory.build.log +9 -0
  283. package/src/index.ts +12 -0
  284. package/src/packlets/converters/bodyConverterRegistry.ts +105 -0
  285. package/src/packlets/converters/envelopeConverter.ts +210 -0
  286. package/src/packlets/converters/index.ts +7 -0
  287. package/src/packlets/index/index.ts +6 -0
  288. package/src/packlets/index/memoryIndex.ts +268 -0
  289. package/src/packlets/observe/index.ts +7 -0
  290. package/src/packlets/observe/memoryObservationStore.ts +153 -0
  291. package/src/packlets/observe/observer.ts +119 -0
  292. package/src/packlets/retrieve/hybridRetriever.ts +181 -0
  293. package/src/packlets/retrieve/index.ts +12 -0
  294. package/src/packlets/retrieve/linkTraversalRetriever.ts +169 -0
  295. package/src/packlets/retrieve/recencyRetriever.ts +54 -0
  296. package/src/packlets/retrieve/retriever.ts +207 -0
  297. package/src/packlets/retrieve/semanticRetriever.ts +147 -0
  298. package/src/packlets/retrieve/structuredFilterRetriever.ts +58 -0
  299. package/src/packlets/retrieve/tagRetriever.ts +58 -0
  300. package/src/packlets/store/fileTreeMemoryStore.ts +1073 -0
  301. package/src/packlets/store/index.ts +7 -0
  302. package/src/packlets/store/scopeEncoding.ts +36 -0
  303. package/src/packlets/types/envelope.ts +138 -0
  304. package/src/packlets/types/filenameSafety.ts +57 -0
  305. package/src/packlets/types/identityCodec.ts +263 -0
  306. package/src/packlets/types/ids.ts +124 -0
  307. package/src/packlets/types/index.ts +10 -0
  308. package/src/packlets/types/writePolicy.ts +447 -0
  309. package/src/packlets/vector/inMemoryCosineIndex.ts +173 -0
  310. package/src/packlets/vector/index.ts +7 -0
  311. package/src/packlets/vector/vectorIndex.ts +78 -0
  312. package/src/test/unit/converters/bodyConverterRegistry.test.ts +89 -0
  313. package/src/test/unit/converters/envelopeConverter.test.ts +261 -0
  314. package/src/test/unit/index/memoryIndex.test.ts +187 -0
  315. package/src/test/unit/observe/memoryObservationStore.test.ts +158 -0
  316. package/src/test/unit/retrieve/linkTraversalRetriever.test.ts +230 -0
  317. package/src/test/unit/retrieve/retrievers.test.ts +662 -0
  318. package/src/test/unit/store/embedOnWrite.test.ts +346 -0
  319. package/src/test/unit/store/fileTreeMemoryStore.test.ts +875 -0
  320. package/src/test/unit/store/observations.test.ts +290 -0
  321. package/src/test/unit/store/scopeEncoding.test.ts +37 -0
  322. package/src/test/unit/types/identityCodec.test.ts +266 -0
  323. package/src/test/unit/types/ids.test.ts +94 -0
  324. package/src/test/unit/types/writePolicy.test.ts +325 -0
  325. package/src/test/unit/vector/inMemoryCosineIndex.test.ts +242 -0
  326. package/src/test/unit/vector/vectorIndex.test.ts +48 -0
  327. package/temp/build/lint/_eslint-5eVG3S6w.json +182 -0
  328. package/temp/build/typescript/ts_8nwakTlr.json +1 -0
  329. package/temp/ts-agent-memory.api.json +12438 -0
  330. package/temp/ts-agent-memory.api.md +525 -0
  331. package/tsconfig.json +8 -0
@@ -0,0 +1,1901 @@
1
+ import { Brand } from '@fgv/ts-utils';
2
+ import { Converter } from '@fgv/ts-utils';
3
+ import { FileTree } from '@fgv/ts-json-base';
4
+ import { JsonSchema } from '@fgv/ts-json-base';
5
+ import { Logging } from '@fgv/ts-utils';
6
+ import { Result } from '@fgv/ts-utils';
7
+
8
+ /**
9
+ * The admission decision returned by {@link IWritePolicy.admit}.
10
+ * @public
11
+ */
12
+ export declare type AdmissionDecision = {
13
+ readonly decision: 'accept';
14
+ } | {
15
+ readonly decision: 'reject';
16
+ readonly reason: string;
17
+ } | {
18
+ readonly decision: 'cull-oldest';
19
+ /** {@link MemoryId}s to evict before writing the incoming record. */
20
+ readonly evict: ReadonlyArray<MemoryId>;
21
+ };
22
+
23
+ /**
24
+ * Validates a single filename stem against the POSIX portable filename set
25
+ * (`[A-Za-z0-9._-]`), rejecting a leading or trailing `.` and reserved Windows
26
+ * device names. This is the cross-platform filename-stem contract for the
27
+ * package: {@link MemoryId} values, the concrete {@link IIdentityCodec}
28
+ * implementations, and the store's `verifyFilenameId` all gate on it.
29
+ *
30
+ * @remarks
31
+ * A trailing `.` is rejected because Windows silently strips trailing dots from
32
+ * filenames, so such a stem would not round-trip verbatim through the file
33
+ * layer even though it is otherwise portable-set-valid.
34
+ * @public
35
+ */
36
+ export declare function assertPortableFilenameStem(stem: string): Result<string>;
37
+
38
+ /**
39
+ * Default in-memory {@link IBodyConverterRegistry}.
40
+ *
41
+ * @remarks
42
+ * Both `register` and `registerSchema` adapt the supplied converter/validator
43
+ * into a `Converter<unknown>` via `Converters.generic`, so the heterogeneous
44
+ * per-kind types are stored uniformly with no cast and no `any`. A
45
+ * `Converter<T>` is not structurally a `Converter<unknown>` (the `map` callback
46
+ * makes the type invariant), so the `generic` wrapper — whose callback returns
47
+ * `Result<T>` (assignable to `Result<unknown>`) — is the type-safe bridge.
48
+ * @public
49
+ */
50
+ export declare class BodyConverterRegistry implements IBodyConverterRegistry {
51
+ private readonly _converters;
52
+ private constructor();
53
+ /** Family-convention factory. */
54
+ static create(): Result<BodyConverterRegistry>;
55
+ /** {@inheritDoc IBodyConverterRegistry.register} */
56
+ register<T>(kind: Kind, converter: Converter<T>): void;
57
+ /** {@inheritDoc IBodyConverterRegistry.registerSchema} */
58
+ registerSchema<T>(kind: Kind, schema: JsonSchema.ISchemaValidator<T>): void;
59
+ /** {@inheritDoc IBodyConverterRegistry.has} */
60
+ has(kind: Kind): boolean;
61
+ /** {@inheritDoc IBodyConverterRegistry.getConverter} */
62
+ getConverter(kind: Kind): Result<Converter<unknown>>;
63
+ /** {@inheritDoc IBodyConverterRegistry.convert} */
64
+ convert(kind: Kind, body: unknown): Result<unknown>;
65
+ }
66
+
67
+ /**
68
+ * Converters for the branded identifier scalars. Each validates an `unknown`
69
+ * value into the corresponding brand, enforcing the shared hygiene
70
+ * (non-empty, length-capped, trimmed).
71
+ * @public
72
+ */
73
+ export declare const Convert: {
74
+ readonly memoryId: Converter<MemoryId>;
75
+ readonly entityId: Converter<EntityId>;
76
+ readonly kind: Converter<Kind>;
77
+ readonly tag: Converter<Tag>;
78
+ readonly scopeKey: Converter<MemoryScopeKey>;
79
+ readonly linkType: Converter<LinkType>;
80
+ };
81
+
82
+ /**
83
+ * The granularity at which the store deduplicates an incoming write against the
84
+ * existing vault, declared per kind via {@link IWritePolicy.dedupScope}.
85
+ *
86
+ * - `'content'`: scope-wide cross-id content dedup. An identical
87
+ * `{ kind, body, links }` triple ANYWHERE in the scope — even under a
88
+ * different id — is a no-op that returns the existing record. The knowledge
89
+ * kind family uses this.
90
+ * - `'entity'`: same-id content dedup only. An identical re-put of the SAME
91
+ * entity is a no-op, but two DISTINCT entities with identical content never
92
+ * collapse. The experience (memory) kind families use this so that, e.g.,
93
+ * two turns whose summaries happen to be byte-identical both persist.
94
+ * @public
95
+ */
96
+ export declare type DedupScope = 'content' | 'entity';
97
+
98
+ /**
99
+ * The default {@link DedupScope} applied when a policy does not declare one.
100
+ * Entity-scoped dedup is the safe default — it never silently collapses two
101
+ * distinct entities with coincidentally-identical content.
102
+ * @public
103
+ */
104
+ export declare const DEFAULT_DEDUP_SCOPE: DedupScope;
105
+
106
+ /**
107
+ * Encode a {@link MemoryScopeKey} to its on-disk directory path. The scope may
108
+ * be multi-segment (`/`-separated) — each component is validated independently
109
+ * against the POSIX portable filename set (via
110
+ * {@link assertPortableFilenameStem}), then rejoined with `/`.
111
+ *
112
+ * @remarks
113
+ * This is the day-one multi-segment scope resolver design-lock §9.1 calls for:
114
+ * the knowledge scope is the single segment `knowledge`, while the Phase-C MTM
115
+ * scope `conversations/<conversationId>` is two segments. Validating each
116
+ * segment independently (rather than the whole path as one stem, which the
117
+ * `ts-prompt-assist` default encoding does) keeps the Phase-C codec additive —
118
+ * no scope-encoding change is needed when MTM ships.
119
+ * @public
120
+ */
121
+ export declare function defaultMemoryScopeEncoding(scope: MemoryScopeKey): Result<string>;
122
+
123
+ /**
124
+ * Converter for an attributed {@link IEdge}.
125
+ * @public
126
+ */
127
+ export declare const edgeConverter: Converter<IEdge>;
128
+
129
+ /**
130
+ * Consumer-supplied domain key. The stable entity identity across versions;
131
+ * the package never mints identity. Equals {@link MemoryId} for non-temporal
132
+ * kinds.
133
+ * @public
134
+ */
135
+ export declare type EntityId = Brand<string, 'EntityId'>;
136
+
137
+ /**
138
+ * Converter for the invariant {@link IMemoryEnvelope}. Validates a plain
139
+ * object (e.g. parsed YAML frontmatter) into a typed envelope.
140
+ * @public
141
+ */
142
+ export declare const envelopeConverter: Converter<IMemoryEnvelope>;
143
+
144
+ /**
145
+ * Converter that parses a YAML frontmatter string into an
146
+ * {@link IMemoryEnvelope}.
147
+ * @public
148
+ */
149
+ export declare const envelopeYamlConverter: Converter<IMemoryEnvelope>;
150
+
151
+ /**
152
+ * Flat-layout, FileTree-backed {@link IMemoryStore}. The FileTree is the source
153
+ * of truth; the {@link IMemoryIndex} is a derived in-memory view patched on
154
+ * every write. Concurrent writes are serialized through a per-instance async
155
+ * write-lock so the index and the on-disk files never interleave.
156
+ *
157
+ * @remarks
158
+ * B1 supports flat (non-versioned) layout only and string (markdown) bodies.
159
+ * A codec reporting `isVersioned: true`, or a non-string body, fails loudly —
160
+ * the versioned/temporal write path is a fast-follow.
161
+ * @public
162
+ */
163
+ export declare class FileTreeMemoryStore implements IMemoryStore {
164
+ private readonly _root;
165
+ private readonly _registry;
166
+ private readonly _writePolicies;
167
+ private readonly _codecs;
168
+ private readonly _defaultCodec;
169
+ private readonly _defaultPolicy;
170
+ private readonly _scopeEncoding;
171
+ private readonly _clock;
172
+ private readonly _index;
173
+ private readonly _hasher;
174
+ private readonly _observers;
175
+ private readonly _logger;
176
+ private readonly _vectorIndex;
177
+ private readonly _embed;
178
+ /** Monotonic write counter; incremented inside the write-lock on each put. */
179
+ private _seq;
180
+ /**
181
+ * Monotonic observation-sequence counter. A distinct authority from `_seq`
182
+ * (the envelope write counter): it numbers the audit stream so a single
183
+ * {@link MemoryObservationStore} fed by this store sees strictly increasing
184
+ * `seq`, satisfying the ring buffer's cursor contract.
185
+ */
186
+ private _observationSeq;
187
+ /** Tail of the write-lock promise chain that serializes mutating ops. */
188
+ private _writeTail;
189
+ /**
190
+ * The record-level mutable-field vocabulary: maps a declared mutable field
191
+ * name to its canonical location on a record. Used to project an incoming
192
+ * record into a merge-patch on update. B1 ships the knowledge-LWW surface
193
+ * (body + envelope metadata); body-internal mutable fields (Phase-C cap-cull)
194
+ * extend this map.
195
+ */
196
+ private static readonly _mutableFieldAccessors;
197
+ private constructor();
198
+ /**
199
+ * Family-convention factory. Builds the derived index and a default LWW
200
+ * policy, then performs an initial FileTree walk so an existing vault is
201
+ * indexed (and the `seq` counter resumes past the highest persisted `seq`).
202
+ */
203
+ static create(params: IFileTreeMemoryStoreCreateParams): Result<FileTreeMemoryStore>;
204
+ /** {@inheritDoc IMemoryStore.get} */
205
+ get(kind: Kind, entityId: EntityId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
206
+ /** {@inheritDoc IMemoryStore.getById} */
207
+ getById(scope: MemoryScopeKey, id: MemoryId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
208
+ /** {@inheritDoc IMemoryStore.list} */
209
+ list(filter?: IMemoryStoreListFilter): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
210
+ /** {@inheritDoc IMemoryStore.put} */
211
+ put(record: IMemoryRecord<unknown>): Promise<Result<IMemoryRecord<unknown>>>;
212
+ /** {@inheritDoc IMemoryStore.delete} */
213
+ delete(kind: Kind, entityId: EntityId): Promise<Result<MemoryId>>;
214
+ /**
215
+ * Serialize a mutating task behind the write-lock. Tasks run in submission
216
+ * order; a failed task does not break the chain for subsequent ones.
217
+ */
218
+ private _enqueue;
219
+ /**
220
+ * Build and fan out one observation record for a completed op. A no-op when no
221
+ * observers are wired (the additive-default path pays nothing). The store is
222
+ * the seq authority — it mints `seq` / `timestamp` so every observer sees the
223
+ * same record. The scope is resolved best-effort via the codec.
224
+ */
225
+ private _fireObservation;
226
+ /** Invoke one observer, swallowing any failure or throw (logged at `warn`). */
227
+ private _safeObserve;
228
+ /**
229
+ * Log a swallowed-issue warning (observer failure or best-effort vector
230
+ * maintenance), tolerating a logger that itself throws — diagnostic logging
231
+ * must never make a store op reject.
232
+ */
233
+ private _warnSwallowed;
234
+ /** Resolve a scope for an observation, best-effort (undefined when unresolvable). */
235
+ private _scopeBestEffort;
236
+ private _putLocked;
237
+ /**
238
+ * Run dedup → policy → stamp → embed → write for a resolved address and content
239
+ * hash. Async because the embed-on-write hook (when wired) does a network call
240
+ * or in-process inference; the whole chain runs inside the write-lock so the
241
+ * vector index, the on-disk file, and the derived index never interleave.
242
+ */
243
+ private _writeResolved;
244
+ /**
245
+ * Build → embed → persist → evict for an admitted write.
246
+ *
247
+ * The durable record store is authoritative; the vector index is a **derived,
248
+ * rebuildable** view, so vector maintenance is **best-effort** — a failed embed
249
+ * or `add` is logged and the durable write still succeeds (the index can be
250
+ * rebuilt via {@link InMemoryCosineIndex.rebuild}). Only genuine record-store
251
+ * failures (body/codec/policy, persist, file eviction) fail the `put`.
252
+ *
253
+ * Ordering: the embed + `add` run immediately before the single `_persist` so
254
+ * the index-returned `embeddingRef` lands in one durable write (a post-persist
255
+ * stamp would need a second write whose failure path is effectively untestable).
256
+ * Build and persist the replacement BEFORE evicting the cull-oldest cohort, so a
257
+ * later eviction failure never loses data with nothing written in its place.
258
+ */
259
+ private _admitWrite;
260
+ /**
261
+ * Best-effort embed-on-write. When a vector index AND an embedder are wired,
262
+ * embeds the built record, `add`s the vector (replace semantics handle a same-id
263
+ * re-embed — no explicit remove), and stamps the returned `embeddingRef`. A
264
+ * failure (returned `fail` OR a thrown/rejected hook) is logged and the
265
+ * unembedded record is returned unchanged — the put still persists, and the
266
+ * derived index is reconciled by a later `rebuild`. A pass-through no-op when
267
+ * unwired (byte-identical record).
268
+ *
269
+ * Always succeeds (`Result` is the chain's shape, never a vector-induced
270
+ * failure).
271
+ */
272
+ private _embedOnWrite;
273
+ /**
274
+ * Evict the records named by a `cull-oldest` decision, best-effort. Runs only
275
+ * after the authoritative `_persist`, so a failed eviction is logged (never
276
+ * fatal) and the cap self-corrects on the next admission. Returns the ids that
277
+ * were actually evicted (so observations / vector pruning cover only those).
278
+ * `accept` / `reject` decisions evict nothing.
279
+ */
280
+ private _applyEvictions;
281
+ /** Best-effort vector removal for each evicted record (never fails the put). */
282
+ private _removeEvictedVectors;
283
+ /**
284
+ * Run a consumer-supplied vector hook, normalizing a thrown/rejected hook into a
285
+ * `Failure` and logging any failure at `warn`. Best-effort: the caller proceeds
286
+ * regardless, since the index is rebuildable.
287
+ */
288
+ private _tryVectorOp;
289
+ /**
290
+ * Best-effort vector removal. A no-op unless the full vector lifecycle is wired
291
+ * (both an index AND an embedder), so an unwired store does no vector work and
292
+ * behaves byte-identically. Failures are logged, never surfaced — a committed
293
+ * delete/eviction must not fail because a derived index could not be pruned.
294
+ */
295
+ private _removeVectorBestEffort;
296
+ /**
297
+ * Build the record to persist. On a first write the incoming envelope is the
298
+ * base (final content equals the incoming content, so the dedup `hash` is
299
+ * reused). On an update the incoming record's mutable fields are projected into
300
+ * a merge-patch and the policy's `applyUpdate` merges them over the existing
301
+ * record (preserving `created`); the persisted body and `contentHash` are then
302
+ * taken from the policy's actual output, so a body-transforming policy is never
303
+ * bypassed and the stored hash always matches the stored `{ kind, body, links }`.
304
+ * The store stamps the transaction-time metadata it owns
305
+ * (`created` / `updated` / `seq` / `contentHash`).
306
+ */
307
+ private _buildRecord;
308
+ /** Serialize and write a fully-stamped record, then patch the index. */
309
+ private _persist;
310
+ private _deleteLocked;
311
+ /** Evict (physically delete) a single record file by id, patching the index. */
312
+ private _evict;
313
+ /** Project the incoming record's mutable fields into a merge-patch. */
314
+ private _projectMutablePatch;
315
+ /**
316
+ * The admission cohort for a write: every indexed record in `scope` of `kind`
317
+ * except the one at `idStem` (the record being written or updated). This is
318
+ * the set a per-kind cap (e.g. {@link MemoryCapCullPolicy}) counts against, so
319
+ * a bounded-ring policy can keep a per-scope/per-kind family within
320
+ * `maxRecords`. Excluding the target id makes the post-write count uniform
321
+ * across first-writes and updates.
322
+ */
323
+ private _admissionCohort;
324
+ /** Find a record in `scope` whose `contentHash` equals `hash`, if any. */
325
+ private _findByContentHash;
326
+ private _contentHash;
327
+ private _codecFor;
328
+ private _policyFor;
329
+ /**
330
+ * Read and validate the record at `<scope>/<idStem>.md`, returning `undefined`
331
+ * when the scope directory or file is absent. Verifies the on-disk id ↔
332
+ * filename round-trip on every load.
333
+ */
334
+ private _readRecord;
335
+ /** Enforce `envelope.id === filename stem` and the codec round-trip on load. */
336
+ private _verifyLoaded;
337
+ /**
338
+ * Resolve the directory for a scope, returning `undefined` when it does not
339
+ * exist. Navigation only — does not create. Folds the path segments through
340
+ * `getChildren` so an absent segment short-circuits to `undefined`.
341
+ */
342
+ private _resolveScopeDir;
343
+ /** Ensure the scope directory exists, creating segments as needed. */
344
+ private _ensureScopeDir;
345
+ /** Write (create or overwrite) `<scope>/<idStem>.md` with `raw`. */
346
+ private _writeFile;
347
+ /**
348
+ * Physically delete `<scope>/<idStem>.md`. The scope-missing and file-missing
349
+ * guards are unreachable through the callers (`delete` / `_evict` both read the
350
+ * record first, so the directory and file exist) but are kept so a future
351
+ * direct caller degrades loudly rather than silently.
352
+ */
353
+ private _deleteFile;
354
+ /**
355
+ * Walk the FileTree once and rebuild the index. Also resumes the `seq`
356
+ * counter past the highest persisted `seq` so new writes stay monotonic.
357
+ */
358
+ private _initialIndex;
359
+ /** Recursively collect every `.md` record under `dir` (scope = path segments). */
360
+ private _collectEntries;
361
+ }
362
+
363
+ /**
364
+ * Enforce the loud-degradation contract for the `semantic` and `asOf` axes
365
+ * against a retriever's `capabilities`: a requested capability the retriever
366
+ * does not support fails loudly rather than returning a silent empty result.
367
+ * @public
368
+ */
369
+ export declare function guardRetrieverCapabilities(query: IMemoryQuery, capabilities: IMemoryRetrieverCapabilities): Result<true>;
370
+
371
+ /**
372
+ * Composes several retrievers, dispatches a query to each, and merges their
373
+ * results via an injectable {@link IMergeStrategy}. Its capabilities are the
374
+ * union of the composed retrievers' capabilities.
375
+ *
376
+ * @remarks
377
+ * The hybrid enforces the loud-degradation contract against its OWN (union)
378
+ * capabilities, then projects the query for each child: a child that does not
379
+ * support the `semantic` (or `asOf`) axis is handed a query with that axis
380
+ * stripped, so it returns its normal results instead of loud-failing on a field
381
+ * a sibling handles. A child that genuinely fails (e.g. a wired semantic backend
382
+ * erroring) propagates — the hybrid never silently drops a failure.
383
+ * @public
384
+ */
385
+ export declare class HybridRetriever implements IMemoryRetriever {
386
+ private readonly _retrievers;
387
+ private readonly _mergeStrategy;
388
+ private readonly _capabilities;
389
+ private constructor();
390
+ /** {@inheritDoc IMemoryRetriever.capabilities} */
391
+ get capabilities(): IMemoryRetrieverCapabilities;
392
+ /**
393
+ * Family-convention factory.
394
+ * @param retrievers - The retrievers to compose (at least one).
395
+ * @param mergeStrategy - How to combine their results.
396
+ */
397
+ static create(retrievers: ReadonlyArray<IMemoryRetriever>, mergeStrategy: IMergeStrategy): Result<HybridRetriever>;
398
+ /** {@inheritDoc IMemoryRetriever.retrieve} */
399
+ retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
400
+ /**
401
+ * Project the query for one child retriever. Two adjustments:
402
+ *
403
+ * - Strip axes the child does not support (`semantic` / `topK` for a
404
+ * non-semantic child, `asOf` for a non-temporal child, the link axes for a
405
+ * non-link child) so it returns its normal results rather than loud-failing
406
+ * on a field a sibling handles.
407
+ * - Strip `limit` unconditionally: limit is a post-merge concern. A child that
408
+ * pre-truncated its result set would starve the merge strategy of candidates
409
+ * it needs to score correctly (a record both children would surface must
410
+ * reach the merge to score 2). The hybrid applies `limit` once, after merge.
411
+ */
412
+ private _projectQuery;
413
+ }
414
+
415
+ /**
416
+ * Registry of per-kind body Converters. Each memory {@link Kind} registers the
417
+ * validated shape of its body; the store dispatches an `unknown` body through
418
+ * the registered Converter on every write. Type-safe — no `any`.
419
+ * @public
420
+ */
421
+ export declare interface IBodyConverterRegistry {
422
+ /**
423
+ * Register a Converter for a kind. Replaces any prior registration for the
424
+ * same kind.
425
+ */
426
+ register<T>(kind: Kind, converter: Converter<T>): void;
427
+ /**
428
+ * Register a `JsonSchema` validator (from `@fgv/ts-json-base`) for a kind —
429
+ * the schema IS a Validator. Replaces any prior registration for the same
430
+ * kind.
431
+ */
432
+ registerSchema<T>(kind: Kind, schema: JsonSchema.ISchemaValidator<T>): void;
433
+ /** Returns `true` if a converter is registered for the kind. */
434
+ has(kind: Kind): boolean;
435
+ /**
436
+ * Get the raw converter registered for a kind. Fails if the kind is
437
+ * unregistered. Exposed for implementors that need to re-validate a patched
438
+ * body (e.g. a temporal-versioned policy's `applyUpdate`).
439
+ */
440
+ getConverter(kind: Kind): Result<Converter<unknown>>;
441
+ /**
442
+ * Convert an `unknown` body value for the given kind. Fails with
443
+ * `no converter registered for kind '<k>'` when unregistered.
444
+ */
445
+ convert(kind: Kind, body: unknown): Result<unknown>;
446
+ }
447
+
448
+ /**
449
+ * An attributed link between two records. Carries the relation type, the
450
+ * target id, and optional confidence / provenance / world-truth validity.
451
+ * Replaces bare string references (e.g. PersonAIlity's `IMtmRef` becomes an
452
+ * `IEdge` with `type: LinkType('mtm-ref')`).
453
+ * @public
454
+ */
455
+ export declare interface IEdge {
456
+ /** Open-vocabulary relation type. */
457
+ readonly type: LinkType;
458
+ /** The linked-to record. */
459
+ readonly target: MemoryId;
460
+ /** Optional confidence in `[0, 1]`. */
461
+ readonly confidence?: number;
462
+ /** Optional structured provenance for the link itself. */
463
+ readonly provenance?: IProvenance;
464
+ /** World-truth validity start (epoch ms). Present only on temporal edges. */
465
+ readonly valid_at?: number;
466
+ /**
467
+ * World-truth validity end (epoch ms). `null` = still valid; absent = no
468
+ * temporal extent.
469
+ */
470
+ readonly invalid_at?: number | null;
471
+ }
472
+
473
+ /**
474
+ * Parameters for {@link FileTreeMemoryStore.create}.
475
+ * @public
476
+ */
477
+ export declare interface IFileTreeMemoryStoreCreateParams {
478
+ /** Root directory under which scope-encoded sub-trees live. Must be mutable. */
479
+ readonly root: FileTree.IMutableFileTreeDirectoryItem;
480
+ /** Per-kind body converter registry. Gates every body on write and read. */
481
+ readonly registry: IBodyConverterRegistry;
482
+ /** Per-kind write policies. Kinds without an entry use a default LWW policy. */
483
+ readonly writePolicies?: ReadonlyMap<Kind, IWritePolicy>;
484
+ /** Per-kind identity codecs. */
485
+ readonly codecs?: ReadonlyMap<Kind, IIdentityCodec>;
486
+ /** Default codec for kinds without an explicit entry. */
487
+ readonly defaultCodec?: IIdentityCodec;
488
+ /** Scope encoding. Defaults to {@link defaultMemoryScopeEncoding}. */
489
+ readonly scopeEncoding?: (scope: MemoryScopeKey) => Result<string>;
490
+ /**
491
+ * Transaction-time clock. Defaults to `Date.now`. Injectable so tests can
492
+ * make `created` / `updated` deterministic. Also stamps observation
493
+ * `timestamp`s.
494
+ */
495
+ readonly clock?: () => number;
496
+ /**
497
+ * Optional observers fired once per public `get` / `put` / `delete` call.
498
+ * Purely additive — when absent, no observation records are produced and the
499
+ * store behaves exactly as it did without this parameter. Observer errors
500
+ * never affect the store operation (swallowed, logged to {@link
501
+ * IFileTreeMemoryStoreCreateParams.logger | logger} at `warn`).
502
+ */
503
+ readonly observers?: ReadonlyArray<IMemoryObserver>;
504
+ /**
505
+ * Diagnostic logger for swallowed observer failures. Defaults to a
506
+ * `Logging.NoOpLogger`.
507
+ */
508
+ readonly logger?: Logging.ILogger;
509
+ /**
510
+ * Optional vector index for semantic recall. Wired together with
511
+ * {@link IFileTreeMemoryStoreCreateParams.embed | embed}: when both are present
512
+ * the store embeds each written record and maintains the index on
513
+ * `put` / `delete` / cap-cull eviction. Absent (or `embed` absent) → no
514
+ * embedding work happens and the store behaves exactly as it does without this
515
+ * parameter (the additive, zero-overhead-when-unwired default — mirrors the
516
+ * observer hook).
517
+ */
518
+ readonly vectorIndex?: IVectorIndex;
519
+ /**
520
+ * Optional embedder applied to each record on write, wired together with
521
+ * {@link IFileTreeMemoryStoreCreateParams.vectorIndex | vectorIndex}. The
522
+ * consumer supplies it (e.g. `callProviderEmbedding` or in-process
523
+ * transformers); the store never calls an embedding provider directly, so the
524
+ * core stays embedder-agnostic. Embedding/index maintenance is **best-effort**:
525
+ * a failed (or throwing) `embed` / `add` / `remove` is logged at `warn` via
526
+ * {@link IFileTreeMemoryStoreCreateParams.logger | logger} and the record
527
+ * operation still succeeds — the vector index is a derived view that a later
528
+ * `rebuild` reconciles, so a vector failure never fails an authoritative write.
529
+ */
530
+ readonly embed?: MemoryEmbedder;
531
+ }
532
+
533
+ /**
534
+ * Maps a consumer-supplied domain key ⇄ a FileTree storage address. Injected
535
+ * per kind so the store never touches raw domain keys: the codec owns all
536
+ * filename escaping and the flat-vs-versioned layout dispatch.
537
+ * @public
538
+ */
539
+ export declare interface IIdentityCodec {
540
+ /**
541
+ * Encode a consumer-supplied entity id to a FileTree address. Deterministic
542
+ * and pure — no I/O.
543
+ */
544
+ encode(entityId: EntityId): Result<IIdentityCodecResult>;
545
+ /**
546
+ * Decode a FileTree address back to the original {@link EntityId}. The exact
547
+ * inverse of {@link IIdentityCodec.encode | encode} for non-versioned kinds.
548
+ */
549
+ decode(scope: MemoryScopeKey, encodedStem: string): Result<EntityId>;
550
+ /**
551
+ * Assert that `encode(decode(scope, stem)).idStem === stem`. Used by the
552
+ * store's `verifyFilenameId` check on load.
553
+ */
554
+ verifyRoundTrip(scope: MemoryScopeKey, stem: string): Result<true>;
555
+ }
556
+
557
+ /**
558
+ * The FileTree storage address an {@link IIdentityCodec} maps a domain key to.
559
+ * @public
560
+ */
561
+ export declare interface IIdentityCodecResult {
562
+ /** Scope path segment (may be multi-level, e.g. `conversations/<id>`). */
563
+ readonly scope: MemoryScopeKey;
564
+ /** Filename stem (the part before `.md`). Filename-safe after encoding. */
565
+ readonly idStem: string;
566
+ /**
567
+ * Whether this kind uses a versioned layout (temporal: multiple files per
568
+ * entity) vs. a flat layout (one file per entity). Non-temporal = always
569
+ * `false`.
570
+ */
571
+ readonly isVersioned: boolean;
572
+ }
573
+
574
+ /**
575
+ * A memory record paired with the {@link MemoryScopeKey | scope} it lives
576
+ * under. The scope is not carried on the {@link IMemoryEnvelope} (it is derived
577
+ * from the entity id by the codec), so the store threads it alongside the
578
+ * record when patching or rebuilding the index. The `(scope, id)` pair is the
579
+ * index's primary key, keeping records distinct across scopes that reuse a
580
+ * filename stem (e.g. `turn-0` under different conversations in Phase C).
581
+ * @public
582
+ */
583
+ export declare interface IIndexedMemoryRecord {
584
+ /** The scope the record is stored under. */
585
+ readonly scope: MemoryScopeKey;
586
+ /** The memory record itself. */
587
+ readonly record: IMemoryRecord<unknown>;
588
+ }
589
+
590
+ /**
591
+ * Parameters for {@link MemoryCapCullPolicy.create}.
592
+ * @public
593
+ */
594
+ export declare interface IMemoryCapCullPolicyParams {
595
+ /**
596
+ * Maximum number of records the policy admits before culling the oldest.
597
+ * Counted over the `existing` cohort passed to {@link IWritePolicy.admit}.
598
+ * Absent = no cap (admission always accepts).
599
+ */
600
+ readonly maxRecords?: number;
601
+ /**
602
+ * The fields a merge-patch update may touch (drawn from the record-level
603
+ * mutable vocabulary: `body` / `tags` / `links` / `provenance` /
604
+ * `embeddingRef`). Fields outside this list are immutable.
605
+ */
606
+ readonly mutableFields: ReadonlyArray<string>;
607
+ }
608
+
609
+ /**
610
+ * The invariant identity + transaction-time envelope carried by every memory
611
+ * record, independent of the per-kind body.
612
+ * @public
613
+ */
614
+ export declare interface IMemoryEnvelope {
615
+ /** Stable file-stem identifier. MUST equal the on-disk filename stem. */
616
+ readonly id: MemoryId;
617
+ /** Consumer-supplied domain key. Equals {@link IMemoryEnvelope.id | id} for non-temporal kinds. */
618
+ readonly entityId: EntityId;
619
+ /** Consumer-registered kind; dispatches the body Converter. */
620
+ readonly kind: Kind;
621
+ /** Open-vocabulary tags. */
622
+ readonly tags: ReadonlyArray<Tag>;
623
+ /** Attributed outbound edges. */
624
+ readonly links: ReadonlyArray<IEdge>;
625
+ /** Epoch ms of the first write. Immutable after creation. */
626
+ readonly created: number;
627
+ /** Epoch ms of the most recent write. */
628
+ readonly updated: number;
629
+ /**
630
+ * Monotonic write counter within the store instance, assigned by the store
631
+ * on every successful put. Enables stable cursor paging over observation
632
+ * records without a full walk.
633
+ */
634
+ readonly seq: number;
635
+ /**
636
+ * Content hash over the canonical `{ kind, body, links }`. The dedup key:
637
+ * an exact match is a no-op upsert that returns the existing record.
638
+ */
639
+ readonly contentHash: string;
640
+ /** Structured provenance (never a flat enum). */
641
+ readonly provenance: IProvenance;
642
+ /** Bi-temporal validity. Present only on temporal kinds. */
643
+ readonly temporal?: ITemporalBlock;
644
+ /**
645
+ * Vector-index entry reference, set by the vector index on write. `null` =
646
+ * not embedded; absent = same as `null` (backwards-compat seam).
647
+ */
648
+ readonly embeddingRef?: string | null;
649
+ }
650
+
651
+ /**
652
+ * The two parts of a memory file: the YAML frontmatter (between the `---`
653
+ * delimiters) and the markdown body (everything after the closing delimiter).
654
+ * @public
655
+ */
656
+ export declare interface IMemoryFileParts {
657
+ /** The raw YAML frontmatter (delimiters stripped). */
658
+ readonly frontmatter: string;
659
+ /** The raw body text following the closing delimiter. */
660
+ readonly body: string;
661
+ }
662
+
663
+ /**
664
+ * The derived, in-memory secondary indexes the store maintains over its
665
+ * records. Never the source of truth — the FileTree is. The index is fully
666
+ * rebuildable from a walk of the store ({@link IMemoryIndex.rebuild}) and is
667
+ * patched incrementally on every write ({@link IMemoryIndex.patch}).
668
+ *
669
+ * @remarks
670
+ * B1 builds the maps; link-traversal BFS over {@link IMemoryIndex.backlinks}
671
+ * is B2. The accessors return records (not bare ids) so the B2 retrievers can
672
+ * consume them directly.
673
+ * @public
674
+ */
675
+ export declare interface IMemoryIndex {
676
+ /**
677
+ * Replace the entire index from a full set of records (a store walk).
678
+ * @returns The number of records indexed.
679
+ */
680
+ rebuild(entries: ReadonlyArray<IIndexedMemoryRecord>): Result<number>;
681
+ /**
682
+ * Apply a single incremental change. `'put'` inserts or replaces the entry
683
+ * at its `(scope, id)` key (removing any prior associations first); `'delete'`
684
+ * removes it.
685
+ * @returns The entry that was applied.
686
+ */
687
+ patch(op: MemoryIndexPatchOp, entry: IIndexedMemoryRecord): Result<IIndexedMemoryRecord>;
688
+ /** Every indexed entry (scope + record). Primary read surface for the store. */
689
+ entries(): ReadonlyArray<IIndexedMemoryRecord>;
690
+ /** Records of the given kind, in recency order (most-recently-updated first). */
691
+ byKind(kind: Kind): ReadonlyArray<IMemoryRecord<unknown>>;
692
+ /** Records carrying the given tag, in recency order. */
693
+ byTag(tag: Tag): ReadonlyArray<IMemoryRecord<unknown>>;
694
+ /** All records in recency order (most-recently-updated first). */
695
+ byRecency(): ReadonlyArray<IMemoryRecord<unknown>>;
696
+ /**
697
+ * The ids of records whose `links` point AT `target` (inbound edges).
698
+ * The seed map for B2 link-traversal.
699
+ */
700
+ backlinks(target: MemoryId): ReadonlyArray<MemoryId>;
701
+ }
702
+
703
+ /**
704
+ * Query criteria for {@link MemoryObservationStore.query}. All supplied criteria
705
+ * are AND-combined.
706
+ * @public
707
+ */
708
+ export declare interface IMemoryObservationQuery {
709
+ /** Only records with `seq > sinceSeq` (incremental paging cursor). */
710
+ readonly sinceSeq?: number;
711
+ /** Return at most this many records — the most-recent N, still oldest-first. */
712
+ readonly limit?: number;
713
+ /** Only records with `timestamp >= since`. */
714
+ readonly since?: number;
715
+ /** Only records with `timestamp <= until`. */
716
+ readonly until?: number;
717
+ /** Only records that touched this scope. */
718
+ readonly scope?: MemoryScopeKey;
719
+ /** Only records that targeted this kind. */
720
+ readonly kind?: Kind;
721
+ /** Only records of this phase. */
722
+ readonly phase?: MemoryObservationPhase;
723
+ /** Only records with this outcome. */
724
+ readonly outcome?: MemoryObservationOutcome;
725
+ }
726
+
727
+ /**
728
+ * A single audit record produced by an observed store (or retriever) operation.
729
+ *
730
+ * @remarks
731
+ * `seq` and `timestamp` are assigned by the firing authority (the store) before
732
+ * fan-out, so the same record carries the same `seq` across every observer it
733
+ * lands in. `seq` is strictly increasing per authority, satisfying the
734
+ * `RetainingRingBuffer` cursor contract that {@link MemoryObservationStore}
735
+ * relies on.
736
+ * @public
737
+ */
738
+ export declare interface IMemoryObservationRecord {
739
+ /**
740
+ * Monotonic 1-based sequence number assigned by the firing authority, stable
741
+ * across a store's ring eviction. The ordering / paging key.
742
+ */
743
+ readonly seq: number;
744
+ /** Milliseconds since epoch when the firing authority produced the record. */
745
+ readonly timestamp: number;
746
+ /** Which operation this record describes. */
747
+ readonly phase: MemoryObservationPhase;
748
+ /** The scope the operation touched, when resolvable. */
749
+ readonly scope?: MemoryScopeKey;
750
+ /** The record id the operation touched, when resolvable. */
751
+ readonly id?: MemoryId;
752
+ /** The kind the operation targeted, when known. */
753
+ readonly kind?: Kind;
754
+ /** Whether the operation succeeded. */
755
+ readonly outcome: MemoryObservationOutcome;
756
+ /** Present on failure: the failure `Result`'s message. */
757
+ readonly error?: string;
758
+ /** Structured provenance of the write, when the operation carried one. */
759
+ readonly provenance?: IProvenance;
760
+ /**
761
+ * For `'retrieve'` observations: an opaque snapshot of the query that drove
762
+ * the retrieval. Carried verbatim; never interpreted by the store.
763
+ */
764
+ readonly querySnapshot?: Readonly<Record<string, unknown>>;
765
+ }
766
+
767
+ /**
768
+ * Construction options for {@link MemoryObservationStore.create}.
769
+ * @public
770
+ */
771
+ export declare interface IMemoryObservationStoreCreateParams {
772
+ /**
773
+ * Maximum number of observation records retained before the oldest is
774
+ * overwritten. Defaults to `1000`. Must be a positive integer if supplied.
775
+ */
776
+ readonly maxRecords?: number;
777
+ }
778
+
779
+ /**
780
+ * Single-method async observer hook. The store fires `observe` once per public
781
+ * `get` / `put` / `delete` call when observers are wired.
782
+ *
783
+ * @remarks
784
+ * Observer errors never affect the store operation — the store swallows a
785
+ * failed `Result` or a thrown / rejected `observe`, logging it to the injected
786
+ * diagnostic logger at `warn`.
787
+ * @public
788
+ */
789
+ export declare interface IMemoryObserver {
790
+ /**
791
+ * When `true`, the store dispatches `observe` without awaiting it, so a slow
792
+ * remote observer (SIEM, network sink) does not extend the store operation's
793
+ * latency. Defaults to `false` (awaited), which is correct for the cheap
794
+ * in-memory default {@link MemoryObservationStore}. Errors are swallowed
795
+ * either way.
796
+ */
797
+ readonly fireAndForget?: boolean;
798
+ /**
799
+ * Receives a fully-formed observation record.
800
+ * @param record - The observation record.
801
+ * @returns A `Result` whose failure is swallowed (logged to the store's
802
+ * diagnostic logger). A rejected promise is likewise swallowed.
803
+ */
804
+ observe(record: IMemoryObservationRecord): Promise<Result<unknown>>;
805
+ }
806
+
807
+ /**
808
+ * A retrieval query. Every field is optional; an empty query is the "recency
809
+ * over everything" request. `semantic` and `asOf` are present from day one (the
810
+ * no-resignature guarantee): a backend that adds semantic or temporal recall
811
+ * sets the matching capability flag, with no interface change.
812
+ * @public
813
+ */
814
+ export declare interface IMemoryQuery {
815
+ /** Restrict to records in this scope. */
816
+ readonly scope?: MemoryScopeKey;
817
+ /** Restrict to records carrying this tag (exact match). */
818
+ readonly tag?: Tag;
819
+ /** Restrict to records of this kind. */
820
+ readonly kind?: Kind;
821
+ /** Restrict to records linked FROM this id (outbound). */
822
+ readonly linkedFrom?: MemoryId;
823
+ /** Restrict to records linked TO this id (inbound / backlinks). */
824
+ readonly linkedTo?: MemoryId;
825
+ /** BFS hop count for link traversal. Default: 1. */
826
+ readonly hops?: number;
827
+ /**
828
+ * Text query for semantic / vector recall. If set and the retriever's
829
+ * `supportsSemanticRecall` is `false`, the retriever returns a loud
830
+ * `Result.fail` ({@link SEMANTIC_UNWIRED_MESSAGE}) — never a silent empty.
831
+ */
832
+ readonly semantic?: string;
833
+ /** Top-K for semantic recall. Default: 10. */
834
+ readonly topK?: number;
835
+ /**
836
+ * As-of epoch ms for temporal "valid at" queries. If set and the retriever's
837
+ * `supportsTemporalQuery` is `false`, the retriever returns a loud
838
+ * `Result.fail` — never a silent empty.
839
+ */
840
+ readonly asOf?: number;
841
+ /** Maximum records to return. Applied after all other filters. */
842
+ readonly limit?: number;
843
+ /** Arbitrary predicate applied after the scope / kind / tag pre-filter. */
844
+ readonly filter?: (record: IMemoryRecord<unknown>) => boolean;
845
+ }
846
+
847
+ /**
848
+ * A complete memory record: the invariant {@link IMemoryEnvelope} plus the
849
+ * typed, per-kind body. The store's public surface uses
850
+ * `IMemoryRecord<unknown>`; consumers narrow `TBody` by checking
851
+ * `envelope.kind` and validating through the registered Converter.
852
+ * @public
853
+ */
854
+ export declare interface IMemoryRecord<TBody = unknown> {
855
+ /** The invariant identity + transaction-time envelope. */
856
+ readonly envelope: IMemoryEnvelope;
857
+ /** The per-kind, Converter-validated body. */
858
+ readonly body: TBody;
859
+ }
860
+
861
+ /**
862
+ * The minimal record-source surface {@link InMemoryCosineIndex.rebuild} reads to
863
+ * re-embed an entire vault. {@link IMemoryStore} satisfies it structurally (its
864
+ * `list` accepts an optional filter, which is assignable to this no-argument
865
+ * shape), so a consumer passes the store directly — without the vector packlet
866
+ * taking a dependency on the store packlet (which depends on the vector packlet
867
+ * for {@link IVectorIndex}, so the reverse import would be a cycle).
868
+ * @public
869
+ */
870
+ export declare interface IMemoryRecordSource {
871
+ /** List every record in the vault. */
872
+ list(): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
873
+ }
874
+
875
+ /**
876
+ * The retrieval contract. A retriever exposes its {@link
877
+ * IMemoryRetrieverCapabilities | capabilities} and answers
878
+ * {@link IMemoryRetriever.retrieve | queries}, degrading loudly (never silently
879
+ * empty) when a requested capability is not wired.
880
+ * @public
881
+ */
882
+ export declare interface IMemoryRetriever {
883
+ /** The capabilities this retriever exposes. Probe before dispatch. */
884
+ readonly capabilities: IMemoryRetrieverCapabilities;
885
+ /**
886
+ * Retrieve records matching `query`. Returns a `Result.fail` with a
887
+ * diagnostic message when the query requests a capability this retriever does
888
+ * not support (never an empty success).
889
+ */
890
+ retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
891
+ }
892
+
893
+ /**
894
+ * The capabilities a retriever exposes. A consumer probes these before
895
+ * dispatching a query so it never silently gets an empty result for a
896
+ * capability the retriever does not implement.
897
+ * @public
898
+ */
899
+ export declare interface IMemoryRetrieverCapabilities {
900
+ /** Semantic / vector recall is operational (an {@link IVectorIndex} is wired). */
901
+ readonly supportsSemanticRecall: boolean;
902
+ /** Temporal "as-of" queries are operational (a temporal index is wired). */
903
+ readonly supportsTemporalQuery: boolean;
904
+ /** Link traversal is supported (an in-memory backlink index is present). */
905
+ readonly supportsLinkTraversal: boolean;
906
+ }
907
+
908
+ /**
909
+ * The writable, FileTree-backed, content-hash-deduped memory store.
910
+ * @public
911
+ */
912
+ export declare interface IMemoryStore {
913
+ /**
914
+ * Keyed read by entity id. Resolves `entityId` to a storage address via the
915
+ * registered {@link IIdentityCodec} for `kind`. Returns `undefined` when no
916
+ * record exists.
917
+ */
918
+ get(kind: Kind, entityId: EntityId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
919
+ /**
920
+ * Direct read by `(scope, MemoryId)`. Returns `undefined` when not found.
921
+ */
922
+ getById(scope: MemoryScopeKey, id: MemoryId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
923
+ /**
924
+ * List records, filtered in-memory over the derived index.
925
+ */
926
+ list(filter?: IMemoryStoreListFilter): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
927
+ /**
928
+ * Write a record. Validates the body, computes a content hash, deduplicates
929
+ * (scope-wide, before policy), applies the kind's {@link IWritePolicy}, stamps
930
+ * transaction-time metadata (`created` / `updated` / `seq` / `contentHash`),
931
+ * writes the file, and patches the index. Returns the written record — or the
932
+ * existing record unchanged on a dedup no-op.
933
+ */
934
+ put(record: IMemoryRecord<unknown>): Promise<Result<IMemoryRecord<unknown>>>;
935
+ /**
936
+ * Delete a record by `(kind, entityId)`. Non-temporal kinds physically delete
937
+ * the file. Returns the {@link MemoryId} of the deleted record.
938
+ */
939
+ delete(kind: Kind, entityId: EntityId): Promise<Result<MemoryId>>;
940
+ }
941
+
942
+ /**
943
+ * Filter for {@link IMemoryStore.list}. All present fields are ANDed together.
944
+ * @public
945
+ */
946
+ export declare interface IMemoryStoreListFilter {
947
+ /** Restrict to records in this scope. */
948
+ readonly scope?: MemoryScopeKey;
949
+ /** Restrict to records of this kind. */
950
+ readonly kind?: Kind;
951
+ /** Restrict to records carrying this tag (exact match). */
952
+ readonly tag?: Tag;
953
+ /**
954
+ * For temporal kinds: return only records valid at this epoch ms. No-op in
955
+ * B1 (no temporal kinds wired).
956
+ */
957
+ readonly asOf?: number;
958
+ }
959
+
960
+ /**
961
+ * Strategy for combining the result sets of the retrievers a
962
+ * {@link HybridRetriever} composes. Injectable so a consumer can weight,
963
+ * re-rank, or intersect instead of the default union.
964
+ * @public
965
+ */
966
+ export declare interface IMergeStrategy {
967
+ /**
968
+ * Merge the per-retriever result sets into a single ordered result.
969
+ * @param resultSets - One entry per composed retriever, in composition order.
970
+ */
971
+ merge(resultSets: ReadonlyArray<ReadonlyArray<IMemoryRecord<unknown>>>): Result<ReadonlyArray<IMemoryRecord<unknown>>>;
972
+ }
973
+
974
+ /**
975
+ * Whether an indexed entry satisfies a query's scope / kind / tag / predicate
976
+ * pre-filter (the axes shared by every v1 retriever). The `semantic` / `asOf` /
977
+ * link axes are NOT applied here — those are each retriever's own concern.
978
+ * @public
979
+ */
980
+ export declare function indexedRecordMatchesQuery(entry: IIndexedMemoryRecord, query: IMemoryQuery): boolean;
981
+
982
+ /**
983
+ * The brute-force, in-memory cosine {@link IVectorIndex}. Stores one
984
+ * `Float32Array` per record and answers a query by computing cosine similarity
985
+ * against every stored vector, returning the top-k by descending score.
986
+ *
987
+ * @remarks
988
+ * This is the **complete** vector implementation for the fgv regime — large-N is
989
+ * explicitly out of scope (the seam stays open for a consumer to swap an external
990
+ * ANN backend once N grows beyond "thousands of records"). No external dependency
991
+ * and no ANN structure: a linear scan over a few thousand vectors is well within
992
+ * an interactive budget.
993
+ *
994
+ * The index has a single dimension established by the first vector added; every
995
+ * subsequent `add` and every `query` vector must match that dimension or fail
996
+ * loudly — a mismatched dimension is an embedder-wiring bug, never a silent
997
+ * zero-similarity result. {@link InMemoryCosineIndex.rebuild | rebuild} clears
998
+ * the index, so a re-embed with a different model (hence dimension) is supported.
999
+ *
1000
+ * Persistence (a JSON sidecar) is deliberately out of scope for this layer — the
1001
+ * index is in-memory and rebuilt from the store via `rebuild`; a sidecar is a
1002
+ * future nicety.
1003
+ * @public
1004
+ */
1005
+ export declare class InMemoryCosineIndex implements IVectorIndex {
1006
+ private readonly _vectors;
1007
+ /** The dimension of every stored vector; `undefined` until the first `add`. */
1008
+ private _dimension;
1009
+ private constructor();
1010
+ /** The number of vectors currently held. */
1011
+ get size(): number;
1012
+ /** Family-convention factory. */
1013
+ static create(): Result<InMemoryCosineIndex>;
1014
+ /** {@inheritDoc IVectorIndex.add} */
1015
+ add(id: MemoryId, vector: Float32Array): Promise<Result<string>>;
1016
+ /** {@inheritDoc IVectorIndex.remove} */
1017
+ remove(id: MemoryId): Promise<Result<MemoryId>>;
1018
+ /** {@inheritDoc IVectorIndex.query} */
1019
+ query(vector: Float32Array, topK: number): Promise<Result<ReadonlyArray<IVectorQueryHit>>>;
1020
+ /**
1021
+ * Re-embed every record from `source` and rebuild the index from scratch.
1022
+ * Clears the current contents (and the established dimension) first, so a
1023
+ * re-embed with a different model is supported. Returns the number of vectors
1024
+ * indexed.
1025
+ *
1026
+ * On any failure (list, embed, or add) the index is rolled back to empty
1027
+ * rather than left in a partially-rebuilt state — a caller that retries a query
1028
+ * after a failed rebuild sees a clean empty index, never a half-populated one.
1029
+ *
1030
+ * @param source - The record source to re-embed (an {@link IMemoryStore}
1031
+ * satisfies this structurally).
1032
+ * @param embed - The embedder applied to each record.
1033
+ */
1034
+ rebuild(source: IMemoryRecordSource, embed: MemoryEmbedder): Promise<Result<number>>;
1035
+ /** Empty the index and forget the established dimension. */
1036
+ private _reset;
1037
+ /** The Euclidean magnitude (L2 norm) of a vector. */
1038
+ private static _magnitude;
1039
+ /**
1040
+ * Cosine similarity between the query (whose magnitude is precomputed once and
1041
+ * reused across the scan) and a stored vector. A zero-magnitude vector on
1042
+ * either side yields `0` rather than `NaN` — a degenerate vector is simply
1043
+ * maximally dissimilar, not an error.
1044
+ */
1045
+ private static _cosine;
1046
+ }
1047
+
1048
+ /**
1049
+ * Structured provenance for a record or an edge. Never a flat enum — the
1050
+ * `[key: string]: unknown` index signature lets a consumer attach an opaque
1051
+ * domain payload (e.g. PersonAIlity's sentiment / epistemic blocks) without
1052
+ * changing this interface, while still satisfying the no-`any` rule.
1053
+ * @public
1054
+ */
1055
+ export declare interface IProvenance {
1056
+ /** Where the attribution came from. */
1057
+ readonly source: ProvenanceSource;
1058
+ /** Optional human or agent identifier responsible for the write. */
1059
+ readonly by?: string;
1060
+ /** Optional model identifier, when a model produced the content. */
1061
+ readonly model?: string;
1062
+ /** Optional confidence in `[0, 1]`. */
1063
+ readonly confidence?: number;
1064
+ /** Back-link to the source experience record. Enables the cross-kind provenance spine. */
1065
+ readonly derivedFrom?: MemoryId;
1066
+ /** Opaque extension payload — consumer-owned, never interpreted by the store. */
1067
+ readonly [key: string]: unknown;
1068
+ }
1069
+
1070
+ /**
1071
+ * The semantic backend wired into a {@link SemanticRetriever}: the vector index
1072
+ * to query and the embedder that turns the query text into a vector. Both are
1073
+ * required together — a vector index is useless without a way to embed the
1074
+ * query, so {@link SemanticRetriever.create} treats them as one unit.
1075
+ * @public
1076
+ */
1077
+ export declare interface ISemanticBackend {
1078
+ /** The vector index to query. */
1079
+ readonly vectorIndex: IVectorIndex;
1080
+ /** Turns the query text into a vector. */
1081
+ readonly embedQuery: QueryEmbedder;
1082
+ }
1083
+
1084
+ /**
1085
+ * Construction options for {@link SemanticRetriever.create}.
1086
+ * @public
1087
+ */
1088
+ export declare interface ISemanticRetrieverCreateParams {
1089
+ /** The record index, used to resolve vector hits back to full records. */
1090
+ readonly index: IMemoryIndex;
1091
+ /**
1092
+ * The semantic backend. When absent, the retriever reports
1093
+ * `supportsSemanticRecall: false` and a `query.semantic` request degrades
1094
+ * loudly ({@link SEMANTIC_UNWIRED_MESSAGE}) rather than returning empty.
1095
+ */
1096
+ readonly backend?: ISemanticBackend;
1097
+ }
1098
+
1099
+ /**
1100
+ * Optional bi-temporal validity block on an envelope. Present only on
1101
+ * temporal kinds; absent = zero cost for atemporal kinds.
1102
+ * @public
1103
+ */
1104
+ export declare interface ITemporalBlock {
1105
+ /** World-truth validity start (epoch ms). */
1106
+ readonly valid_at?: number;
1107
+ /** World-truth validity end (epoch ms). `null` = still valid. */
1108
+ readonly invalid_at?: number | null;
1109
+ }
1110
+
1111
+ /**
1112
+ * The vector-index seam an embedding backend implements to make
1113
+ * {@link SemanticRetriever | semantic recall} operational.
1114
+ *
1115
+ * @remarks
1116
+ * Vectors cross this seam as `Float32Array` (the in-memory representation an
1117
+ * embedding model produces); `number[]` is reserved for the JSON-wire edges
1118
+ * (e.g. a provider's embedding response). The in-package brute-force cosine
1119
+ * implementation is {@link InMemoryCosineIndex}; a consumer can swap an external
1120
+ * ANN backend behind the same seam once N grows beyond the in-memory regime.
1121
+ *
1122
+ * Every operation returns a `Result` (async, since a real backend does I/O) so
1123
+ * failure is explicit and never throws across the seam.
1124
+ * @public
1125
+ */
1126
+ export declare interface IVectorIndex {
1127
+ /**
1128
+ * Add (or replace) the embedding for `id`. Returns the opaque
1129
+ * {@link IMemoryEnvelope.embeddingRef | embeddingRef} the store stamps onto
1130
+ * the envelope so a later read knows the record is embedded.
1131
+ */
1132
+ add(id: MemoryId, vector: Float32Array): Promise<Result<string>>;
1133
+ /**
1134
+ * Remove the embedding for `id`. Returns the removed id. Idempotent — removing
1135
+ * an id with no embedding still succeeds (returns the id).
1136
+ */
1137
+ remove(id: MemoryId): Promise<Result<MemoryId>>;
1138
+ /**
1139
+ * Return the `topK` nearest records to `vector`, in descending score order.
1140
+ */
1141
+ query(vector: Float32Array, topK: number): Promise<Result<ReadonlyArray<IVectorQueryHit>>>;
1142
+ }
1143
+
1144
+ /**
1145
+ * A single hit returned by {@link IVectorIndex.query}: the matched record id and
1146
+ * the backend's similarity score (higher = more similar; the exact scale is
1147
+ * backend-defined). Hits are returned in descending score order.
1148
+ * @public
1149
+ */
1150
+ export declare interface IVectorQueryHit {
1151
+ /** The id of the matched record. */
1152
+ readonly id: MemoryId;
1153
+ /** Backend similarity score; higher is more similar. */
1154
+ readonly score: number;
1155
+ }
1156
+
1157
+ /**
1158
+ * A per-kind write policy, injected at store construction. Invoked AFTER
1159
+ * content-hash dedup (dedup is always pre-policy). The policy decides
1160
+ * admission and, on update, applies a JSON Merge Patch (RFC-7386) restricted
1161
+ * to the declared mutable fields.
1162
+ * @public
1163
+ */
1164
+ export declare interface IWritePolicy {
1165
+ /**
1166
+ * Names of the fields a merge-patch update may touch. Fields outside this
1167
+ * list are immutable; a change to one constitutes a new entity (its
1168
+ * `contentHash` differs). Used by {@link IWritePolicy.applyUpdate} to
1169
+ * restrict which fields the patch applies.
1170
+ */
1171
+ readonly mutableFields: ReadonlyArray<string>;
1172
+ /**
1173
+ * The granularity at which the store deduplicates an incoming write for this
1174
+ * kind. Optional; when absent the store applies {@link DEFAULT_DEDUP_SCOPE}
1175
+ * (`'entity'`). See {@link DedupScope}.
1176
+ */
1177
+ readonly dedupScope?: DedupScope;
1178
+ /**
1179
+ * Determine whether the incoming record is admitted.
1180
+ * @param incoming - The record about to be written.
1181
+ * @param existing - The admission cohort the kind's cap applies to: the
1182
+ * records in the same scope of the same kind, EXCLUDING the record at
1183
+ * `incoming`'s target id. Empty on a first write into an empty cohort.
1184
+ * Excluding the target id makes the post-write count uniform
1185
+ * (`existing.length + 1`) across first-writes and same-id updates. A
1186
+ * last-write-wins policy that has no cap ignores this argument.
1187
+ * @returns A {@link AdmissionDecision}.
1188
+ */
1189
+ admit(incoming: IMemoryRecord<unknown>, existing: ReadonlyArray<IMemoryRecord<unknown>>): Result<AdmissionDecision>;
1190
+ /**
1191
+ * Apply a JSON Merge Patch (RFC-7386) to the mutable fields of an existing
1192
+ * record. Called when admission is `accept` AND a record with the same
1193
+ * `entityId` already exists (an update, not a first write).
1194
+ *
1195
+ * @param existing - The current persisted record.
1196
+ * @param patch - A partial JSON object in Merge Patch format. `null`
1197
+ * deletes the corresponding key; arrays replace wholesale; nested objects
1198
+ * deep-merge. Only keys in {@link IWritePolicy.mutableFields} are applied.
1199
+ * @returns The updated record (envelope + body).
1200
+ */
1201
+ applyUpdate(existing: IMemoryRecord<unknown>, patch: Record<string, unknown>): Result<IMemoryRecord<unknown>>;
1202
+ }
1203
+
1204
+ /**
1205
+ * Join a YAML frontmatter string and a body into the canonical
1206
+ * `---\n<yaml>\n---\n<body>` memory-file format.
1207
+ * @public
1208
+ */
1209
+ export declare function joinFrontmatter(frontmatter: string, body: string): string;
1210
+
1211
+ /**
1212
+ * Open-vocabulary record classifier. Consumers register one body
1213
+ * {@link https://www.npmjs.com/package/@fgv/ts-utils | Converter} per kind.
1214
+ * @public
1215
+ */
1216
+ export declare type Kind = Brand<string, 'Kind'>;
1217
+
1218
+ /**
1219
+ /**
1220
+ * Identity codec for the knowledge kind family. A knowledge entity is keyed
1221
+ * by its consumer-supplied `docId`, which is used verbatim as the filename
1222
+ * stem under the flat `knowledge` scope.
1223
+ *
1224
+ * @remarks
1225
+ * - `encode`: scope = `knowledge`, idStem = `docId`, `isVersioned = false`.
1226
+ * - `decode`: brands the stem back to an {@link EntityId}.
1227
+ * - Escaping: the `docId` must match the POSIX portable filename set.
1228
+ * - Layout: `vault/knowledge/<docId>.md`.
1229
+ * @public
1230
+ */
1231
+ export declare class KnowledgeIdentityCodec implements IIdentityCodec {
1232
+ /** The fixed scope for every knowledge entity. */
1233
+ static readonly scope: MemoryScopeKey;
1234
+ /** {@inheritDoc IIdentityCodec.encode} */
1235
+ encode(entityId: EntityId): Result<IIdentityCodecResult>;
1236
+ /** {@inheritDoc IIdentityCodec.decode} */
1237
+ decode(scope: MemoryScopeKey, encodedStem: string): Result<EntityId>;
1238
+ /** {@inheritDoc IIdentityCodec.verifyRoundTrip} */
1239
+ verifyRoundTrip(scope: MemoryScopeKey, stem: string): Result<true>;
1240
+ }
1241
+
1242
+ /**
1243
+ * Last-write-wins write policy for the knowledge kind family. Admission
1244
+ * always accepts (no cap, no cull); updates apply an RFC-7386 merge patch
1245
+ * restricted to the knowledge mutable surface.
1246
+ *
1247
+ * @remarks
1248
+ * **Merge-surface pin (resolves design-lock §5.3's body-vs-envelope muddle).**
1249
+ * The declared `mutableFields` span both axes of a record: `body` is the
1250
+ * per-kind body, while `tags` / `links` / `provenance` / `embeddingRef` live
1251
+ * on the {@link IMemoryEnvelope}. `applyUpdate` projects exactly those fields
1252
+ * — each read from its canonical location — into a single record-level JSON
1253
+ * view, runs the merge over that view, then rebuilds a coherent record. The
1254
+ * identity and transaction-time envelope fields (`id`, `entityId`, `kind`,
1255
+ * `created`, `updated`, `seq`, `contentHash`) are NOT mutable and are
1256
+ * preserved verbatim; the store stamps `updated` / `seq` on write.
1257
+ * @public
1258
+ */
1259
+ export declare class KnowledgeLwwPolicy implements IWritePolicy {
1260
+ /**
1261
+ * The knowledge mutable surface: the body plus the envelope metadata a
1262
+ * consumer may revise without minting a new entity.
1263
+ */
1264
+ readonly mutableFields: ReadonlyArray<string>;
1265
+ /**
1266
+ * Knowledge dedups scope-wide: an identical `{ kind, body, links }` triple
1267
+ * anywhere in the `knowledge` scope — even under a different `docId` — is a
1268
+ * no-op. Declared explicitly so the B1 content-dedup behavior (and its tests)
1269
+ * are unchanged by the {@link DedupScope} amendment.
1270
+ */
1271
+ readonly dedupScope: DedupScope;
1272
+ /** Deep-clones the mutable view without RFC-7386 null-deletion semantics. */
1273
+ private readonly _cloneEditor;
1274
+ /** Applies the RFC-7386 merge patch. */
1275
+ private readonly _mergeEditor;
1276
+ private constructor();
1277
+ /**
1278
+ * Family-convention factory. Constructs the shared `JsonEditor` instances
1279
+ * (one for cloning, one for the RFC-7386 merge), both with the template /
1280
+ * conditional / multivalue / reference rules disabled (empty rules array).
1281
+ */
1282
+ static create(): Result<KnowledgeLwwPolicy>;
1283
+ /** {@inheritDoc IWritePolicy.admit} */
1284
+ admit(__incoming: IMemoryRecord<unknown>, __existing: ReadonlyArray<IMemoryRecord<unknown>>): Result<AdmissionDecision>;
1285
+ /** {@inheritDoc IWritePolicy.applyUpdate} */
1286
+ applyUpdate(existing: IMemoryRecord<unknown>, patch: Record<string, unknown>): Result<IMemoryRecord<unknown>>;
1287
+ /**
1288
+ * Reassemble a record from the merged mutable view. `body` / `tags` /
1289
+ * `links` / `provenance` are required and may not be deleted by a patch.
1290
+ * `embeddingRef` is optional: when it is absent from the merged view —
1291
+ * because the existing record never carried it OR a `null` patch deleted it
1292
+ * (RFC-7386) — it is restored as `undefined` (absent), NOT `null`. This keeps
1293
+ * an originally-absent `embeddingRef` from silently flipping to `null` on an
1294
+ * unrelated update, so the field round-trips hash-stably through the store's
1295
+ * content-hash recomputation.
1296
+ */
1297
+ private _rebuild;
1298
+ }
1299
+
1300
+ /**
1301
+ * Truncate to `query.limit` records (a no-op when `limit` is absent). Applied
1302
+ * last, after ordering, so it always takes the top-N of the ordered result. A
1303
+ * non-positive `limit` is public query input and means "no records" — it returns
1304
+ * an empty array rather than letting a negative value slip into `slice`.
1305
+ * @public
1306
+ */
1307
+ export declare function limitRecords(records: ReadonlyArray<IMemoryRecord<unknown>>, limit?: number): ReadonlyArray<IMemoryRecord<unknown>>;
1308
+
1309
+ /**
1310
+ * The loud-degradation message returned when a link-traversal query supplies no
1311
+ * seed (`linkedFrom` / `linkedTo`).
1312
+ * @public
1313
+ */
1314
+ export declare const LINK_TRAVERSAL_NO_SEED_MESSAGE: string;
1315
+
1316
+ /**
1317
+ * The loud-degradation message a retriever returns when a link-traversal axis
1318
+ * (`linkedFrom` / `linkedTo` / `hops`) is requested but no backlink index is
1319
+ * wired.
1320
+ * @public
1321
+ */
1322
+ export declare const LINK_TRAVERSAL_UNWIRED_MESSAGE: string;
1323
+
1324
+ /**
1325
+ * Breadth-first link-traversal retriever. From a seed {@link MemoryId} it walks
1326
+ * the link graph up to `query.hops` levels and returns the records reached
1327
+ * (excluding the seed), recency-ordered and limited.
1328
+ *
1329
+ * @remarks
1330
+ * - **Direction.** `linkedFrom` walks OUTBOUND edges (each record's
1331
+ * `envelope.links[].target`); `linkedTo` walks INBOUND edges (the index's
1332
+ * `backlinks`). Exactly one is the seed; `linkedFrom` wins if both are set.
1333
+ * - **Bound + cycle safety.** Traversal is bounded by `hops` (default `1` — a
1334
+ * single hop) and a visited-set guard. The graph is keyed by bare
1335
+ * string {@link MemoryId}s, so a `Set<string>` visited-set is the exact,
1336
+ * collision-free cycle key — no structural hashing (e.g. `Crc32Normalizer`) is
1337
+ * needed. A self-loop or any multi-hop cycle terminates because a revisited id
1338
+ * is never re-expanded.
1339
+ * - **Post-filter.** The scope / kind / tag / predicate axes of the query are
1340
+ * applied to the reached records (the link axes are the traversal itself).
1341
+ * @public
1342
+ */
1343
+ export declare class LinkTraversalRetriever implements IMemoryRetriever {
1344
+ private readonly _index;
1345
+ private constructor();
1346
+ /** Family-convention factory. */
1347
+ static create(index: IMemoryIndex): Result<LinkTraversalRetriever>;
1348
+ /** {@inheritDoc IMemoryRetriever.capabilities} */
1349
+ get capabilities(): IMemoryRetrieverCapabilities;
1350
+ /** {@inheritDoc IMemoryRetriever.retrieve} */
1351
+ retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
1352
+ /** Run the bounded, cycle-safe BFS and post-filter the reached records. */
1353
+ private _traverse;
1354
+ /**
1355
+ * Group the index's entries by bare {@link MemoryId}. An id can map to more
1356
+ * than one entry when distinct scopes reuse a filename stem (e.g. `turn-0` in
1357
+ * two conversations), so the value is an array.
1358
+ *
1359
+ * @remarks
1360
+ * **Design note (links are globally-scoped identifiers in this phase).** An
1361
+ * {@link IEdge.target} is a bare `MemoryId`, not a `(scope, id)` pair, so
1362
+ * traversal resolves a target across ALL scopes that hold that id. When two
1363
+ * scopes reuse a stem, following an edge to it reaches every match. This
1364
+ * mirrors the `backlinks` index, which is also keyed by bare id. Scope-
1365
+ * qualified link resolution is intentionally out of scope for Phase C and
1366
+ * would be an additive change here (and to {@link IEdge} / the index).
1367
+ */
1368
+ private _indexById;
1369
+ /** Outbound neighbors: the targets of every edge on the records with this id. */
1370
+ private _outbound;
1371
+ /** Inbound neighbors: the ids whose edges point AT this id (the backlinks). */
1372
+ private _inbound;
1373
+ }
1374
+
1375
+ /**
1376
+ * Open-vocabulary link-relation type for an attributed {@link IEdge}.
1377
+ * @public
1378
+ */
1379
+ export declare type LinkType = Brand<string, 'LinkType'>;
1380
+
1381
+ /**
1382
+ * Identity codec for the long-term-memory (LTM) kind family. An LTM entity is
1383
+ * keyed by its `conversationId`, used verbatim as the filename stem under the
1384
+ * flat `conversations` scope.
1385
+ *
1386
+ * @remarks
1387
+ * - `encode`: scope = `conversations`, idStem = `conversationId`, `isVersioned = false`.
1388
+ * - `decode`: brands the stem back to an {@link EntityId}.
1389
+ * - Escaping: the `conversationId` must match the POSIX portable filename set.
1390
+ * - Layout: `vault/conversations/<conversationId>.md`.
1391
+ *
1392
+ * An LTM file (`conversations/<id>.md`) and the MTM subtree
1393
+ * (`conversations/<id>/turn-N.md`) coexist — a file and a same-named directory
1394
+ * are independent on every supported FileTree backend.
1395
+ * @public
1396
+ */
1397
+ export declare class LtmIdentityCodec implements IIdentityCodec {
1398
+ /** The fixed scope for every LTM entity. */
1399
+ static readonly scope: MemoryScopeKey;
1400
+ /** {@inheritDoc IIdentityCodec.encode} */
1401
+ encode(entityId: EntityId): Result<IIdentityCodecResult>;
1402
+ /** {@inheritDoc IIdentityCodec.decode} */
1403
+ decode(scope: MemoryScopeKey, encodedStem: string): Result<EntityId>;
1404
+ /** {@inheritDoc IIdentityCodec.verifyRoundTrip} */
1405
+ verifyRoundTrip(scope: MemoryScopeKey, stem: string): Result<true>;
1406
+ }
1407
+
1408
+ /**
1409
+ * Bounded-ring write policy for the experience (memory) kind families.
1410
+ * Admission accepts until `maxRecords` is reached, then evicts the oldest
1411
+ * record(s) by `created` ascending (design-lock §5.3); updates apply the same
1412
+ * RFC-7386 merge patch as {@link KnowledgeLwwPolicy}, restricted to the declared
1413
+ * {@link IMemoryCapCullPolicyParams.mutableFields | mutableFields}.
1414
+ *
1415
+ * @remarks
1416
+ * - **Dedup scope.** Declares `dedupScope: 'entity'` — two distinct memory
1417
+ * entities (e.g. `turn-5` / `turn-9`) with identical `{ kind, body, links }`
1418
+ * never collapse; only an identical re-put of the SAME entity is a no-op.
1419
+ * - **Eviction boundary.** `admit` only DECIDES (returns the `MemoryId`s to
1420
+ * evict); the store executes the file deletions and index patches. The
1421
+ * `existing` cohort the cap counts against is whatever the store supplies to
1422
+ * `admit`.
1423
+ * @public
1424
+ */
1425
+ export declare class MemoryCapCullPolicy implements IWritePolicy {
1426
+ /** {@inheritDoc IWritePolicy.mutableFields} */
1427
+ readonly mutableFields: ReadonlyArray<string>;
1428
+ /** Experience kinds dedup per-entity (see the class remarks). */
1429
+ readonly dedupScope: DedupScope;
1430
+ /** The admission cap; `undefined` = no cap. */
1431
+ private readonly _maxRecords;
1432
+ /** Deep-clones the mutable view without RFC-7386 null-deletion semantics. */
1433
+ private readonly _cloneEditor;
1434
+ /** Applies the RFC-7386 merge patch. */
1435
+ private readonly _mergeEditor;
1436
+ private constructor();
1437
+ /**
1438
+ * Family-convention factory. Constructs the shared `JsonEditor` instances
1439
+ * (one for cloning, one for the RFC-7386 merge) with the same merge config as
1440
+ * {@link KnowledgeLwwPolicy} (`nullAsDelete` true, `arrayMergeBehavior`
1441
+ * `'replace'`, rules disabled).
1442
+ */
1443
+ static create(params: IMemoryCapCullPolicyParams): Result<MemoryCapCullPolicy>;
1444
+ /** {@inheritDoc IWritePolicy.admit} */
1445
+ admit(__incoming: IMemoryRecord<unknown>, existing: ReadonlyArray<IMemoryRecord<unknown>>): Result<AdmissionDecision>;
1446
+ /** {@inheritDoc IWritePolicy.applyUpdate} */
1447
+ applyUpdate(existing: IMemoryRecord<unknown>, patch: Record<string, unknown>): Result<IMemoryRecord<unknown>>;
1448
+ /**
1449
+ * Reassemble a record from the merged mutable view. Only the declared mutable
1450
+ * fields are taken from the merge; undeclared fields are preserved verbatim
1451
+ * from `existing`. A `null` patch that deletes a *declared mutable* required
1452
+ * field (`body` / `tags` / `links` / `provenance`) is an error — a required
1453
+ * field that is NOT declared mutable simply falls through to its `existing.*`
1454
+ * value and is never at risk. `embeddingRef`, when mutable, is restored as
1455
+ * `undefined` (absent) if the merge dropped it — same hash-stable semantics as
1456
+ * {@link KnowledgeLwwPolicy}.
1457
+ */
1458
+ private _rebuild;
1459
+ }
1460
+
1461
+ /**
1462
+ * Embeds a complete record into a vector for the store's embed-on-write hook.
1463
+ * Async and `Result`-returning, since a real embedder does a network call (cloud
1464
+ * provider) or in-process model inference. The consumer wires this — the core
1465
+ * package never calls an embedding provider directly, staying embedder-agnostic.
1466
+ * @public
1467
+ */
1468
+ export declare type MemoryEmbedder = (record: IMemoryRecord<unknown>) => Promise<Result<Float32Array>>;
1469
+
1470
+ /**
1471
+ * Stable file-stem identifier for a memory record. Equals the codec-produced
1472
+ * `idStem` and the on-disk filename stem (`verifyFilenameId` enforces the
1473
+ * round-trip).
1474
+ * @public
1475
+ */
1476
+ export declare type MemoryId = Brand<string, 'MemoryId'>;
1477
+
1478
+ /**
1479
+ * Default in-memory {@link IMemoryIndex}. Maintains the derived `byKind` /
1480
+ * `byTag` / `byRecency` / `backlinks` views incrementally; a `'put'` for an
1481
+ * already-indexed key first removes the prior entry's associations so a changed
1482
+ * kind / tag / link set never leaves a stale reference behind.
1483
+ * @public
1484
+ */
1485
+ export declare class MemoryIndex implements IMemoryIndex {
1486
+ /** Primary store: `(scope, id)` composite key → indexed entry. */
1487
+ private readonly _byKey;
1488
+ /** kind → set of composite keys. */
1489
+ private readonly _byKind;
1490
+ /** tag → set of composite keys. */
1491
+ private readonly _byTag;
1492
+ /**
1493
+ * link target id → (source composite key → source id). Keyed by the source's
1494
+ * `(scope, id)` composite — NOT its bare id — so two distinct source records
1495
+ * that share an id across scopes (e.g. `turn-0` in different conversations)
1496
+ * are tracked independently and removing one never drops the other's edge.
1497
+ */
1498
+ private readonly _backlinks;
1499
+ private constructor();
1500
+ /** Family-convention factory. */
1501
+ static create(): Result<MemoryIndex>;
1502
+ /**
1503
+ * The composite primary key for an entry: scope + id, NUL-separated. NUL
1504
+ * is excluded from both components (scope segments pass
1505
+ * `assertPortableFilenameStem`; `MemoryId` is portable-filename-safe), so it
1506
+ * is a collision-proof separator across every scope/id pair the codecs produce.
1507
+ */
1508
+ private static _keyOf;
1509
+ /** {@inheritDoc IMemoryIndex.rebuild} */
1510
+ rebuild(entries: ReadonlyArray<IIndexedMemoryRecord>): Result<number>;
1511
+ /** {@inheritDoc IMemoryIndex.patch} */
1512
+ patch(op: MemoryIndexPatchOp, entry: IIndexedMemoryRecord): Result<IIndexedMemoryRecord>;
1513
+ /** {@inheritDoc IMemoryIndex.entries} */
1514
+ entries(): ReadonlyArray<IIndexedMemoryRecord>;
1515
+ /** {@inheritDoc IMemoryIndex.byKind} */
1516
+ byKind(kind: Kind): ReadonlyArray<IMemoryRecord<unknown>>;
1517
+ /** {@inheritDoc IMemoryIndex.byTag} */
1518
+ byTag(tag: Tag): ReadonlyArray<IMemoryRecord<unknown>>;
1519
+ /** {@inheritDoc IMemoryIndex.byRecency} */
1520
+ byRecency(): ReadonlyArray<IMemoryRecord<unknown>>;
1521
+ /** {@inheritDoc IMemoryIndex.backlinks} */
1522
+ backlinks(target: MemoryId): ReadonlyArray<MemoryId>;
1523
+ /**
1524
+ * Resolve a set of composite keys to their records, ordered
1525
+ * most-recently-updated first (with a `seq` tiebreak so equal-`updated`
1526
+ * records sort deterministically).
1527
+ */
1528
+ private _recencyOrdered;
1529
+ /** Insert an entry and register all its derived associations. */
1530
+ private _add;
1531
+ /** Remove the entry at `key` (if present) and all its derived associations. */
1532
+ private _remove;
1533
+ /** Register `sourceId` (keyed by its composite `sourceKey`) as linking at `target`. */
1534
+ private _addBacklink;
1535
+ /** Drop the backlink from `sourceKey` to `target`, removing the target map when empty. */
1536
+ private _removeBacklink;
1537
+ /** Add `member` to the set at `mapKey`, creating the set on first use. */
1538
+ private _addToSetMap;
1539
+ /** Remove `member` from the set at `mapKey`, dropping the set when empty. */
1540
+ private _removeFromSetMap;
1541
+ }
1542
+
1543
+ /**
1544
+ * The mutation a {@link IMemoryIndex.patch | patch} applies: a record was
1545
+ * written (`'put'`) or removed (`'delete'`).
1546
+ * @public
1547
+ */
1548
+ export declare type MemoryIndexPatchOp = 'put' | 'delete';
1549
+
1550
+ /**
1551
+ * The outcome of the observed operation.
1552
+ * @public
1553
+ */
1554
+ export declare type MemoryObservationOutcome = 'success' | 'failure';
1555
+
1556
+ /**
1557
+ * The store/retriever operation an observation record describes.
1558
+ *
1559
+ * @remarks
1560
+ * `'read'` / `'write'` / `'delete'` are fired post-op by
1561
+ * {@link FileTreeMemoryStore} (on `get` / `put` / `delete` respectively) when
1562
+ * observers are wired. `'retrieve'` is reserved for retriever-fired
1563
+ * observations; no B2 retriever fires one (a single seq authority per
1564
+ * observation store is the supported topology), so it never appears in B2 but
1565
+ * is part of the vocabulary so a future retriever-firing hook is additive.
1566
+ * @public
1567
+ */
1568
+ export declare type MemoryObservationPhase = 'read' | 'write' | 'delete' | 'retrieve';
1569
+
1570
+ /**
1571
+ * The default in-memory observation store: an {@link IMemoryObserver} that
1572
+ * retains the records it observes in a bounded ring and answers schema-aware
1573
+ * {@link MemoryObservationStore.query | queries} over them.
1574
+ *
1575
+ * @remarks
1576
+ * **Privacy posture — this store is most-permissive by design.** It retains
1577
+ * every field of every record verbatim, including any `provenance` and
1578
+ * `querySnapshot`. The library bakes in **no** redaction, retention, or
1579
+ * field-stripping policy — that is deployment policy, not library policy. A
1580
+ * deployment that must redact wraps this store with its own
1581
+ * {@link IMemoryObserver} that transforms records before forwarding, or
1582
+ * substitutes a different observer entirely. Size is the only bounded
1583
+ * dimension, via `maxRecords`.
1584
+ *
1585
+ * The store composes `RetainingRingBuffer` from `@fgv/ts-utils` (it does not
1586
+ * hand-roll a ring) and implements {@link IMemoryObserver} directly — `observe`
1587
+ * (the hook) and `query` (the read surface) live on the same class. Wire it via
1588
+ * {@link IFileTreeMemoryStoreCreateParams.observers}. `seq` and `timestamp` are
1589
+ * assigned by the firing authority (the store) before `observe`, so this store
1590
+ * never mints them.
1591
+ * @public
1592
+ */
1593
+ export declare class MemoryObservationStore implements IMemoryObserver {
1594
+ /**
1595
+ * The bounded ring of observed records. The firing authority assigns each
1596
+ * record's `seq`, so the ring's monotonic-`seq` cursor contract is satisfied
1597
+ * by that authority's per-instance counter.
1598
+ * @internal
1599
+ */
1600
+ private readonly _buffer;
1601
+ /**
1602
+ * @param buffer - The pre-constructed backing ring buffer.
1603
+ * @internal
1604
+ */
1605
+ private constructor();
1606
+ /**
1607
+ * The highest `seq` observed so far. Hold this value and pass it as
1608
+ * `sinceSeq` to {@link MemoryObservationStore.query | query} to page only
1609
+ * records observed afterward. Stable across ring eviction and
1610
+ * {@link MemoryObservationStore.clear | clear}.
1611
+ */
1612
+ get lastSeq(): number;
1613
+ /**
1614
+ * The number of records currently retained.
1615
+ */
1616
+ get size(): number;
1617
+ /**
1618
+ * Family-convention factory.
1619
+ * @param params - {@link IMemoryObservationStoreCreateParams | Construction options}.
1620
+ * @returns On success, a new store. Fails if `maxRecords` is supplied and is
1621
+ * not a positive integer.
1622
+ */
1623
+ static create(params?: IMemoryObservationStoreCreateParams): Result<MemoryObservationStore>;
1624
+ /**
1625
+ * {@inheritDoc IMemoryObserver.observe}
1626
+ */
1627
+ observe(record: IMemoryObservationRecord): Promise<Result<unknown>>;
1628
+ /**
1629
+ * Returns retained records, oldest-first, narrowed by the supplied criteria.
1630
+ * @param criteria - {@link IMemoryObservationQuery | AND-combined filter criteria}.
1631
+ * @returns The matching records, oldest-first.
1632
+ */
1633
+ query(criteria?: IMemoryObservationQuery): ReadonlyArray<IMemoryObservationRecord>;
1634
+ /**
1635
+ * Clears all retained records. Does NOT reset
1636
+ * {@link MemoryObservationStore.lastSeq | lastSeq}, so a held `sinceSeq`
1637
+ * cursor never re-sees a sequence number.
1638
+ */
1639
+ clear(): void;
1640
+ /**
1641
+ * Tests a record against the non-`seq`/`limit` criteria (those are applied by
1642
+ * the ring buffer itself).
1643
+ * @internal
1644
+ */
1645
+ private static _matches;
1646
+ }
1647
+
1648
+ /**
1649
+ * Scope path segment. May be multi-segment (`/`-separated) for kinds whose
1650
+ * codec maps an entity into a sub-tree (e.g. MTM: `conversations/<id>`). The
1651
+ * codec — not this brand — owns filename-safe escaping, so the converter
1652
+ * validates only the non-empty/length/whitespace hygiene shared by every
1653
+ * brand.
1654
+ * @public
1655
+ */
1656
+ export declare type MemoryScopeKey = Brand<string, 'MemoryScopeKey'>;
1657
+
1658
+ /**
1659
+ * Identity codec for the medium-term-memory (MTM) kind family. An MTM entity is
1660
+ * keyed by the colon-composite `<conversationId>:<turnIndex>` and maps into a
1661
+ * per-conversation subtree.
1662
+ *
1663
+ * @remarks
1664
+ * - `encode`: splits the entity id on `:`; scope =
1665
+ * `conversations/<conversationId>` (multi-segment), idStem = `turn-<turnIndex>`,
1666
+ * `isVersioned = false`.
1667
+ * - `decode`: reverses scope `conversations/<id>` + stem `turn-<N>` to the
1668
+ * composite `<id>:<N>`.
1669
+ * - Escaping: `conversationId` must match the POSIX portable filename set (so it
1670
+ * contains no `/` or `:`); `turnIndex` must be a non-negative integer string,
1671
+ * preserved verbatim so the round-trip is exact.
1672
+ * - Layout: `vault/conversations/<conversationId>/turn-<N>.md`. The `/` in the
1673
+ * scope is handled by the store's multi-segment scope resolver.
1674
+ *
1675
+ * **Verbatim turn index (caller-canonicalization note).** The turn index is
1676
+ * preserved exactly — `conv-1:7` and `conv-1:007` are DISTINCT entities mapping
1677
+ * to distinct files (`turn-7.md` / `turn-007.md`). Verbatim preservation is what
1678
+ * makes the round-trip exact, but it means a caller that formats turn indices
1679
+ * inconsistently (some zero-padded, some not) will silently mint separate
1680
+ * entities. Callers should canonicalize to one form (e.g. no leading zeros).
1681
+ * @public
1682
+ */
1683
+ export declare class MtmIdentityCodec implements IIdentityCodec {
1684
+ /** The top-level scope segment under which every MTM subtree lives. */
1685
+ static readonly rootScopeSegment: string;
1686
+ /** The fixed filename-stem prefix for a turn record. */
1687
+ static readonly turnStemPrefix: string;
1688
+ /** A non-negative integer string (the turn index), preserved verbatim. */
1689
+ private static readonly _turnIndexRe;
1690
+ /** {@inheritDoc IIdentityCodec.encode} */
1691
+ encode(entityId: EntityId): Result<IIdentityCodecResult>;
1692
+ /** {@inheritDoc IIdentityCodec.decode} */
1693
+ decode(scope: MemoryScopeKey, encodedStem: string): Result<EntityId>;
1694
+ /** {@inheritDoc IIdentityCodec.verifyRoundTrip} */
1695
+ verifyRoundTrip(scope: MemoryScopeKey, stem: string): Result<true>;
1696
+ /** Validate and extract the `conversationId` from a `conversations/<id>` scope. */
1697
+ private static _conversationIdFromScope;
1698
+ /** Validate and extract the turn-index digits from a `turn-<N>` stem. */
1699
+ private static _turnIndexFromStem;
1700
+ /** Assert a string is a non-negative integer (the turn index). */
1701
+ private static _assertTurnIndex;
1702
+ }
1703
+
1704
+ /**
1705
+ * The capabilities every non-semantic, non-temporal, non-link v1 retriever
1706
+ * exposes (all three flags `false`).
1707
+ * @public
1708
+ */
1709
+ export declare const NON_SEMANTIC_CAPABILITIES: IMemoryRetrieverCapabilities;
1710
+
1711
+ /**
1712
+ * Parse a complete memory file into a typed {@link IMemoryRecord}. Splits the
1713
+ * frontmatter, validates the envelope, and dispatches the body through the
1714
+ * registered Converter for the envelope's kind.
1715
+ * @public
1716
+ */
1717
+ export declare function parseMemoryFile(raw: string, registry: IBodyConverterRegistry): Result<IMemoryRecord<unknown>>;
1718
+
1719
+ /**
1720
+ * Converter for {@link IProvenance}. Validates the known fields and preserves
1721
+ * any extension keys verbatim (the `[key: string]: unknown` opaque payload),
1722
+ * so a round-trip never drops consumer-attached data.
1723
+ * @public
1724
+ */
1725
+ export declare const provenanceConverter: Converter<IProvenance>;
1726
+
1727
+ /**
1728
+ * Origin of a provenance attribution. Open vocabulary: the three named
1729
+ * sources are conventional, but the `(string & {})` arm admits any other
1730
+ * source string without resignature.
1731
+ * @public
1732
+ */
1733
+ export declare type ProvenanceSource = 'agent' | 'host-ingest' | 'human' | (string & {});
1734
+
1735
+ /**
1736
+ * Embeds a query string into a vector for {@link IVectorIndex.query}. Async and
1737
+ * `Result`-returning, since a real embedder does a network call.
1738
+ * @public
1739
+ */
1740
+ export declare type QueryEmbedder = (text: string) => Promise<Result<Float32Array>>;
1741
+
1742
+ /**
1743
+ * Recency comparator: most-recently-updated first, with a `seq` tiebreak so
1744
+ * equal-`updated` records sort deterministically. Mirrors the B1 index ordering.
1745
+ * @public
1746
+ */
1747
+ export declare function recencyCompare(a: IMemoryRecord<unknown>, b: IMemoryRecord<unknown>): number;
1748
+
1749
+ /**
1750
+ * Returns records matching the query's scope / kind / tag / predicate filters,
1751
+ * ordered most-recently-updated first. The universal v1 retriever — an empty
1752
+ * query returns the whole vault in recency order.
1753
+ * @public
1754
+ */
1755
+ export declare class RecencyRetriever implements IMemoryRetriever {
1756
+ private readonly _index;
1757
+ private constructor();
1758
+ /** {@inheritDoc IMemoryRetriever.capabilities} */
1759
+ get capabilities(): IMemoryRetrieverCapabilities;
1760
+ /** Family-convention factory. */
1761
+ static create(index: IMemoryIndex): Result<RecencyRetriever>;
1762
+ /** {@inheritDoc IMemoryRetriever.retrieve} */
1763
+ retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
1764
+ }
1765
+
1766
+ /**
1767
+ * The reference {@link IMergeStrategy}: a score-union. Every record is scored by
1768
+ * the number of composed result sets it appears in (deduplicated by
1769
+ * {@link IMemoryEnvelope.id | id}); the merged result is ordered by descending
1770
+ * score, then by recency. Records surfaced by more retrievers rank higher.
1771
+ *
1772
+ * @remarks
1773
+ * Dedup is by `id` alone, which is unambiguous for the flat (one-file-per-entity)
1774
+ * kinds B2 ships. Phase-C versioned kinds that reuse a stem across scopes will
1775
+ * extend the dedup key — additive, no API change.
1776
+ * @public
1777
+ */
1778
+ export declare class ScoreUnionMergeStrategy implements IMergeStrategy {
1779
+ private constructor();
1780
+ /** Family-convention factory. */
1781
+ static create(): Result<ScoreUnionMergeStrategy>;
1782
+ /** {@inheritDoc IMergeStrategy.merge} */
1783
+ merge(resultSets: ReadonlyArray<ReadonlyArray<IMemoryRecord<unknown>>>): Result<ReadonlyArray<IMemoryRecord<unknown>>>;
1784
+ }
1785
+
1786
+ /**
1787
+ * Apply the shared scope / kind / tag / predicate pre-filter to a set of indexed
1788
+ * entries, returning the surviving records (unordered, unlimited).
1789
+ * @public
1790
+ */
1791
+ export declare function selectByQuery(entries: ReadonlyArray<IIndexedMemoryRecord>, query: IMemoryQuery): IMemoryRecord<unknown>[];
1792
+
1793
+ /**
1794
+ * The loud-degradation message a retriever returns when `query.semantic` is set
1795
+ * but no {@link IVectorIndex} is wired.
1796
+ * @public
1797
+ */
1798
+ export declare const SEMANTIC_UNWIRED_MESSAGE: string;
1799
+
1800
+ /**
1801
+ * Vector-recall retriever. When a {@link ISemanticBackend | backend} is wired it
1802
+ * embeds `query.semantic`, queries the vector index, and resolves the hits back
1803
+ * to records (preserving vector score order). When no backend is wired,
1804
+ * `supportsSemanticRecall` is `false` and any `query.semantic` request degrades
1805
+ * loudly — it NEVER returns a silent empty.
1806
+ *
1807
+ * @remarks
1808
+ * A consumer-supplied backend that rejects (throws) is normalized into a
1809
+ * `Failure` — `retrieve` always honors its `Promise<Result<...>>` contract.
1810
+ * @public
1811
+ */
1812
+ export declare class SemanticRetriever implements IMemoryRetriever {
1813
+ private readonly _index;
1814
+ private readonly _backend;
1815
+ private constructor();
1816
+ /** {@inheritDoc IMemoryRetriever.capabilities} */
1817
+ get capabilities(): IMemoryRetrieverCapabilities;
1818
+ /** Family-convention factory. */
1819
+ static create(params: ISemanticRetrieverCreateParams): Result<SemanticRetriever>;
1820
+ /** {@inheritDoc IMemoryRetriever.retrieve} */
1821
+ retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
1822
+ /**
1823
+ * Invoke a consumer-supplied backend hook, normalizing both a returned `fail`
1824
+ * and a thrown/rejected promise into a single `semantic recall: <label> failed`
1825
+ * `Failure`. Keeps `retrieve` within the `Promise<Result<...>>` contract even
1826
+ * when the injected `embedQuery` / `vectorIndex` misbehaves.
1827
+ */
1828
+ private static _callBackend;
1829
+ }
1830
+
1831
+ /**
1832
+ * Serialize an envelope and its rendered body text into a memory file. The
1833
+ * envelope is emitted as YAML frontmatter; the body is written verbatim after
1834
+ * the closing delimiter.
1835
+ * @public
1836
+ */
1837
+ export declare function serializeMemoryFile(envelope: IMemoryEnvelope, body: string): Result<string>;
1838
+
1839
+ /**
1840
+ * Split a `---\n<yaml>\n---\n<body>` memory file into its frontmatter and
1841
+ * body parts. Pure string handling — no external dependency.
1842
+ * @public
1843
+ */
1844
+ export declare function splitFrontmatter(raw: string): Result<IMemoryFileParts>;
1845
+
1846
+ /**
1847
+ * Returns records matching `query.filter`, narrowed by any scope / kind / tag
1848
+ * pre-filter and recency-ordered. The predicate is this retriever's axis: a
1849
+ * query without a `filter` is not its concern and yields an empty success (so it
1850
+ * contributes nothing to a {@link HybridRetriever}, rather than failing).
1851
+ * @public
1852
+ */
1853
+ export declare class StructuredFilterRetriever implements IMemoryRetriever {
1854
+ private readonly _index;
1855
+ private constructor();
1856
+ /** {@inheritDoc IMemoryRetriever.capabilities} */
1857
+ get capabilities(): IMemoryRetrieverCapabilities;
1858
+ /** Family-convention factory. */
1859
+ static create(index: IMemoryIndex): Result<StructuredFilterRetriever>;
1860
+ /** {@inheritDoc IMemoryRetriever.retrieve} */
1861
+ retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
1862
+ }
1863
+
1864
+ /**
1865
+ * Open-vocabulary tag label.
1866
+ * @public
1867
+ */
1868
+ export declare type Tag = Brand<string, 'Tag'>;
1869
+
1870
+ /**
1871
+ * Returns records carrying `query.tag`, recency-ordered within the tag and
1872
+ * narrowed by any scope / kind / predicate filters. Tag is this retriever's
1873
+ * axis: a query without a `tag` is not its concern and yields an empty success
1874
+ * (so it contributes nothing to a {@link HybridRetriever}, rather than failing).
1875
+ * @public
1876
+ */
1877
+ export declare class TagRetriever implements IMemoryRetriever {
1878
+ private readonly _index;
1879
+ private constructor();
1880
+ /** {@inheritDoc IMemoryRetriever.capabilities} */
1881
+ get capabilities(): IMemoryRetrieverCapabilities;
1882
+ /** Family-convention factory. */
1883
+ static create(index: IMemoryIndex): Result<TagRetriever>;
1884
+ /** {@inheritDoc IMemoryRetriever.retrieve} */
1885
+ retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
1886
+ }
1887
+
1888
+ /**
1889
+ * Converter for the optional {@link ITemporalBlock}.
1890
+ * @public
1891
+ */
1892
+ export declare const temporalConverter: Converter<ITemporalBlock>;
1893
+
1894
+ /**
1895
+ * Build the loud-degradation message a retriever returns when `query.asOf` is
1896
+ * set but no temporal index is wired.
1897
+ * @public
1898
+ */
1899
+ export declare function temporalUnwiredMessage(kind?: Kind): string;
1900
+
1901
+ export { }