@remnic/core 9.63.6 → 9.63.8

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 (304) hide show
  1. package/dist/access-admin-ops-surface.d.ts +3 -2
  2. package/dist/access-admin-ops-surface.js +31 -27
  3. package/dist/access-authorization-probe.d.ts +3 -2
  4. package/dist/access-authorization-probe.js +32 -28
  5. package/dist/access-boundary.d.ts +3 -2
  6. package/dist/access-boundary.js +31 -27
  7. package/dist/access-cli.js +98 -95
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +3 -2
  10. package/dist/access-extraction-force-flush.js +31 -27
  11. package/dist/access-http-lcm-compaction.d.ts +3 -2
  12. package/dist/access-http-lifecycle-flush.d.ts +3 -2
  13. package/dist/access-http-offline-stream.d.ts +3 -2
  14. package/dist/access-http-query.js +33 -29
  15. package/dist/access-http.d.ts +4 -3
  16. package/dist/access-http.js +47 -43
  17. package/dist/access-identity-continuity-surface.d.ts +2 -1
  18. package/dist/access-identity-continuity-surface.js +31 -27
  19. package/dist/access-lcm-surface.d.ts +3 -2
  20. package/dist/access-lcm-surface.js +31 -27
  21. package/dist/access-mcp-output-schemas.js +1 -1
  22. package/dist/access-mcp.d.ts +3 -2
  23. package/dist/access-mcp.js +38 -34
  24. package/dist/access-namespace-preflight.js +31 -27
  25. package/dist/access-observe-write-surface.d.ts +3 -2
  26. package/dist/access-observe-write-surface.js +31 -27
  27. package/dist/access-offline-manifest.d.ts +2 -1
  28. package/dist/access-offline-manifest.js +5 -4
  29. package/dist/access-operations-batch.js +32 -28
  30. package/dist/access-operations.d.ts +3 -2
  31. package/dist/access-operations.js +36 -32
  32. package/dist/access-recall-concurrency.d.ts +3 -2
  33. package/dist/access-recall-concurrency.js +31 -27
  34. package/dist/access-recall-response.d.ts +3 -2
  35. package/dist/access-recall-response.js +31 -27
  36. package/dist/access-recall-surface.d.ts +3 -2
  37. package/dist/access-recall-surface.js +31 -27
  38. package/dist/access-schema.js +6 -5
  39. package/dist/{access-service-cKQrte9Z.d.ts → access-service-BaPa_km6.d.ts} +1 -1
  40. package/dist/access-service-helpers.d.ts +3 -2
  41. package/dist/access-service.d.ts +3 -2
  42. package/dist/access-service.js +31 -27
  43. package/dist/access-surface-catalog.d.ts +3 -2
  44. package/dist/access-surface-catalog.js +33 -29
  45. package/dist/access-surface-catalog.js.map +1 -1
  46. package/dist/active-recall.js +4 -2
  47. package/dist/active-recall.js.map +1 -1
  48. package/dist/adapters/index.js +4 -4
  49. package/dist/adapters/registry.js +2 -2
  50. package/dist/{auto-sync-BKRJDMKX.js → auto-sync-3SHMZVQS.js} +5 -3
  51. package/dist/{auto-sync-BKRJDMKX.js.map → auto-sync-3SHMZVQS.js.map} +1 -1
  52. package/dist/bootstrap.d.ts +2 -1
  53. package/dist/briefing.js +10 -10
  54. package/dist/calibration.d.ts +2 -1
  55. package/dist/calibration.js +7 -0
  56. package/dist/calibration.js.map +1 -1
  57. package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
  58. package/dist/causal-consolidation.js +11 -11
  59. package/dist/census-validation.d.ts +19 -0
  60. package/dist/census-validation.js +14 -0
  61. package/dist/census-validation.js.map +1 -0
  62. package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
  63. package/dist/chunk-2YA5N2BY.js +65 -0
  64. package/dist/chunk-2YA5N2BY.js.map +1 -0
  65. package/dist/{chunk-PB4WVYGC.js → chunk-3IMYRX3W.js} +2 -2
  66. package/dist/{chunk-R6UMNP5C.js → chunk-3T6HIIKA.js} +2 -2
  67. package/dist/{chunk-77QZW2D6.js → chunk-3TDAA7VA.js} +2 -2
  68. package/dist/{chunk-TWTUGCTY.js → chunk-3YTTAGPB.js} +6 -1
  69. package/dist/chunk-3YTTAGPB.js.map +1 -0
  70. package/dist/{chunk-DXDAQZ2K.js → chunk-42TIIO2M.js} +2 -2
  71. package/dist/{chunk-Y7COCXY2.js → chunk-4F67JJPG.js} +2 -2
  72. package/dist/{chunk-OW7NVMGQ.js → chunk-5OOTHWGJ.js} +2 -2
  73. package/dist/{chunk-KYTRF64R.js → chunk-5SCFDQEJ.js} +2 -2
  74. package/dist/{chunk-DYZR3Z6D.js → chunk-5TF5STAV.js} +4 -4
  75. package/dist/{chunk-GG4DN63W.js → chunk-62Y5AGCM.js} +2 -2
  76. package/dist/{chunk-PMVPCZJZ.js → chunk-6433HV72.js} +2 -2
  77. package/dist/{chunk-KHCUVYCY.js → chunk-6UKSOXAO.js} +3 -3
  78. package/dist/{chunk-GF7RQWXC.js → chunk-AJRJDXYR.js} +2 -2
  79. package/dist/{chunk-YEQCMA5L.js → chunk-BOSIHHOH.js} +2 -2
  80. package/dist/{chunk-IVXVLDNT.js → chunk-BPQ7L27U.js} +77 -92
  81. package/dist/chunk-BPQ7L27U.js.map +1 -0
  82. package/dist/{chunk-7LF2OHIJ.js → chunk-BRHKW7GY.js} +2 -2
  83. package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
  84. package/dist/{chunk-LX4TNSAE.js → chunk-CBY54QYW.js} +4 -4
  85. package/dist/{chunk-CIAI24TQ.js → chunk-DGUVXXAU.js} +3 -3
  86. package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
  87. package/dist/{chunk-QI5RDDEL.js → chunk-EDZNW3HE.js} +3 -3
  88. package/dist/chunk-FEHIOYML.js +168 -0
  89. package/dist/chunk-FEHIOYML.js.map +1 -0
  90. package/dist/{chunk-Z4N7SVVF.js → chunk-FZEEWOI2.js} +9 -4
  91. package/dist/chunk-FZEEWOI2.js.map +1 -0
  92. package/dist/{chunk-6YMEU6OQ.js → chunk-G72IPMR7.js} +2 -2
  93. package/dist/{chunk-7AF243WZ.js → chunk-GBVRVYF4.js} +1 -1
  94. package/dist/{chunk-FPEZ74F7.js → chunk-I2HTKOOP.js} +3 -3
  95. package/dist/{chunk-R7TZ2HCS.js → chunk-JG22O53B.js} +58 -3
  96. package/dist/chunk-JG22O53B.js.map +1 -0
  97. package/dist/{chunk-VPHSMJ2E.js → chunk-JPWSYHLB.js} +2 -2
  98. package/dist/{chunk-X7LEDA74.js → chunk-KFB4YNXM.js} +2 -2
  99. package/dist/{chunk-I5FLIB2J.js → chunk-KXWE62IH.js} +2 -2
  100. package/dist/chunk-LQWOFU6L.js +17 -0
  101. package/dist/chunk-LQWOFU6L.js.map +1 -0
  102. package/dist/{chunk-TSTI6A3A.js → chunk-LTYH2L6E.js} +13 -13
  103. package/dist/{chunk-ZUPKNWRZ.js → chunk-MIUL6AUZ.js} +3 -3
  104. package/dist/{chunk-EJY3HJMT.js → chunk-MYI3RKI6.js} +2 -2
  105. package/dist/{chunk-UCLMKNHA.js → chunk-N7V3P4V5.js} +2 -2
  106. package/dist/{chunk-NA56NSKL.js → chunk-O52TB5SL.js} +2 -2
  107. package/dist/{chunk-7KQB4EBS.js → chunk-OPPBTPUU.js} +4 -4
  108. package/dist/{chunk-ERPBRXVZ.js → chunk-PHKU6BZ2.js} +2 -2
  109. package/dist/{chunk-GTD4Q62X.js → chunk-PQHNZ63P.js} +4 -4
  110. package/dist/{chunk-FHKXVTM5.js → chunk-Q5XKKDFQ.js} +16 -16
  111. package/dist/{chunk-QRWMS6SI.js → chunk-Q6OL23WM.js} +2 -2
  112. package/dist/{chunk-V3KIRICY.js → chunk-QQYHYW2N.js} +3 -3
  113. package/dist/{chunk-YFCEBB5P.js → chunk-QTXNS3HB.js} +2 -2
  114. package/dist/{chunk-2QSZNTDO.js → chunk-RKNJBZ55.js} +4 -4
  115. package/dist/{chunk-E4KMY4KR.js → chunk-SNEUAZ6B.js} +2 -2
  116. package/dist/{chunk-F6JYBVL6.js → chunk-SY5JUJ2X.js} +52 -52
  117. package/dist/{chunk-EFKZT6AY.js → chunk-T42L3S6A.js} +6 -11
  118. package/dist/chunk-T42L3S6A.js.map +1 -0
  119. package/dist/{chunk-YXMHUBN2.js → chunk-TOP3FSDW.js} +25 -102
  120. package/dist/chunk-TOP3FSDW.js.map +1 -0
  121. package/dist/{chunk-PBRCYYO7.js → chunk-ULZFZL7K.js} +2 -2
  122. package/dist/{chunk-YYQAKIDJ.js → chunk-VD2OT77P.js} +2 -2
  123. package/dist/chunk-VD2OT77P.js.map +1 -0
  124. package/dist/{chunk-IPLYGWQF.js → chunk-VDX2J7OX.js} +6 -6
  125. package/dist/{chunk-UGHCZS6K.js → chunk-VFZQXYN5.js} +2 -2
  126. package/dist/{chunk-NKB43PGI.js → chunk-VYMICVRA.js} +2 -2
  127. package/dist/{chunk-OETHJBAL.js → chunk-WBPD6SBZ.js} +109 -116
  128. package/dist/chunk-WBPD6SBZ.js.map +1 -0
  129. package/dist/{chunk-2UM6WHME.js → chunk-XE2QCCT2.js} +2 -2
  130. package/dist/{chunk-SYVGVK4S.js → chunk-XTMYB2HY.js} +2 -2
  131. package/dist/{chunk-AYVCKGA6.js → chunk-YTXNDEUS.js} +2 -2
  132. package/dist/{chunk-3Z5TGRFA.js → chunk-ZOAAY2OE.js} +9 -9
  133. package/dist/{chunk-L3CHRBHE.js → chunk-ZRUEP4IK.js} +17 -11
  134. package/dist/chunk-ZRUEP4IK.js.map +1 -0
  135. package/dist/{chunk-PRDJMOST.js → chunk-ZVZHG7AI.js} +65 -15
  136. package/dist/chunk-ZVZHG7AI.js.map +1 -0
  137. package/dist/{chunk-RYST72N5.js → chunk-ZWYXSF2T.js} +4 -154
  138. package/dist/chunk-ZWYXSF2T.js.map +1 -0
  139. package/dist/{cli-BFBDYV0D.d.ts → cli-D0tV7eeU.d.ts} +2 -2
  140. package/dist/cli.d.ts +4 -3
  141. package/dist/cli.js +69 -65
  142. package/dist/compounding/engine.js +10 -10
  143. package/dist/config.js +4 -2
  144. package/dist/connectors/codex-materialize-runner.js +10 -10
  145. package/dist/connectors/index.js +10 -10
  146. package/dist/consolidation-provenance-check.js +2 -2
  147. package/dist/convergence-refresh.js +12 -12
  148. package/dist/conversation-index/backend.js +2 -2
  149. package/dist/corpus-watermark.js +12 -12
  150. package/dist/entity-retrieval.js +10 -10
  151. package/dist/explicit-capture.d.ts +2 -1
  152. package/dist/external-wiki-access.d.ts +3 -2
  153. package/dist/external-wiki-access.js +32 -28
  154. package/dist/external-wiki-mcp-tools.d.ts +3 -2
  155. package/dist/extraction-judge.d.ts +2 -1
  156. package/dist/extraction-judge.js +6 -1
  157. package/dist/extraction-normalization.js +2 -2
  158. package/dist/extraction-prompt.d.ts +20 -1
  159. package/dist/extraction-prompt.js +11 -1
  160. package/dist/extraction.js +13 -13
  161. package/dist/harmonic-retrieval.js +1 -1
  162. package/dist/included-memories.d.ts +11 -0
  163. package/dist/included-memories.js +14 -0
  164. package/dist/included-memories.js.map +1 -0
  165. package/dist/index.d.ts +6 -5
  166. package/dist/index.js +117 -114
  167. package/dist/lcm/index.js +3 -3
  168. package/dist/maintenance/memory-governance.js +10 -10
  169. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +10 -10
  170. package/dist/maintenance/rebuild-memory-projection.js +11 -11
  171. package/dist/mcp-memory-inspector-app.d.ts +3 -2
  172. package/dist/namespaces/migrate.js +11 -11
  173. package/dist/namespaces/search.js +4 -4
  174. package/dist/namespaces/storage.js +10 -10
  175. package/dist/offline-sync.js +2 -1
  176. package/dist/operator-doctor-corpus.js +13 -13
  177. package/dist/operator-toolkit.js +23 -21
  178. package/dist/orchestration/maintenance.js +16 -16
  179. package/dist/{orchestrator-CSc9GfQv.d.ts → orchestrator-Bay_AofR.d.ts} +2 -3
  180. package/dist/orchestrator.d.ts +2 -1
  181. package/dist/orchestrator.js +100 -97
  182. package/dist/{public-http-8PcrDIYi.d.ts → public-http-BtjiyKah.d.ts} +1 -1
  183. package/dist/recall-explain-renderer.d.ts +1 -0
  184. package/dist/recall-state.d.ts +6 -2
  185. package/dist/recall-state.js +6 -2
  186. package/dist/reconcile/cursor.js +7 -3
  187. package/dist/reconcile/cursor.js.map +1 -1
  188. package/dist/reconcile/manifest.js +3 -7
  189. package/dist/reconcile/plan.d.ts +15 -1
  190. package/dist/reconcile/plan.js +6 -10
  191. package/dist/resume-bundles.js +5 -3
  192. package/dist/search/factory.js +3 -3
  193. package/dist/search/index.js +3 -3
  194. package/dist/semantic-consolidation.js +16 -16
  195. package/dist/semantic-rule-promotion.js +10 -10
  196. package/dist/semantic-rule-verifier.js +10 -10
  197. package/dist/source-agent-qualifier.js +10 -10
  198. package/dist/storage.js +9 -9
  199. package/dist/support-passport/index.d.ts +6 -5
  200. package/dist/support-passport/index.js +34 -30
  201. package/dist/transfer/autodetect.js +1 -1
  202. package/dist/transfer/backup.js +2 -2
  203. package/dist/transfer/capsule-export.js +3 -3
  204. package/dist/transfer/capsule-import.js +2 -2
  205. package/dist/verified-recall.js +10 -10
  206. package/package.json +2 -2
  207. package/src/access-mcp-output-schemas.ts +1 -1
  208. package/src/access-recall-response.ts +4 -2
  209. package/src/access-recall-surface.ts +9 -9
  210. package/src/access-service-namespace.test.ts +9 -9
  211. package/src/access-service-raw-excerpt-read-gate.test.ts +1 -1
  212. package/src/calibration.ts +3 -1
  213. package/src/census-validation.ts +25 -0
  214. package/src/coding/architecture-surfaces.test.ts +9 -10
  215. package/src/coding/architecture-surfaces.ts +2 -35
  216. package/src/coding/codegraph-runtime-loader.test.ts +228 -0
  217. package/src/coding/codegraph-runtime.ts +30 -50
  218. package/src/coding/codegraph-surfaces.ts +2 -2
  219. package/src/coding/coding-knowledge-config.ts +35 -1
  220. package/src/coding/decision-surfaces.test.ts +9 -10
  221. package/src/coding/decision-surfaces.ts +2 -40
  222. package/src/coding/session-delta-surfaces.test.ts +9 -10
  223. package/src/coding/session-delta-surfaces.ts +2 -33
  224. package/src/extraction-judge.ts +3 -1
  225. package/src/extraction-output-language.test.ts +116 -0
  226. package/src/extraction-prompt.ts +70 -1
  227. package/src/extraction.ts +23 -95
  228. package/src/included-memories.ts +88 -0
  229. package/src/offline-sync.ts +4 -4
  230. package/src/orchestration/recall-internal-deps.ts +2 -4
  231. package/src/orchestration/recall-internal.ts +9 -13
  232. package/src/orchestration/recall-result-formatter-display-safe.test.ts +13 -16
  233. package/src/orchestration/recall-result-formatter.ts +32 -45
  234. package/src/orchestration/recall-section-coordinator.ts +20 -26
  235. package/src/orchestrator.ts +2 -4
  236. package/src/recall-explain-renderer.test.ts +4 -0
  237. package/src/recall-state.test.ts +108 -5
  238. package/src/recall-state.ts +85 -23
  239. package/src/recall-token-budget.test.ts +1 -1
  240. package/src/reconcile/census-parity.test.ts +152 -0
  241. package/src/reconcile/cursor.ts +5 -5
  242. package/src/reconcile/manifest.ts +4 -11
  243. package/src/reconcile/plan.ts +18 -15
  244. package/dist/chunk-EFKZT6AY.js.map +0 -1
  245. package/dist/chunk-IVXVLDNT.js.map +0 -1
  246. package/dist/chunk-L3CHRBHE.js.map +0 -1
  247. package/dist/chunk-OETHJBAL.js.map +0 -1
  248. package/dist/chunk-PRDJMOST.js.map +0 -1
  249. package/dist/chunk-R7TZ2HCS.js.map +0 -1
  250. package/dist/chunk-RYST72N5.js.map +0 -1
  251. package/dist/chunk-TWTUGCTY.js.map +0 -1
  252. package/dist/chunk-YXMHUBN2.js.map +0 -1
  253. package/dist/chunk-YYQAKIDJ.js.map +0 -1
  254. package/dist/chunk-Z4N7SVVF.js.map +0 -1
  255. /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
  256. /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
  257. /package/dist/{chunk-PB4WVYGC.js.map → chunk-3IMYRX3W.js.map} +0 -0
  258. /package/dist/{chunk-R6UMNP5C.js.map → chunk-3T6HIIKA.js.map} +0 -0
  259. /package/dist/{chunk-77QZW2D6.js.map → chunk-3TDAA7VA.js.map} +0 -0
  260. /package/dist/{chunk-DXDAQZ2K.js.map → chunk-42TIIO2M.js.map} +0 -0
  261. /package/dist/{chunk-Y7COCXY2.js.map → chunk-4F67JJPG.js.map} +0 -0
  262. /package/dist/{chunk-OW7NVMGQ.js.map → chunk-5OOTHWGJ.js.map} +0 -0
  263. /package/dist/{chunk-KYTRF64R.js.map → chunk-5SCFDQEJ.js.map} +0 -0
  264. /package/dist/{chunk-DYZR3Z6D.js.map → chunk-5TF5STAV.js.map} +0 -0
  265. /package/dist/{chunk-GG4DN63W.js.map → chunk-62Y5AGCM.js.map} +0 -0
  266. /package/dist/{chunk-PMVPCZJZ.js.map → chunk-6433HV72.js.map} +0 -0
  267. /package/dist/{chunk-KHCUVYCY.js.map → chunk-6UKSOXAO.js.map} +0 -0
  268. /package/dist/{chunk-GF7RQWXC.js.map → chunk-AJRJDXYR.js.map} +0 -0
  269. /package/dist/{chunk-YEQCMA5L.js.map → chunk-BOSIHHOH.js.map} +0 -0
  270. /package/dist/{chunk-7LF2OHIJ.js.map → chunk-BRHKW7GY.js.map} +0 -0
  271. /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  272. /package/dist/{chunk-LX4TNSAE.js.map → chunk-CBY54QYW.js.map} +0 -0
  273. /package/dist/{chunk-CIAI24TQ.js.map → chunk-DGUVXXAU.js.map} +0 -0
  274. /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
  275. /package/dist/{chunk-QI5RDDEL.js.map → chunk-EDZNW3HE.js.map} +0 -0
  276. /package/dist/{chunk-6YMEU6OQ.js.map → chunk-G72IPMR7.js.map} +0 -0
  277. /package/dist/{chunk-7AF243WZ.js.map → chunk-GBVRVYF4.js.map} +0 -0
  278. /package/dist/{chunk-FPEZ74F7.js.map → chunk-I2HTKOOP.js.map} +0 -0
  279. /package/dist/{chunk-VPHSMJ2E.js.map → chunk-JPWSYHLB.js.map} +0 -0
  280. /package/dist/{chunk-X7LEDA74.js.map → chunk-KFB4YNXM.js.map} +0 -0
  281. /package/dist/{chunk-I5FLIB2J.js.map → chunk-KXWE62IH.js.map} +0 -0
  282. /package/dist/{chunk-TSTI6A3A.js.map → chunk-LTYH2L6E.js.map} +0 -0
  283. /package/dist/{chunk-ZUPKNWRZ.js.map → chunk-MIUL6AUZ.js.map} +0 -0
  284. /package/dist/{chunk-EJY3HJMT.js.map → chunk-MYI3RKI6.js.map} +0 -0
  285. /package/dist/{chunk-UCLMKNHA.js.map → chunk-N7V3P4V5.js.map} +0 -0
  286. /package/dist/{chunk-NA56NSKL.js.map → chunk-O52TB5SL.js.map} +0 -0
  287. /package/dist/{chunk-7KQB4EBS.js.map → chunk-OPPBTPUU.js.map} +0 -0
  288. /package/dist/{chunk-ERPBRXVZ.js.map → chunk-PHKU6BZ2.js.map} +0 -0
  289. /package/dist/{chunk-GTD4Q62X.js.map → chunk-PQHNZ63P.js.map} +0 -0
  290. /package/dist/{chunk-FHKXVTM5.js.map → chunk-Q5XKKDFQ.js.map} +0 -0
  291. /package/dist/{chunk-QRWMS6SI.js.map → chunk-Q6OL23WM.js.map} +0 -0
  292. /package/dist/{chunk-V3KIRICY.js.map → chunk-QQYHYW2N.js.map} +0 -0
  293. /package/dist/{chunk-YFCEBB5P.js.map → chunk-QTXNS3HB.js.map} +0 -0
  294. /package/dist/{chunk-2QSZNTDO.js.map → chunk-RKNJBZ55.js.map} +0 -0
  295. /package/dist/{chunk-E4KMY4KR.js.map → chunk-SNEUAZ6B.js.map} +0 -0
  296. /package/dist/{chunk-F6JYBVL6.js.map → chunk-SY5JUJ2X.js.map} +0 -0
  297. /package/dist/{chunk-PBRCYYO7.js.map → chunk-ULZFZL7K.js.map} +0 -0
  298. /package/dist/{chunk-IPLYGWQF.js.map → chunk-VDX2J7OX.js.map} +0 -0
  299. /package/dist/{chunk-UGHCZS6K.js.map → chunk-VFZQXYN5.js.map} +0 -0
  300. /package/dist/{chunk-NKB43PGI.js.map → chunk-VYMICVRA.js.map} +0 -0
  301. /package/dist/{chunk-2UM6WHME.js.map → chunk-XE2QCCT2.js.map} +0 -0
  302. /package/dist/{chunk-SYVGVK4S.js.map → chunk-XTMYB2HY.js.map} +0 -0
  303. /package/dist/{chunk-AYVCKGA6.js.map → chunk-YTXNDEUS.js.map} +0 -0
  304. /package/dist/{chunk-3Z5TGRFA.js.map → chunk-ZOAAY2OE.js.map} +0 -0
