@remnic/core 9.69.73 → 9.69.75

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 (263) hide show
  1. package/dist/access-admin-ops-surface.js +37 -37
  2. package/dist/access-authorization-probe.js +38 -38
  3. package/dist/access-boundary.js +37 -37
  4. package/dist/access-cli.js +110 -108
  5. package/dist/access-cli.js.map +1 -1
  6. package/dist/access-extraction-force-flush.js +37 -37
  7. package/dist/access-http-briefing.js +38 -38
  8. package/dist/access-http-query.js +39 -39
  9. package/dist/access-http.js +57 -57
  10. package/dist/access-identity-continuity-surface.js +37 -37
  11. package/dist/access-lcm-surface.js +37 -37
  12. package/dist/access-mcp.js +48 -48
  13. package/dist/access-namespace-preflight.js +37 -37
  14. package/dist/access-observe-write-category.js +6 -6
  15. package/dist/access-observe-write-surface.js +37 -37
  16. package/dist/access-offline-manifest.js +3 -3
  17. package/dist/access-operations-batch.js +40 -40
  18. package/dist/access-operations.js +47 -47
  19. package/dist/access-recall-concurrency.js +37 -37
  20. package/dist/access-recall-response.js +37 -37
  21. package/dist/access-recall-surface.js +37 -37
  22. package/dist/access-schema.js +5 -5
  23. package/dist/access-service.js +37 -37
  24. package/dist/access-surface-catalog.js +39 -39
  25. package/dist/active-recall.js +16 -15
  26. package/dist/active-recall.js.map +1 -1
  27. package/dist/briefing.js +8 -8
  28. package/dist/buffer.js +1 -1
  29. package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
  30. package/dist/causal-behavior.js +2 -2
  31. package/dist/causal-chain.js +2 -2
  32. package/dist/causal-consolidation.js +11 -11
  33. package/dist/causal-retrieval.js +2 -2
  34. package/dist/causal-trajectory-graph.js +2 -2
  35. package/dist/causal-trajectory.js +1 -1
  36. package/dist/{chunk-TRLPF7ZP.js → chunk-25LKLNSJ.js} +2 -2
  37. package/dist/{chunk-GWK7FEUL.js → chunk-2U3R3DDH.js} +6 -6
  38. package/dist/{chunk-GWQVMKUJ.js → chunk-2UPTRDGM.js} +3 -3
  39. package/dist/{chunk-MQTCNXTG.js → chunk-4GPI3GVE.js} +7 -7
  40. package/dist/{chunk-H7BZBSP6.js → chunk-52II7PB6.js} +4 -4
  41. package/dist/{chunk-HRQWSXNB.js → chunk-5HP5F2SQ.js} +3 -3
  42. package/dist/{chunk-ICMXLHSC.js → chunk-5KNEOYTF.js} +2 -2
  43. package/dist/{chunk-5I63ZRIH.js → chunk-5LPDXYU3.js} +4 -4
  44. package/dist/{chunk-JDBZSRUA.js → chunk-62AE2EUZ.js} +2 -2
  45. package/dist/{chunk-D5F2Z6WO.js → chunk-6BFW7SGF.js} +2 -2
  46. package/dist/{chunk-HW4DKAAA.js → chunk-6BSPRNFF.js} +2 -2
  47. package/dist/{chunk-JX2NWPQ4.js → chunk-6JA22L5X.js} +10 -10
  48. package/dist/{chunk-JUOJGZPV.js → chunk-6OACG7JV.js} +3 -3
  49. package/dist/{chunk-NZUHZVHF.js → chunk-7COBZFUF.js} +2 -2
  50. package/dist/{chunk-XY25CPAO.js → chunk-AQJBFLUA.js} +5 -5
  51. package/dist/{chunk-SUI5JQVE.js → chunk-AWEMJYN2.js} +2 -2
  52. package/dist/{chunk-VQJ7UAKA.js → chunk-B6PY25JB.js} +1 -1
  53. package/dist/{chunk-W7PY7IIB.js → chunk-BXCZPPRO.js} +16 -16
  54. package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
  55. package/dist/{chunk-DQFZOPDL.js → chunk-CGO3A7SR.js} +2 -2
  56. package/dist/{chunk-SF6RFI5Z.js → chunk-CHDGJJV6.js} +2 -2
  57. package/dist/{chunk-GUWH5SOO.js → chunk-COHJUEBQ.js} +2 -2
  58. package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
  59. package/dist/chunk-GBGLS44T.js +20 -0
  60. package/dist/chunk-GBGLS44T.js.map +1 -0
  61. package/dist/{chunk-5ID5RTHY.js → chunk-GFD7TWAZ.js} +2 -2
  62. package/dist/{chunk-G3QJVHFG.js → chunk-GH5YSAAI.js} +15 -12
  63. package/dist/chunk-GH5YSAAI.js.map +1 -0
  64. package/dist/{chunk-ZDTG7ALZ.js → chunk-HPK66ZM5.js} +2 -2
  65. package/dist/{chunk-5TC6MQOW.js → chunk-HS75MCQF.js} +4 -4
  66. package/dist/{chunk-BSCR5TEN.js → chunk-HZDOLAZV.js} +2 -2
  67. package/dist/{chunk-UBCVHKZQ.js → chunk-I6Y6QKWF.js} +2 -2
  68. package/dist/{chunk-YHU5XUF4.js → chunk-IFCKHPY4.js} +2 -2
  69. package/dist/{chunk-YEHKKZ5T.js → chunk-IGSVMAPQ.js} +2 -2
  70. package/dist/{chunk-2VV3XLZB.js → chunk-IXLHREAB.js} +4 -4
  71. package/dist/{chunk-266NJ2YF.js → chunk-JDES3G7T.js} +2 -2
  72. package/dist/{chunk-VVKLAB3Y.js → chunk-JOMGKV72.js} +2 -2
  73. package/dist/{chunk-YDMN7TUM.js → chunk-KMHE76A2.js} +2 -2
  74. package/dist/{chunk-CMAGVPS2.js → chunk-KPSJA45G.js} +2 -2
  75. package/dist/{chunk-2XGPN5TL.js → chunk-LBL77UXO.js} +7 -7
  76. package/dist/{chunk-ADWCQWK3.js → chunk-LDOURFFA.js} +2 -2
  77. package/dist/{chunk-B6RTKSOT.js → chunk-LH6UP5SR.js} +3 -3
  78. package/dist/chunk-LJLGH2DE.js +65 -0
  79. package/dist/chunk-LJLGH2DE.js.map +1 -0
  80. package/dist/{chunk-A7GQBJP5.js → chunk-LVFI5LG7.js} +7 -7
  81. package/dist/{chunk-6E5GYDIE.js → chunk-MFZACYZ6.js} +2 -2
  82. package/dist/{chunk-WXPIEWQW.js → chunk-MKNENZCK.js} +3 -3
  83. package/dist/{chunk-VDKZTNG5.js → chunk-MSRNAAWW.js} +2 -2
  84. package/dist/{chunk-RG7ZWG3M.js → chunk-NF6LF76X.js} +2 -2
  85. package/dist/{chunk-7FL25VH3.js → chunk-O4QH33GV.js} +6 -6
  86. package/dist/{chunk-BIKX37D2.js → chunk-OB2YI57R.js} +35 -35
  87. package/dist/{chunk-B2FMRNHA.js → chunk-ODP62HIA.js} +2 -2
  88. package/dist/{chunk-BGBW4H7C.js → chunk-OMYCECTS.js} +2 -2
  89. package/dist/{chunk-BICNRVEC.js → chunk-QWUJWBZ5.js} +2 -2
  90. package/dist/{chunk-NEARGPN7.js → chunk-S5FWSNLI.js} +2 -2
  91. package/dist/{chunk-FN6E373Q.js → chunk-SA2JMMMS.js} +2 -2
  92. package/dist/{chunk-QVWNNN64.js → chunk-TY5JOP2W.js} +139 -98
  93. package/dist/chunk-TY5JOP2W.js.map +1 -0
  94. package/dist/{chunk-WJPRWNZN.js → chunk-UFBHEMNR.js} +2 -2
  95. package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
  96. package/dist/{chunk-OVO545UE.js → chunk-VIRTAUJO.js} +2 -2
  97. package/dist/{chunk-ZHXSOMYH.js → chunk-VVX5PZFS.js} +2 -2
  98. package/dist/{chunk-AYDU5MJC.js → chunk-VXNWOHOR.js} +2 -2
  99. package/dist/{chunk-LMMQKZK3.js → chunk-VZBW6CDG.js} +1 -1
  100. package/dist/{chunk-KNPWG3VI.js → chunk-WDBKDYK2.js} +41 -41
  101. package/dist/{chunk-ADZLUBNE.js → chunk-WDP7CJZQ.js} +3 -3
  102. package/dist/{chunk-2ZU6CYTJ.js → chunk-WZKKI6S2.js} +2 -2
  103. package/dist/{chunk-GRSFFLUY.js → chunk-X2PBZOYZ.js} +2 -2
  104. package/dist/{chunk-ONEUTVGJ.js → chunk-Y52T5Y6B.js} +2 -2
  105. package/dist/{chunk-DDNML3YE.js → chunk-YCYFXA6P.js} +2 -2
  106. package/dist/{chunk-RDWVTUXZ.js → chunk-YMSPN4W4.js} +2 -2
  107. package/dist/{chunk-AJEUESNJ.js → chunk-YYRMOMX3.js} +2 -2
  108. package/dist/{chunk-2WMXZYMS.js → chunk-YZENVZWY.js} +2 -2
  109. package/dist/{chunk-WQZZDN5M.js → chunk-ZHOXXHT5.js} +4 -4
  110. package/dist/{chunk-GNC5X3J7.js → chunk-ZPED47SP.js} +11 -11
  111. package/dist/{chunk-RFVF5PLN.js → chunk-ZVTG7JTG.js} +2 -2
  112. package/dist/cli.js +84 -83
  113. package/dist/coding/export-okf-codegraph.js +7 -7
  114. package/dist/coding/pre-action-gate.js +2 -2
  115. package/dist/compounding/engine.js +8 -8
  116. package/dist/config-search-backend.d.ts +5 -0
  117. package/dist/config-search-backend.d.ts.map +1 -0
  118. package/dist/config-search-backend.js +8 -0
  119. package/dist/config.d.ts.map +1 -1
  120. package/dist/config.js +16 -15
  121. package/dist/connectors/codex-materialize-runner.js +8 -8
  122. package/dist/connectors/index.js +8 -8
  123. package/dist/convergence-refresh.js +10 -10
  124. package/dist/corpus-watermark.js +10 -10
  125. package/dist/deep-recall-http-glue.js +6 -6
  126. package/dist/deep-recall.js +2 -2
  127. package/dist/entity-retrieval.js +8 -8
  128. package/dist/event-order-recall.js +2 -2
  129. package/dist/external-wiki-access.js +38 -38
  130. package/dist/extraction.js +10 -10
  131. package/dist/{graph-edge-decay-ROSUPDX3.js → graph-edge-decay-PVKDKLQK.js} +5 -5
  132. package/dist/graph-edge-decay-PVKDKLQK.js.map +1 -0
  133. package/dist/graph-jsonl.js +3 -3
  134. package/dist/graph-snapshot.js +3 -3
  135. package/dist/graph.js +4 -4
  136. package/dist/harmonic-retrieval.js +1 -1
  137. package/dist/index.js +124 -122
  138. package/dist/lcm/engine.js +3 -3
  139. package/dist/lcm/index.js +11 -11
  140. package/dist/location/index.js +10 -10
  141. package/dist/maintenance/memory-governance.js +8 -8
  142. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +8 -8
  143. package/dist/maintenance/rebuild-memory-projection.js +9 -9
  144. package/dist/memory-browse-operations.js +38 -38
  145. package/dist/namespaces/migrate.js +9 -9
  146. package/dist/namespaces/search.js +4 -4
  147. package/dist/namespaces/storage.js +8 -8
  148. package/dist/offline-sync.js +2 -2
  149. package/dist/operator-doctor-corpus.js +11 -11
  150. package/dist/operator-toolkit.js +27 -26
  151. package/dist/orchestration/extraction-persist-citation.d.ts +4 -0
  152. package/dist/orchestration/extraction-persist-citation.d.ts.map +1 -0
  153. package/dist/orchestration/extraction-persist.d.ts +1 -3
  154. package/dist/orchestration/extraction-persist.d.ts.map +1 -1
  155. package/dist/orchestration/maintenance.js +16 -16
  156. package/dist/orchestration/recall-entry.d.ts.map +1 -1
  157. package/dist/orchestrator.js +110 -108
  158. package/dist/recall-navigation-operations.js +38 -38
  159. package/dist/recall-navigation.js +37 -37
  160. package/dist/resume-bundles.js +17 -16
  161. package/dist/search/factory.js +3 -3
  162. package/dist/search/index.js +7 -7
  163. package/dist/semantic-consolidation.js +9 -9
  164. package/dist/semantic-rule-promotion.js +8 -8
  165. package/dist/semantic-rule-verifier.js +8 -8
  166. package/dist/source-agent-qualifier.js +8 -8
  167. package/dist/standing-memory-recall.d.ts +22 -0
  168. package/dist/standing-memory-recall.d.ts.map +1 -0
  169. package/dist/standing-memory-recall.js +16 -0
  170. package/dist/standing-memory-recall.js.map +1 -0
  171. package/dist/standup/build.js +8 -8
  172. package/dist/storage.js +7 -7
  173. package/dist/support-passport/index.js +40 -40
  174. package/dist/transfer/backup.js +2 -2
  175. package/dist/transfer/capsule-export.js +2 -2
  176. package/dist/transfer/capsule-import.js +2 -2
  177. package/dist/transfer/export-okf.js +8 -8
  178. package/dist/verified-recall.js +8 -8
  179. package/dist/who-knows-cli.js +9 -9
  180. package/dist/who-knows.js +8 -8
  181. package/package.json +2 -2
  182. package/src/config-search-backend.test.ts +21 -0
  183. package/src/config-search-backend.ts +17 -0
  184. package/src/config.ts +2 -3
  185. package/src/orchestration/extraction-persist-citation.test.ts +9 -0
  186. package/src/orchestration/extraction-persist-citation.ts +37 -0
  187. package/src/orchestration/extraction-persist.ts +8 -42
  188. package/src/orchestration/recall-entry.ts +54 -13
  189. package/src/standing-memory-block.test.ts +4 -3
  190. package/src/standing-memory-recall.test.ts +30 -0
  191. package/src/standing-memory-recall.ts +87 -0
  192. package/dist/chunk-G3QJVHFG.js.map +0 -1
  193. package/dist/chunk-QVWNNN64.js.map +0 -1
  194. /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
  195. /package/dist/{chunk-TRLPF7ZP.js.map → chunk-25LKLNSJ.js.map} +0 -0
  196. /package/dist/{chunk-GWK7FEUL.js.map → chunk-2U3R3DDH.js.map} +0 -0
  197. /package/dist/{chunk-GWQVMKUJ.js.map → chunk-2UPTRDGM.js.map} +0 -0
  198. /package/dist/{chunk-MQTCNXTG.js.map → chunk-4GPI3GVE.js.map} +0 -0
  199. /package/dist/{chunk-H7BZBSP6.js.map → chunk-52II7PB6.js.map} +0 -0
  200. /package/dist/{chunk-HRQWSXNB.js.map → chunk-5HP5F2SQ.js.map} +0 -0
  201. /package/dist/{chunk-ICMXLHSC.js.map → chunk-5KNEOYTF.js.map} +0 -0
  202. /package/dist/{chunk-5I63ZRIH.js.map → chunk-5LPDXYU3.js.map} +0 -0
  203. /package/dist/{chunk-JDBZSRUA.js.map → chunk-62AE2EUZ.js.map} +0 -0
  204. /package/dist/{chunk-D5F2Z6WO.js.map → chunk-6BFW7SGF.js.map} +0 -0
  205. /package/dist/{chunk-HW4DKAAA.js.map → chunk-6BSPRNFF.js.map} +0 -0
  206. /package/dist/{chunk-JX2NWPQ4.js.map → chunk-6JA22L5X.js.map} +0 -0
  207. /package/dist/{chunk-JUOJGZPV.js.map → chunk-6OACG7JV.js.map} +0 -0
  208. /package/dist/{chunk-NZUHZVHF.js.map → chunk-7COBZFUF.js.map} +0 -0
  209. /package/dist/{chunk-XY25CPAO.js.map → chunk-AQJBFLUA.js.map} +0 -0
  210. /package/dist/{chunk-SUI5JQVE.js.map → chunk-AWEMJYN2.js.map} +0 -0
  211. /package/dist/{chunk-VQJ7UAKA.js.map → chunk-B6PY25JB.js.map} +0 -0
  212. /package/dist/{chunk-W7PY7IIB.js.map → chunk-BXCZPPRO.js.map} +0 -0
  213. /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  214. /package/dist/{chunk-DQFZOPDL.js.map → chunk-CGO3A7SR.js.map} +0 -0
  215. /package/dist/{chunk-SF6RFI5Z.js.map → chunk-CHDGJJV6.js.map} +0 -0
  216. /package/dist/{chunk-GUWH5SOO.js.map → chunk-COHJUEBQ.js.map} +0 -0
  217. /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
  218. /package/dist/{chunk-5ID5RTHY.js.map → chunk-GFD7TWAZ.js.map} +0 -0
  219. /package/dist/{chunk-ZDTG7ALZ.js.map → chunk-HPK66ZM5.js.map} +0 -0
  220. /package/dist/{chunk-5TC6MQOW.js.map → chunk-HS75MCQF.js.map} +0 -0
  221. /package/dist/{chunk-BSCR5TEN.js.map → chunk-HZDOLAZV.js.map} +0 -0
  222. /package/dist/{chunk-UBCVHKZQ.js.map → chunk-I6Y6QKWF.js.map} +0 -0
  223. /package/dist/{chunk-YHU5XUF4.js.map → chunk-IFCKHPY4.js.map} +0 -0
  224. /package/dist/{chunk-YEHKKZ5T.js.map → chunk-IGSVMAPQ.js.map} +0 -0
  225. /package/dist/{chunk-2VV3XLZB.js.map → chunk-IXLHREAB.js.map} +0 -0
  226. /package/dist/{chunk-266NJ2YF.js.map → chunk-JDES3G7T.js.map} +0 -0
  227. /package/dist/{chunk-VVKLAB3Y.js.map → chunk-JOMGKV72.js.map} +0 -0
  228. /package/dist/{chunk-YDMN7TUM.js.map → chunk-KMHE76A2.js.map} +0 -0
  229. /package/dist/{chunk-CMAGVPS2.js.map → chunk-KPSJA45G.js.map} +0 -0
  230. /package/dist/{chunk-2XGPN5TL.js.map → chunk-LBL77UXO.js.map} +0 -0
  231. /package/dist/{chunk-ADWCQWK3.js.map → chunk-LDOURFFA.js.map} +0 -0
  232. /package/dist/{chunk-B6RTKSOT.js.map → chunk-LH6UP5SR.js.map} +0 -0
  233. /package/dist/{chunk-A7GQBJP5.js.map → chunk-LVFI5LG7.js.map} +0 -0
  234. /package/dist/{chunk-6E5GYDIE.js.map → chunk-MFZACYZ6.js.map} +0 -0
  235. /package/dist/{chunk-WXPIEWQW.js.map → chunk-MKNENZCK.js.map} +0 -0
  236. /package/dist/{chunk-VDKZTNG5.js.map → chunk-MSRNAAWW.js.map} +0 -0
  237. /package/dist/{chunk-RG7ZWG3M.js.map → chunk-NF6LF76X.js.map} +0 -0
  238. /package/dist/{chunk-7FL25VH3.js.map → chunk-O4QH33GV.js.map} +0 -0
  239. /package/dist/{chunk-BIKX37D2.js.map → chunk-OB2YI57R.js.map} +0 -0
  240. /package/dist/{chunk-B2FMRNHA.js.map → chunk-ODP62HIA.js.map} +0 -0
  241. /package/dist/{chunk-BGBW4H7C.js.map → chunk-OMYCECTS.js.map} +0 -0
  242. /package/dist/{chunk-BICNRVEC.js.map → chunk-QWUJWBZ5.js.map} +0 -0
  243. /package/dist/{chunk-NEARGPN7.js.map → chunk-S5FWSNLI.js.map} +0 -0
  244. /package/dist/{chunk-FN6E373Q.js.map → chunk-SA2JMMMS.js.map} +0 -0
  245. /package/dist/{chunk-WJPRWNZN.js.map → chunk-UFBHEMNR.js.map} +0 -0
  246. /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
  247. /package/dist/{chunk-OVO545UE.js.map → chunk-VIRTAUJO.js.map} +0 -0
  248. /package/dist/{chunk-ZHXSOMYH.js.map → chunk-VVX5PZFS.js.map} +0 -0
  249. /package/dist/{chunk-AYDU5MJC.js.map → chunk-VXNWOHOR.js.map} +0 -0
  250. /package/dist/{chunk-LMMQKZK3.js.map → chunk-VZBW6CDG.js.map} +0 -0
  251. /package/dist/{chunk-KNPWG3VI.js.map → chunk-WDBKDYK2.js.map} +0 -0
  252. /package/dist/{chunk-ADZLUBNE.js.map → chunk-WDP7CJZQ.js.map} +0 -0
  253. /package/dist/{chunk-2ZU6CYTJ.js.map → chunk-WZKKI6S2.js.map} +0 -0
  254. /package/dist/{chunk-GRSFFLUY.js.map → chunk-X2PBZOYZ.js.map} +0 -0
  255. /package/dist/{chunk-ONEUTVGJ.js.map → chunk-Y52T5Y6B.js.map} +0 -0
  256. /package/dist/{chunk-DDNML3YE.js.map → chunk-YCYFXA6P.js.map} +0 -0
  257. /package/dist/{chunk-RDWVTUXZ.js.map → chunk-YMSPN4W4.js.map} +0 -0
  258. /package/dist/{chunk-AJEUESNJ.js.map → chunk-YYRMOMX3.js.map} +0 -0
  259. /package/dist/{chunk-2WMXZYMS.js.map → chunk-YZENVZWY.js.map} +0 -0
  260. /package/dist/{chunk-WQZZDN5M.js.map → chunk-ZHOXXHT5.js.map} +0 -0
  261. /package/dist/{chunk-GNC5X3J7.js.map → chunk-ZPED47SP.js.map} +0 -0
  262. /package/dist/{chunk-RFVF5PLN.js.map → chunk-ZVTG7JTG.js.map} +0 -0
  263. /package/dist/{graph-edge-decay-ROSUPDX3.js.map → config-search-backend.js.map} +0 -0
