@remnic/core 10.0.36 → 10.0.38

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 (422) hide show
  1. package/dist/access-admin-ops-surface.js +84 -84
  2. package/dist/access-authorization-probe.js +85 -85
  3. package/dist/access-boundary.js +84 -84
  4. package/dist/access-citation-namespace.js +2 -2
  5. package/dist/access-cli.js +178 -176
  6. package/dist/access-cli.js.map +1 -1
  7. package/dist/access-extraction-force-flush.js +84 -84
  8. package/dist/access-http-briefing.js +85 -85
  9. package/dist/access-http-query.js +86 -86
  10. package/dist/access-http.js +108 -108
  11. package/dist/access-identity-continuity-surface.js +84 -84
  12. package/dist/access-lcm-surface.js +84 -84
  13. package/dist/access-mcp.js +97 -97
  14. package/dist/access-namespace-preflight.js +84 -84
  15. package/dist/access-observe-write-category.js +13 -13
  16. package/dist/access-observe-write-surface.js +84 -84
  17. package/dist/access-offline-manifest.js +12 -12
  18. package/dist/access-operations-batch.js +88 -88
  19. package/dist/access-operations.js +95 -95
  20. package/dist/access-recall-concurrency.js +84 -84
  21. package/dist/access-recall-diagnostics.js +2 -2
  22. package/dist/access-recall-response.js +84 -84
  23. package/dist/access-recall-surface.js +84 -84
  24. package/dist/access-schema.js +8 -8
  25. package/dist/access-service.js +84 -84
  26. package/dist/access-surface-catalog.js +86 -86
  27. package/dist/active-recall.js +43 -43
  28. package/dist/adapters/index.js +7 -7
  29. package/dist/adapters/registry.js +3 -3
  30. package/dist/{auto-sync-VPHR3FBI.js → auto-sync-432USQDH.js} +9 -9
  31. package/dist/briefing.js +32 -32
  32. package/dist/buffer-eviction.d.ts +16 -0
  33. package/dist/buffer-eviction.d.ts.map +1 -0
  34. package/dist/buffer-eviction.js +8 -0
  35. package/dist/buffer-persistence.d.ts +45 -0
  36. package/dist/buffer-persistence.d.ts.map +1 -0
  37. package/dist/buffer-persistence.js +8 -0
  38. package/dist/buffer.d.ts +5 -2
  39. package/dist/buffer.d.ts.map +1 -1
  40. package/dist/buffer.js +13 -11
  41. package/dist/calibration.js +1 -1
  42. package/dist/causal-behavior.js +2 -2
  43. package/dist/causal-chain.js +2 -2
  44. package/dist/causal-consolidation.js +35 -35
  45. package/dist/causal-retrieval.js +2 -2
  46. package/dist/causal-trajectory-graph.js +2 -2
  47. package/dist/causal-trajectory.js +1 -1
  48. package/dist/{chunk-FL6SLVAJ.js → chunk-2AKIVSHP.js} +2 -2
  49. package/dist/{chunk-ORWDCX5Q.js → chunk-3AODCBKX.js} +11 -11
  50. package/dist/{chunk-XFDHL252.js → chunk-3K5IEJTK.js} +4 -4
  51. package/dist/{chunk-6FIFEXFF.js → chunk-3PLAL2KP.js} +21 -7
  52. package/dist/chunk-3PLAL2KP.js.map +1 -0
  53. package/dist/{chunk-XVZA6VXC.js → chunk-3SL52JKD.js} +4 -4
  54. package/dist/{chunk-ZSAQSLKL.js → chunk-3XVBGGF3.js} +2 -2
  55. package/dist/{chunk-XO4HOBM2.js → chunk-4B37KNMP.js} +2 -2
  56. package/dist/{chunk-NIANATGL.js → chunk-4IZ6AC2U.js} +2 -2
  57. package/dist/chunk-4OFXLQJD.js +58 -0
  58. package/dist/chunk-4OFXLQJD.js.map +1 -0
  59. package/dist/{chunk-S2PDFSXS.js → chunk-4P4VLPGB.js} +1 -1
  60. package/dist/{chunk-G5UR4DXQ.js → chunk-53BLBDV6.js} +2 -2
  61. package/dist/{chunk-PDYP7SUC.js → chunk-5ANUG4JZ.js} +2 -2
  62. package/dist/{chunk-2ZYIAUYU.js → chunk-5CWH2LKL.js} +4 -4
  63. package/dist/{chunk-S2S4U4G3.js → chunk-5DCS4C4S.js} +4 -4
  64. package/dist/{chunk-7WTTE5FW.js → chunk-5K23NQRI.js} +2 -2
  65. package/dist/{chunk-V3JZZJ2E.js → chunk-5UPOKIFP.js} +12 -12
  66. package/dist/{chunk-K567EIW3.js → chunk-63YPKHAU.js} +2 -2
  67. package/dist/{chunk-G3T6YMBO.js → chunk-64S6X4IU.js} +7 -7
  68. package/dist/{chunk-HJM23E65.js → chunk-6DTIYAAN.js} +2 -2
  69. package/dist/{chunk-G7XAZU2L.js → chunk-6F5BGIAF.js} +3 -3
  70. package/dist/{chunk-IHTKBQBS.js → chunk-6JEEY42N.js} +2 -2
  71. package/dist/{chunk-NHB4RC3G.js → chunk-6QOL4G76.js} +2 -2
  72. package/dist/{chunk-AD3ZB72W.js → chunk-6SYS5YX3.js} +2 -2
  73. package/dist/{chunk-DFP37GUN.js → chunk-7HXZOWTR.js} +2 -2
  74. package/dist/{chunk-DGBWPSM6.js → chunk-7VFNGQ4V.js} +2 -2
  75. package/dist/{chunk-77ZK533I.js → chunk-7ZRRJ6RG.js} +2 -2
  76. package/dist/{chunk-GMMZ45C4.js → chunk-AVVCPA7U.js} +6 -8
  77. package/dist/chunk-AVVCPA7U.js.map +1 -0
  78. package/dist/{chunk-QISYYK4L.js → chunk-AYBAC2N4.js} +3 -3
  79. package/dist/{chunk-V44DWTFA.js → chunk-AYXRK264.js} +6 -6
  80. package/dist/{chunk-LJSBF6PW.js → chunk-C2KOW2UQ.js} +2 -2
  81. package/dist/{chunk-GY4R4P2A.js → chunk-CUWOSRCS.js} +2 -2
  82. package/dist/{chunk-VNAIUNXI.js → chunk-CVMAOPAH.js} +10 -10
  83. package/dist/{chunk-CJKHLACF.js → chunk-DG4H56SK.js} +2 -2
  84. package/dist/{chunk-BQ6DGL6A.js → chunk-DKHX2FHI.js} +2 -2
  85. package/dist/{chunk-77IXBNV6.js → chunk-E24RUQEN.js} +2 -2
  86. package/dist/{chunk-HRT2SJPC.js → chunk-E3NBMTTX.js} +2 -2
  87. package/dist/{chunk-PTQZPVRQ.js → chunk-E5PVMB3I.js} +2 -2
  88. package/dist/{chunk-AHS3QEEA.js → chunk-EEOYF3IB.js} +2 -2
  89. package/dist/{chunk-5XTSIZ3L.js → chunk-EGNONTVT.js} +6 -6
  90. package/dist/{chunk-PH33R7GN.js → chunk-EHIKY2IA.js} +2 -2
  91. package/dist/{chunk-4ISHIPOC.js → chunk-FGEY2AGV.js} +2 -2
  92. package/dist/{chunk-O6YJI5VX.js → chunk-FKTMWDN2.js} +2 -2
  93. package/dist/{chunk-KQUN4RSX.js → chunk-FQFMLOAC.js} +18 -18
  94. package/dist/{chunk-5LWODP5R.js → chunk-FRAL3EU4.js} +2 -2
  95. package/dist/{chunk-AAANTXCQ.js → chunk-FZVZYU5C.js} +2 -2
  96. package/dist/{chunk-TGAXRT7N.js → chunk-GFYFKXWZ.js} +2 -2
  97. package/dist/{chunk-ID2PLENW.js → chunk-GGI6FLO6.js} +2 -2
  98. package/dist/{chunk-GDYLZ6FR.js → chunk-HJ3UTGIW.js} +3 -3
  99. package/dist/{chunk-X3IFRQKS.js → chunk-I73ZSORJ.js} +4 -4
  100. package/dist/{chunk-X73SCHKR.js → chunk-I75BWXRZ.js} +2 -2
  101. package/dist/{chunk-M3GKSCFN.js → chunk-J7G656MY.js} +4 -4
  102. package/dist/{chunk-EH6KLYIE.js → chunk-JF3MEIHO.js} +4 -4
  103. package/dist/{chunk-XUB4I2N6.js → chunk-JFI3ATK4.js} +2 -2
  104. package/dist/{chunk-R4SATHCV.js → chunk-JH2ALMPR.js} +2 -2
  105. package/dist/{chunk-TKBW4YLS.js → chunk-JH4FCVWJ.js} +2 -2
  106. package/dist/{chunk-DG5UKN2Y.js → chunk-JIA435P3.js} +2 -2
  107. package/dist/chunk-KASJJGRG.js +29 -0
  108. package/dist/chunk-KASJJGRG.js.map +1 -0
  109. package/dist/{chunk-4Z7O2QVJ.js → chunk-KOAVX2IT.js} +2 -2
  110. package/dist/{chunk-6NXHX6MI.js → chunk-KOY25HUB.js} +2 -2
  111. package/dist/{chunk-TRW7N4FS.js → chunk-L2JQSG5M.js} +2 -2
  112. package/dist/{chunk-QQ4T622E.js → chunk-L7PGPH4E.js} +2 -2
  113. package/dist/{chunk-TYT4TEQV.js → chunk-LDWE7OZS.js} +6 -2
  114. package/dist/chunk-LDWE7OZS.js.map +1 -0
  115. package/dist/{chunk-23VGZ65V.js → chunk-LHBOFROT.js} +2 -2
  116. package/dist/{chunk-VKB2FGNW.js → chunk-LOMSBYNS.js} +90 -90
  117. package/dist/{chunk-NDJ42GKB.js → chunk-MCPSMWUC.js} +6 -6
  118. package/dist/{chunk-ERMT5WQM.js → chunk-MKE5DP3S.js} +2 -2
  119. package/dist/{chunk-64IO6ZEE.js → chunk-MZWHIAOL.js} +2 -2
  120. package/dist/{chunk-LDXS746V.js → chunk-N7DVBHU3.js} +3 -3
  121. package/dist/{chunk-F2JLBXMG.js → chunk-NH6GZEQN.js} +8 -8
  122. package/dist/{chunk-7FG2JSU6.js → chunk-NMKETOAX.js} +2 -2
  123. package/dist/{chunk-GAARPWMN.js → chunk-OKKBOTRA.js} +2 -2
  124. package/dist/{chunk-PCIIKQXW.js → chunk-OLH4XCLU.js} +2 -2
  125. package/dist/{chunk-XA32GZ6B.js → chunk-OLHN4ZNT.js} +3 -3
  126. package/dist/{chunk-UR25IQVT.js → chunk-P5CUEB2Q.js} +8 -8
  127. package/dist/{chunk-LO775P3S.js → chunk-POGPI5GR.js} +2 -2
  128. package/dist/{chunk-FXO43NBW.js → chunk-PSQ2P2T3.js} +3 -3
  129. package/dist/{chunk-KRAMCBIW.js → chunk-QKXPOLQD.js} +4 -4
  130. package/dist/{chunk-65JLKIVA.js → chunk-QO5KDQGG.js} +8 -8
  131. package/dist/{chunk-A4B7WL5N.js → chunk-QOUKZ2N3.js} +2 -2
  132. package/dist/{chunk-ZABEDRGQ.js → chunk-RGKXF4W3.js} +2 -2
  133. package/dist/{chunk-IKCGNTGS.js → chunk-RWRHGE75.js} +2 -2
  134. package/dist/{chunk-NBH7IRME.js → chunk-SWZOAQUM.js} +54 -54
  135. package/dist/{chunk-FQ52AJXX.js → chunk-SZPPCEYT.js} +2 -2
  136. package/dist/{chunk-4YYIZ475.js → chunk-TAEJ2MRR.js} +52 -52
  137. package/dist/{chunk-3ODEGTVV.js → chunk-TDCR6PQL.js} +2 -2
  138. package/dist/{chunk-QCP75JGO.js → chunk-TFA6HPOA.js} +5 -5
  139. package/dist/{chunk-BBDASWNT.js → chunk-TJ5YGCPV.js} +81 -76
  140. package/dist/chunk-TJ5YGCPV.js.map +1 -0
  141. package/dist/{chunk-SE3JAD22.js → chunk-TPKB7T6Z.js} +2 -2
  142. package/dist/{chunk-6VYY2XFK.js → chunk-TVIGN3XZ.js} +19 -19
  143. package/dist/{chunk-OHMGR6QN.js → chunk-TXP7Q7T5.js} +2 -2
  144. package/dist/{chunk-ZG3HZZ6K.js → chunk-TYGLV6ZG.js} +5 -1
  145. package/dist/{chunk-ZG3HZZ6K.js.map → chunk-TYGLV6ZG.js.map} +1 -1
  146. package/dist/{chunk-AI2VXOSO.js → chunk-TYLNWE4D.js} +2 -2
  147. package/dist/{chunk-WI6MIJYK.js → chunk-U7HJBODU.js} +5 -5
  148. package/dist/{chunk-IS4HKNWP.js → chunk-UBN5AOLT.js} +2 -2
  149. package/dist/{chunk-A6PKEU7T.js → chunk-UFM3PJDT.js} +1 -1
  150. package/dist/chunk-UFM3PJDT.js.map +1 -0
  151. package/dist/{chunk-JNELS2TW.js → chunk-UJDTXWMT.js} +2 -2
  152. package/dist/{chunk-DJMC4W6N.js → chunk-VC3X7XP3.js} +2 -2
  153. package/dist/{chunk-A2D3WICT.js → chunk-VGFNTY3Y.js} +2 -2
  154. package/dist/{chunk-X544TW54.js → chunk-VGRM43X6.js} +2 -2
  155. package/dist/{chunk-CSGFGQBI.js → chunk-VPO53QMG.js} +2 -2
  156. package/dist/{chunk-BRZRP5WD.js → chunk-VSSQIBVU.js} +2 -2
  157. package/dist/{chunk-O3VKQMWC.js → chunk-WCBLPKG3.js} +366 -168
  158. package/dist/chunk-WCBLPKG3.js.map +1 -0
  159. package/dist/{chunk-GKNX4QO3.js → chunk-WCIDCJOQ.js} +3 -3
  160. package/dist/{chunk-7VJEZQYF.js → chunk-WEK3OUGO.js} +3 -3
  161. package/dist/{chunk-IVYAPAHG.js → chunk-WRDFYSUC.js} +2 -2
  162. package/dist/{chunk-5EILJ6W2.js → chunk-WXPBDEMW.js} +2 -2
  163. package/dist/{chunk-QZP3RMYP.js → chunk-X247CYL6.js} +4 -4
  164. package/dist/{chunk-UAYA4NJN.js → chunk-XHVO3CGX.js} +28 -36
  165. package/dist/chunk-XHVO3CGX.js.map +1 -0
  166. package/dist/{chunk-YLF42JQ7.js → chunk-XHX67LX6.js} +2 -2
  167. package/dist/{chunk-C6S2Y7HE.js → chunk-XKDQTDXN.js} +4 -4
  168. package/dist/{chunk-4AHKNZW7.js → chunk-XLEP7SS3.js} +2 -2
  169. package/dist/{chunk-B6L7BKA7.js → chunk-XRFLR3XF.js} +4 -4
  170. package/dist/{chunk-H7QC7WCU.js → chunk-XTBEXZFN.js} +4 -4
  171. package/dist/{chunk-CIJRM6SQ.js → chunk-Y5ZHZKZD.js} +2 -2
  172. package/dist/{chunk-H6SKBCNI.js → chunk-YC2C67F7.js} +2 -2
  173. package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
  174. package/dist/{chunk-YOL56HY5.js → chunk-YQ6SLFNZ.js} +3 -3
  175. package/dist/{chunk-SIIWHIBK.js → chunk-YYGZ4EIY.js} +2 -2
  176. package/dist/{chunk-G22A6WJQ.js → chunk-Z2T5BPOZ.js} +2 -2
  177. package/dist/{chunk-RYUSWAAU.js → chunk-ZAP7BKTZ.js} +6 -6
  178. package/dist/cli.js +136 -136
  179. package/dist/coding/export-okf-codegraph.js +33 -33
  180. package/dist/coding/pre-action-gate.js +2 -2
  181. package/dist/compounding/engine.js +34 -34
  182. package/dist/config.d.ts.map +1 -1
  183. package/dist/config.js +43 -43
  184. package/dist/connectors/codex-materialize-runner.js +32 -32
  185. package/dist/connectors/index.js +32 -32
  186. package/dist/contradiction/index.js +5 -5
  187. package/dist/convergence-refresh.js +34 -34
  188. package/dist/conversation-index/backend.js +2 -2
  189. package/dist/corpus-watermark.js +34 -34
  190. package/dist/dashboard-runtime.js +2 -2
  191. package/dist/deep-recall-http-glue.js +9 -9
  192. package/dist/deep-recall-policy-llm.js +2 -2
  193. package/dist/entity-retrieval.js +34 -34
  194. package/dist/explicit-capture.js +7 -7
  195. package/dist/external-wiki-access.js +85 -85
  196. package/dist/extraction-faithfulness.js +2 -2
  197. package/dist/extraction-judge.d.ts +42 -2
  198. package/dist/extraction-judge.d.ts.map +1 -1
  199. package/dist/extraction-judge.js +12 -2
  200. package/dist/extraction-span-materialize.js +2 -2
  201. package/dist/extraction.js +47 -47
  202. package/dist/fallback-llm.d.ts +1 -0
  203. package/dist/fallback-llm.d.ts.map +1 -1
  204. package/dist/fallback-llm.js +1 -1
  205. package/dist/{graph-edge-decay-IU75NV42.js → graph-edge-decay-2BZTY2IM.js} +5 -5
  206. package/dist/graph-edge-decay-2BZTY2IM.js.map +1 -0
  207. package/dist/graph-jsonl.js +3 -3
  208. package/dist/graph-snapshot.js +3 -3
  209. package/dist/graph.js +2 -2
  210. package/dist/harmonic-retrieval.js +33 -33
  211. package/dist/harmonic-source-lookup.js +2 -2
  212. package/dist/index.js +236 -234
  213. package/dist/lcm/index.js +3 -3
  214. package/dist/location/index.js +35 -35
  215. package/dist/maintenance/memory-governance.js +32 -32
  216. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +32 -32
  217. package/dist/maintenance/rebuild-memory-projection-runner.js +34 -34
  218. package/dist/maintenance/rebuild-memory-projection.js +33 -33
  219. package/dist/memory-browse-operations.js +85 -85
  220. package/dist/memory-browse.js +5 -5
  221. package/dist/memory-subject.js +3 -3
  222. package/dist/namespaces/migrate.js +33 -33
  223. package/dist/namespaces/search.js +11 -11
  224. package/dist/namespaces/storage.js +32 -32
  225. package/dist/offline-sync-changeset-generations.js +3 -3
  226. package/dist/offline-sync-embedding-generation.js +2 -2
  227. package/dist/offline-sync-file-io.js +2 -2
  228. package/dist/offline-sync-impression-drain.js +3 -3
  229. package/dist/offline-sync-runtime-state.d.ts.map +1 -1
  230. package/dist/offline-sync-runtime-state.js +1 -1
  231. package/dist/offline-sync-snapshot-stream.js +8 -8
  232. package/dist/offline-sync-upload-staging.js +3 -3
  233. package/dist/offline-sync.js +8 -8
  234. package/dist/operator-doctor-corpus.js +35 -35
  235. package/dist/operator-toolkit.js +54 -54
  236. package/dist/orchestration/maintenance.js +44 -44
  237. package/dist/orchestrator.js +183 -181
  238. package/dist/qmd.js +4 -4
  239. package/dist/recall-explain-renderer.js +3 -3
  240. package/dist/recall-navigate-access.js +2 -2
  241. package/dist/recall-navigate-disclosure.js +2 -2
  242. package/dist/recall-navigate.js +2 -2
  243. package/dist/recall-navigation-operations.js +85 -85
  244. package/dist/recall-navigation.js +84 -84
  245. package/dist/recall-planner-llm.js +1 -1
  246. package/dist/recall-state-view-admission.js +5 -5
  247. package/dist/recall-why-service.js +5 -5
  248. package/dist/recall-xray-cli.js +4 -4
  249. package/dist/recall-xray-renderer.js +3 -3
  250. package/dist/recall-xray.js +2 -2
  251. package/dist/reconcile/manifest.js +3 -3
  252. package/dist/{resolution-V6JBMW7U.js → resolution-4ZEQPXUZ.js} +6 -6
  253. package/dist/resolution-4ZEQPXUZ.js.map +1 -0
  254. package/dist/resume-bundles.js +44 -44
  255. package/dist/retrieval-agents.js +2 -2
  256. package/dist/salvage-envelope.js +5 -5
  257. package/dist/search/factory.js +10 -10
  258. package/dist/search/index.js +14 -14
  259. package/dist/search/lancedb-backend.js +2 -2
  260. package/dist/search/meilisearch-backend.js +2 -2
  261. package/dist/search/orama-backend.js +2 -2
  262. package/dist/secure-store/index.js +2 -2
  263. package/dist/semantic-consolidation.js +33 -33
  264. package/dist/semantic-rule-promotion.js +32 -32
  265. package/dist/semantic-rule-verifier.js +32 -32
  266. package/dist/source-agent-qualifier.js +37 -37
  267. package/dist/standup/build.js +32 -32
  268. package/dist/storage/buffer-session-files.d.ts +69 -0
  269. package/dist/storage/buffer-session-files.d.ts.map +1 -0
  270. package/dist/storage.d.ts +5 -1
  271. package/dist/storage.d.ts.map +1 -1
  272. package/dist/storage.js +31 -31
  273. package/dist/subject-config.js +4 -4
  274. package/dist/summarizer.js +2 -2
  275. package/dist/support-passport/index.js +87 -87
  276. package/dist/transfer/export-okf.js +33 -33
  277. package/dist/types.d.ts +12 -0
  278. package/dist/types.d.ts.map +1 -1
  279. package/dist/types.js +1 -1
  280. package/dist/verified-recall.js +32 -32
  281. package/dist/who-knows-cli.js +33 -33
  282. package/dist/who-knows.js +32 -32
  283. package/dist/write-envelope.js +4 -4
  284. package/package.json +2 -2
  285. package/src/buffer-eviction.ts +51 -0
  286. package/src/buffer-incremental-persistence.test.ts +256 -0
  287. package/src/buffer-persistence.ts +89 -0
  288. package/src/buffer.ts +32 -61
  289. package/src/config.test.ts +16 -0
  290. package/src/config.ts +14 -0
  291. package/src/extraction-judge-chain.test.ts +298 -2
  292. package/src/extraction-judge.ts +147 -82
  293. package/src/fallback-llm.test.ts +94 -0
  294. package/src/fallback-llm.ts +7 -7
  295. package/src/offline-sync-runtime-state.ts +24 -2
  296. package/src/offline-sync.test.ts +9 -0
  297. package/src/secure-store/secure-fs.ts +11 -0
  298. package/src/secure-store/secure-store.test.ts +22 -0
  299. package/src/storage/buffer-session-files.ts +249 -0
  300. package/src/storage-buffer-sessions.test.ts +369 -0
  301. package/src/storage.ts +11 -16
  302. package/src/types.ts +12 -0
  303. package/dist/chunk-6FIFEXFF.js.map +0 -1
  304. package/dist/chunk-A6PKEU7T.js.map +0 -1
  305. package/dist/chunk-BBDASWNT.js.map +0 -1
  306. package/dist/chunk-GMMZ45C4.js.map +0 -1
  307. package/dist/chunk-O3VKQMWC.js.map +0 -1
  308. package/dist/chunk-TYT4TEQV.js.map +0 -1
  309. package/dist/chunk-UAYA4NJN.js.map +0 -1
  310. /package/dist/{auto-sync-VPHR3FBI.js.map → auto-sync-432USQDH.js.map} +0 -0
  311. /package/dist/{graph-edge-decay-IU75NV42.js.map → buffer-eviction.js.map} +0 -0
  312. /package/dist/{resolution-V6JBMW7U.js.map → buffer-persistence.js.map} +0 -0
  313. /package/dist/{chunk-FL6SLVAJ.js.map → chunk-2AKIVSHP.js.map} +0 -0
  314. /package/dist/{chunk-ORWDCX5Q.js.map → chunk-3AODCBKX.js.map} +0 -0
  315. /package/dist/{chunk-XFDHL252.js.map → chunk-3K5IEJTK.js.map} +0 -0
  316. /package/dist/{chunk-XVZA6VXC.js.map → chunk-3SL52JKD.js.map} +0 -0
  317. /package/dist/{chunk-ZSAQSLKL.js.map → chunk-3XVBGGF3.js.map} +0 -0
  318. /package/dist/{chunk-XO4HOBM2.js.map → chunk-4B37KNMP.js.map} +0 -0
  319. /package/dist/{chunk-NIANATGL.js.map → chunk-4IZ6AC2U.js.map} +0 -0
  320. /package/dist/{chunk-S2PDFSXS.js.map → chunk-4P4VLPGB.js.map} +0 -0
  321. /package/dist/{chunk-G5UR4DXQ.js.map → chunk-53BLBDV6.js.map} +0 -0
  322. /package/dist/{chunk-PDYP7SUC.js.map → chunk-5ANUG4JZ.js.map} +0 -0
  323. /package/dist/{chunk-2ZYIAUYU.js.map → chunk-5CWH2LKL.js.map} +0 -0
  324. /package/dist/{chunk-S2S4U4G3.js.map → chunk-5DCS4C4S.js.map} +0 -0
  325. /package/dist/{chunk-7WTTE5FW.js.map → chunk-5K23NQRI.js.map} +0 -0
  326. /package/dist/{chunk-V3JZZJ2E.js.map → chunk-5UPOKIFP.js.map} +0 -0
  327. /package/dist/{chunk-K567EIW3.js.map → chunk-63YPKHAU.js.map} +0 -0
  328. /package/dist/{chunk-G3T6YMBO.js.map → chunk-64S6X4IU.js.map} +0 -0
  329. /package/dist/{chunk-HJM23E65.js.map → chunk-6DTIYAAN.js.map} +0 -0
  330. /package/dist/{chunk-G7XAZU2L.js.map → chunk-6F5BGIAF.js.map} +0 -0
  331. /package/dist/{chunk-IHTKBQBS.js.map → chunk-6JEEY42N.js.map} +0 -0
  332. /package/dist/{chunk-NHB4RC3G.js.map → chunk-6QOL4G76.js.map} +0 -0
  333. /package/dist/{chunk-AD3ZB72W.js.map → chunk-6SYS5YX3.js.map} +0 -0
  334. /package/dist/{chunk-DFP37GUN.js.map → chunk-7HXZOWTR.js.map} +0 -0
  335. /package/dist/{chunk-DGBWPSM6.js.map → chunk-7VFNGQ4V.js.map} +0 -0
  336. /package/dist/{chunk-77ZK533I.js.map → chunk-7ZRRJ6RG.js.map} +0 -0
  337. /package/dist/{chunk-QISYYK4L.js.map → chunk-AYBAC2N4.js.map} +0 -0
  338. /package/dist/{chunk-V44DWTFA.js.map → chunk-AYXRK264.js.map} +0 -0
  339. /package/dist/{chunk-LJSBF6PW.js.map → chunk-C2KOW2UQ.js.map} +0 -0
  340. /package/dist/{chunk-GY4R4P2A.js.map → chunk-CUWOSRCS.js.map} +0 -0
  341. /package/dist/{chunk-VNAIUNXI.js.map → chunk-CVMAOPAH.js.map} +0 -0
  342. /package/dist/{chunk-CJKHLACF.js.map → chunk-DG4H56SK.js.map} +0 -0
  343. /package/dist/{chunk-BQ6DGL6A.js.map → chunk-DKHX2FHI.js.map} +0 -0
  344. /package/dist/{chunk-77IXBNV6.js.map → chunk-E24RUQEN.js.map} +0 -0
  345. /package/dist/{chunk-HRT2SJPC.js.map → chunk-E3NBMTTX.js.map} +0 -0
  346. /package/dist/{chunk-PTQZPVRQ.js.map → chunk-E5PVMB3I.js.map} +0 -0
  347. /package/dist/{chunk-AHS3QEEA.js.map → chunk-EEOYF3IB.js.map} +0 -0
  348. /package/dist/{chunk-5XTSIZ3L.js.map → chunk-EGNONTVT.js.map} +0 -0
  349. /package/dist/{chunk-PH33R7GN.js.map → chunk-EHIKY2IA.js.map} +0 -0
  350. /package/dist/{chunk-4ISHIPOC.js.map → chunk-FGEY2AGV.js.map} +0 -0
  351. /package/dist/{chunk-O6YJI5VX.js.map → chunk-FKTMWDN2.js.map} +0 -0
  352. /package/dist/{chunk-KQUN4RSX.js.map → chunk-FQFMLOAC.js.map} +0 -0
  353. /package/dist/{chunk-5LWODP5R.js.map → chunk-FRAL3EU4.js.map} +0 -0
  354. /package/dist/{chunk-AAANTXCQ.js.map → chunk-FZVZYU5C.js.map} +0 -0
  355. /package/dist/{chunk-TGAXRT7N.js.map → chunk-GFYFKXWZ.js.map} +0 -0
  356. /package/dist/{chunk-ID2PLENW.js.map → chunk-GGI6FLO6.js.map} +0 -0
  357. /package/dist/{chunk-GDYLZ6FR.js.map → chunk-HJ3UTGIW.js.map} +0 -0
  358. /package/dist/{chunk-X3IFRQKS.js.map → chunk-I73ZSORJ.js.map} +0 -0
  359. /package/dist/{chunk-X73SCHKR.js.map → chunk-I75BWXRZ.js.map} +0 -0
  360. /package/dist/{chunk-M3GKSCFN.js.map → chunk-J7G656MY.js.map} +0 -0
  361. /package/dist/{chunk-EH6KLYIE.js.map → chunk-JF3MEIHO.js.map} +0 -0
  362. /package/dist/{chunk-XUB4I2N6.js.map → chunk-JFI3ATK4.js.map} +0 -0
  363. /package/dist/{chunk-R4SATHCV.js.map → chunk-JH2ALMPR.js.map} +0 -0
  364. /package/dist/{chunk-TKBW4YLS.js.map → chunk-JH4FCVWJ.js.map} +0 -0
  365. /package/dist/{chunk-DG5UKN2Y.js.map → chunk-JIA435P3.js.map} +0 -0
  366. /package/dist/{chunk-4Z7O2QVJ.js.map → chunk-KOAVX2IT.js.map} +0 -0
  367. /package/dist/{chunk-6NXHX6MI.js.map → chunk-KOY25HUB.js.map} +0 -0
  368. /package/dist/{chunk-TRW7N4FS.js.map → chunk-L2JQSG5M.js.map} +0 -0
  369. /package/dist/{chunk-QQ4T622E.js.map → chunk-L7PGPH4E.js.map} +0 -0
  370. /package/dist/{chunk-23VGZ65V.js.map → chunk-LHBOFROT.js.map} +0 -0
  371. /package/dist/{chunk-VKB2FGNW.js.map → chunk-LOMSBYNS.js.map} +0 -0
  372. /package/dist/{chunk-NDJ42GKB.js.map → chunk-MCPSMWUC.js.map} +0 -0
  373. /package/dist/{chunk-ERMT5WQM.js.map → chunk-MKE5DP3S.js.map} +0 -0
  374. /package/dist/{chunk-64IO6ZEE.js.map → chunk-MZWHIAOL.js.map} +0 -0
  375. /package/dist/{chunk-LDXS746V.js.map → chunk-N7DVBHU3.js.map} +0 -0
  376. /package/dist/{chunk-F2JLBXMG.js.map → chunk-NH6GZEQN.js.map} +0 -0
  377. /package/dist/{chunk-7FG2JSU6.js.map → chunk-NMKETOAX.js.map} +0 -0
  378. /package/dist/{chunk-GAARPWMN.js.map → chunk-OKKBOTRA.js.map} +0 -0
  379. /package/dist/{chunk-PCIIKQXW.js.map → chunk-OLH4XCLU.js.map} +0 -0
  380. /package/dist/{chunk-XA32GZ6B.js.map → chunk-OLHN4ZNT.js.map} +0 -0
  381. /package/dist/{chunk-UR25IQVT.js.map → chunk-P5CUEB2Q.js.map} +0 -0
  382. /package/dist/{chunk-LO775P3S.js.map → chunk-POGPI5GR.js.map} +0 -0
  383. /package/dist/{chunk-FXO43NBW.js.map → chunk-PSQ2P2T3.js.map} +0 -0
  384. /package/dist/{chunk-KRAMCBIW.js.map → chunk-QKXPOLQD.js.map} +0 -0
  385. /package/dist/{chunk-65JLKIVA.js.map → chunk-QO5KDQGG.js.map} +0 -0
  386. /package/dist/{chunk-A4B7WL5N.js.map → chunk-QOUKZ2N3.js.map} +0 -0
  387. /package/dist/{chunk-ZABEDRGQ.js.map → chunk-RGKXF4W3.js.map} +0 -0
  388. /package/dist/{chunk-IKCGNTGS.js.map → chunk-RWRHGE75.js.map} +0 -0
  389. /package/dist/{chunk-NBH7IRME.js.map → chunk-SWZOAQUM.js.map} +0 -0
  390. /package/dist/{chunk-FQ52AJXX.js.map → chunk-SZPPCEYT.js.map} +0 -0
  391. /package/dist/{chunk-4YYIZ475.js.map → chunk-TAEJ2MRR.js.map} +0 -0
  392. /package/dist/{chunk-3ODEGTVV.js.map → chunk-TDCR6PQL.js.map} +0 -0
  393. /package/dist/{chunk-QCP75JGO.js.map → chunk-TFA6HPOA.js.map} +0 -0
  394. /package/dist/{chunk-SE3JAD22.js.map → chunk-TPKB7T6Z.js.map} +0 -0
  395. /package/dist/{chunk-6VYY2XFK.js.map → chunk-TVIGN3XZ.js.map} +0 -0
  396. /package/dist/{chunk-OHMGR6QN.js.map → chunk-TXP7Q7T5.js.map} +0 -0
  397. /package/dist/{chunk-AI2VXOSO.js.map → chunk-TYLNWE4D.js.map} +0 -0
  398. /package/dist/{chunk-WI6MIJYK.js.map → chunk-U7HJBODU.js.map} +0 -0
  399. /package/dist/{chunk-IS4HKNWP.js.map → chunk-UBN5AOLT.js.map} +0 -0
  400. /package/dist/{chunk-JNELS2TW.js.map → chunk-UJDTXWMT.js.map} +0 -0
  401. /package/dist/{chunk-DJMC4W6N.js.map → chunk-VC3X7XP3.js.map} +0 -0
  402. /package/dist/{chunk-A2D3WICT.js.map → chunk-VGFNTY3Y.js.map} +0 -0
  403. /package/dist/{chunk-X544TW54.js.map → chunk-VGRM43X6.js.map} +0 -0
  404. /package/dist/{chunk-CSGFGQBI.js.map → chunk-VPO53QMG.js.map} +0 -0
  405. /package/dist/{chunk-BRZRP5WD.js.map → chunk-VSSQIBVU.js.map} +0 -0
  406. /package/dist/{chunk-GKNX4QO3.js.map → chunk-WCIDCJOQ.js.map} +0 -0
  407. /package/dist/{chunk-7VJEZQYF.js.map → chunk-WEK3OUGO.js.map} +0 -0
  408. /package/dist/{chunk-IVYAPAHG.js.map → chunk-WRDFYSUC.js.map} +0 -0
  409. /package/dist/{chunk-5EILJ6W2.js.map → chunk-WXPBDEMW.js.map} +0 -0
  410. /package/dist/{chunk-QZP3RMYP.js.map → chunk-X247CYL6.js.map} +0 -0
  411. /package/dist/{chunk-YLF42JQ7.js.map → chunk-XHX67LX6.js.map} +0 -0
  412. /package/dist/{chunk-C6S2Y7HE.js.map → chunk-XKDQTDXN.js.map} +0 -0
  413. /package/dist/{chunk-4AHKNZW7.js.map → chunk-XLEP7SS3.js.map} +0 -0
  414. /package/dist/{chunk-B6L7BKA7.js.map → chunk-XRFLR3XF.js.map} +0 -0
  415. /package/dist/{chunk-H7QC7WCU.js.map → chunk-XTBEXZFN.js.map} +0 -0
  416. /package/dist/{chunk-CIJRM6SQ.js.map → chunk-Y5ZHZKZD.js.map} +0 -0
  417. /package/dist/{chunk-H6SKBCNI.js.map → chunk-YC2C67F7.js.map} +0 -0
  418. /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
  419. /package/dist/{chunk-YOL56HY5.js.map → chunk-YQ6SLFNZ.js.map} +0 -0
  420. /package/dist/{chunk-SIIWHIBK.js.map → chunk-YYGZ4EIY.js.map} +0 -0
  421. /package/dist/{chunk-G22A6WJQ.js.map → chunk-Z2T5BPOZ.js.map} +0 -0
  422. /package/dist/{chunk-RYUSWAAU.js.map → chunk-ZAP7BKTZ.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/extraction-judge.ts"],"sourcesContent":["/**\n * Extraction Judge — LLM-as-judge fact-worthiness gate (issue #376).\n *\n * Evaluates extracted facts against a durability rubric before they are\n * persisted. Facts that are unlikely to be useful 30+ days from now or\n * across sessions are rejected (or shadow-logged depending on config).\n *\n * Design constraints:\n * - Corrections and principles are auto-approved (safety bypass).\n * - Critical-importance facts are auto-approved.\n * - Batches respect extractionJudgeBatchSize.\n * - Content-hash caching avoids redundant LLM calls.\n * - LLM calls use extractionJudgeTimeoutMs (default 20s: measured 2.1-2.5 s\n * per compact verdict request with a batch-scaled completion budget on a\n * small fast judge model; 13-22 s per compact call, 41 s verbose, on the\n * big shared core model — raise it there; the old 150s default only\n * papered over 59-305s verbose replies).\n */\n\nimport { createHash } from \"node:crypto\";\nimport { log } from \"./logger.js\";\nimport type { PluginConfig, ImportanceLevel } from \"./types.js\";\nimport type { LocalLlmClient } from \"./local-llm.js\";\nimport { type FallbackLlmClient, gatewayTaskChainOptions } from \"./fallback-llm.js\";\nimport { extractJsonCandidates } from \"./json-extract.js\";\nimport { normalizeProcedureSteps } from \"./procedural/procedure-types.js\";\nimport { OUTPUT_LANGUAGE_POLICY } from \"./extraction-prompt.js\";\n\n// ---------------------------------------------------------------------------\n// Public interfaces\n// ---------------------------------------------------------------------------\n\nexport interface JudgeCandidate {\n text: string;\n category: string;\n confidence: number;\n tags?: string[];\n /** Local importance level, set by caller before judging. */\n importanceLevel?: ImportanceLevel;\n}\n\n/**\n * Verdict kinds (issue #562, PR 1).\n *\n * - `\"accept\"`: fact is durable, persist it.\n * - `\"reject\"`: fact is not durable, drop it.\n * - `\"defer\"`: fact is ambiguous; push it back into the buffer for another\n * pass with fresh context. Inspired by MemReader (arxiv 2604.07877).\n *\n * PR 1 only introduces the type. No emit path produces `\"defer\"` yet — the\n * defer-capable prompt, buffer re-routing, telemetry, and GRPO data\n * collection are landing in PRs 2, 3, and 4 respectively.\n */\nexport type JudgeVerdictKind = \"accept\" | \"reject\" | \"defer\";\n\n/**\n * Judge verdict shape.\n *\n * Back-compat note: `kind` is optional. Verdicts serialized before PR 1\n * (both in-memory cache entries and any persisted caches) only carry\n * `{ durable, reason }`. Downstream consumers must either read `durable`\n * directly, or use {@link getVerdictKind} / {@link isDurableVerdict} which\n * gracefully fall back to the boolean when `kind` is missing, and ignore\n * unknown future `kind` values rather than crashing.\n */\nexport interface JudgeVerdict {\n /**\n * True iff the fact should be persisted. For `\"defer\"` verdicts this is\n * `false` — a deferred fact is not (yet) persisted, so callers that only\n * look at `durable` will treat defer as \"skip this turn\", which matches\n * the pre-PR-1 fail-closed behavior for non-accepted verdicts.\n */\n durable: boolean;\n reason: string;\n /**\n * Optional explicit verdict kind. Added in PR 1 of issue #562. Legacy\n * verdicts (including cache entries produced before this field existed)\n * do not set `kind`; use {@link getVerdictKind} to read this safely.\n */\n kind?: JudgeVerdictKind;\n}\n\n/**\n * Resolve a verdict's effective kind.\n *\n * - If `kind` is explicitly set to one of the known values, return it.\n * - If `kind` is absent, infer from `durable` (back-compat with pre-PR-1\n * cache entries and emit paths that have not been updated yet).\n * - If `kind` is set to an unrecognised value (forward-compat, e.g. a\n * future cache entry loaded by an older build), fall back to `durable`\n * so we never crash on unknown strings.\n */\nexport function getVerdictKind(verdict: JudgeVerdict): JudgeVerdictKind {\n const raw = verdict.kind;\n if (raw === \"accept\" || raw === \"reject\" || raw === \"defer\") {\n return raw;\n }\n return verdict.durable ? \"accept\" : \"reject\";\n}\n\n/**\n * Type guard: returns `true` only for verdicts that should be persisted.\n * Treats both `\"reject\"` and `\"defer\"` as \"not durable\" — defer means the\n * caller should re-evaluate later, not write now.\n */\nexport function isDurableVerdict(verdict: JudgeVerdict): boolean {\n return getVerdictKind(verdict) === \"accept\";\n}\n\n/**\n * Validate a cache entry loaded from persistence / another process.\n *\n * Strict: accepts legacy `{ durable, reason }` entries and new entries\n * whose `kind` is one of the three known `JudgeVerdictKind` values.\n * Rejects structurally wrong types and unknown `kind` strings so the\n * type-guard narrowing is sound — callers that receive\n * `value is JudgeVerdict` can safely treat `kind` as the declared\n * union.\n *\n * Forward-compat is handled by {@link normalizeCachedVerdict}, which\n * drops unknown `kind` strings before validation so a newer build's\n * cache entry still loads instead of being rejected.\n */\nexport function isValidCachedVerdict(value: unknown): value is JudgeVerdict {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Record<string, unknown>;\n if (typeof v.durable !== \"boolean\") return false;\n if (typeof v.reason !== \"string\") return false;\n if (v.kind !== undefined) {\n if (v.kind !== \"accept\" && v.kind !== \"reject\" && v.kind !== \"defer\") {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Forward-compatible cache-entry loader.\n *\n * Drops unknown `kind` strings to `undefined` (so `getVerdictKind` can\n * fall back to `durable`), then validates structurally. Non-string\n * `kind` values are still treated as structural violations and rejected.\n * Returns the sanitised verdict, or `null` when the entry is structurally\n * unusable.\n */\nexport function normalizeCachedVerdict(value: unknown): JudgeVerdict | null {\n if (typeof value !== \"object\" || value === null) return null;\n const v = value as Record<string, unknown>;\n if (typeof v.durable !== \"boolean\") return null;\n if (typeof v.reason !== \"string\") return null;\n let kind: JudgeVerdictKind | undefined;\n if (v.kind !== undefined) {\n if (typeof v.kind !== \"string\") return null;\n if (v.kind === \"accept\" || v.kind === \"reject\" || v.kind === \"defer\") {\n kind = v.kind;\n }\n // Unknown string `kind`: dropped to undefined for forward-compat.\n }\n const out: JudgeVerdict = { durable: v.durable, reason: v.reason };\n if (kind !== undefined) out.kind = kind;\n return out;\n}\n\nexport interface JudgeBatchResult {\n verdicts: Map<number, JudgeVerdict>;\n /** Number of verdicts served from cache. */\n cached: number;\n /** Number of verdicts produced by an LLM call. */\n judged: number;\n /** Total wall-clock time in milliseconds. */\n elapsed: number;\n /**\n * Number of verdicts in this batch that resolved to `\"defer\"` (issue #562,\n * PR 2). Callers can use this to decide whether to retain buffer turns for\n * the next extraction pass.\n */\n deferred: number;\n /**\n * Number of defers that were forcibly converted to `\"reject\"` because the\n * same candidate text had already been deferred at least\n * `extractionJudgeMaxDeferrals` times. Rolled out of `deferred` — a\n * candidate counted here is *not* also in `deferred`.\n */\n deferredCappedToReject: number;\n}\n\n/**\n * Per-verdict observation emitted by `judgeFactDurability` when an\n * `onVerdict` callback is supplied (issue #562, PR 3). Used to wire the\n * observation ledger / telemetry stream without coupling the judge module\n * directly to filesystem I/O. One event is emitted for every resolved\n * verdict, including auto-approved and cache-hit paths.\n */\nexport interface JudgeVerdictObservation {\n verdict: JudgeVerdict;\n /** The original `JudgeCandidate` passed in (same reference). */\n candidate: JudgeCandidate;\n /** SHA-256 of `text\\0category`, same key the cache/deferCounter use. */\n contentHash: string;\n /** Verdict resolution path. Useful for debugging + dashboards. */\n source: \"auto-approve\" | \"cache\" | \"llm\" | \"llm-cap-rejected\" | \"fail-open\";\n /**\n * How many times this candidate had already been deferred before this\n * verdict resolved. 0 when the candidate had never been deferred.\n */\n priorDeferrals: number;\n /**\n * Milliseconds from batch start to now. Shared across verdicts emitted in\n * the same batch.\n */\n elapsedMs: number;\n}\n\n// ---------------------------------------------------------------------------\n// Prompt (embedded; mirrors prompts/extraction_judge.prompt.md)\n// ---------------------------------------------------------------------------\n\nexport const JUDGE_SYSTEM_PROMPT = `You are a memory curator evaluating whether extracted facts are **durable** — worth storing for long-term recall across sessions.\n\nA fact is **durable** if it will still be useful 30+ days from now and is relevant across multiple sessions, not just the current task.\n\nThe user message is a JSON array of candidates: [{\"index\": 0, \"text\": \"...\", \"category\": \"...\", \"confidence\": 0.5}, ...].\n\nVerdicts:\n- \"accept\" — durable. Personal preferences, identities, relationships; decisions with rationale that affect future work; corrections to previously held beliefs; principles, rules, or constraints the user wants respected; stable facts about projects, tools, or workflows; commitments, deadlines, or obligations.\n- \"reject\" — not durable. Transient task details (\"currently debugging line 42\"); ephemeral state (\"the build is running now\"); routine operations (\"ran npm install\"); conversational filler; anything stale within hours; step-by-step instructions for a one-time task.\n- \"defer\" — MIGHT be durable but the candidate alone cannot say: ambiguous referents (\"he said they'd follow up\"), in-progress statements that may become durable once completed, future commitments with unclear subject or timeline. Defer is NOT a soft reject: use it only when another turn of context would genuinely change the verdict; when torn between accept and reject, lean accept — losing a useful fact is worse than keeping a marginal one.\n\nReply with a JSON object with a single \"verdicts\" key, exactly one object per input candidate:\n{\"verdicts\": [{\"index\": <candidate index>, \"kind\": \"accept\" | \"reject\" | \"defer\"}]}\n\nRules:\n1. The top level must be one object {\"verdicts\": [...]} — JSON mode rejects a bare top-level array.\n2. Copy each object's \"index\" from the input candidate. One object per candidate, exactly.\n3. No other fields — no \"reason\", no \"durable\", no commentary.\n4. Output valid JSON only. No markdown fences.\n5. ${OUTPUT_LANGUAGE_POLICY}\n\nExample output:\n{\"verdicts\": [{\"index\": 0, \"kind\": \"accept\"}, {\"index\": 1, \"kind\": \"reject\"}, {\"index\": 2, \"kind\": \"defer\"}]}`;\n\n// ---------------------------------------------------------------------------\n// Judge request assembly (PR 3264 follow-up)\n// ---------------------------------------------------------------------------\n\n/** Completion tokens reserved per candidate verdict (measured 13 on a small judge model). */\nconst JUDGE_TOKENS_PER_CANDIDATE = 24;\n/** Ceiling on one judge reply: the old flat budget. */\nexport const MAX_JUDGE_TOKENS = 2048;\n/**\n * Extra completion tokens for a judge call routed through the Responses API. Reasoning tokens count against\n * `max_output_tokens`, so the compact verdict budget alone can be spent before a reasoning-enabled model answers; the\n * unparsed batch would then fail open as durable. A cap, not a target: a non-reasoning model still writes a short reply.\n */\nexport const JUDGE_REASONING_HEADROOM_TOKENS = 1024;\n/** Largest batch whose verdict array fits MAX_JUDGE_TOKENS; a larger configured batch is split. */\nexport const MAX_JUDGE_BATCH = Math.floor(MAX_JUDGE_TOKENS / JUDGE_TOKENS_PER_CANDIDATE);\n\n/**\n * Compact completion budget for one judge call. A verdict is\n * `{\"index\":12,\"kind\":\"reject\"}` (~14 tokens), so the old flat 2048 only gave\n * a slow model room to produce 59-305s replies that hid inside the timeout.\n * Scales with the batch size (about 24 tokens per candidate verdict, measured\n * 13 per verdict on a small judge model) so a large batch is never truncated;\n * capped at 2048, the old flat budget.\n */\nexport function judgeMaxTokens(batchSize: number): number {\n return Math.min(MAX_JUDGE_TOKENS, Math.max(64, batchSize * JUDGE_TOKENS_PER_CANDIDATE));\n}\n\n/** One indexed candidate entry in a judge request payload. */\nexport interface JudgeRequestEntry {\n index: number;\n text: string;\n category: string;\n confidence: number;\n}\n\n/** Full judge LLM request: messages plus the completion budget. */\nexport interface JudgeRequest {\n messages: Array<{ role: \"system\" | \"user\"; content: string }>;\n maxTokens: number;\n}\n\n/** Build a full judge request body: messages plus the completion budget. */\nexport function buildJudgeRequest(entries: readonly JudgeRequestEntry[]): JudgeRequest {\n return {\n messages: [\n { role: \"system\", content: JUDGE_SYSTEM_PROMPT },\n { role: \"user\", content: JSON.stringify(entries) },\n ],\n maxTokens: judgeMaxTokens(entries.length),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Content-hash cache (in-memory, per-process fallback)\n// ---------------------------------------------------------------------------\n\n/** Maximum entries before evicting the oldest half. */\nconst VERDICT_CACHE_MAX_SIZE = 10_000;\n\n/** Module-level fallback cache, used when callers do not pass their own. */\nconst defaultVerdictCache = new Map<string, JudgeVerdict>();\n\n/**\n * Per-content-hash deferral counter (issue #562, PR 2).\n *\n * When the judge emits a `\"defer\"` verdict for a candidate whose content\n * has already been deferred `extractionJudgeMaxDeferrals` times, the verdict\n * is forcibly converted to `\"reject\"` so a pathological LLM response cannot\n * produce an infinite defer loop.\n *\n * Module-level with a size cap so stale test state cannot leak between runs\n * in the unlikely case a caller does not clear it between processes.\n */\nconst defaultDeferCounts = new Map<string, number>();\nconst DEFER_COUNT_MAX_SIZE = 20_000;\n\nfunction cacheKey(text: string, category: string): string {\n return createHash(\"sha256\").update(`${text}\\0${category}`).digest(\"hex\");\n}\n\n/**\n * Resolve the effective defer cap from config, defaulting to 2 when the\n * config value is missing or non-positive. Matches the PR 2 spec.\n */\nfunction resolveDeferCap(config: PluginConfig): number {\n const raw = (config as { extractionJudgeMaxDeferrals?: number })\n .extractionJudgeMaxDeferrals;\n if (typeof raw === \"number\" && Number.isFinite(raw) && raw >= 1) {\n return Math.floor(raw);\n }\n return 2;\n}\n\n/**\n * Enforce the max-size invariant on a verdict cache. When the cache exceeds\n * VERDICT_CACHE_MAX_SIZE, the oldest half of entries are deleted (Map\n * iteration order is insertion order).\n */\nfunction enforceMaxCacheSize(cache: Map<string, JudgeVerdict>): void {\n if (cache.size <= VERDICT_CACHE_MAX_SIZE) return;\n const deleteCount = Math.floor(cache.size / 2);\n let deleted = 0;\n for (const key of cache.keys()) {\n if (deleted >= deleteCount) break;\n cache.delete(key);\n deleted++;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Categories that bypass the judge (safety / correctness)\n// ---------------------------------------------------------------------------\n\nconst AUTO_APPROVE_CATEGORIES = new Set([\"correction\", \"principle\"]);\n\n/** Explicit trigger phrasing — procedures must match to persist (issue #519). */\nconst PROCEDURE_TRIGGER_RE =\n /(when you|whenever|before you|before running|always\\s|first\\b.*\\bthen|to deploy|to ship|run these steps|follow these steps|how (i|we)\\s|recipe for|workflow|each time you)/i;\n\n/**\n * Deterministic gate for extracted `procedure` memories: ≥2 steps with non-empty\n * intents and explicit trigger wording in title and/or steps.\n */\nexport function validateProcedureExtraction(input: {\n content: string;\n procedureSteps?: unknown;\n}): JudgeVerdict {\n const steps = normalizeProcedureSteps(input.procedureSteps);\n if (steps.length < 2) {\n return { durable: false, reason: \"Procedure requires at least two steps with intents\" };\n }\n const combined = [input.content, ...steps.map((s) => s.intent)].join(\" \").toLowerCase();\n if (!PROCEDURE_TRIGGER_RE.test(combined)) {\n return { durable: false, reason: \"Procedure missing explicit trigger phrasing\" };\n }\n return { durable: true, reason: \"Procedure structure validated\" };\n}\n\n// ---------------------------------------------------------------------------\n// Core judge function\n// ---------------------------------------------------------------------------\n\n/**\n * Evaluate a batch of candidate facts for durability.\n *\n * Auto-approves corrections, principles, and critical-importance facts.\n * Remaining candidates are batched (up to extractionJudgeBatchSize),\n * checked against an in-memory content-hash cache, and sent to the LLM\n * for verdict.\n */\nexport async function judgeFactDurability(\n candidates: JudgeCandidate[],\n config: PluginConfig,\n localLlm: LocalLlmClient | null,\n fallbackLlm: FallbackLlmClient | null,\n cache?: Map<string, JudgeVerdict>,\n deferCounts?: Map<string, number>,\n onVerdict?: (observation: JudgeVerdictObservation) => void,\n): Promise<JudgeBatchResult> {\n const startMs = Date.now();\n const verdicts = new Map<number, JudgeVerdict>();\n let cached = 0;\n let judged = 0;\n let deferred = 0;\n let deferredCappedToReject = 0;\n\n // Use caller-provided cache for per-orchestrator scoping, or fall back\n // to the module-level default cache.\n const verdictCache = cache ?? defaultVerdictCache;\n const deferCountMap = deferCounts ?? defaultDeferCounts;\n const deferCap = resolveDeferCap(config);\n\n // Lazy emit (Codex P2): when `onVerdict` is undefined (default path —\n // telemetry off), payload construction is skipped entirely. Callers\n // pass a factory instead of a pre-built observation so the `sha256`\n // `contentHash` and surrounding object allocation only run when a\n // subscriber is present. For large batches with telemetry off this\n // removes per-verdict overhead that would otherwise fire on every\n // auto-approved / cache / fail-open path.\n const emit = (build: () => JudgeVerdictObservation): void => {\n if (!onVerdict) return;\n let observation: JudgeVerdictObservation;\n try {\n observation = build();\n } catch (err) {\n log.debug(\n `extraction-judge: onVerdict builder threw (non-fatal): ${err instanceof Error ? err.message : String(err)}`,\n );\n return;\n }\n try {\n onVerdict(observation);\n } catch (err) {\n // Fail-open: telemetry errors must never block extraction.\n log.debug(\n `extraction-judge: onVerdict callback threw (non-fatal): ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n };\n\n if (candidates.length === 0) {\n return {\n verdicts,\n cached,\n judged,\n elapsed: 0,\n deferred,\n deferredCappedToReject,\n };\n }\n\n // Indices that need LLM judgment\n const pendingIndices: number[] = [];\n\n for (let i = 0; i < candidates.length; i++) {\n const c = candidates[i];\n\n // Auto-approve safety categories\n if (AUTO_APPROVE_CATEGORIES.has(c.category)) {\n const v: JudgeVerdict = {\n durable: true,\n reason: `Auto-approved: ${c.category} category bypasses judge`,\n };\n verdicts.set(i, v);\n emit(() => ({\n verdict: v,\n candidate: c,\n contentHash: cacheKey(c.text, c.category),\n source: \"auto-approve\",\n priorDeferrals: 0,\n elapsedMs: Date.now() - startMs,\n }));\n continue;\n }\n\n // Auto-approve critical importance\n if (c.importanceLevel === \"critical\") {\n const v: JudgeVerdict = {\n durable: true,\n reason: \"Auto-approved: critical importance\",\n };\n verdicts.set(i, v);\n emit(() => ({\n verdict: v,\n candidate: c,\n contentHash: cacheKey(c.text, c.category),\n source: \"auto-approve\",\n priorDeferrals: 0,\n elapsedMs: Date.now() - startMs,\n }));\n continue;\n }\n\n // Check cache\n const key = cacheKey(c.text, c.category);\n const cachedVerdict = verdictCache.get(key);\n if (cachedVerdict) {\n verdicts.set(i, cachedVerdict);\n cached++;\n emit(() => ({\n verdict: cachedVerdict,\n candidate: c,\n contentHash: key,\n source: \"cache\",\n priorDeferrals: deferCountMap.get(key) ?? 0,\n elapsedMs: Date.now() - startMs,\n }));\n continue;\n }\n\n pendingIndices.push(i);\n }\n\n // If all resolved without LLM, return early\n if (pendingIndices.length === 0) {\n return {\n verdicts,\n cached,\n judged,\n elapsed: Date.now() - startMs,\n deferred,\n deferredCappedToReject,\n };\n }\n\n // Batch the pending candidates up to batchSize\n const batchSize = Math.min(config.extractionJudgeBatchSize, MAX_JUDGE_BATCH);\n // Defer bookkeeping spans the WHOLE call, not one batch: identical candidates can land in different batches, and each key\n // must advance the defer cap once and decide against the same prior count (the snapshot taken at its first sighting).\n const deferredThisCall = new Set<string>();\n const priorDefersSeen = new Map<string, number>();\n for (let batchStart = 0; batchStart < pendingIndices.length; batchStart += batchSize) {\n const batchIndices = pendingIndices.slice(batchStart, batchStart + batchSize);\n const request = buildJudgeRequest(\n batchIndices.map((idx) => ({\n index: idx,\n text: candidates[idx].text,\n category: candidates[idx].category,\n confidence: candidates[idx].confidence,\n })),\n );\n\n try {\n const llmResponse = await callJudgeLlm(request, config, localLlm, fallbackLlm);\n\n if (llmResponse) {\n const parsed = parseJudgeResponse(llmResponse, batchIndices);\n // Per-call defer-increment dedupe (codex P2): a single extraction\n // pass must not advance the cap more than once for identical\n // candidate content, even if the same text appears several times in\n // one LLM response or in different batches of one call. Duplicate\n // hits share the first sighting's `priorDeferrals` snapshot.\n for (const [idx, rawVerdict] of parsed.entries()) {\n const c = candidates[idx];\n const key = cacheKey(c.text, c.category);\n let verdict = rawVerdict;\n let source: JudgeVerdictObservation[\"source\"] = \"llm\";\n if (!priorDefersSeen.has(key)) priorDefersSeen.set(key, deferCountMap.get(key) ?? 0);\n const priorDefers = priorDefersSeen.get(key) ?? 0;\n\n // Defer cap (issue #562, PR 2). A candidate that has already been\n // deferred `deferCap` times is forcibly rejected so a pathological\n // LLM response cannot produce an infinite defer loop.\n if (getVerdictKind(verdict) === \"defer\") {\n if (priorDefers >= deferCap) {\n verdict = {\n durable: false,\n reason: `Defer cap reached (${deferCap} prior defers); rejecting`,\n kind: \"reject\",\n };\n source = \"llm-cap-rejected\";\n // Only clear + count the cap conversion once per batch for\n // this key — duplicates in the same response all resolve to\n // reject but should not inflate the cap-rejection counter.\n if (!deferredThisCall.has(key)) {\n deferCountMap.delete(key);\n deferredCappedToReject++;\n deferredThisCall.add(key);\n }\n } else if (!deferredThisCall.has(key)) {\n deferCountMap.set(key, priorDefers + 1);\n deferred++;\n deferredThisCall.add(key);\n // Bound the per-process defer-counter map.\n if (deferCountMap.size > DEFER_COUNT_MAX_SIZE) {\n const drop = Math.floor(deferCountMap.size / 2);\n let dropped = 0;\n for (const k of deferCountMap.keys()) {\n if (dropped >= drop) break;\n deferCountMap.delete(k);\n dropped++;\n }\n }\n }\n // else: duplicate defer for a key already counted this call —\n // no additional counter increment, verdict still marked defer.\n } else {\n // On accept/reject, clear any outstanding defer counter so a\n // future reappearance of the same text starts fresh.\n deferCountMap.delete(key);\n priorDefersSeen.set(key, 0);\n deferredThisCall.delete(key);\n }\n\n verdicts.set(idx, verdict);\n judged++;\n // Cache non-defer verdicts. Defer is intentionally NOT cached:\n // caching it would short-circuit the re-evaluation pass that is\n // the entire point of the defer verdict.\n if (getVerdictKind(verdict) !== \"defer\") {\n verdictCache.set(key, verdict);\n }\n emit(() => ({\n verdict,\n candidate: c,\n contentHash: key,\n source,\n priorDeferrals: priorDefers,\n elapsedMs: Date.now() - startMs,\n }));\n }\n // Evict oldest entries if cache exceeds max size\n enforceMaxCacheSize(verdictCache);\n }\n } catch (err) {\n // Fail-open: if the LLM call fails, approve all candidates in this batch\n log.warn(\n `extraction-judge: LLM call failed, approving batch (fail-open): ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Fill in any missing verdicts from this batch (fail-open: approve).\n // Clear defer counts so a transient outage doesn't leave stale state\n // that causes later defers to hit the cap early.\n for (const idx of batchIndices) {\n if (!verdicts.has(idx)) {\n const c = candidates[idx];\n const hash = cacheKey(c.text, c.category);\n // Capture the prior deferral count BEFORE clearing so the\n // telemetry event reflects the true state rather than always 0.\n const priorDefers = deferCountMap.get(hash) ?? 0;\n deferCountMap.delete(hash);\n priorDefersSeen.set(hash, 0);\n deferredThisCall.delete(hash);\n const v: JudgeVerdict = {\n durable: true,\n reason: \"Approved by default (judge unavailable or parse error)\",\n };\n verdicts.set(idx, v);\n emit(() => {\n return {\n verdict: v,\n candidate: c,\n contentHash: hash,\n source: \"fail-open\",\n priorDeferrals: priorDefers,\n elapsedMs: Date.now() - startMs,\n };\n });\n }\n }\n }\n\n return {\n verdicts,\n cached,\n judged,\n elapsed: Date.now() - startMs,\n deferred,\n deferredCappedToReject,\n };\n}\n\n// ---------------------------------------------------------------------------\n// LLM call helpers\n// ---------------------------------------------------------------------------\n\nasync function callJudgeLlm(\n request: JudgeRequest,\n config: PluginConfig,\n localLlm: LocalLlmClient | null,\n fallbackLlm: FallbackLlmClient | null,\n): Promise<string | null> {\n const { messages, maxTokens } = request;\n\n const modelOverride = config.extractionJudgeModel || undefined;\n\n // When modelSource is \"gateway\", skip localLlm and go directly to fallback\n // (the gateway-routed backend). This respects the operator's explicit\n // routing preference.\n const skipLocal = config.modelSource === \"gateway\";\n\n // Route judge-gated extractions through the SAME shared resolution as every\n // other background task (taskModelChain > gatewayAgentId in gateway mode), so\n // the judge never silently falls back to the persona/default chain when a\n // task chain is configured (gotcha #22, #39). Issue #1365 / PR #1425.\n const gatewayChain = gatewayTaskChainOptions(config);\n\n // Try local LLM first (unless modelSource says gateway)\n if (localLlm && !skipLocal) {\n try {\n const result = await (localLlm as any).chatCompletion(messages, {\n temperature: 0.1,\n maxTokens,\n // A verdict needs no reasoning: keep a thinking-capable model from spending the compact budget on it.\n disableThinking: true,\n responseFormat: { type: \"json_object\" },\n timeoutMs: config.extractionJudgeTimeoutMs,\n // The client applies timeoutMs per attempt and retries an abort once:\n // one deadline signal bounds the whole call to the configured time.\n signal: AbortSignal.timeout(config.extractionJudgeTimeoutMs),\n operation: \"extraction-judge\",\n ...(modelOverride ? { model: modelOverride } : {}),\n });\n if (result?.content) {\n return result.content;\n }\n } catch (err) {\n log.debug(\n `extraction-judge: local LLM failed, trying fallback: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n // Try fallback LLM\n if (fallbackLlm) {\n try {\n const result = await fallbackLlm.chatCompletion(\n messages as Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n {\n temperature: 0.1,\n maxTokens,\n reasoningHeadroomTokens: JUDGE_REASONING_HEADROOM_TOKENS,\n timeoutMs: config.extractionJudgeTimeoutMs,\n ...(modelOverride ? { model: modelOverride } : {}),\n ...gatewayChain,\n },\n );\n if (result?.content) {\n return result.content;\n }\n } catch (err) {\n log.debug(\n `extraction-judge: fallback LLM failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n return null;\n}\n\ninterface JudgeVerdictItem {\n index?: number;\n kind?: string;\n action?: string;\n durable?: boolean;\n reason?: string;\n}\n\n/** What a judge model may return: a bare array, or one object wrapping verdicts. */\ninterface JudgeEnvelope {\n verdicts?: JudgeVerdictItem[];\n index?: number;\n}\n\ntype ParsedJudgeJson = JudgeVerdictItem[] | JudgeEnvelope | null | undefined;\n\n/**\n * Normalise the object shapes a judge model returns to a verdict array.\n * Requested shape {\"verdicts\": [...]} (response_format json_object forces a\n * top-level object); a single verdict object counts as one verdict at its\n * index, never the whole batch; legacy: any array-valued key.\n */\nfunction unwrapJudgeEnvelope(parsed: ParsedJudgeJson): JudgeVerdictItem[] | null {\n if (!parsed || Array.isArray(parsed)) return null;\n if (Array.isArray(parsed.verdicts)) return parsed.verdicts;\n if (Number.isInteger(parsed.index)) return [parsed];\n for (const v of Object.values(parsed)) {\n if (Array.isArray(v)) return v;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Response parsing\n// ---------------------------------------------------------------------------\n\nfunction parseJudgeResponse(\n raw: string,\n expectedIndices: number[],\n): Map<number, JudgeVerdict> {\n const result = new Map<number, JudgeVerdict>();\n const expectedSet = new Set(expectedIndices);\n\n try {\n // Try direct parse first, then fall back to JSON extraction\n let parsed: ParsedJudgeJson;\n try {\n parsed = JSON.parse(raw);\n } catch {\n const candidates = extractJsonCandidates(raw);\n if (candidates.length > 0) {\n parsed = JSON.parse(candidates[0]);\n }\n }\n\n if (!Array.isArray(parsed)) {\n const unwrapped = unwrapJudgeEnvelope(parsed);\n if (unwrapped === null) {\n log.debug(\"extraction-judge: response is not an array, cannot parse\");\n return result;\n }\n parsed = unwrapped;\n }\n\n for (const item of parsed) {\n if (\n typeof item !== \"object\" ||\n item === null ||\n typeof (item as any).index !== \"number\"\n ) {\n continue;\n }\n const idx = (item as any).index as number;\n if (!expectedSet.has(idx)) continue;\n\n // Parse kind first — it's the primary signal in PR 2 and above.\n // Fall back to durable for pre-PR-2 model responses that only return\n // the boolean.\n let kind: JudgeVerdictKind | undefined;\n const rawKind = (item as any).kind;\n const rawAction = (item as any).action;\n if (rawKind === \"accept\" || rawKind === \"reject\" || rawKind === \"defer\") {\n kind = rawKind;\n } else if (\n rawAction === \"accept\" ||\n rawAction === \"reject\" ||\n rawAction === \"defer\"\n ) {\n // Tolerate `action` as an alias — MemReader uses that word in the\n // paper and models may echo it.\n kind = rawAction;\n }\n\n const hasDurable = typeof (item as any).durable === \"boolean\";\n const durableFromModel = hasDurable\n ? ((item as any).durable as boolean)\n : undefined;\n\n // Resolve the durable flag from kind when present; otherwise trust\n // the model's boolean; otherwise fail-open to durable=true.\n let durable: boolean;\n if (kind === \"accept\") {\n durable = true;\n } else if (kind === \"reject\" || kind === \"defer\") {\n durable = false;\n } else if (durableFromModel !== undefined) {\n durable = durableFromModel;\n } else {\n durable = true; // fail-open\n }\n\n const reason =\n typeof (item as any).reason === \"string\"\n ? ((item as any).reason as string).slice(0, 120)\n : \"No reason provided\";\n\n const verdict: JudgeVerdict = { durable, reason };\n if (kind !== undefined) verdict.kind = kind;\n result.set(idx, verdict);\n }\n } catch (err) {\n log.debug(\n `extraction-judge: failed to parse response: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Cache management (exposed for testing)\n// ---------------------------------------------------------------------------\n\n/** Clear the in-memory default verdict cache. Primarily for tests. */\nexport function clearVerdictCache(): void {\n defaultVerdictCache.clear();\n defaultDeferCounts.clear();\n}\n\n/** Return the current default verdict cache size. Primarily for tests. */\nexport function verdictCacheSize(): number {\n return defaultVerdictCache.size;\n}\n\n/** Create a new per-instance verdict cache. Orchestrators should hold one. */\nexport function createVerdictCache(): Map<string, JudgeVerdict> {\n return new Map();\n}\n\n/**\n * Create a new per-instance defer-counter map. Orchestrators should hold one\n * alongside their verdict cache so defer counts survive across extraction\n * passes within a single orchestrator but do not leak across orchestrators.\n */\nexport function createDeferCountMap(): Map<string, number> {\n return new Map();\n}\n"],"mappings":"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","names":[]}
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-B7RWBZXW.js";
4
4
  import {
5
5
  resolveCausalTrajectoryStoreDir
6
- } from "./chunk-S2PDFSXS.js";
6
+ } from "./chunk-4P4VLPGB.js";
7
7
  import {
8
8
  normalizeRecallTokens
9
9
  } from "./chunk-YCVB7X56.js";