@@ -622,7 +622,7 @@ export class RecallInternalCoordinator {
622
622
  qmdHybridFetchLimit,
623
623
  }),
624
624
  latencyMs: Date.now() - recallStart,
625
- resultPaths: [],
625
+ includedMemories: [],
626
626
  policyVersion,
627
627
  appendImpression: this.deps.config.recordEmptyRecallImpressions,
628
628
  identityInjection: {
@@ -4944,14 +4944,14 @@ export class RecallInternalCoordinator {
4944
4944
  const assembledRecall = this.deps.assembleRecallSections(
4945
4945
  sectionBuckets, contextBudgetForFooter(recallBudgetChars, curiosityFooter),
4946
4946
  );
4947
- recalledMemoryIds = assembledRecall.includedMemoryIds;
4948
- recalledMemoryPaths = assembledRecall.includedMemoryPaths;
4949
- recalledMemoryNamespaces = assembledRecall.includedMemoryNamespaces;
4950
- recalledMemoryCount = assembledRecall.includedMemoryIds.length;
4947
+ recalledMemoryIds = assembledRecall.includedMemories.map((memory) => memory.id);
4948
+ recalledMemoryPaths = assembledRecall.includedMemories.map((memory) => memory.path);
4949
+ recalledMemoryNamespaces = assembledRecall.includedMemories.map((memory) => memory.namespace);
4950
+ recalledMemoryCount = assembledRecall.includedMemories.length;
4951
4951
  this.deps.trackMemoryAccess(
4952
- assembledRecall.includedMemoryIds,
4953
- assembledRecall.includedMemoryPaths,
4954
- assembledRecall.includedMemoryNamespaces,
4952
+ recalledMemoryIds,
4953
+ recalledMemoryPaths,
4954
+ recalledMemoryNamespaces,
4955
4955
  );
4956
4956
  const recalledContext = assembledRecall.sections.join("\n\n---\n\n");
4957
4957
  const composition = boundRecallContextComposition({
@@ -4987,9 +4987,6 @@ export class RecallInternalCoordinator {
4987
4987
  truncated: assembledRecall.truncated || compositionTruncated || curiosityFooterTruncated,
4988
4988
  includedSections,
4989
4989
  omittedSections,
4990
- includedMemoryIds: assembledRecall.includedMemoryIds,
4991
- includedMemoryPaths: assembledRecall.includedMemoryPaths,
4992
- includedMemoryNamespaces: assembledRecall.includedMemoryNamespaces,
4993
4990
  omittedMemoryIds: assembledRecall.omittedMemoryIds,
4994
4991
  });
4995
4992
  // X-ray capture (issue #570 PR 1). Only fires when the caller
@@ -5241,8 +5238,7 @@ export class RecallInternalCoordinator {
5241
5238
  sourcesUsed,
5242
5239
  budgetsApplied,
5243
5240
  latencyMs: Date.now() - recallStart,
5244
- resultPaths: recalledMemoryPaths,
5245
- resultNamespaces: recalledMemoryNamespaces,
5241
+ includedMemories: assembledRecall.includedMemories,
5246
5242
  policyVersion,
5247
5243
  appendImpression:
5248
5244
  recalledMemoryIds.length > 0 ||
@@ -2,19 +2,17 @@ import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
3
  import { displaySafeRecallSnapshot } from "./recall-result-formatter.js";
4
4
 
5
- test("displaySafeRecallSnapshot relativizes result, budget, and tier-anchor paths without mutating input (#2077)", () => {
5
+ test("displaySafeRecallSnapshot relativizes included-memory and tier-anchor paths without mutating input (#2077)", () => {
6
6
  const memoryDir = "/srv/memory";
7
7
  const flatAbs = `${memoryDir}/facts/2026-07-19/b.md`;
8
8
  const nsResultAbs = `${memoryDir}/namespaces/tok-team/facts/2026-07-19/r.md`;
9
- // An anchor that is NOT among the returned results — no authoritative owner.
9
+ // An anchor that is NOT among the included memories — no authoritative owner.
10
10
  const unmatchedAnchorAbs = `${memoryDir}/namespaces/ns-616c706861/facts/2026-07-19/a.md`;
11
11
  const snapshot = {
12
- resultPaths: [flatAbs, nsResultAbs],
13
- resultNamespaces: [undefined, "team-alpha"],
14
- budgetsApplied: {
15
- includedMemoryPaths: [flatAbs, nsResultAbs],
16
- includedMemoryNamespaces: [undefined, "team-alpha"],
17
- },
12
+ includedMemories: [
13
+ { id: "mem-b", path: flatAbs },
14
+ { id: "mem-r", path: nsResultAbs, namespace: "team-alpha" },
15
+ ],
18
16
  tierExplain: {
19
17
  tier: "direct-answer",
20
18
  tierReason: "single high-confidence hit",
@@ -31,21 +29,20 @@ test("displaySafeRecallSnapshot relativizes result, budget, and tier-anchor path
31
29
 
32
30
  const safe = displaySafeRecallSnapshot(snapshot, memoryDir);
33
31
 
34
- assert.deepEqual(safe.resultPaths, ["facts/2026-07-19/b.md", "team-alpha/facts/2026-07-19/r.md"]);
35
- assert.deepEqual(safe.budgetsApplied.includedMemoryPaths, [
36
- "facts/2026-07-19/b.md",
37
- "team-alpha/facts/2026-07-19/r.md",
32
+ assert.deepEqual(safe.includedMemories, [
33
+ { id: "mem-b", path: "facts/2026-07-19/b.md" },
34
+ { id: "mem-r", path: "team-alpha/facts/2026-07-19/r.md", namespace: "team-alpha" },
38
35
  ]);
39
36
  assert.deepEqual(safe.tierExplain.sourceAnchors, [
40
- // Anchor coincides with a namespaced result → reuses its authoritative namespace.
37
+ // Anchor coincides with a namespaced included memory → reuses its authoritative namespace.
41
38
  { path: "team-alpha/facts/2026-07-19/r.md", lineRange: [1, 2] },
42
- // Anchor not among the results → truthful storage-relative segment, never a decode.
39
+ // Anchor not among the included memories → truthful storage-relative segment, never a decode.
43
40
  { path: "namespaces/ns-616c706861/facts/2026-07-19/a.md" },
44
- // Anchor coincides with a default-namespace result → memoryDir-relative.
41
+ // Anchor coincides with a default-namespace included memory → memoryDir-relative.
45
42
  { path: "facts/2026-07-19/b.md" },
46
43
  ]);
47
44
 
48
45
  // The input snapshot must not be mutated — the live cache keeps absolute paths.
49
46
  assert.equal(snapshot.tierExplain.sourceAnchors[0].path, nsResultAbs);
50
- assert.equal(snapshot.resultPaths[1], nsResultAbs);
47
+ assert.equal(snapshot.includedMemories[1].path, nsResultAbs);
51
48
  });
@@ -33,6 +33,7 @@ import type { WorkProductLedgerSearchResult } from "../work-product-ledger.js";
33
33
  import { trustResultFor, type TrustStageResultItem } from "../trust-score-stage.js";
34
34
  import { CONNECTOR_ID_PATTERN, CONNECTOR_LABEL_MAX_LENGTH } from "../connectors/label.js";
35
35
  import { isValidConnectorId } from "../connectors/index.js";
36
+ import { coerceIncludedMemories, type IncludedMemory } from "../included-memories.js";
36
37
  import type {
37
38
  ContinuityIncidentRecord,
38
39
  IdentityInjectionMode,
@@ -112,43 +113,26 @@ export function displayResultPath(
112
113
  : resultPath;
113
114
  }
114
115
 
115
- /**
116
- * Return a copy of budget metadata with `includedMemoryPaths` rendered
117
- * memoryDir-relative, so recall/last-recall API callers never receive operator
118
- * filesystem paths via budget output even though the internal snapshot keeps
119
- * absolute paths for tracking/x-ray (#2020). Other fields are unchanged.
120
- */
121
- export function displaySafeBudgetsApplied<
122
- T extends {
123
- includedMemoryPaths?: string[];
124
- includedMemoryNamespaces?: Array<string | undefined>;
125
- },
126
- >(budgetsApplied: T | undefined, memoryDir: string): T | undefined {
127
- if (!budgetsApplied?.includedMemoryPaths) return budgetsApplied;
128
- return {
129
- ...budgetsApplied,
130
- includedMemoryPaths: budgetsApplied.includedMemoryPaths.map((p, i) =>
131
- displayResultPath(p, memoryDir, budgetsApplied.includedMemoryNamespaces?.[i]),
132
- ),
133
- };
134
- }
135
-
136
116
  /**
137
117
  * Return a display-safe copy of a recall snapshot for the `includeDebug=true`
138
- * surface (#2077). `resultPaths` and `budgetsApplied.includedMemoryPaths` are
139
- * rendered namespace-relative from their aligned namespace metadata; a
140
- * `tierExplain.sourceAnchors[]` entry reuses that SAME authoritative metadata
141
- * when its absolute path matches a result/included path, and otherwise falls
142
- * back to the memoryDir-relative on-disk form. Either way the debug flag never
143
- * leaks absolute operator paths, and an anchor is never attributed to a decoded
144
- * (guessed) namespace an anchor carries no owner of its own. Returns a
145
- * shallow copy; the input snapshot is never mutated.
118
+ * surface (#2077). `includedMemories[].path` is rendered namespace-relative
119
+ * from each memory's own namespace the same rendering `resultPaths` received
120
+ * before the struct consolidation; a `tierExplain.sourceAnchors[]` entry
121
+ * reuses that SAME authoritative metadata when its absolute path matches an
122
+ * included memory's path, and otherwise falls back to the memoryDir-relative
123
+ * on-disk form. Either way the debug flag never leaks absolute operator
124
+ * paths, and an anchor is never attributed to a decoded (guessed) namespace —
125
+ * an anchor carries no owner of its own. Returns a shallow copy; the input
126
+ * snapshot is never mutated.
146
127
  */
147
128
  export function displaySafeRecallSnapshot<
148
129
  T extends {
130
+ includedMemories?: IncludedMemory[];
131
+ memoryIds?: string[];
149
132
  resultPaths?: string[];
150
133
  resultNamespaces?: Array<string | undefined>;
151
134
  budgetsApplied?: {
135
+ includedMemoryIds?: string[];
152
136
  includedMemoryPaths?: string[];
153
137
  includedMemoryNamespaces?: Array<string | undefined>;
154
138
  };
@@ -157,21 +141,14 @@ export function displaySafeRecallSnapshot<
157
141
  };
158
142
  },
159
143
  >(snapshot: T, memoryDir: string): T {
160
- const resultPaths = snapshot.resultPaths?.map((p, i) =>
161
- displayResultPath(p, memoryDir, snapshot.resultNamespaces?.[i]),
162
- );
163
- // Authoritative absolute-path -> namespace map recorded at capture time, so a
164
- // tier anchor that coincides with a returned result renders under the SAME
165
- // namespace as that result instead of the raw storage segment (#2077).
144
+ const includedMemories = coerceIncludedMemories(snapshot).map((memory) => ({
145
+ ...memory,
146
+ path: displayResultPath(memory.path, memoryDir, memory.namespace),
147
+ }));
166
148
  const namespaceByPath = new Map<string, string | undefined>();
167
- snapshot.resultPaths?.forEach((p, i) => {
168
- if (!namespaceByPath.has(p)) namespaceByPath.set(p, snapshot.resultNamespaces?.[i]);
169
- });
170
- snapshot.budgetsApplied?.includedMemoryPaths?.forEach((p, i) => {
171
- if (!namespaceByPath.has(p)) {
172
- namespaceByPath.set(p, snapshot.budgetsApplied?.includedMemoryNamespaces?.[i]);
173
- }
174
- });
149
+ for (const memory of coerceIncludedMemories(snapshot)) {
150
+ if (!namespaceByPath.has(memory.path)) namespaceByPath.set(memory.path, memory.namespace);
151
+ }
175
152
  const tierExplain =
176
153
  snapshot.tierExplain?.sourceAnchors
177
154
  ? {
@@ -182,11 +159,21 @@ export function displaySafeRecallSnapshot<
182
159
  })),
183
160
  }
184
161
  : undefined;
162
+ const resultPaths = includedMemories.map((memory) => memory.path);
163
+ const resultNamespaces = includedMemories.map((memory) => memory.namespace);
185
164
  return {
186
165
  ...snapshot,
187
- ...(resultPaths ? { resultPaths } : {}),
166
+ includedMemories,
167
+ resultPaths,
168
+ resultNamespaces,
188
169
  ...(snapshot.budgetsApplied
189
- ? { budgetsApplied: displaySafeBudgetsApplied(snapshot.budgetsApplied, memoryDir) }
170
+ ? {
171
+ budgetsApplied: {
172
+ ...snapshot.budgetsApplied,
173
+ includedMemoryPaths: resultPaths,
174
+ includedMemoryNamespaces: resultNamespaces,
175
+ },
176
+ }
190
177
  : {}),
191
178
  ...(tierExplain ? { tierExplain } : {}),
192
179
  };
@@ -17,7 +17,7 @@
17
17
  * TierMigrationCoordinator accessor pattern.
18
18
  */
19
19
 
20
- import type { LastRecallBudgetSummary } from "../recall-state.js";
20
+ import type { IncludedMemory, LastRecallBudgetSummary } from "../recall-state.js";
21
21
  import { estimateTokenCount } from "../token-estimate.js";
22
22
  import { graphemeUnits, truncateGraphemeSafe } from "../whitespace.js";
23
23
  import type { PluginConfig, RecallSectionConfig } from "../types.js";
@@ -273,6 +273,7 @@ export class RecallSectionCoordinator {
273
273
  omittedIds: string[];
274
274
  truncated: boolean;
275
275
  finalChars: number;
276
+ includedMemories: IncludedMemory[];
276
277
  includedMemoryIds: string[];
277
278
  includedMemoryPaths: string[];
278
279
  includedMemoryNamespaces: Array<string | undefined>;
@@ -340,6 +341,7 @@ export class RecallSectionCoordinator {
340
341
  omittedIds: orderedSections.map((entry) => entry.id),
341
342
  truncated: orderedSections.length > 0,
342
343
  finalChars: 0,
344
+ includedMemories: [],
343
345
  includedMemoryIds: [],
344
346
  includedMemoryPaths: [],
345
347
  includedMemoryNamespaces: [],
@@ -372,9 +374,7 @@ export class RecallSectionCoordinator {
372
374
  break;
373
375
  }
374
376
  }
375
- const includedMemoryIds: string[] = [];
376
- const includedMemoryPaths: string[] = [];
377
- const includedMemoryNamespaces: Array<string | undefined> = [];
377
+ const includedMemories: IncludedMemory[] = [];
378
378
  let usedChars = 0;
379
379
  let usedTokens = 0;
380
380
  let truncated = false;
@@ -492,12 +492,12 @@ export class RecallSectionCoordinator {
492
492
  rendered = chunk.content;
493
493
  includedLeadingContent = false;
494
494
  includedAtomicCount = 1;
495
- // Push id/path/namespace together so the parallel tracking arrays
496
- // never misalign when a chunk carries only one of them (#2020).
497
495
  if (chunk.memoryId && chunk.memoryPath) {
498
- includedMemoryIds.push(chunk.memoryId);
499
- includedMemoryPaths.push(chunk.memoryPath);
500
- includedMemoryNamespaces.push(chunk.memoryNamespace);
496
+ includedMemories.push(
497
+ chunk.memoryNamespace
498
+ ? { id: chunk.memoryId, path: chunk.memoryPath, namespace: chunk.memoryNamespace }
499
+ : { id: chunk.memoryId, path: chunk.memoryPath },
500
+ );
501
501
  }
502
502
  continue;
503
503
  }
@@ -522,9 +522,11 @@ export class RecallSectionCoordinator {
522
522
  if (chunk.atomic) {
523
523
  includedAtomicCount += 1;
524
524
  if (chunk.memoryId && chunk.memoryPath) {
525
- includedMemoryIds.push(chunk.memoryId);
526
- includedMemoryPaths.push(chunk.memoryPath);
527
- includedMemoryNamespaces.push(chunk.memoryNamespace);
525
+ includedMemories.push(
526
+ chunk.memoryNamespace
527
+ ? { id: chunk.memoryId, path: chunk.memoryPath, namespace: chunk.memoryNamespace }
528
+ : { id: chunk.memoryId, path: chunk.memoryPath },
529
+ );
528
530
  }
529
531
  } else {
530
532
  includedPostAtomicContent = true;
@@ -574,16 +576,14 @@ export class RecallSectionCoordinator {
574
576
  omittedIds,
575
577
  truncated,
576
578
  finalChars: usedChars,
577
- includedMemoryIds,
578
- includedMemoryPaths,
579
- includedMemoryNamespaces,
579
+ includedMemories,
580
+ includedMemoryIds: includedMemories.map((memory) => memory.id),
581
+ includedMemoryPaths: includedMemories.map((memory) => memory.path),
582
+ includedMemoryNamespaces: includedMemories.map((memory) => memory.namespace),
580
583
  omittedMemoryIds: (() => {
581
- // Key by (namespace, id): the same memory id can exist in more than one
582
- // namespace, so an id-only subtraction would hide a budget-dropped copy
583
- // when another namespace's copy was included (#2020).
584
584
  const includedKeys = new Set(
585
- includedMemoryIds.map(
586
- (id, i) => `${includedMemoryNamespaces[i] ?? ""}\u0000${id}`,
585
+ includedMemories.map(
586
+ (memory) => `${memory.namespace ?? ""}\u0000${memory.id}`,
587
587
  ),
588
588
  );
589
589
  return candidateMemoryChunks
@@ -604,9 +604,6 @@ export class RecallSectionCoordinator {
604
604
  finalContextChars?: number;
605
605
  truncated?: boolean;
606
606
  includedSections?: string[];
607
- includedMemoryIds?: string[];
608
- includedMemoryPaths?: string[];
609
- includedMemoryNamespaces?: Array<string | undefined>;
610
607
  omittedMemoryIds?: string[];
611
608
  omittedSections?: string[];
612
609
  }): LastRecallBudgetSummary {
@@ -619,9 +616,6 @@ export class RecallSectionCoordinator {
619
616
  qmdHybridFetchLimit: options.qmdHybridFetchLimit,
620
617
  finalContextChars: options.finalContextChars,
621
618
  truncated: options.truncated,
622
- includedMemoryIds: [...(options.includedMemoryIds ?? [])],
623
- includedMemoryPaths: [...(options.includedMemoryPaths ?? [])],
624
- includedMemoryNamespaces: [...(options.includedMemoryNamespaces ?? [])],
625
619
  omittedMemoryIds: [...(options.omittedMemoryIds ?? [])],
626
620
  includedSections: [...(options.includedSections ?? [])],
627
621
  omittedSections: [...(options.omittedSections ?? [])],
@@ -260,6 +260,7 @@ import { NegativeExampleStore } from "./negative.js";
260
260
  import {
261
261
  LastRecallStore,
262
262
  RecallHandleHistoryStore,
263
+ type IncludedMemory,
263
264
  type LastRecallBudgetSummary,
264
265
  TierMigrationStatusStore,
265
266
  clampGraphRecallExpandedEntries,
@@ -2716,7 +2717,7 @@ export class Orchestrator {
2716
2717
  includedIds: string[];
2717
2718
  omittedIds: string[];
2718
2719
  truncated: boolean;
2719
- finalChars: number;
2720
+ includedMemories: IncludedMemory[];
2720
2721
  includedMemoryIds: string[];
2721
2722
  includedMemoryPaths: string[];
2722
2723
  includedMemoryNamespaces: Array<string | undefined>;
@@ -3542,9 +3543,6 @@ export class Orchestrator {
3542
3543
  finalContextChars?: number;
3543
3544
  truncated?: boolean;
3544
3545
  includedSections?: string[];
3545
- includedMemoryIds?: string[];
3546
- includedMemoryPaths?: string[];
3547
- includedMemoryNamespaces?: Array<string | undefined>;
3548
3546
  omittedMemoryIds?: string[];
3549
3547
  omittedSections?: string[];
3550
3548
  }): LastRecallBudgetSummary {
@@ -17,6 +17,10 @@ function legacySnapshot(
17
17
  queryHash: "deadbeef",
18
18
  queryLen: 21,
19
19
  memoryIds: ["mem-1", "mem-2"],
20
+ includedMemories: [
21
+ { id: "mem-1", path: "" },
22
+ { id: "mem-2", path: "" },
23
+ ],
20
24
  source: "hot_qmd",
21
25
  sourcesUsed: ["hot_qmd", "memories"],
22
26
  namespace: "workspace-a",
@@ -4,7 +4,7 @@ import { chmod, lstat, mkdir, mkdtemp, readFile, readdir, rm, stat, symlink, wri
4
4
  import os from "node:os";
5
5
  import path from "node:path";
6
6
 
7
- import { clampGraphRecallExpandedEntries, LastRecallStore } from "./recall-state.js";
7
+ import { clampGraphRecallExpandedEntries, LastRecallStore, RecallHandleHistoryStore } from "./recall-state.js";
8
8
  import type { RecallTierExplain } from "./types.js";
9
9
  import { listContainedSpillFiles } from "./utils/path-containment.js";
10
10
 
@@ -83,19 +83,69 @@ test("LastRecallStore.record persists tierExplain and round-trips to JSON on dis
83
83
  assert.deepEqual(parsed["s1"]?.tierExplain, tierExplain);
84
84
  });
85
85
 
86
- test("LastRecallStore.record persists per-result namespaces", async () => {
86
+ test("LastRecallStore.record shims legacy resultPaths/resultNamespaces into includedMemories", async () => {
87
87
  const { store } = await freshStore();
88
- const resultNamespaces = ["main", "shared"] as Array<string | undefined>;
89
88
  await store.record({
90
89
  sessionKey: "s1",
91
90
  query: "namespaced recall",
92
91
  memoryIds: ["same-id", "same-id"],
93
92
  resultPaths: ["facts/same-id.md", "facts/same-id.md"],
94
- resultNamespaces,
93
+ resultNamespaces: ["main", "shared"],
95
94
  });
96
95
  const snap = store.get("s1");
97
96
  assert.ok(snap);
98
- assert.deepEqual(snap.resultNamespaces, resultNamespaces);
97
+ assert.deepEqual(snap.includedMemories, [
98
+ { id: "same-id", path: "facts/same-id.md", namespace: "main" },
99
+ { id: "same-id", path: "facts/same-id.md", namespace: "shared" },
100
+ ]);
101
+ assert.deepEqual(snap.memoryIds, ["same-id", "same-id"]);
102
+ });
103
+
104
+ // ── Legacy on-disk shapes hydrate to includedMemories (#2476) ─────────────
105
+
106
+ test("LastRecallStore.load shims legacy last_recall.json shapes to includedMemories", async () => {
107
+ const { dir } = await freshStore();
108
+ const fixturePath = path.resolve(
109
+ import.meta.dirname,
110
+ "../../../tests/fixtures/last-recall-legacy-shape.json",
111
+ );
112
+ const fixture = JSON.parse(await readFile(fixturePath, "utf-8")) as Record<string, unknown>;
113
+
114
+ await mkdir(path.join(dir, "state"), { recursive: true });
115
+ await writeFile(
116
+ path.join(dir, "state", "last_recall.json"),
117
+ JSON.stringify(fixture),
118
+ "utf-8",
119
+ );
120
+ const store = new LastRecallStore(dir);
121
+ await store.load();
122
+
123
+ const full = store.get("legacy-full");
124
+ assert.ok(full);
125
+ assert.deepEqual(full.includedMemories, [
126
+ {
127
+ id: "fact-alpha",
128
+ path: "/memory-under-test/namespaces/team-alpha/facts/2026-08-01/fact-alpha.md",
129
+ namespace: "team-alpha",
130
+ },
131
+ { id: "fact-beta", path: "/memory-under-test/facts/2026-08-01/fact-beta.md" },
132
+ {
133
+ id: "fact-gamma",
134
+ path: "/memory-under-test/namespaces/team-alpha/facts/2026-08-01/fact-gamma.md",
135
+ namespace: "team-alpha",
136
+ },
137
+ ]);
138
+ assert.deepEqual(full.memoryIds, ["fact-alpha", "fact-beta", "fact-gamma"]);
139
+ assert.deepEqual(
140
+ full.resultPaths,
141
+ full.includedMemories?.map((memory) => memory.path),
142
+ );
143
+ assert.deepEqual(full.budgetsApplied?.omittedMemoryIds, ["fact-dropped"]);
144
+
145
+ const idsOnly = store.get("legacy-ids-only");
146
+ assert.ok(idsOnly);
147
+ assert.deepEqual(idsOnly.includedMemories, [{ id: "fact-delta", path: "" }]);
148
+ assert.deepEqual(idsOnly.memoryIds, ["fact-delta"]);
99
149
  });
100
150
 
101
151
  // ── Defensive copies isolate the stored snapshot from caller mutation ──────
@@ -1083,3 +1133,56 @@ test("LastRecallStore.drainPendingImpressions reports pendingDeferred when a spi
1083
1133
  await rm(dir, { recursive: true, force: true });
1084
1134
  }
1085
1135
  });
1136
+ +
1137
+ test("LastRecallStore rejects unsafe session keys on every read/write path", async () => {
1138
+ const { store, dir } = await freshStore();
1139
+ for (const key of ["__proto__", "constructor", "prototype"]) {
1140
+ await store.record({ sessionKey: key, query: "q", memoryIds: ["m-1"] });
1141
+ assert.equal(store.get(key), null, `get(${key}) must not surface prototype junk`);
1142
+ }
1143
+ assert.equal(store.getMostRecent(), null);
1144
+
1145
+ await store.annotateTierExplain("__proto__", {
1146
+ tier: "direct-answer",
1147
+ tierReason: "",
1148
+ filteredBy: [],
1149
+ candidatesConsidered: 0,
1150
+ latencyMs: 0,
1151
+ });
1152
+ assert.equal(store.get("__proto__"), null);
1153
+ const persistedKeys = await readFile(path.join(dir, "state", "last_recall.json"), "utf-8")
1154
+ .then((raw) => Object.keys(JSON.parse(raw) as object))
1155
+ .catch(() => [] as string[]);
1156
+ assert.deepEqual(persistedKeys, [], "no unsafe key persisted");
1157
+ });
1158
+
1159
+ test("RecallHandleHistoryStore rejects unsafe session keys", async () => {
1160
+ const dir = await mkdtemp(path.join(os.tmpdir(), "engram-handle-history-"));
1161
+ const store = new RecallHandleHistoryStore(dir);
1162
+ await store.load();
1163
+
1164
+ await store.record("__proto__", ["m-1"]);
1165
+ await store.record("constructor", ["m-2"]);
1166
+ assert.deepEqual(store.recent("__proto__"), []);
1167
+ assert.deepEqual(store.recent("constructor"), []);
1168
+
1169
+ await store.record("ok", ["m-3"]);
1170
+ assert.deepEqual(store.recent("ok"), [["m-3"]]);
1171
+ await rm(dir, { recursive: true, force: true });
1172
+ });
1173
+
1174
+ test("RecallHandleHistoryStore.load drops unsafe and malformed entries from persisted state", async () => {
1175
+ const dir = await mkdtemp(path.join(os.tmpdir(), "engram-handle-history-"));
1176
+ await mkdir(path.join(dir, "state"), { recursive: true });
1177
+ // JSON.parse materializes "__proto__" as an OWN key; load must not adopt it.
1178
+ const poisoned =
1179
+ '{"__proto__": [{"at": "t", "ids": ["evil"]}], "bad": "not-an-array", "ok": [{"at": "t", "ids": ["m-1"]}]}';
1180
+ await writeFile(path.join(dir, "state", "handle_history.json"), poisoned, "utf-8");
1181
+
1182
+ const store = new RecallHandleHistoryStore(dir);
1183
+ await store.load();
1184
+ assert.deepEqual(store.recent("__proto__"), []);
1185
+ assert.deepEqual(store.recent("bad"), []);
1186
+ assert.deepEqual(store.recent("ok"), [["m-1"]]);
1187
+ await rm(dir, { recursive: true, force: true });
1188
+ });