package/src/config.ts CHANGED
@@ -26,6 +26,7 @@ import type {
26
26
  TrustWeights,
27
27
  } from "./types.js";
28
28
  import { parseBackgroundGeneration } from "./background-generation-config.js";
29
+ import { parseSearchBackend } from "./config-search-backend.js";
29
30
  import { parseLocalLlmConfig } from "./local-llm-config.js";
30
31
  import { parseConvergeConfig } from "./converge-config.js";
31
32
  import { parseExternalWikiRecallGuard } from "./external-wiki-guard.js";
@@ -3173,9 +3174,7 @@ export function parseConfig(
3173
3174
  : 500,
3174
3175
 
3175
3176
  // Search backend abstraction
3176
- searchBackend: (["qmd", "remote", "noop", "lancedb", "meilisearch", "orama"] as const).includes(cfg.searchBackend as any)
3177
- ? (cfg.searchBackend as "qmd" | "remote" | "noop" | "lancedb" | "meilisearch" | "orama")
3178
- : "qmd",
3177
+ searchBackend: parseSearchBackend(cfg.searchBackend),
3179
3178
  remoteSearchBaseUrl: typeof cfg.remoteSearchBaseUrl === "string" ? cfg.remoteSearchBaseUrl : undefined,
3180
3179
  remoteSearchApiKey: typeof cfg.remoteSearchApiKey === "string" ? cfg.remoteSearchApiKey : undefined,
3181
3180
  remoteSearchTimeoutMs: typeof cfg.remoteSearchTimeoutMs === "number" ? cfg.remoteSearchTimeoutMs : 30_000,
@@ -0,0 +1,9 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import { applyInlineCitation, normalizeStoredHashSource } from "./extraction-persist-citation.js";
5
+
6
+ test("#3091 citation helpers no-op when inline attribution is off", () => {
7
+ assert.equal(applyInlineCitation("hello", false, "[{ts}]", {}), "hello");
8
+ assert.equal(normalizeStoredHashSource("hello", false, "[{ts}]"), "hello");
9
+ });
@@ -0,0 +1,37 @@
1
+ import { ContentHashIndex } from "../index.js";
2
+ import { sanitizeMemoryContent } from "../sanitize.js";
3
+ import {
4
+ attachCitation,
5
+ type CitationContext,
6
+ hasCitationForTemplate,
7
+ stripCitationForTemplate,
8
+ } from "../source-attribution.js";
9
+
10
+ export function normalizeStoredHashSource(
11
+ raw: string,
12
+ citationEnabled: boolean,
13
+ citationTemplate: string,
14
+ ): string {
15
+ return ContentHashIndex.normalizeContent(
16
+ sanitizeMemoryContent(
17
+ citationEnabled && hasCitationForTemplate(raw, citationTemplate)
18
+ ? stripCitationForTemplate(raw, citationTemplate)
19
+ : raw,
20
+ ).text,
21
+ );
22
+ }
23
+
24
+ export function applyInlineCitation(
25
+ content: string,
26
+ citationEnabled: boolean,
27
+ citationTemplate: string,
28
+ citationContextBase: Omit<CitationContext, "ts">,
29
+ ): string {
30
+ if (!citationEnabled) return content;
31
+ if (typeof content !== "string" || content.length === 0) return content;
32
+ const citationContext: CitationContext = {
33
+ ...citationContextBase,
34
+ ts: new Date().toISOString(),
35
+ };
36
+ return attachCitation(content, citationContext, citationTemplate);
37
+ }
@@ -125,6 +125,10 @@ import { applySemanticMergeAtPersist, runMergedTargetPostEffects, writeMergedVer
125
125
  import { buildMergedTargetPromotionPayload } from "./semantic-merge-promotion-payload.js";
126
126
  import { persistMergedTargetThreadEpisode } from "./semantic-merge-commit-effects.js";
127
127
  import { ExtractionAnchorSnapshot } from "./extraction-anchor-snapshot.js";
128
+ import {
129
+ applyInlineCitation as applyInlineCitationToContent,
130
+ normalizeStoredHashSource as normalizeStoredHashSourceContent,
131
+ } from "./extraction-persist-citation.js";
128
132
 
129
133
  export class ExtractionPersistCoordinator {
130
134
  constructor(
@@ -145,26 +149,12 @@ export class ExtractionPersistCoordinator {
145
149
  sourceContext?: ExtractionSourceContext,
146
150
  baseNamespace?: string,
147
151
  scopeProfileWritePlan?: ResolvedScopeProfilePlan | null,
148
- /** Verbatim source turn text the facts were extracted from (faithfulness gate #1576). */
149
152
  sourceText?: string,
150
153
  graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.deps.config),
151
154
  lifecycleCaps: MemoryLifecycleCapabilitySet = resolveMemoryLifecycleCapabilities(this.deps.config),
152
155
  ): Promise<{ persistedIds: string[]; memoryPathById: Map<string, string> }> {
153
- // Inline source attribution (issue #369). When enabled, every extracted
154
- // fact is rewritten to carry a compact provenance tag inside its body so
155
- // the citation survives hostile memory text, copy/paste, and LLM quoting.
156
- // The helper is a no-op when the feature flag is off, so legacy pipelines
157
- // see zero behavioral change.
158
156
  const citationEnabled = resolvePipelineProcessingCapabilities(this.deps.config).inlineSourceAttribution === true;
159
157
  const citationTemplate = this.deps.config.inlineSourceAttributionFormat;
160
- // #1909: the main-path fact writes defer their per-fact fact-hash-index flush
161
- // to the orchestrator's end-of-persist reconciling batch save ONLY when fact
162
- // deduplication is enabled (with it off, contentHashIndexForStorage() returns
163
- // null and the batch save is a no-op, so the write must save immediately).
164
- // Round 11: there is NO fact-hashes.ready marker anymore — the fact-hash
165
- // index is ALWAYS rebuilt from the corpus on restart (see
166
- // ensureFactHashIndexAuthoritative), so a deferred write, crash, or
167
- // multi-process interleave is safe by construction with no marker to guard.
168
158
  const factDedupEnabled = resolveRecallAuxiliaryCapabilities(this.deps.config).factDeduplication;
169
159
  const harmonicConstructionEnabled = resolveCapabilities(this.deps.config).harmonicRetrieval;
170
160
  const harmonicAnchorsEnabled =
@@ -182,40 +172,16 @@ export class ExtractionPersistCoordinator {
182
172
  let harmonicSourceOrder = 0;
183
173
  const promotedCopyProbe = createBatchPromotedCopyProbe(this.deps.config, this.deps.getStorageRouter, scopeProfileWritePlan); // #2330 finding F: one promoted-copy scan per namespace per batch
184
174
 
185
- // Canonicalize stored content for dedup comparison: strip citations
186
- // (using the same template), sanitize, then normalize whitespace.
187
- const normalizeStoredHashSource = (raw: string): string =>
188
- ContentHashIndex.normalizeContent(
189
- sanitizeMemoryContent(
190
- citationEnabled && hasCitationForTemplate(raw, citationTemplate)
191
- ? stripCitationForTemplate(raw, citationTemplate)
192
- : raw,
193
- ).text,
194
- );
195
- // The stable fields (agent, session) are computed once; `ts` is intentionally
196
- // omitted here and added fresh per invocation so each fact in a large batch
197
- // gets its own insertion timestamp rather than sharing a single batch-start time.
175
+ const normalizeStoredHashSource = (raw: string): string =>
176
+ normalizeStoredHashSourceContent(raw, citationEnabled, citationTemplate);
198
177
  const citationContextBase: Omit<CitationContext, "ts"> = citationEnabled
199
178
  ? {
200
179
  agent: sourceContext?.principal,
201
180
  session: sourceContext?.sessionKey,
202
181
  }
203
182
  : {};
204
- const applyInlineCitation = (content: string): string => {
205
- if (!citationEnabled) return content;
206
- if (typeof content !== "string" || content.length === 0) return content;
207
- // Build a fresh CitationContext per call so `ts` reflects the actual
208
- // insertion time of each individual fact rather than the batch-start time.
209
- const citationContext: CitationContext = {
210
- ...citationContextBase,
211
- ts: new Date().toISOString(),
212
- };
213
- // `attachCitation` already calls `hasCitationForTemplate` internally and
214
- // is a no-op when the content already carries a citation (default or
215
- // custom template). The outer check was redundant and has been removed
216
- // to avoid a maintenance hazard where the two guard paths could diverge.
217
- return attachCitation(content, citationContext, citationTemplate);
218
- };
183
+ const applyInlineCitation = (content: string): string =>
184
+ applyInlineCitationToContent(content, citationEnabled, citationTemplate, citationContextBase);
219
185
  const persistedIds: string[] = [];
220
186
  const memoryPathById = new Map<string, string>();
221
187
  const anchorSnapshots = new ExtractionAnchorSnapshot({
@@ -23,7 +23,12 @@ import type { IdentityInjectionMode, PluginConfig, QmdSearchResult } from "../ty
23
23
  import { stateViewPacketActive } from "../recall-state-view-anchors.js";
24
24
  import { resultStateViewKey, stateViewPacketKeys } from "../recall-state-view.js";
25
25
  import { applyRecallStateViews } from "../recall-state-view-wire.js";
26
- import { composeRecallContext } from "../recall-context-composition.js";
26
+ import { composeRecallContext, type RecallContextComposition } from "../recall-context-composition.js";
27
+ import {
28
+ memoriesToStandingEntries,
29
+ prefixStandingMemoryBlock,
30
+ renderStandingMemoryBlock,
31
+ } from "../standing-memory-recall.js";
27
32
  import {
28
33
  notifyContextComposition,
29
34
  recallFailureComposition,
@@ -151,16 +156,53 @@ export class RecallEntryCoordinator {
151
156
  return lockedMsg;
152
157
  }
153
158
 
154
- // Keep outer recall timeout above worst-case serialized hybrid search:
155
- // QMD subprocess BM25 (30s) + vector (30s) can consume ~60s under contention.
159
+ let standingText = "";
160
+ const standingBudget =
161
+ typeof options.budgetCharsOverride === "number" &&
162
+ Number.isInteger(options.budgetCharsOverride) &&
163
+ options.budgetCharsOverride >= 0
164
+ ? options.budgetCharsOverride
165
+ : this.deps.config.recallBudgetChars;
166
+ if (this.deps.config.recallStandingBlock && !namespacesEnabled && standingBudget !== 0 && !options.asOf) {
167
+ try {
168
+ const memories = await this.deps.storage.readAllMemories({
169
+ abortSignal: abortController.signal,
170
+ });
171
+ standingText = renderStandingMemoryBlock(
172
+ this.deps.config,
173
+ memoriesToStandingEntries(memories, { requestingConnector: options.sourceConnector }),
174
+ );
175
+ } catch (err) {
176
+ log.warn(`standing memory block skipped: ${err}`);
177
+ }
178
+ }
179
+ const innerObserver = options.onContextComposition;
180
+ const innerBudget =
181
+ standingText.length > 0 && standingBudget && standingBudget > 0
182
+ ? Math.max(0, standingBudget - standingText.length - 2)
183
+ : options.budgetCharsOverride;
184
+ const recallOptions = {
185
+ ...options,
186
+ abortSignal: abortController.signal,
187
+ budgetCharsOverride: innerBudget,
188
+ onContextComposition:
189
+ standingText.length > 0
190
+ ? (composition: RecallContextComposition) =>
191
+ innerObserver?.({
192
+ ...composition,
193
+ context: prefixStandingMemoryBlock(
194
+ composition.context ?? "",
195
+ standingText,
196
+ standingBudget,
197
+ ),
198
+ })
199
+ : innerObserver,
200
+ };
156
201
  try {
157
- const recallPromise = this.deps.recallInternal(prompt, sessionKey, {
158
- ...options,
159
- abortSignal: abortController.signal,
160
- }, caps, graphCaps);
202
+ const recallPromise = this.deps.recallInternal(prompt, sessionKey, recallOptions, caps, graphCaps);
161
203
  const RECALL_TIMEOUT_MS = this.deps.config.recallOuterTimeoutMs ?? 75_000;
162
204
  if (RECALL_TIMEOUT_MS <= 0) {
163
- return await recallPromise;
205
+ return prefixStandingMemoryBlock(await recallPromise, standingText, standingBudget);
164
206
  }
165
207
 
166
208
  let timeoutHandle: NodeJS.Timeout | null = null;
@@ -196,18 +238,17 @@ export class RecallEntryCoordinator {
196
238
  }
197
239
  }
198
240
 
199
- return recallResult;
241
+ return prefixStandingMemoryBlock(recallResult, standingText, standingBudget);
200
242
  } catch (err) {
201
243
  this.deps.logRecallFailure(err);
202
- // endTrace() is safe here: if no trace is active (disabled or already
203
- // closed by recallInternal's try/finally), it returns null immediately.
204
244
  this.deps.profiler.endTrace();
205
- // Caller-cancelled recalls stay quiet: the failure was the caller's
206
- // abort, not a recall degradation (issue #2972 contract).
207
245
  const missing = options.abortSignal?.aborted
208
246
  ? null
209
247
  : recallFailureComposition(err);
210
248
  if (!missing) return "";
249
+ if (standingText.length > 0) {
250
+ missing.context = prefixStandingMemoryBlock(missing.context ?? "", standingText, standingBudget);
251
+ }
211
252
  notifyContextComposition(options.onContextComposition, missing, (observerErr) => {
212
253
  log.warn("recall: context composition observer failed open", observerErr);
213
254
  });
@@ -230,6 +230,7 @@ async function writeFact(memoryDir: string): Promise<void> {
230
230
  `created: ${now}`,
231
231
  `updated: ${now}`,
232
232
  "source: extraction",
233
+ "origin: user",
233
234
  "confidence: 0.8",
234
235
  "confidenceTier: high",
235
236
  "tags: []",
@@ -242,7 +243,7 @@ async function writeFact(memoryDir: string): Promise<void> {
242
243
  await writeFile(path.join(factsDir, "standing-fact.md"), `${fact.join("\n")}\n`, "utf-8");
243
244
  }
244
245
 
245
- test("zero-diff: recall output is byte-identical with the flag off vs on (pre-wiring)", async () => {
246
+ test("recall injects the standing memory block when the flag is on", async () => {
246
247
  const off = await makeOrchestrator();
247
248
  const on = await makeOrchestrator({ recallStandingBlock: true });
248
249
  try {
@@ -250,8 +251,8 @@ test("zero-diff: recall output is byte-identical with the flag off vs on (pre-wi
250
251
  await writeFact(on.memoryDir);
251
252
  const outOff = await off.orchestrator.recall("how do deploys go out", "sess-standing-off");
252
253
  const outOn = await on.orchestrator.recall("how do deploys go out", "sess-standing-on");
253
- assert.equal(outOn, outOff, "recall must not change until the wiring slice lands");
254
- assert.ok(!outOn.includes("## Standing Memory (Remnic)"), "no standing block in recall output");
254
+ assert.ok(!outOff.includes("## Standing Memory (Remnic)"), "flag off keeps recall unchanged");
255
+ assert.ok(outOn.includes("## Standing Memory (Remnic)"), "flag on injects the standing block");
255
256
  assert.ok(outOn.includes("blue pipeline"), "sanity: the fact is recalled");
256
257
  } finally {
257
258
  await off.orchestrator.destroy();
@@ -0,0 +1,30 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import { parseConfig } from "./config.js";
5
+ import {
6
+ memoriesToStandingEntries,
7
+ prefixStandingMemoryBlock,
8
+ renderStandingMemoryBlock,
9
+ } from "./standing-memory-recall.js";
10
+
11
+ test("#3089 standing block is omitted when recallStandingBlock is off", () => {
12
+ const off = parseConfig({});
13
+ const on = parseConfig({ recallStandingBlock: true });
14
+ const entries = memoriesToStandingEntries([
15
+ {
16
+ id: "fact-1",
17
+ content: "The blue pipeline is the only deploy path.",
18
+ frontmatter: { id: "fact-1", pinned: true, origin: "user" },
19
+ },
20
+ ]);
21
+ const recall = "per-turn recall";
22
+ assert.equal(renderStandingMemoryBlock(off, entries), "");
23
+ assert.equal(prefixStandingMemoryBlock(recall, renderStandingMemoryBlock(off, entries)), recall);
24
+ const standing = renderStandingMemoryBlock(on, entries);
25
+ assert.ok(standing.includes("## Standing Memory (Remnic)"));
26
+ assert.ok(standing.includes("blue pipeline"));
27
+ const prefixed = prefixStandingMemoryBlock(recall, standing);
28
+ assert.ok(prefixed.startsWith(standing));
29
+ assert.ok(prefixed.includes("per-turn recall"));
30
+ });
@@ -0,0 +1,87 @@
1
+ import {
2
+ DEFAULT_UNTRUSTED_ORIGINS,
3
+ isUntrustedOrigin,
4
+ parseOriginClass,
5
+ } from "./security/origin-authority.js";
6
+ import type { PluginConfig } from "./types.js";
7
+ import {
8
+ buildStandingMemoryBlock,
9
+ lintStandingBlockVolatility,
10
+ type StandingMemoryEntry,
11
+ } from "./standing-memory-block.js";
12
+
13
+ export interface StandingMemorySource {
14
+ id?: string;
15
+ path?: string;
16
+ content: string;
17
+ frontmatter: {
18
+ id?: unknown;
19
+ pinned?: unknown;
20
+ updated?: unknown;
21
+ origin?: unknown;
22
+ status?: unknown;
23
+ toolScoped?: unknown;
24
+ sourceConnector?: unknown;
25
+ };
26
+ }
27
+
28
+ export function memoriesToStandingEntries(
29
+ memories: readonly StandingMemorySource[],
30
+ opts: { requestingConnector?: string } = {},
31
+ ): StandingMemoryEntry[] {
32
+ const entries: StandingMemoryEntry[] = [];
33
+ for (const memory of memories) {
34
+ const id = String(memory.frontmatter.id ?? memory.id ?? memory.path ?? "");
35
+ if (!id) continue;
36
+ if (isUntrustedOrigin(parseOriginClass(memory.frontmatter.origin), DEFAULT_UNTRUSTED_ORIGINS)) {
37
+ continue;
38
+ }
39
+ if (typeof memory.frontmatter.status === "string" && memory.frontmatter.status !== "active") {
40
+ continue;
41
+ }
42
+ const requestingConnector = opts.requestingConnector?.trim();
43
+ const memoryConnector =
44
+ typeof memory.frontmatter.sourceConnector === "string" ? memory.frontmatter.sourceConnector.trim() : "";
45
+ if (memory.frontmatter.toolScoped === true && memoryConnector && requestingConnector && memoryConnector !== requestingConnector) {
46
+ continue;
47
+ }
48
+ const description =
49
+ memory.content
50
+ .split("\n")
51
+ .map((line) => line.trim())
52
+ .find((line) => line.length > 0 && !line.startsWith("#") && !line.startsWith("---")) ?? "";
53
+ if (description.length < 8) continue;
54
+ if (lintStandingBlockVolatility(description).length > 0) continue;
55
+ const pinned = memory.frontmatter.pinned === true;
56
+ const lastChangedAt =
57
+ typeof memory.frontmatter.updated === "string" ? memory.frontmatter.updated : undefined;
58
+ entries.push({ id, description: description.slice(0, 200), pinned, lastChangedAt });
59
+ }
60
+ return entries;
61
+ }
62
+
63
+ export function renderStandingMemoryBlock(config: PluginConfig, entries: StandingMemoryEntry[]): string {
64
+ if (!config.recallStandingBlock || entries.length === 0) return "";
65
+ try {
66
+ return buildStandingMemoryBlock({
67
+ entries,
68
+ nowMs: Date.now(),
69
+ maxChars: config.standingBlockMaxChars,
70
+ freshDays: config.standingBlockFreshDays,
71
+ }).text;
72
+ } catch {
73
+ return "";
74
+ }
75
+ }
76
+
77
+ export function prefixStandingMemoryBlock(
78
+ recallResult: string,
79
+ standingText: string,
80
+ budgetChars?: number,
81
+ ): string {
82
+ if (standingText.length === 0) return recallResult;
83
+ if (budgetChars === 0) return recallResult;
84
+ const combined = `${standingText}\n\n${recallResult}`;
85
+ if (!budgetChars || combined.length <= budgetChars) return combined;
86
+ return combined.slice(0, budgetChars);
87
+ }