@@ -339,4 +339,4 @@ export {
339
339
  scoreStitchCandidate,
340
340
  stitchCausalChain
341
341
  };
342
- //# sourceMappingURL=chunk-SE3JAD22.js.map
342
+ //# sourceMappingURL=chunk-TPKB7T6Z.js.map
@@ -8,22 +8,11 @@ import {
8
8
  pruneOfflineUploadStaging,
9
9
  writeOfflineUploadChunk,
10
10
  writeSafeFileFromUpload
11
- } from "./chunk-IVYAPAHG.js";
12
- import {
13
- OFFLINE_SYNC_FAST_BASE_MTIME_TOLERANCE_MS,
14
- SYNC_INTERNAL_DIR,
15
- assertOfflineSyncMtimeMs,
16
- isEncryptedOfflineSyncFile,
17
- plainFileDigest,
18
- readPlainOfflineSyncFileChunk,
19
- setSafeFileMtime,
20
- sha256OfflineSyncFile,
21
- shouldExcludeOfflineSyncFile
22
- } from "./chunk-GY4R4P2A.js";
11
+ } from "./chunk-WRDFYSUC.js";
23
12
  import {
24
13
  applyChangesetEmbeddingGenerations,
25
14
  normalizeChangesetGenerations
26
- } from "./chunk-WI6MIJYK.js";
15
+ } from "./chunk-U7HJBODU.js";
27
16
  import {
28
17
  applyIncomingEmbeddingGenerations,
29
18
  assertEmbeddingGenerationStillIncluded,
@@ -32,22 +21,33 @@ import {
32
21
  embeddingGenerationMembership,
33
22
  isEmbeddingGenerationDirPath,
34
23
  isPathInOmittedEmbeddingGeneration
35
- } from "./chunk-X3IFRQKS.js";
24
+ } from "./chunk-I73ZSORJ.js";
36
25
  import {
37
26
  isEmbeddingGenerationMarkerPath,
38
27
  matchesOfflineSyncDefaultExclude
39
28
  } from "./chunk-63LFM77Z.js";
40
29
  import {
41
- isCanonicalRuntimeStatePath,
42
- shouldDeleteAbsentIncomingOfflineRuntimeFile,
43
- shouldPreferIncomingOfflineRuntimeFile
44
- } from "./chunk-TYT4TEQV.js";
30
+ OFFLINE_SYNC_FAST_BASE_MTIME_TOLERANCE_MS,
31
+ SYNC_INTERNAL_DIR,
32
+ assertOfflineSyncMtimeMs,
33
+ isEncryptedOfflineSyncFile,
34
+ plainFileDigest,
35
+ readPlainOfflineSyncFileChunk,
36
+ setSafeFileMtime,
37
+ sha256OfflineSyncFile,
38
+ shouldExcludeOfflineSyncFile
39
+ } from "./chunk-CUWOSRCS.js";
45
40
  import {
46
41
  prepareSafeArchiveRoot,
47
42
  resolveSafeArchiveTarget,
48
43
  sha256Bytes,
49
44
  validateArchiveRelativePath
50
45
  } from "./chunk-GCGJW34D.js";
46
+ import {
47
+ isCanonicalRuntimeStatePath,
48
+ shouldDeleteAbsentIncomingOfflineRuntimeFile,
49
+ shouldPreferIncomingOfflineRuntimeFile
50
+ } from "./chunk-LDWE7OZS.js";
51
51
  import {
52
52
  withEmbeddingGenerationLock,
53
53
  withEmbeddingGenerationLockIter
@@ -1792,4 +1792,4 @@ export {
1792
1792
  normalizeOfflineSyncState,
1793
1793
  fileStatesFromSnapshot
1794
1794
  };
1795
- //# sourceMappingURL=chunk-6VYY2XFK.js.map
1795
+ //# sourceMappingURL=chunk-TVIGN3XZ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  defineOperation
3
- } from "./chunk-4YYIZ475.js";
3
+ } from "./chunk-TAEJ2MRR.js";
4
4
  import {
5
5
  EngramAccessInputError
6
6
  } from "./chunk-3MUKQQ7A.js";
@@ -71,4 +71,4 @@ defineOperation({
71
71
  })
72
72
  })
73
73
  });
74
- //# sourceMappingURL=chunk-OHMGR6QN.js.map
74
+ //# sourceMappingURL=chunk-TXP7Q7T5.js.map
@@ -532,6 +532,7 @@ function isEncryptableStoragePath(filePath, rootDir) {
532
532
  const normalized = normalizeStorageRelativePath(rel);
533
533
  if (normalized === "profile.md") return true;
534
534
  if (isEncryptableStateSidecar(normalized)) return true;
535
+ if (isEncryptableBufferSessionFile(normalized)) return true;
535
536
  if (isEncryptableSummarySidecar(normalized)) return true;
536
537
  const firstSegment = normalized.split("/", 1)[0];
537
538
  return ENCRYPTABLE_MARKDOWN_STORAGE_ROOTS.has(firstSegment) && normalized.endsWith(".md");
@@ -578,6 +579,9 @@ var ENCRYPTABLE_STATE_SIDECARS = /* @__PURE__ */ new Set([
578
579
  function isEncryptableStateSidecar(normalized) {
579
580
  return ENCRYPTABLE_STATE_SIDECARS.has(normalized);
580
581
  }
582
+ function isEncryptableBufferSessionFile(normalized) {
583
+ return normalized.startsWith("state/buffer/") && normalized.endsWith(".json");
584
+ }
581
585
  function isEncryptableSummarySidecar(normalized) {
582
586
  return normalized.startsWith("summaries/") && normalized.endsWith(".json");
583
587
  }
@@ -604,4 +608,4 @@ export {
604
608
  migrateMemoryDirToEncrypted,
605
609
  decryptMemoryDirToPlaintext
606
610
  };
607
- //# sourceMappingURL=chunk-ZG3HZZ6K.js.map
611
+ //# sourceMappingURL=chunk-TYGLV6ZG.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/secure-store/secure-fs.ts","../src/secure-store/entity-file-read.ts"],"sourcesContent":["/**\n * Transparent file-level encryption for the secure-store module.\n *\n * Issue #690 (PR 3/4) — storage.ts integration layer.\n *\n * This module sits between the raw filesystem and StorageManager.\n * Every memory file is either:\n * - a plain UTF-8 text file (legacy, back-compat), or\n * - a REMNIC-ENC sealed file (AES-256-GCM, see format below).\n *\n * On-disk format\n * --------------\n * Encrypted files begin with a 9-byte magic header:\n *\n * REMNIC-ENC (7 ASCII bytes)\n * VER (1 byte, currently 0x01)\n * FLAGS (1 byte, reserved, must be 0x00)\n *\n * Followed immediately by a `seal()` envelope from `cipher.ts`:\n *\n * [VERSION:1][SALT:16][IV:12][AUTHTAG:16][CIPHERTEXT:...]\n *\n * The magic header makes encrypted files sniffable without attempting\n * a full `open()` call and gives operators a clear signal that the\n * file cannot be read by opening it in an editor.\n *\n * AAD\n * ---\n * The file path relative to the memory root is bound as Associated\n * Authenticated Data (AAD) on both encrypt and decrypt. This means\n * moving or renaming an encrypted file without re-encrypting it will\n * cause auth-tag failure on the next read — the file is tied to its\n * path. Callers that move files must re-encrypt them.\n *\n * Back-compat\n * -----------\n * `readMaybeEncryptedFile` transparently handles both formats: if the\n * file does NOT start with the magic bytes, it is returned as-is (plain\n * text). This lets an operator migrate incrementally: newly-written\n * files are encrypted while existing files continue to be read in plain\n * form until `migrateMemoryDirToEncrypted` is run.\n *\n * Naming: `secure-fs.ts` (not `vault-fs.ts`) — see `kdf.ts` naming note.\n */\n\nimport { createCipheriv, createDecipheriv, randomBytes, randomUUID } from \"node:crypto\";\nimport { lstat, mkdir, open as openFile, readFile, readdir, rename, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport {\n AUTH_TAG_LENGTH,\n ENVELOPE_HEADER_SIZE,\n ENVELOPE_LAYOUT,\n ENVELOPE_SALT_LENGTH,\n ENVELOPE_VERSION,\n IV_LENGTH,\n generateSalt,\n open as openEnvelope,\n parseEnvelope,\n seal,\n} from \"./cipher.js\";\nimport { RECALL_FALLBACK_DIRS } from \"../utils/category-dir.js\";\nimport { isErrnoCode } from \"../utils/errno.js\";\nimport { readStoreFileBufferTolerant as readStoreFileBuffer } from \"./entity-file-read.js\";\n\n// ---------------------------------------------------------------------------\n// Error classes\n// ---------------------------------------------------------------------------\n\n/**\n * Thrown when a read is attempted but the keyring entry for this\n * store is absent (i.e. `secure-store unlock` has not been run\n * since the last daemon start).\n */\nexport class SecureStoreLockedError extends Error {\n constructor(message = \"secure-store is locked — run `remnic secure-store unlock` to decrypt\") {\n super(message);\n this.name = \"SecureStoreLockedError\";\n }\n}\n\n/**\n * Thrown when `open()` fails because the auth tag does not validate.\n * This covers both wrong-key and tampered-ciphertext scenarios —\n * intentionally indistinguishable from the caller's perspective.\n */\nexport class SecureStoreDecryptError extends Error {\n constructor(message = \"secure-store decryption failed — wrong key or tampered ciphertext\") {\n super(message);\n this.name = \"SecureStoreDecryptError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Magic header\n// ---------------------------------------------------------------------------\n\n/** Magic bytes: the ASCII string \"REMNIC-ENC\" (10 bytes). */\nexport const MAGIC_BYTES = Buffer.from(\"REMNIC-ENC\", \"ascii\");\n\n/** Current on-disk version byte. */\nexport const FILE_FORMAT_VERSION = 0x01;\n\n/** Reserved flags byte — must be 0x00. */\nexport const FILE_FORMAT_FLAGS = 0x00;\n\n/** Total size of the magic header prefix (magic + version + flags). */\nexport const MAGIC_HEADER_SIZE = MAGIC_BYTES.length + 2; // 12 bytes\n\n/**\n * Exact, deterministic bytes `writeMaybeEncryptedFile` adds to an encrypted\n * file beyond its plaintext body: the magic header prefix plus the fixed\n * envelope header (version + salt + IV + auth tag). AES-256-GCM ciphertext\n * matches the plaintext length and the state-file write path applies no\n * compression, so an encrypted state file is exactly `plaintext +\n * SECURE_STORE_ENVELOPE_OVERHEAD_BYTES` on disk. Compaction reserves this so an\n * encrypted ledger lands strictly below the reader's whole-file decrypt cap\n * (issue #2033).\n */\nexport const SECURE_STORE_ENVELOPE_OVERHEAD_BYTES = MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE;\n\n// ---------------------------------------------------------------------------\n// Detection\n// ---------------------------------------------------------------------------\n\n/**\n * Return true iff `buf` begins with the REMNIC-ENC magic header.\n * Does not validate the envelope; just identifies the format.\n */\nexport function isEncryptedFile(buf: Uint8Array): boolean {\n if (buf.length < MAGIC_HEADER_SIZE) return false;\n const b = Buffer.isBuffer(buf) ? buf : Buffer.from(buf);\n return b.subarray(0, MAGIC_BYTES.length).equals(MAGIC_BYTES);\n}\n\ntype PositionedFileReader = {\n read: (buffer: Buffer, offset: number, length: number, position: number) => Promise<{ bytesRead: number }>;\n};\n\nasync function readPositionedPrefix(handle: PositionedFileReader, buffer: Buffer): Promise<number> {\n let bytesRead = 0;\n while (bytesRead < buffer.length) {\n const result = await handle.read(buffer, bytesRead, buffer.length - bytesRead, bytesRead);\n if (result.bytesRead === 0) break;\n bytesRead += result.bytesRead;\n }\n return bytesRead;\n}\n\n/**\n * True when the REGULAR file at `probePath` is encrypted at rest (its first\n * bytes are the REMNIC-ENC magic header). ENOENT resolves to false — an absent\n * file has nothing to probe. A symlink, FIFO, device, or any other non-regular\n * path is REFUSED with a throw rather than opened: opening a FIFO blocks until a\n * writer appears and a symlink would redirect the probe outside our tree. The\n * ledgers and per-event spills we manage are always regular files, so a\n * non-regular path is an anomaly the caller must treat as unsafe, never follow\n * (#2033). Shared by the CLI ledger recovery probe and the auto-compaction probe\n * so both enforce identical open safety.\n */\nexport async function probeEncryptedRegularFileHeader(probePath: string): Promise<boolean> {\n let entryStat;\n try {\n entryStat = await lstat(probePath);\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return false;\n throw err;\n }\n if (!entryStat.isFile()) {\n throw new Error(\n `refusing to probe non-regular state path ${probePath} ` +\n `(symlink/FIFO/device); opening it could block or escape containment (#2033)`\n );\n }\n const handle = await openFile(probePath, \"r\");\n try {\n const header = Buffer.alloc(MAGIC_HEADER_SIZE);\n const bytesRead = await readPositionedPrefix(handle, header);\n return isEncryptedFile(header.subarray(0, bytesRead));\n } finally {\n await handle.close();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Encrypt / decrypt file body\n// ---------------------------------------------------------------------------\n\n/**\n * Encrypt `plain` (UTF-8 content of a memory file) and return a\n * Buffer ready to write to disk.\n *\n * @param plain Plain-text file content (UTF-8 string or Buffer).\n * @param key 32-byte AES-256 key from the keyring.\n * @param aad Optional associated data — defaults to empty if omitted.\n * Callers should pass the file path relative to memoryDir\n * so the ciphertext is bound to its location.\n */\nexport function encryptFileBody(plain: string | Buffer, key: Buffer, aad?: Buffer): Buffer {\n const plainBuf = typeof plain === \"string\" ? Buffer.from(plain, \"utf8\") : plain;\n const salt = generateSalt();\n const envelope = seal(key, salt, plainBuf, aad ? { aad } : {});\n\n const header = Buffer.alloc(MAGIC_HEADER_SIZE);\n MAGIC_BYTES.copy(header, 0);\n header.writeUInt8(FILE_FORMAT_VERSION, MAGIC_BYTES.length);\n header.writeUInt8(FILE_FORMAT_FLAGS, MAGIC_BYTES.length + 1);\n\n return Buffer.concat([header, envelope]);\n}\n\n/**\n * Decrypt a buffer produced by `encryptFileBody` and return the\n * original UTF-8 content.\n *\n * Throws `SecureStoreDecryptError` on auth failure (wrong key or\n * tampered ciphertext). Throws a plain `Error` for structural problems\n * (truncated buffer, wrong magic, unsupported version).\n */\nexport function decryptFileBody(buf: Buffer, key: Buffer, aad?: Buffer): Buffer {\n if (!isEncryptedFile(buf)) {\n throw new Error(\"decryptFileBody: buffer does not start with REMNIC-ENC magic header\");\n }\n const version = buf.readUInt8(MAGIC_BYTES.length);\n if (version !== FILE_FORMAT_VERSION) {\n throw new Error(\n `decryptFileBody: unsupported file format version ${version} (this build supports ${FILE_FORMAT_VERSION})`\n );\n }\n const flags = buf.readUInt8(MAGIC_BYTES.length + 1);\n if (flags !== FILE_FORMAT_FLAGS) {\n throw new Error(`decryptFileBody: unknown flags byte 0x${flags.toString(16).padStart(2, \"0\")}`);\n }\n const envelope = buf.subarray(MAGIC_HEADER_SIZE);\n parseEnvelope(envelope);\n try {\n return openEnvelope(key, envelope, aad ? { aad } : {});\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new SecureStoreDecryptError(`secure-store decryption failed: ${msg}`);\n }\n}\n\nfunction buildHeaderAad(salt: Uint8Array): Buffer {\n const out = Buffer.alloc(1 + ENVELOPE_SALT_LENGTH);\n out.writeUInt8(ENVELOPE_VERSION, 0);\n Buffer.from(salt).copy(out, 1);\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Path → AAD helper\n// ---------------------------------------------------------------------------\n\n/**\n * Build the AAD buffer for a file at `filePath` relative to\n * `memoryDir`. The AAD binds the ciphertext to its path so a\n * file cannot be silently relocated without re-encryption.\n *\n * When `memoryDir` is supplied and `filePath` is absolute, the\n * relative sub-path is used. Otherwise `filePath` is used verbatim.\n */\nexport function filePathAad(filePath: string, memoryDir?: string): Buffer {\n let rel = filePath;\n if (memoryDir && path.isAbsolute(filePath)) {\n rel = path.relative(memoryDir, filePath);\n }\n return Buffer.from(rel, \"utf8\");\n}\n\n// ---------------------------------------------------------------------------\n// High-level read / write helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Read a file from `filePath`.\n *\n * - If the file is plaintext (no magic header), return its content\n * as-is — back-compat with unencrypted stores.\n * - If the file is encrypted AND `key` is provided, decrypt and return\n * the plaintext content.\n * - If the file is encrypted AND `key` is null, throw\n * `SecureStoreLockedError`.\n *\n * @param filePath Absolute path to the file.\n * @param key 32-byte AES-256 key, or null when the store is locked.\n * @param memoryDir Memory root for path-bound AAD. Should be absolute.\n */\nexport async function readMaybeEncryptedFileBuffer(\n filePath: string,\n key: Buffer | null,\n memoryDir?: string,\n opts?: { aadFilePath?: string }\n): Promise<Buffer> {\n const buf = memoryDir ? await readStoreFileBuffer(filePath, memoryDir) : await readFile(filePath);\n if (!isEncryptedFile(buf)) {\n // Plain file — legacy or unencrypted store.\n return buf;\n }\n // Encrypted — key required.\n if (key === null) {\n throw new SecureStoreLockedError(\n `secure-store is locked — cannot read encrypted file at ${filePath}. Run \\`remnic secure-store unlock\\` to decrypt.`\n );\n }\n return decryptFileBodyForPath(buf, key, filePath, memoryDir, opts?.aadFilePath);\n}\n\nexport async function readMaybeEncryptedFile(\n filePath: string,\n key: Buffer | null,\n memoryDir?: string\n): Promise<string> {\n return (await readMaybeEncryptedFileBuffer(filePath, key, memoryDir)).toString(\"utf8\");\n}\n\nexport interface WriteMaybeEncryptedFileOptions {\n /**\n * File mode bits. Default 0o600 (owner read/write only).\n * Applied only on create; existing files inherit their existing mode.\n */\n mode?: number;\n /**\n * If true, write atomically via a temp file + rename (CLAUDE.md gotcha #54).\n * Default true.\n */\n atomic?: boolean;\n /**\n * ABSOLUTE final path whose canonical AAD (via {@link filePathAad})\n * replaces the physical `filePath`'s. Used by the offline-sync generation\n * transaction: staged ciphertext physically lives under a staging\n * directory but must decrypt at its FINAL published path after the\n * staging directory is swapped into place by rename. Deriving the AAD\n * from the absolute final path through the SAME filePathAad logic as\n * ordinary reads keeps write and read derivations identical on every\n * platform (POSIX and Windows separators alike). (issue #3148, round 4/5)\n */\n aadFilePath?: string;\n}\n\n/**\n * Write `content` to `filePath`.\n *\n * - If `key` is provided and non-null, encrypt the content first.\n * - If `key` is null, write the content as plain UTF-8 (unencrypted store).\n *\n * Writes atomically: content is written to a unique temp file\n * first, then renamed into place (CLAUDE.md gotcha #54 — never delete\n * before write).\n */\nexport async function writeMaybeEncryptedFile(\n filePath: string,\n content: string | Buffer,\n key: Buffer | null,\n options: WriteMaybeEncryptedFileOptions = {},\n memoryDir?: string\n): Promise<void> {\n const { mode = 0o600, atomic = true, aadFilePath } = options;\n await mkdir(path.dirname(filePath), { recursive: true });\n\n let data: Buffer | string;\n if (key !== null) {\n const aad = aadFilePath !== undefined ? filePathAad(aadFilePath, memoryDir) : filePathAad(filePath, memoryDir);\n data = encryptFileBody(content, key, aad);\n } else {\n data = content;\n }\n\n if (atomic) {\n const tempPath = uniqueAtomicTempPath(filePath, \"tmp\");\n try {\n await writeFile(tempPath, data, { mode });\n await rename(tempPath, filePath);\n } catch (err) {\n // Best-effort cleanup of the temp file.\n try {\n await unlink(tempPath);\n } catch {\n // ignore\n }\n throw err;\n }\n } else {\n await writeFile(filePath, data, { mode });\n }\n}\n\nexport async function writeMaybeEncryptedFileFromChunks(\n filePath: string,\n chunks: AsyncIterable<Buffer>,\n key: Buffer | null,\n options: WriteMaybeEncryptedFileOptions = {},\n memoryDir?: string\n): Promise<void> {\n const { mode = 0o600, atomic = true } = options;\n await mkdir(path.dirname(filePath), { recursive: true });\n const writePath = atomic ? `${filePath}.tmp-${process.pid}-${Date.now()}` : filePath;\n let completed = false;\n try {\n const handle = await openFile(writePath, \"w\", mode);\n try {\n if (key !== null) {\n const salt = generateSalt();\n const iv = randomBytes(IV_LENGTH);\n const header = Buffer.alloc(MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE);\n MAGIC_BYTES.copy(header, 0);\n header.writeUInt8(FILE_FORMAT_VERSION, MAGIC_BYTES.length);\n header.writeUInt8(FILE_FORMAT_FLAGS, MAGIC_BYTES.length + 1);\n const envelopeOffset = MAGIC_HEADER_SIZE;\n header.writeUInt8(ENVELOPE_VERSION, envelopeOffset + ENVELOPE_LAYOUT.version);\n salt.copy(header, envelopeOffset + ENVELOPE_LAYOUT.salt);\n iv.copy(header, envelopeOffset + ENVELOPE_LAYOUT.iv);\n await handle.write(header);\n\n const cipher = createCipheriv(\"aes-256-gcm\", key, iv, { authTagLength: AUTH_TAG_LENGTH });\n const aad = filePathAad(filePath, memoryDir);\n cipher.setAAD(Buffer.concat([buildHeaderAad(salt), aad]));\n for await (const chunk of chunks) {\n if (chunk.length === 0) continue;\n const encrypted = cipher.update(chunk);\n if (encrypted.length > 0) await handle.write(encrypted);\n }\n const final = cipher.final();\n if (final.length > 0) await handle.write(final);\n const authTag = cipher.getAuthTag();\n await handle.write(authTag, 0, authTag.length, MAGIC_HEADER_SIZE + ENVELOPE_LAYOUT.authTag);\n } else {\n for await (const chunk of chunks) {\n if (chunk.length > 0) await handle.write(chunk);\n }\n }\n } finally {\n await handle.close();\n }\n if (atomic) {\n await rename(writePath, filePath);\n }\n completed = true;\n } finally {\n if (!completed && atomic) {\n await unlink(writePath).catch(() => {});\n }\n }\n}\n\n/**\n * Stream a file through the secure-store reader without buffering the whole\n * payload. Plaintext files are passed through unchanged; encrypted files are\n * authenticated and decrypted incrementally.\n */\nexport async function* readMaybeEncryptedFileFromChunks(\n filePath: string,\n key: Buffer | null,\n memoryDir?: string,\n chunkSize = 64 * 1024\n): AsyncIterable<Buffer> {\n const handle = await openFile(filePath, \"r\");\n const headerSize = MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE;\n try {\n const prefix = Buffer.alloc(headerSize);\n const prefixBytes = await readPositionedPrefix(handle, prefix);\n const prefixView = prefix.subarray(0, prefixBytes);\n if (!isEncryptedFile(prefixView)) {\n if (prefixBytes > 0) yield Buffer.from(prefixView);\n let position = prefixBytes;\n const buffer = Buffer.alloc(chunkSize);\n for (;;) {\n const { bytesRead } = await handle.read(buffer, 0, buffer.length, position);\n if (bytesRead === 0) break;\n position += bytesRead;\n yield Buffer.from(buffer.subarray(0, bytesRead));\n }\n return;\n }\n if (prefixBytes < headerSize) {\n throw new Error(`encrypted file header is truncated: ${filePath}`);\n }\n if (key === null) {\n throw new SecureStoreLockedError(\n `secure-store is locked — cannot read encrypted file at ${filePath}. ` +\n \"Run `remnic secure-store unlock` to decrypt.\"\n );\n }\n const envelope = prefix.subarray(MAGIC_HEADER_SIZE);\n const version = envelope.readUInt8(ENVELOPE_LAYOUT.version);\n if (version !== ENVELOPE_VERSION) {\n throw new Error(`secure-store: unsupported envelope version ${version}`);\n }\n const salt = envelope.subarray(ENVELOPE_LAYOUT.salt, ENVELOPE_LAYOUT.salt + ENVELOPE_SALT_LENGTH);\n const iv = envelope.subarray(ENVELOPE_LAYOUT.iv, ENVELOPE_LAYOUT.iv + IV_LENGTH);\n const authTag = envelope.subarray(ENVELOPE_LAYOUT.authTag, ENVELOPE_LAYOUT.authTag + AUTH_TAG_LENGTH);\n const decipher = createDecipheriv(\"aes-256-gcm\", key, iv, { authTagLength: AUTH_TAG_LENGTH });\n decipher.setAAD(Buffer.concat([buildHeaderAad(salt), filePathAad(filePath, memoryDir)]));\n decipher.setAuthTag(authTag);\n let position = headerSize;\n const buffer = Buffer.alloc(chunkSize);\n try {\n for (;;) {\n const { bytesRead } = await handle.read(buffer, 0, buffer.length, position);\n if (bytesRead === 0) break;\n position += bytesRead;\n const plain = decipher.update(buffer.subarray(0, bytesRead));\n if (plain.length > 0) yield plain;\n }\n const final = decipher.final();\n if (final.length > 0) yield final;\n } catch (err) {\n if (err instanceof SecureStoreDecryptError) throw err;\n const message = err instanceof Error ? err.message : String(err);\n throw new SecureStoreDecryptError(`secure-store decryption failed: ${message}`);\n }\n } finally {\n await handle.close();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Migration\n// ---------------------------------------------------------------------------\n\nexport interface MigrateResult {\n /** Number of files successfully encrypted. */\n encrypted: number;\n /** Number of files already encrypted (skipped). */\n skipped: number;\n /** Files that failed to encrypt (path → error message). */\n errors: Array<{ filePath: string; error: string }>;\n}\n\nexport interface DecryptResult {\n /** Number of files successfully decrypted back to plaintext. */\n decrypted: number;\n /** Number of files already plaintext (skipped). */\n skipped: number;\n /** Files that failed to decrypt (path → error message). */\n errors: Array<{ filePath: string; error: string }>;\n}\n\n/**\n * Walk `dir` recursively, find encryptable storage-managed files that are not\n * yet encrypted, and re-write them as encrypted files under `key`.\n *\n * Safety rules per CLAUDE.md gotchas #54 and #25:\n * 1. A page-version snapshot is taken (via `createVersion`) BEFORE\n * each overwrite so the plaintext version is preserved in history.\n * Since this module has no direct access to `page-versioning.ts`\n * internals, callers who have page-versioning configured should\n * pass `onBeforeEncrypt` to take the snapshot.\n * 2. The new encrypted content is written to a temp file first,\n * then renamed atomically — never deleted before written.\n * 3. If encryption of any file fails, the error is recorded and the\n * original file is left intact (partial migration is safe).\n *\n * @param dir Absolute path to the memory directory.\n * @param key 32-byte AES-256 key.\n * @param onBeforeEncrypt Optional callback invoked before encrypting\n * each file. Can be used to take page-version\n * snapshots. Errors here are non-fatal.\n */\nexport async function migrateMemoryDirToEncrypted(\n dir: string,\n key: Buffer,\n onBeforeEncrypt?: (filePath: string) => Promise<void>\n): Promise<MigrateResult> {\n const result: MigrateResult = { encrypted: 0, skipped: 0, errors: [] };\n\n const files = await collectEncryptableStorageFiles(dir);\n for (const filePath of files) {\n try {\n const buf = await readFile(filePath);\n if (isEncryptedFile(buf)) {\n result.skipped++;\n continue;\n }\n // Call optional pre-encryption hook (e.g. page-version snapshot).\n if (onBeforeEncrypt) {\n try {\n await onBeforeEncrypt(filePath);\n } catch {\n // Non-fatal — continue with encryption even if snapshot fails.\n }\n }\n const content = buf.toString(\"utf8\");\n const aad = filePathAad(filePath, dir);\n const encrypted = encryptFileBody(content, key, aad);\n\n // Atomic write: temp → rename (gotcha #54).\n const tempPath = uniqueAtomicTempPath(filePath, \"enc-tmp\");\n try {\n await writeFile(tempPath, encrypted, { mode: 0o600 });\n await rename(tempPath, filePath);\n result.encrypted++;\n } catch (writeErr) {\n // Clean up temp file, leave original intact.\n try {\n const { unlink } = await import(\"node:fs/promises\");\n await unlink(tempPath);\n } catch {\n // ignore\n }\n throw writeErr;\n }\n } catch (err) {\n result.errors.push({\n filePath,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return result;\n}\n\n/**\n * Walk `dir` recursively, find storage-managed encrypted files, and\n * re-write them as plaintext under the same paths.\n *\n * This is the reversible counterpart to {@link migrateMemoryDirToEncrypted}.\n * It only touches files under the same storage-managed roots, skips\n * plaintext files, skips symlinks, excludes `.secure-store/`, and writes\n * each plaintext replacement via temp-file + rename so a per-file failure\n * leaves the ciphertext intact.\n */\nexport async function decryptMemoryDirToPlaintext(dir: string, key: Buffer): Promise<DecryptResult> {\n const result: DecryptResult = { decrypted: 0, skipped: 0, errors: [] };\n\n const files = await collectStorageManagedFiles(dir, isDecryptableStoragePath);\n for (const filePath of files) {\n try {\n const buf = await readFile(filePath);\n if (!isEncryptedFile(buf)) {\n result.skipped++;\n continue;\n }\n\n const plaintext = decryptFileBodyForPath(buf, key, filePath, dir);\n const tempPath = uniqueAtomicTempPath(filePath, \"dec-tmp\");\n try {\n await writeFile(tempPath, plaintext, { mode: 0o600 });\n await rename(tempPath, filePath);\n result.decrypted++;\n } catch (writeErr) {\n try {\n await unlink(tempPath);\n } catch {\n // ignore cleanup errors; original ciphertext is still intact.\n }\n throw writeErr;\n }\n } catch (err) {\n result.errors.push({\n filePath,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction uniqueAtomicTempPath(filePath: string, label: string): string {\n return `${filePath}.${label}-${process.pid}-${Date.now()}-${randomUUID()}`;\n}\n\nfunction decryptFileBodyForPath(\n buf: Buffer,\n key: Buffer,\n filePath: string,\n memoryDir?: string,\n aadFilePath?: string\n): Buffer {\n // A canonical-AAD stage read (offline-sync generation transaction) binds\n // the FINAL published path, not the physical staging path.\n const aad = aadFilePath !== undefined ? filePathAad(aadFilePath, memoryDir) : filePathAad(filePath, memoryDir);\n try {\n return decryptFileBody(buf, key, aad);\n } catch (err) {\n if (!(err instanceof SecureStoreDecryptError)) {\n throw err;\n }\n const legacyRoot = legacyNamespaceAadRootForFile(filePath, memoryDir);\n if (legacyRoot) {\n try {\n return decryptFileBody(buf, key, filePathAad(filePath, legacyRoot));\n } catch {\n // Fall through to the namespace-reader fallback below.\n }\n }\n\n const topLevelRoot = topLevelAadRootForNamespaceReader(filePath, memoryDir);\n if (topLevelRoot) {\n try {\n return decryptFileBody(buf, key, filePathAad(filePath, topLevelRoot));\n } catch {\n // Preserve the caller-facing error from the canonical decrypt attempt.\n }\n }\n\n throw err;\n }\n}\n\nfunction topLevelAadRootForNamespaceReader(filePath: string, memoryDir?: string): string | null {\n if (!memoryDir || !path.isAbsolute(filePath)) return null;\n const resolvedMemoryDir = path.resolve(memoryDir);\n const rel = path.relative(resolvedMemoryDir, filePath);\n if (rel === \"\" || rel.startsWith(\"..\") || path.isAbsolute(rel)) return null;\n const parts = resolvedMemoryDir.split(path.sep);\n if (parts.length < 3 || parts.at(-2) !== \"namespaces\" || !parts.at(-1)) return null;\n const topLevelRoot = parts.slice(0, -2).join(path.sep) || path.sep;\n const topRel = path.relative(topLevelRoot, filePath);\n if (topRel === \"\" || topRel.startsWith(\"..\") || path.isAbsolute(topRel)) {\n return null;\n }\n const topParts = topRel.split(path.sep);\n if (topParts[0] !== \"namespaces\" || topParts[1] !== parts.at(-1)) {\n return null;\n }\n return topLevelRoot;\n}\n\nfunction legacyNamespaceAadRootForFile(filePath: string, memoryDir?: string): string | null {\n if (!memoryDir || !path.isAbsolute(filePath)) return null;\n const rel = path.relative(memoryDir, filePath);\n if (rel === \"\" || rel.startsWith(\"..\") || path.isAbsolute(rel)) return null;\n const parts = rel.split(path.sep);\n if (parts[0] === \"namespaces\" && parts.length >= 3 && parts[1]) {\n return path.join(memoryDir, \"namespaces\", parts[1]);\n }\n return null;\n}\n\n/**\n * Recursively collect files under `dir` that are read through the\n * storage-layer secure-store helpers, excluding symlinked entries and\n * `.secure-store/` metadata.\n */\nasync function collectEncryptableStorageFiles(dir: string, rootDir = dir): Promise<string[]> {\n return collectStorageManagedFiles(dir, isEncryptableStoragePath, rootDir);\n}\n\n/**\n * Recursively collect regular files under storage-managed roots, excluding\n * symlinked entries and `.secure-store/` metadata. This broader collector is\n * used by the decrypt/disable path so future encrypted sidecars can be\n * restored without requiring extension-specific logic.\n */\nasync function collectStorageManagedFiles(\n dir: string,\n includeFile: (filePath: string, rootDir: string) => boolean,\n rootDir = dir\n): Promise<string[]> {\n const results: string[] = [];\n let scanDir = dir;\n let scanRootDir = rootDir;\n if (path.resolve(dir) === path.resolve(rootDir)) {\n const normalizedRoot = await resolveStorageManagedRootForScan(dir);\n if (!normalizedRoot) return results;\n scanDir = normalizedRoot;\n scanRootDir = normalizedRoot;\n }\n let names: string[];\n try {\n names = await readdir(scanDir, { encoding: \"utf8\" });\n } catch {\n return results;\n }\n for (const name of names) {\n if (name.startsWith(\".secure-store\")) continue;\n const full = path.join(scanDir, name);\n let isDir = false;\n let isFile = false;\n try {\n const s = await lstat(full);\n if (s.isSymbolicLink()) continue;\n isDir = s.isDirectory();\n isFile = s.isFile();\n } catch {\n continue;\n }\n if (isDir) {\n const sub = await collectStorageManagedFiles(full, includeFile, scanRootDir);\n results.push(...sub);\n } else if (isFile && includeFile(full, scanRootDir)) {\n results.push(full);\n }\n }\n return results;\n}\n\nasync function resolveStorageManagedRootForScan(dir: string): Promise<string | null> {\n const lstatPath = normalizePathForLstat(dir);\n let stat: Awaited<ReturnType<typeof lstat>>;\n try {\n stat = await lstat(lstatPath);\n } catch (error) {\n if (isFsErrorWithCode(error, \"ENOENT\")) return null;\n throw error;\n }\n if (stat.isSymbolicLink()) {\n throw new Error(`secure-store migration root must not be a symlink: ${dir}`);\n }\n if (!stat.isDirectory()) {\n throw new Error(`secure-store migration root must be a directory: ${dir}`);\n }\n return lstatPath;\n}\n\nfunction normalizePathForLstat(filePath: string): string {\n return stripTrailingPathSeparators(path.normalize(filePath));\n}\n\nfunction isFsErrorWithCode(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && (error as { code?: unknown }).code === code;\n}\n\nfunction stripTrailingPathSeparators(filePath: string): string {\n const root = path.parse(filePath).root;\n let end = filePath.length;\n while (\n end > root.length &&\n (filePath[end - 1] === path.sep || filePath[end - 1] === path.posix.sep || filePath[end - 1] === path.win32.sep)\n ) {\n end -= 1;\n }\n return end === filePath.length ? filePath : filePath.slice(0, end);\n}\n\nfunction isEncryptableStoragePath(filePath: string, rootDir: string): boolean {\n const rel = path.relative(rootDir, filePath);\n if (rel === \"\" || rel.startsWith(\"..\") || path.isAbsolute(rel)) return false;\n const normalized = normalizeStorageRelativePath(rel);\n if (normalized === \"profile.md\") return true;\n if (isEncryptableStateSidecar(normalized)) return true;\n if (isEncryptableSummarySidecar(normalized)) return true;\n const firstSegment = normalized.split(\"/\", 1)[0];\n return ENCRYPTABLE_MARKDOWN_STORAGE_ROOTS.has(firstSegment) && normalized.endsWith(\".md\");\n}\n\nfunction isDecryptableStoragePath(filePath: string, rootDir: string): boolean {\n if (isEncryptableStoragePath(filePath, rootDir)) return true;\n const rel = path.relative(rootDir, filePath);\n if (rel === \"\" || rel.startsWith(\"..\") || path.isAbsolute(rel)) return false;\n const normalized = normalizeStorageRelativePath(rel);\n const firstSegment = normalized.split(\"/\", 1)[0];\n return DECRYPTABLE_SIDECAR_ROOTS.has(firstSegment);\n}\n\nfunction normalizeStorageRelativePath(rel: string): string {\n const normalized = rel.split(path.sep).join(\"/\");\n const parts = normalized.split(\"/\");\n if (parts[0] === \"namespaces\" && parts.length >= 3) {\n return parts.slice(2).join(\"/\");\n }\n return normalized;\n}\n\n// Every recall MEMORY category directory (facts/ + the CATEGORY_DIR_MAP memory\n// dirs) must be encryptable at rest — #1546 routes decision/preference/moment/...\n// memories into their own dirs, so hardcoding only facts/corrections/procedures/\n// reasoning-traces would silently write those categories in plaintext on\n// encrypted stores. RECALL_FALLBACK_DIRS is the single source of truth for that\n// set; the extra non-category markdown roots (artifacts/archive/entities/\n// identity) are appended.\n//\n// questions/ is deliberately EXCLUDED (RECALL_FALLBACK_DIRS omits the non-memory\n// queue dirs): the question queue is written/resolved through plain readFile/\n// writeFile (StorageManager.writeQuestion/resolveQuestion), NOT the secure-file\n// helpers. Encrypting questions/ here would make migration seal those files,\n// after which resolveQuestion() would read ciphertext as UTF-8, fail to update\n// the frontmatter, and overwrite/corrupt the file while returning success\n// (codex #1563 review). Keeping questions/ plaintext preserves the queue's\n// existing behavior; #1546 does not change question encryption.\nconst ENCRYPTABLE_MARKDOWN_STORAGE_ROOTS = new Set<string>([\n ...RECALL_FALLBACK_DIRS,\n \"artifacts\",\n \"archive\",\n \"entities\",\n \"identity\",\n]);\n\nconst ENCRYPTABLE_STATE_SIDECARS = new Set([\n \"state/behavior-signals.jsonl\",\n \"state/buffer-surprise-ledger.jsonl\",\n \"state/buffer.json\",\n \"state/compression-guideline-draft-state.json\",\n \"state/compression-guideline-state.json\",\n \"state/compression-guidelines.draft.md\",\n \"state/compression-guidelines.md\",\n \"state/entity-synthesis-queue.json\",\n \"state/fact-hashes.txt\",\n \"state/memory-actions.jsonl\",\n \"state/memory-lifecycle-ledger.jsonl\",\n \"state/meta.json\",\n \"state/reextract-jobs.jsonl\",\n \"state/topics.json\",\n]);\n\nfunction isEncryptableStateSidecar(normalized: string): boolean {\n return ENCRYPTABLE_STATE_SIDECARS.has(normalized);\n}\n\nfunction isEncryptableSummarySidecar(normalized: string): boolean {\n return normalized.startsWith(\"summaries/\") && normalized.endsWith(\".json\");\n}\n\nconst DECRYPTABLE_SIDECAR_ROOTS = new Set([\"state\", \"indexes\", \"index\", \"provenance\"]);\n","import { constants } from \"node:fs\";\nimport { lstat, open, readFile, realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { assertPathInsideRoot } from \"../utils/path-containment.js\";\n\nexport async function readStoreFileBuffer(filePath: string, memoryDir: string): Promise<Buffer> {\n const root = path.resolve(memoryDir);\n const entities = path.join(root, \"entities\");\n const target = path.resolve(filePath);\n const relative = path.relative(entities, target);\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {\n return readFile(filePath);\n }\n const handle = await open(target, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));\n try {\n for (let parent = path.dirname(target); ; parent = path.dirname(parent)) {\n const info = await lstat(parent);\n if (info.isSymbolicLink() || !info.isDirectory()) {\n throw new Error(`Refusing unsafe entity directory: ${parent}.`);\n }\n if (parent === root) break;\n }\n const [opened, entry, realRoot, realEntities, realTarget] = await Promise.all([\n handle.stat(), lstat(target), realpath(root), realpath(entities), realpath(target),\n ]);\n if (!opened.isFile() || entry.isSymbolicLink() || !entry.isFile()\n || opened.dev !== entry.dev || opened.ino !== entry.ino\n || realEntities !== path.join(realRoot, \"entities\")) {\n throw new Error(`Refusing unsafe entity file: ${filePath}.`);\n }\n assertPathInsideRoot(realEntities, realTarget, filePath);\n return await handle.readFile();\n } finally {\n await handle.close();\n }\n}\n\n\n/**\n * Atomic-replacement-tolerant variant: entity writes ship as temp-file +\n * rename, so an open/lstat identity mismatch during a concurrent write is an\n * ordinary race, not tampering. Retry a bounded number of times with fresh\n * containment checks before surfacing the mismatch as unsafe.\n */\nexport async function readStoreFileBufferTolerant(filePath: string, memoryDir: string, attempts = 3): Promise<Buffer> {\n for (let attempt = 0; ; attempt += 1) {\n try {\n return await readStoreFileBuffer(filePath, memoryDir);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const identityRace = /unsafe entity (?:file|directory)/.test(message);\n if (!identityRace || attempt >= attempts - 1) throw err;\n }\n }\n}\n"],"mappings":"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","names":["lstat","readFile","path","open","open","lstat","path","readFile","position","buffer","unlink"]}
1
+ {"version":3,"sources":["../src/secure-store/secure-fs.ts","../src/secure-store/entity-file-read.ts"],"sourcesContent":["/**\n * Transparent file-level encryption for the secure-store module.\n *\n * Issue #690 (PR 3/4) — storage.ts integration layer.\n *\n * This module sits between the raw filesystem and StorageManager.\n * Every memory file is either:\n * - a plain UTF-8 text file (legacy, back-compat), or\n * - a REMNIC-ENC sealed file (AES-256-GCM, see format below).\n *\n * On-disk format\n * --------------\n * Encrypted files begin with a 9-byte magic header:\n *\n * REMNIC-ENC (7 ASCII bytes)\n * VER (1 byte, currently 0x01)\n * FLAGS (1 byte, reserved, must be 0x00)\n *\n * Followed immediately by a `seal()` envelope from `cipher.ts`:\n *\n * [VERSION:1][SALT:16][IV:12][AUTHTAG:16][CIPHERTEXT:...]\n *\n * The magic header makes encrypted files sniffable without attempting\n * a full `open()` call and gives operators a clear signal that the\n * file cannot be read by opening it in an editor.\n *\n * AAD\n * ---\n * The file path relative to the memory root is bound as Associated\n * Authenticated Data (AAD) on both encrypt and decrypt. This means\n * moving or renaming an encrypted file without re-encrypting it will\n * cause auth-tag failure on the next read — the file is tied to its\n * path. Callers that move files must re-encrypt them.\n *\n * Back-compat\n * -----------\n * `readMaybeEncryptedFile` transparently handles both formats: if the\n * file does NOT start with the magic bytes, it is returned as-is (plain\n * text). This lets an operator migrate incrementally: newly-written\n * files are encrypted while existing files continue to be read in plain\n * form until `migrateMemoryDirToEncrypted` is run.\n *\n * Naming: `secure-fs.ts` (not `vault-fs.ts`) — see `kdf.ts` naming note.\n */\n\nimport { createCipheriv, createDecipheriv, randomBytes, randomUUID } from \"node:crypto\";\nimport { lstat, mkdir, open as openFile, readFile, readdir, rename, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport {\n AUTH_TAG_LENGTH,\n ENVELOPE_HEADER_SIZE,\n ENVELOPE_LAYOUT,\n ENVELOPE_SALT_LENGTH,\n ENVELOPE_VERSION,\n IV_LENGTH,\n generateSalt,\n open as openEnvelope,\n parseEnvelope,\n seal,\n} from \"./cipher.js\";\nimport { RECALL_FALLBACK_DIRS } from \"../utils/category-dir.js\";\nimport { isErrnoCode } from \"../utils/errno.js\";\nimport { readStoreFileBufferTolerant as readStoreFileBuffer } from \"./entity-file-read.js\";\n\n// ---------------------------------------------------------------------------\n// Error classes\n// ---------------------------------------------------------------------------\n\n/**\n * Thrown when a read is attempted but the keyring entry for this\n * store is absent (i.e. `secure-store unlock` has not been run\n * since the last daemon start).\n */\nexport class SecureStoreLockedError extends Error {\n constructor(message = \"secure-store is locked — run `remnic secure-store unlock` to decrypt\") {\n super(message);\n this.name = \"SecureStoreLockedError\";\n }\n}\n\n/**\n * Thrown when `open()` fails because the auth tag does not validate.\n * This covers both wrong-key and tampered-ciphertext scenarios —\n * intentionally indistinguishable from the caller's perspective.\n */\nexport class SecureStoreDecryptError extends Error {\n constructor(message = \"secure-store decryption failed — wrong key or tampered ciphertext\") {\n super(message);\n this.name = \"SecureStoreDecryptError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Magic header\n// ---------------------------------------------------------------------------\n\n/** Magic bytes: the ASCII string \"REMNIC-ENC\" (10 bytes). */\nexport const MAGIC_BYTES = Buffer.from(\"REMNIC-ENC\", \"ascii\");\n\n/** Current on-disk version byte. */\nexport const FILE_FORMAT_VERSION = 0x01;\n\n/** Reserved flags byte — must be 0x00. */\nexport const FILE_FORMAT_FLAGS = 0x00;\n\n/** Total size of the magic header prefix (magic + version + flags). */\nexport const MAGIC_HEADER_SIZE = MAGIC_BYTES.length + 2; // 12 bytes\n\n/**\n * Exact, deterministic bytes `writeMaybeEncryptedFile` adds to an encrypted\n * file beyond its plaintext body: the magic header prefix plus the fixed\n * envelope header (version + salt + IV + auth tag). AES-256-GCM ciphertext\n * matches the plaintext length and the state-file write path applies no\n * compression, so an encrypted state file is exactly `plaintext +\n * SECURE_STORE_ENVELOPE_OVERHEAD_BYTES` on disk. Compaction reserves this so an\n * encrypted ledger lands strictly below the reader's whole-file decrypt cap\n * (issue #2033).\n */\nexport const SECURE_STORE_ENVELOPE_OVERHEAD_BYTES = MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE;\n\n// ---------------------------------------------------------------------------\n// Detection\n// ---------------------------------------------------------------------------\n\n/**\n * Return true iff `buf` begins with the REMNIC-ENC magic header.\n * Does not validate the envelope; just identifies the format.\n */\nexport function isEncryptedFile(buf: Uint8Array): boolean {\n if (buf.length < MAGIC_HEADER_SIZE) return false;\n const b = Buffer.isBuffer(buf) ? buf : Buffer.from(buf);\n return b.subarray(0, MAGIC_BYTES.length).equals(MAGIC_BYTES);\n}\n\ntype PositionedFileReader = {\n read: (buffer: Buffer, offset: number, length: number, position: number) => Promise<{ bytesRead: number }>;\n};\n\nasync function readPositionedPrefix(handle: PositionedFileReader, buffer: Buffer): Promise<number> {\n let bytesRead = 0;\n while (bytesRead < buffer.length) {\n const result = await handle.read(buffer, bytesRead, buffer.length - bytesRead, bytesRead);\n if (result.bytesRead === 0) break;\n bytesRead += result.bytesRead;\n }\n return bytesRead;\n}\n\n/**\n * True when the REGULAR file at `probePath` is encrypted at rest (its first\n * bytes are the REMNIC-ENC magic header). ENOENT resolves to false — an absent\n * file has nothing to probe. A symlink, FIFO, device, or any other non-regular\n * path is REFUSED with a throw rather than opened: opening a FIFO blocks until a\n * writer appears and a symlink would redirect the probe outside our tree. The\n * ledgers and per-event spills we manage are always regular files, so a\n * non-regular path is an anomaly the caller must treat as unsafe, never follow\n * (#2033). Shared by the CLI ledger recovery probe and the auto-compaction probe\n * so both enforce identical open safety.\n */\nexport async function probeEncryptedRegularFileHeader(probePath: string): Promise<boolean> {\n let entryStat;\n try {\n entryStat = await lstat(probePath);\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return false;\n throw err;\n }\n if (!entryStat.isFile()) {\n throw new Error(\n `refusing to probe non-regular state path ${probePath} ` +\n `(symlink/FIFO/device); opening it could block or escape containment (#2033)`\n );\n }\n const handle = await openFile(probePath, \"r\");\n try {\n const header = Buffer.alloc(MAGIC_HEADER_SIZE);\n const bytesRead = await readPositionedPrefix(handle, header);\n return isEncryptedFile(header.subarray(0, bytesRead));\n } finally {\n await handle.close();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Encrypt / decrypt file body\n// ---------------------------------------------------------------------------\n\n/**\n * Encrypt `plain` (UTF-8 content of a memory file) and return a\n * Buffer ready to write to disk.\n *\n * @param plain Plain-text file content (UTF-8 string or Buffer).\n * @param key 32-byte AES-256 key from the keyring.\n * @param aad Optional associated data — defaults to empty if omitted.\n * Callers should pass the file path relative to memoryDir\n * so the ciphertext is bound to its location.\n */\nexport function encryptFileBody(plain: string | Buffer, key: Buffer, aad?: Buffer): Buffer {\n const plainBuf = typeof plain === \"string\" ? Buffer.from(plain, \"utf8\") : plain;\n const salt = generateSalt();\n const envelope = seal(key, salt, plainBuf, aad ? { aad } : {});\n\n const header = Buffer.alloc(MAGIC_HEADER_SIZE);\n MAGIC_BYTES.copy(header, 0);\n header.writeUInt8(FILE_FORMAT_VERSION, MAGIC_BYTES.length);\n header.writeUInt8(FILE_FORMAT_FLAGS, MAGIC_BYTES.length + 1);\n\n return Buffer.concat([header, envelope]);\n}\n\n/**\n * Decrypt a buffer produced by `encryptFileBody` and return the\n * original UTF-8 content.\n *\n * Throws `SecureStoreDecryptError` on auth failure (wrong key or\n * tampered ciphertext). Throws a plain `Error` for structural problems\n * (truncated buffer, wrong magic, unsupported version).\n */\nexport function decryptFileBody(buf: Buffer, key: Buffer, aad?: Buffer): Buffer {\n if (!isEncryptedFile(buf)) {\n throw new Error(\"decryptFileBody: buffer does not start with REMNIC-ENC magic header\");\n }\n const version = buf.readUInt8(MAGIC_BYTES.length);\n if (version !== FILE_FORMAT_VERSION) {\n throw new Error(\n `decryptFileBody: unsupported file format version ${version} (this build supports ${FILE_FORMAT_VERSION})`\n );\n }\n const flags = buf.readUInt8(MAGIC_BYTES.length + 1);\n if (flags !== FILE_FORMAT_FLAGS) {\n throw new Error(`decryptFileBody: unknown flags byte 0x${flags.toString(16).padStart(2, \"0\")}`);\n }\n const envelope = buf.subarray(MAGIC_HEADER_SIZE);\n parseEnvelope(envelope);\n try {\n return openEnvelope(key, envelope, aad ? { aad } : {});\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new SecureStoreDecryptError(`secure-store decryption failed: ${msg}`);\n }\n}\n\nfunction buildHeaderAad(salt: Uint8Array): Buffer {\n const out = Buffer.alloc(1 + ENVELOPE_SALT_LENGTH);\n out.writeUInt8(ENVELOPE_VERSION, 0);\n Buffer.from(salt).copy(out, 1);\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Path → AAD helper\n// ---------------------------------------------------------------------------\n\n/**\n * Build the AAD buffer for a file at `filePath` relative to\n * `memoryDir`. The AAD binds the ciphertext to its path so a\n * file cannot be silently relocated without re-encryption.\n *\n * When `memoryDir` is supplied and `filePath` is absolute, the\n * relative sub-path is used. Otherwise `filePath` is used verbatim.\n */\nexport function filePathAad(filePath: string, memoryDir?: string): Buffer {\n let rel = filePath;\n if (memoryDir && path.isAbsolute(filePath)) {\n rel = path.relative(memoryDir, filePath);\n }\n return Buffer.from(rel, \"utf8\");\n}\n\n// ---------------------------------------------------------------------------\n// High-level read / write helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Read a file from `filePath`.\n *\n * - If the file is plaintext (no magic header), return its content\n * as-is — back-compat with unencrypted stores.\n * - If the file is encrypted AND `key` is provided, decrypt and return\n * the plaintext content.\n * - If the file is encrypted AND `key` is null, throw\n * `SecureStoreLockedError`.\n *\n * @param filePath Absolute path to the file.\n * @param key 32-byte AES-256 key, or null when the store is locked.\n * @param memoryDir Memory root for path-bound AAD. Should be absolute.\n */\nexport async function readMaybeEncryptedFileBuffer(\n filePath: string,\n key: Buffer | null,\n memoryDir?: string,\n opts?: { aadFilePath?: string }\n): Promise<Buffer> {\n const buf = memoryDir ? await readStoreFileBuffer(filePath, memoryDir) : await readFile(filePath);\n if (!isEncryptedFile(buf)) {\n // Plain file — legacy or unencrypted store.\n return buf;\n }\n // Encrypted — key required.\n if (key === null) {\n throw new SecureStoreLockedError(\n `secure-store is locked — cannot read encrypted file at ${filePath}. Run \\`remnic secure-store unlock\\` to decrypt.`\n );\n }\n return decryptFileBodyForPath(buf, key, filePath, memoryDir, opts?.aadFilePath);\n}\n\nexport async function readMaybeEncryptedFile(\n filePath: string,\n key: Buffer | null,\n memoryDir?: string\n): Promise<string> {\n return (await readMaybeEncryptedFileBuffer(filePath, key, memoryDir)).toString(\"utf8\");\n}\n\nexport interface WriteMaybeEncryptedFileOptions {\n /**\n * File mode bits. Default 0o600 (owner read/write only).\n * Applied only on create; existing files inherit their existing mode.\n */\n mode?: number;\n /**\n * If true, write atomically via a temp file + rename (CLAUDE.md gotcha #54).\n * Default true.\n */\n atomic?: boolean;\n /**\n * ABSOLUTE final path whose canonical AAD (via {@link filePathAad})\n * replaces the physical `filePath`'s. Used by the offline-sync generation\n * transaction: staged ciphertext physically lives under a staging\n * directory but must decrypt at its FINAL published path after the\n * staging directory is swapped into place by rename. Deriving the AAD\n * from the absolute final path through the SAME filePathAad logic as\n * ordinary reads keeps write and read derivations identical on every\n * platform (POSIX and Windows separators alike). (issue #3148, round 4/5)\n */\n aadFilePath?: string;\n}\n\n/**\n * Write `content` to `filePath`.\n *\n * - If `key` is provided and non-null, encrypt the content first.\n * - If `key` is null, write the content as plain UTF-8 (unencrypted store).\n *\n * Writes atomically: content is written to a unique temp file\n * first, then renamed into place (CLAUDE.md gotcha #54 — never delete\n * before write).\n */\nexport async function writeMaybeEncryptedFile(\n filePath: string,\n content: string | Buffer,\n key: Buffer | null,\n options: WriteMaybeEncryptedFileOptions = {},\n memoryDir?: string\n): Promise<void> {\n const { mode = 0o600, atomic = true, aadFilePath } = options;\n await mkdir(path.dirname(filePath), { recursive: true });\n\n let data: Buffer | string;\n if (key !== null) {\n const aad = aadFilePath !== undefined ? filePathAad(aadFilePath, memoryDir) : filePathAad(filePath, memoryDir);\n data = encryptFileBody(content, key, aad);\n } else {\n data = content;\n }\n\n if (atomic) {\n const tempPath = uniqueAtomicTempPath(filePath, \"tmp\");\n try {\n await writeFile(tempPath, data, { mode });\n await rename(tempPath, filePath);\n } catch (err) {\n // Best-effort cleanup of the temp file.\n try {\n await unlink(tempPath);\n } catch {\n // ignore\n }\n throw err;\n }\n } else {\n await writeFile(filePath, data, { mode });\n }\n}\n\nexport async function writeMaybeEncryptedFileFromChunks(\n filePath: string,\n chunks: AsyncIterable<Buffer>,\n key: Buffer | null,\n options: WriteMaybeEncryptedFileOptions = {},\n memoryDir?: string\n): Promise<void> {\n const { mode = 0o600, atomic = true } = options;\n await mkdir(path.dirname(filePath), { recursive: true });\n const writePath = atomic ? `${filePath}.tmp-${process.pid}-${Date.now()}` : filePath;\n let completed = false;\n try {\n const handle = await openFile(writePath, \"w\", mode);\n try {\n if (key !== null) {\n const salt = generateSalt();\n const iv = randomBytes(IV_LENGTH);\n const header = Buffer.alloc(MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE);\n MAGIC_BYTES.copy(header, 0);\n header.writeUInt8(FILE_FORMAT_VERSION, MAGIC_BYTES.length);\n header.writeUInt8(FILE_FORMAT_FLAGS, MAGIC_BYTES.length + 1);\n const envelopeOffset = MAGIC_HEADER_SIZE;\n header.writeUInt8(ENVELOPE_VERSION, envelopeOffset + ENVELOPE_LAYOUT.version);\n salt.copy(header, envelopeOffset + ENVELOPE_LAYOUT.salt);\n iv.copy(header, envelopeOffset + ENVELOPE_LAYOUT.iv);\n await handle.write(header);\n\n const cipher = createCipheriv(\"aes-256-gcm\", key, iv, { authTagLength: AUTH_TAG_LENGTH });\n const aad = filePathAad(filePath, memoryDir);\n cipher.setAAD(Buffer.concat([buildHeaderAad(salt), aad]));\n for await (const chunk of chunks) {\n if (chunk.length === 0) continue;\n const encrypted = cipher.update(chunk);\n if (encrypted.length > 0) await handle.write(encrypted);\n }\n const final = cipher.final();\n if (final.length > 0) await handle.write(final);\n const authTag = cipher.getAuthTag();\n await handle.write(authTag, 0, authTag.length, MAGIC_HEADER_SIZE + ENVELOPE_LAYOUT.authTag);\n } else {\n for await (const chunk of chunks) {\n if (chunk.length > 0) await handle.write(chunk);\n }\n }\n } finally {\n await handle.close();\n }\n if (atomic) {\n await rename(writePath, filePath);\n }\n completed = true;\n } finally {\n if (!completed && atomic) {\n await unlink(writePath).catch(() => {});\n }\n }\n}\n\n/**\n * Stream a file through the secure-store reader without buffering the whole\n * payload. Plaintext files are passed through unchanged; encrypted files are\n * authenticated and decrypted incrementally.\n */\nexport async function* readMaybeEncryptedFileFromChunks(\n filePath: string,\n key: Buffer | null,\n memoryDir?: string,\n chunkSize = 64 * 1024\n): AsyncIterable<Buffer> {\n const handle = await openFile(filePath, \"r\");\n const headerSize = MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE;\n try {\n const prefix = Buffer.alloc(headerSize);\n const prefixBytes = await readPositionedPrefix(handle, prefix);\n const prefixView = prefix.subarray(0, prefixBytes);\n if (!isEncryptedFile(prefixView)) {\n if (prefixBytes > 0) yield Buffer.from(prefixView);\n let position = prefixBytes;\n const buffer = Buffer.alloc(chunkSize);\n for (;;) {\n const { bytesRead } = await handle.read(buffer, 0, buffer.length, position);\n if (bytesRead === 0) break;\n position += bytesRead;\n yield Buffer.from(buffer.subarray(0, bytesRead));\n }\n return;\n }\n if (prefixBytes < headerSize) {\n throw new Error(`encrypted file header is truncated: ${filePath}`);\n }\n if (key === null) {\n throw new SecureStoreLockedError(\n `secure-store is locked — cannot read encrypted file at ${filePath}. ` +\n \"Run `remnic secure-store unlock` to decrypt.\"\n );\n }\n const envelope = prefix.subarray(MAGIC_HEADER_SIZE);\n const version = envelope.readUInt8(ENVELOPE_LAYOUT.version);\n if (version !== ENVELOPE_VERSION) {\n throw new Error(`secure-store: unsupported envelope version ${version}`);\n }\n const salt = envelope.subarray(ENVELOPE_LAYOUT.salt, ENVELOPE_LAYOUT.salt + ENVELOPE_SALT_LENGTH);\n const iv = envelope.subarray(ENVELOPE_LAYOUT.iv, ENVELOPE_LAYOUT.iv + IV_LENGTH);\n const authTag = envelope.subarray(ENVELOPE_LAYOUT.authTag, ENVELOPE_LAYOUT.authTag + AUTH_TAG_LENGTH);\n const decipher = createDecipheriv(\"aes-256-gcm\", key, iv, { authTagLength: AUTH_TAG_LENGTH });\n decipher.setAAD(Buffer.concat([buildHeaderAad(salt), filePathAad(filePath, memoryDir)]));\n decipher.setAuthTag(authTag);\n let position = headerSize;\n const buffer = Buffer.alloc(chunkSize);\n try {\n for (;;) {\n const { bytesRead } = await handle.read(buffer, 0, buffer.length, position);\n if (bytesRead === 0) break;\n position += bytesRead;\n const plain = decipher.update(buffer.subarray(0, bytesRead));\n if (plain.length > 0) yield plain;\n }\n const final = decipher.final();\n if (final.length > 0) yield final;\n } catch (err) {\n if (err instanceof SecureStoreDecryptError) throw err;\n const message = err instanceof Error ? err.message : String(err);\n throw new SecureStoreDecryptError(`secure-store decryption failed: ${message}`);\n }\n } finally {\n await handle.close();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Migration\n// ---------------------------------------------------------------------------\n\nexport interface MigrateResult {\n /** Number of files successfully encrypted. */\n encrypted: number;\n /** Number of files already encrypted (skipped). */\n skipped: number;\n /** Files that failed to encrypt (path → error message). */\n errors: Array<{ filePath: string; error: string }>;\n}\n\nexport interface DecryptResult {\n /** Number of files successfully decrypted back to plaintext. */\n decrypted: number;\n /** Number of files already plaintext (skipped). */\n skipped: number;\n /** Files that failed to decrypt (path → error message). */\n errors: Array<{ filePath: string; error: string }>;\n}\n\n/**\n * Walk `dir` recursively, find encryptable storage-managed files that are not\n * yet encrypted, and re-write them as encrypted files under `key`.\n *\n * Safety rules per CLAUDE.md gotchas #54 and #25:\n * 1. A page-version snapshot is taken (via `createVersion`) BEFORE\n * each overwrite so the plaintext version is preserved in history.\n * Since this module has no direct access to `page-versioning.ts`\n * internals, callers who have page-versioning configured should\n * pass `onBeforeEncrypt` to take the snapshot.\n * 2. The new encrypted content is written to a temp file first,\n * then renamed atomically — never deleted before written.\n * 3. If encryption of any file fails, the error is recorded and the\n * original file is left intact (partial migration is safe).\n *\n * @param dir Absolute path to the memory directory.\n * @param key 32-byte AES-256 key.\n * @param onBeforeEncrypt Optional callback invoked before encrypting\n * each file. Can be used to take page-version\n * snapshots. Errors here are non-fatal.\n */\nexport async function migrateMemoryDirToEncrypted(\n dir: string,\n key: Buffer,\n onBeforeEncrypt?: (filePath: string) => Promise<void>\n): Promise<MigrateResult> {\n const result: MigrateResult = { encrypted: 0, skipped: 0, errors: [] };\n\n const files = await collectEncryptableStorageFiles(dir);\n for (const filePath of files) {\n try {\n const buf = await readFile(filePath);\n if (isEncryptedFile(buf)) {\n result.skipped++;\n continue;\n }\n // Call optional pre-encryption hook (e.g. page-version snapshot).\n if (onBeforeEncrypt) {\n try {\n await onBeforeEncrypt(filePath);\n } catch {\n // Non-fatal — continue with encryption even if snapshot fails.\n }\n }\n const content = buf.toString(\"utf8\");\n const aad = filePathAad(filePath, dir);\n const encrypted = encryptFileBody(content, key, aad);\n\n // Atomic write: temp → rename (gotcha #54).\n const tempPath = uniqueAtomicTempPath(filePath, \"enc-tmp\");\n try {\n await writeFile(tempPath, encrypted, { mode: 0o600 });\n await rename(tempPath, filePath);\n result.encrypted++;\n } catch (writeErr) {\n // Clean up temp file, leave original intact.\n try {\n const { unlink } = await import(\"node:fs/promises\");\n await unlink(tempPath);\n } catch {\n // ignore\n }\n throw writeErr;\n }\n } catch (err) {\n result.errors.push({\n filePath,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return result;\n}\n\n/**\n * Walk `dir` recursively, find storage-managed encrypted files, and\n * re-write them as plaintext under the same paths.\n *\n * This is the reversible counterpart to {@link migrateMemoryDirToEncrypted}.\n * It only touches files under the same storage-managed roots, skips\n * plaintext files, skips symlinks, excludes `.secure-store/`, and writes\n * each plaintext replacement via temp-file + rename so a per-file failure\n * leaves the ciphertext intact.\n */\nexport async function decryptMemoryDirToPlaintext(dir: string, key: Buffer): Promise<DecryptResult> {\n const result: DecryptResult = { decrypted: 0, skipped: 0, errors: [] };\n\n const files = await collectStorageManagedFiles(dir, isDecryptableStoragePath);\n for (const filePath of files) {\n try {\n const buf = await readFile(filePath);\n if (!isEncryptedFile(buf)) {\n result.skipped++;\n continue;\n }\n\n const plaintext = decryptFileBodyForPath(buf, key, filePath, dir);\n const tempPath = uniqueAtomicTempPath(filePath, \"dec-tmp\");\n try {\n await writeFile(tempPath, plaintext, { mode: 0o600 });\n await rename(tempPath, filePath);\n result.decrypted++;\n } catch (writeErr) {\n try {\n await unlink(tempPath);\n } catch {\n // ignore cleanup errors; original ciphertext is still intact.\n }\n throw writeErr;\n }\n } catch (err) {\n result.errors.push({\n filePath,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction uniqueAtomicTempPath(filePath: string, label: string): string {\n return `${filePath}.${label}-${process.pid}-${Date.now()}-${randomUUID()}`;\n}\n\nfunction decryptFileBodyForPath(\n buf: Buffer,\n key: Buffer,\n filePath: string,\n memoryDir?: string,\n aadFilePath?: string\n): Buffer {\n // A canonical-AAD stage read (offline-sync generation transaction) binds\n // the FINAL published path, not the physical staging path.\n const aad = aadFilePath !== undefined ? filePathAad(aadFilePath, memoryDir) : filePathAad(filePath, memoryDir);\n try {\n return decryptFileBody(buf, key, aad);\n } catch (err) {\n if (!(err instanceof SecureStoreDecryptError)) {\n throw err;\n }\n const legacyRoot = legacyNamespaceAadRootForFile(filePath, memoryDir);\n if (legacyRoot) {\n try {\n return decryptFileBody(buf, key, filePathAad(filePath, legacyRoot));\n } catch {\n // Fall through to the namespace-reader fallback below.\n }\n }\n\n const topLevelRoot = topLevelAadRootForNamespaceReader(filePath, memoryDir);\n if (topLevelRoot) {\n try {\n return decryptFileBody(buf, key, filePathAad(filePath, topLevelRoot));\n } catch {\n // Preserve the caller-facing error from the canonical decrypt attempt.\n }\n }\n\n throw err;\n }\n}\n\nfunction topLevelAadRootForNamespaceReader(filePath: string, memoryDir?: string): string | null {\n if (!memoryDir || !path.isAbsolute(filePath)) return null;\n const resolvedMemoryDir = path.resolve(memoryDir);\n const rel = path.relative(resolvedMemoryDir, filePath);\n if (rel === \"\" || rel.startsWith(\"..\") || path.isAbsolute(rel)) return null;\n const parts = resolvedMemoryDir.split(path.sep);\n if (parts.length < 3 || parts.at(-2) !== \"namespaces\" || !parts.at(-1)) return null;\n const topLevelRoot = parts.slice(0, -2).join(path.sep) || path.sep;\n const topRel = path.relative(topLevelRoot, filePath);\n if (topRel === \"\" || topRel.startsWith(\"..\") || path.isAbsolute(topRel)) {\n return null;\n }\n const topParts = topRel.split(path.sep);\n if (topParts[0] !== \"namespaces\" || topParts[1] !== parts.at(-1)) {\n return null;\n }\n return topLevelRoot;\n}\n\nfunction legacyNamespaceAadRootForFile(filePath: string, memoryDir?: string): string | null {\n if (!memoryDir || !path.isAbsolute(filePath)) return null;\n const rel = path.relative(memoryDir, filePath);\n if (rel === \"\" || rel.startsWith(\"..\") || path.isAbsolute(rel)) return null;\n const parts = rel.split(path.sep);\n if (parts[0] === \"namespaces\" && parts.length >= 3 && parts[1]) {\n return path.join(memoryDir, \"namespaces\", parts[1]);\n }\n return null;\n}\n\n/**\n * Recursively collect files under `dir` that are read through the\n * storage-layer secure-store helpers, excluding symlinked entries and\n * `.secure-store/` metadata.\n */\nasync function collectEncryptableStorageFiles(dir: string, rootDir = dir): Promise<string[]> {\n return collectStorageManagedFiles(dir, isEncryptableStoragePath, rootDir);\n}\n\n/**\n * Recursively collect regular files under storage-managed roots, excluding\n * symlinked entries and `.secure-store/` metadata. This broader collector is\n * used by the decrypt/disable path so future encrypted sidecars can be\n * restored without requiring extension-specific logic.\n */\nasync function collectStorageManagedFiles(\n dir: string,\n includeFile: (filePath: string, rootDir: string) => boolean,\n rootDir = dir\n): Promise<string[]> {\n const results: string[] = [];\n let scanDir = dir;\n let scanRootDir = rootDir;\n if (path.resolve(dir) === path.resolve(rootDir)) {\n const normalizedRoot = await resolveStorageManagedRootForScan(dir);\n if (!normalizedRoot) return results;\n scanDir = normalizedRoot;\n scanRootDir = normalizedRoot;\n }\n let names: string[];\n try {\n names = await readdir(scanDir, { encoding: \"utf8\" });\n } catch {\n return results;\n }\n for (const name of names) {\n if (name.startsWith(\".secure-store\")) continue;\n const full = path.join(scanDir, name);\n let isDir = false;\n let isFile = false;\n try {\n const s = await lstat(full);\n if (s.isSymbolicLink()) continue;\n isDir = s.isDirectory();\n isFile = s.isFile();\n } catch {\n continue;\n }\n if (isDir) {\n const sub = await collectStorageManagedFiles(full, includeFile, scanRootDir);\n results.push(...sub);\n } else if (isFile && includeFile(full, scanRootDir)) {\n results.push(full);\n }\n }\n return results;\n}\n\nasync function resolveStorageManagedRootForScan(dir: string): Promise<string | null> {\n const lstatPath = normalizePathForLstat(dir);\n let stat: Awaited<ReturnType<typeof lstat>>;\n try {\n stat = await lstat(lstatPath);\n } catch (error) {\n if (isFsErrorWithCode(error, \"ENOENT\")) return null;\n throw error;\n }\n if (stat.isSymbolicLink()) {\n throw new Error(`secure-store migration root must not be a symlink: ${dir}`);\n }\n if (!stat.isDirectory()) {\n throw new Error(`secure-store migration root must be a directory: ${dir}`);\n }\n return lstatPath;\n}\n\nfunction normalizePathForLstat(filePath: string): string {\n return stripTrailingPathSeparators(path.normalize(filePath));\n}\n\nfunction isFsErrorWithCode(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && (error as { code?: unknown }).code === code;\n}\n\nfunction stripTrailingPathSeparators(filePath: string): string {\n const root = path.parse(filePath).root;\n let end = filePath.length;\n while (\n end > root.length &&\n (filePath[end - 1] === path.sep || filePath[end - 1] === path.posix.sep || filePath[end - 1] === path.win32.sep)\n ) {\n end -= 1;\n }\n return end === filePath.length ? filePath : filePath.slice(0, end);\n}\n\nfunction isEncryptableStoragePath(filePath: string, rootDir: string): boolean {\n const rel = path.relative(rootDir, filePath);\n if (rel === \"\" || rel.startsWith(\"..\") || path.isAbsolute(rel)) return false;\n const normalized = normalizeStorageRelativePath(rel);\n if (normalized === \"profile.md\") return true;\n if (isEncryptableStateSidecar(normalized)) return true;\n if (isEncryptableBufferSessionFile(normalized)) return true;\n if (isEncryptableSummarySidecar(normalized)) return true;\n const firstSegment = normalized.split(\"/\", 1)[0];\n return ENCRYPTABLE_MARKDOWN_STORAGE_ROOTS.has(firstSegment) && normalized.endsWith(\".md\");\n}\n\nfunction isDecryptableStoragePath(filePath: string, rootDir: string): boolean {\n if (isEncryptableStoragePath(filePath, rootDir)) return true;\n const rel = path.relative(rootDir, filePath);\n if (rel === \"\" || rel.startsWith(\"..\") || path.isAbsolute(rel)) return false;\n const normalized = normalizeStorageRelativePath(rel);\n const firstSegment = normalized.split(\"/\", 1)[0];\n return DECRYPTABLE_SIDECAR_ROOTS.has(firstSegment);\n}\n\nfunction normalizeStorageRelativePath(rel: string): string {\n const normalized = rel.split(path.sep).join(\"/\");\n const parts = normalized.split(\"/\");\n if (parts[0] === \"namespaces\" && parts.length >= 3) {\n return parts.slice(2).join(\"/\");\n }\n return normalized;\n}\n\n// Every recall MEMORY category directory (facts/ + the CATEGORY_DIR_MAP memory\n// dirs) must be encryptable at rest — #1546 routes decision/preference/moment/...\n// memories into their own dirs, so hardcoding only facts/corrections/procedures/\n// reasoning-traces would silently write those categories in plaintext on\n// encrypted stores. RECALL_FALLBACK_DIRS is the single source of truth for that\n// set; the extra non-category markdown roots (artifacts/archive/entities/\n// identity) are appended.\n//\n// questions/ is deliberately EXCLUDED (RECALL_FALLBACK_DIRS omits the non-memory\n// queue dirs): the question queue is written/resolved through plain readFile/\n// writeFile (StorageManager.writeQuestion/resolveQuestion), NOT the secure-file\n// helpers. Encrypting questions/ here would make migration seal those files,\n// after which resolveQuestion() would read ciphertext as UTF-8, fail to update\n// the frontmatter, and overwrite/corrupt the file while returning success\n// (codex #1563 review). Keeping questions/ plaintext preserves the queue's\n// existing behavior; #1546 does not change question encryption.\nconst ENCRYPTABLE_MARKDOWN_STORAGE_ROOTS = new Set<string>([\n ...RECALL_FALLBACK_DIRS,\n \"artifacts\",\n \"archive\",\n \"entities\",\n \"identity\",\n]);\n\nconst ENCRYPTABLE_STATE_SIDECARS = new Set([\n \"state/behavior-signals.jsonl\",\n \"state/buffer-surprise-ledger.jsonl\",\n \"state/buffer.json\",\n \"state/compression-guideline-draft-state.json\",\n \"state/compression-guideline-state.json\",\n \"state/compression-guidelines.draft.md\",\n \"state/compression-guidelines.md\",\n \"state/entity-synthesis-queue.json\",\n \"state/fact-hashes.txt\",\n \"state/memory-actions.jsonl\",\n \"state/memory-lifecycle-ledger.jsonl\",\n \"state/meta.json\",\n \"state/reextract-jobs.jsonl\",\n \"state/topics.json\",\n]);\n\nfunction isEncryptableStateSidecar(normalized: string): boolean {\n return ENCRYPTABLE_STATE_SIDECARS.has(normalized);\n}\n\n/**\n * Per-session buffer state files (`state/buffer/<session>.json`) hold the same\n * buffered turns the legacy `state/buffer.json` held, so they are encryptable\n * state sidecars too — otherwise enabling the secure store would leave the\n * daemon's buffered turns in plaintext on disk.\n */\nfunction isEncryptableBufferSessionFile(normalized: string): boolean {\n return normalized.startsWith(\"state/buffer/\") && normalized.endsWith(\".json\");\n}\n\nfunction isEncryptableSummarySidecar(normalized: string): boolean {\n return normalized.startsWith(\"summaries/\") && normalized.endsWith(\".json\");\n}\n\nconst DECRYPTABLE_SIDECAR_ROOTS = new Set([\"state\", \"indexes\", \"index\", \"provenance\"]);\n","import { constants } from \"node:fs\";\nimport { lstat, open, readFile, realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { assertPathInsideRoot } from \"../utils/path-containment.js\";\n\nexport async function readStoreFileBuffer(filePath: string, memoryDir: string): Promise<Buffer> {\n const root = path.resolve(memoryDir);\n const entities = path.join(root, \"entities\");\n const target = path.resolve(filePath);\n const relative = path.relative(entities, target);\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {\n return readFile(filePath);\n }\n const handle = await open(target, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));\n try {\n for (let parent = path.dirname(target); ; parent = path.dirname(parent)) {\n const info = await lstat(parent);\n if (info.isSymbolicLink() || !info.isDirectory()) {\n throw new Error(`Refusing unsafe entity directory: ${parent}.`);\n }\n if (parent === root) break;\n }\n const [opened, entry, realRoot, realEntities, realTarget] = await Promise.all([\n handle.stat(), lstat(target), realpath(root), realpath(entities), realpath(target),\n ]);\n if (!opened.isFile() || entry.isSymbolicLink() || !entry.isFile()\n || opened.dev !== entry.dev || opened.ino !== entry.ino\n || realEntities !== path.join(realRoot, \"entities\")) {\n throw new Error(`Refusing unsafe entity file: ${filePath}.`);\n }\n assertPathInsideRoot(realEntities, realTarget, filePath);\n return await handle.readFile();\n } finally {\n await handle.close();\n }\n}\n\n\n/**\n * Atomic-replacement-tolerant variant: entity writes ship as temp-file +\n * rename, so an open/lstat identity mismatch during a concurrent write is an\n * ordinary race, not tampering. Retry a bounded number of times with fresh\n * containment checks before surfacing the mismatch as unsafe.\n */\nexport async function readStoreFileBufferTolerant(filePath: string, memoryDir: string, attempts = 3): Promise<Buffer> {\n for (let attempt = 0; ; attempt += 1) {\n try {\n return await readStoreFileBuffer(filePath, memoryDir);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const identityRace = /unsafe entity (?:file|directory)/.test(message);\n if (!identityRace || attempt >= attempts - 1) throw err;\n }\n }\n}\n"],"mappings":"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","names":["lstat","readFile","path","open","open","lstat","path","readFile","position","buffer","unlink"]}
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-TBBDFYXW.js";
4
4
  import {
5
5
  StorageManager
6
- } from "./chunk-O3VKQMWC.js";
6
+ } from "./chunk-WCBLPKG3.js";
7
7
  import {
8
8
  bumpMemoryCorpusVersionForDir
9
9
  } from "./chunk-M5GVCJSJ.js";
@@ -769,4 +769,4 @@ export {
769
769
  listMemoryGovernanceRuns,
770
770
  readMemoryGovernanceRunArtifact
771
771
  };
772
- //# sourceMappingURL=chunk-AI2VXOSO.js.map
772
+ //# sourceMappingURL=chunk-TYLNWE4D.js.map
@@ -5,13 +5,13 @@ import {
5
5
  embeddingGenerationMembership,
6
6
  embeddingShardDirOf,
7
7
  isEmbeddingGenerationDirPath
8
- } from "./chunk-X3IFRQKS.js";
9
- import {
10
- EMBEDDING_SHARD_FILE_PATTERN
11
- } from "./chunk-TYT4TEQV.js";
8
+ } from "./chunk-I73ZSORJ.js";
12
9
  import {
13
10
  resolveSafeArchiveTarget
14
11
  } from "./chunk-GCGJW34D.js";
12
+ import {
13
+ EMBEDDING_SHARD_FILE_PATTERN
14
+ } from "./chunk-LDWE7OZS.js";
15
15
  import {
16
16
  EmbeddingIndexStorageError
17
17
  } from "./chunk-Y57GJDG5.js";
@@ -369,4 +369,4 @@ export {
369
369
  applyChangesetEmbeddingGenerations,
370
370
  buildChangesetGenerationManifest
371
371
  };
372
- //# sourceMappingURL=chunk-WI6MIJYK.js.map
372
+ //# sourceMappingURL=chunk-U7HJBODU.js.map
@@ -9,7 +9,7 @@ import {
9
9
  SecureStoreLockedError,
10
10
  readMaybeEncryptedFile,
11
11
  writeMaybeEncryptedFile
12
- } from "./chunk-ZG3HZZ6K.js";
12
+ } from "./chunk-TYGLV6ZG.js";
13
13
  import {
14
14
  isErrnoCode
15
15
  } from "./chunk-KNA3BXXL.js";
@@ -577,4 +577,4 @@ export {
577
577
  FactHashIndexNotAuthoritativeError,
578
578
  ContentHashIndex
579
579
  };
580
- //# sourceMappingURL=chunk-IS4HKNWP.js.map
580
+ //# sourceMappingURL=chunk-UBN5AOLT.js.map
@@ -19,4 +19,4 @@ export {
19
19
  confidenceTier,
20
20
  SPECULATIVE_TTL_DAYS
21
21
  };
22
- //# sourceMappingURL=chunk-A6PKEU7T.js.map
22
+ //# sourceMappingURL=chunk-UFM3PJDT.js.map