@remnic/core 1.1.1 → 1.1.3

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 (497) hide show
  1. package/dist/abort-error.js +1 -0
  2. package/dist/abstraction-nodes.js +1 -0
  3. package/dist/access-audit.js +1 -0
  4. package/dist/access-cli.js +76 -51
  5. package/dist/access-cli.js.map +1 -1
  6. package/dist/access-http.d.ts +50 -5
  7. package/dist/access-http.js +38 -16
  8. package/dist/access-idempotency.js +1 -0
  9. package/dist/access-mcp.d.ts +10 -5
  10. package/dist/access-mcp.js +37 -14
  11. package/dist/access-schema.d.ts +133 -13
  12. package/dist/access-schema.js +20 -1
  13. package/dist/access-service-_AEUMVyX.d.ts +1981 -0
  14. package/dist/access-service.d.ts +11 -6
  15. package/dist/access-service.js +39 -14
  16. package/dist/active-memory-bridge.js +1 -0
  17. package/dist/active-recall.js +1 -0
  18. package/dist/active-recall.js.map +1 -1
  19. package/dist/behavior-learner.js +1 -0
  20. package/dist/behavior-learner.js.map +1 -1
  21. package/dist/behavior-signals.js +1 -0
  22. package/dist/bootstrap.d.ts +6 -4
  23. package/dist/bootstrap.js +1 -0
  24. package/dist/boxes.js +1 -0
  25. package/dist/briefing.d.ts +9 -5
  26. package/dist/briefing.js +10 -6
  27. package/dist/buffer-surprise-report.js +1 -0
  28. package/dist/buffer-surprise.js +1 -0
  29. package/dist/buffer.d.ts +1 -1
  30. package/dist/buffer.js +1 -0
  31. package/dist/calibration.d.ts +8 -1
  32. package/dist/calibration.js +10 -2
  33. package/dist/calibration.js.map +1 -1
  34. package/dist/capsule-cli.d.ts +137 -0
  35. package/dist/capsule-cli.js +34 -0
  36. package/dist/capsule-crypto-5CYAGVC5.js +18 -0
  37. package/dist/capsule-export-NZQPOTQ4.js +17 -0
  38. package/dist/capsule-export-NZQPOTQ4.js.map +1 -0
  39. package/dist/capsule-import-SDCUXLEV.js +16 -0
  40. package/dist/capsule-import-SDCUXLEV.js.map +1 -0
  41. package/dist/capsule-merge-DI7PNQ2H.js +189 -0
  42. package/dist/capsule-merge-DI7PNQ2H.js.map +1 -0
  43. package/dist/causal-behavior.js +1 -0
  44. package/dist/causal-behavior.js.map +1 -1
  45. package/dist/causal-chain.js +1 -0
  46. package/dist/causal-consolidation.js +12 -9
  47. package/dist/causal-consolidation.js.map +1 -1
  48. package/dist/causal-retrieval.js +2 -1
  49. package/dist/causal-retrieval.js.map +1 -1
  50. package/dist/causal-trajectory-graph.js +4 -1
  51. package/dist/causal-trajectory-graph.js.map +1 -1
  52. package/dist/causal-trajectory.js +2 -1
  53. package/dist/chunk-2LSZVONP.js +67 -0
  54. package/dist/chunk-2LSZVONP.js.map +1 -0
  55. package/dist/chunk-32KD5IHZ.js +245 -0
  56. package/dist/chunk-32KD5IHZ.js.map +1 -0
  57. package/dist/{chunk-VDX363PS.js → chunk-34F3PLWZ.js} +10 -3
  58. package/dist/chunk-34F3PLWZ.js.map +1 -0
  59. package/dist/chunk-3KIS4VGT.js +228 -0
  60. package/dist/chunk-3KIS4VGT.js.map +1 -0
  61. package/dist/chunk-3LCWFNVS.js +350 -0
  62. package/dist/chunk-3LCWFNVS.js.map +1 -0
  63. package/dist/chunk-43EKP2UK.js +26 -0
  64. package/dist/chunk-43EKP2UK.js.map +1 -0
  65. package/dist/chunk-457A4P3L.js +119 -0
  66. package/dist/chunk-457A4P3L.js.map +1 -0
  67. package/dist/{chunk-KUB6JU6H.js → chunk-47WOM4YW.js} +2 -2
  68. package/dist/{chunk-HK3FGIEW.js → chunk-4PLGJRBV.js} +656 -20
  69. package/dist/chunk-4PLGJRBV.js.map +1 -0
  70. package/dist/{chunk-BGJGXLZ7.js → chunk-55FXRRSJ.js} +11 -8
  71. package/dist/chunk-55FXRRSJ.js.map +1 -0
  72. package/dist/{chunk-ULYOGL6R.js → chunk-5HRY2WRF.js} +7 -3
  73. package/dist/chunk-5HRY2WRF.js.map +1 -0
  74. package/dist/chunk-6TBWYBJ3.js +236 -0
  75. package/dist/chunk-6TBWYBJ3.js.map +1 -0
  76. package/dist/chunk-74EMIVE4.js +329 -0
  77. package/dist/chunk-74EMIVE4.js.map +1 -0
  78. package/dist/chunk-74WWN7ZW.js +82 -0
  79. package/dist/chunk-74WWN7ZW.js.map +1 -0
  80. package/dist/{chunk-B5WXLVDY.js → chunk-7GCMLT7J.js} +245 -25
  81. package/dist/chunk-7GCMLT7J.js.map +1 -0
  82. package/dist/chunk-A6XUJE5D.js +126 -0
  83. package/dist/chunk-A6XUJE5D.js.map +1 -0
  84. package/dist/chunk-AJA46VX5.js +393 -0
  85. package/dist/chunk-AJA46VX5.js.map +1 -0
  86. package/dist/{chunk-DFTTJYSO.js → chunk-AKUCB2OG.js} +525 -24
  87. package/dist/chunk-AKUCB2OG.js.map +1 -0
  88. package/dist/chunk-ASIQZXYO.js +277 -0
  89. package/dist/chunk-ASIQZXYO.js.map +1 -0
  90. package/dist/{chunk-ZEM3OK2K.js → chunk-B2TL6GA2.js} +3 -3
  91. package/dist/chunk-BJMBJZ2Y.js +290 -0
  92. package/dist/chunk-BJMBJZ2Y.js.map +1 -0
  93. package/dist/chunk-BT7NVCML.js +79 -0
  94. package/dist/chunk-BT7NVCML.js.map +1 -0
  95. package/dist/chunk-CK5NTM2S.js +454 -0
  96. package/dist/chunk-CK5NTM2S.js.map +1 -0
  97. package/dist/{chunk-3GXCSUXR.js → chunk-CRU27Q4J.js} +2 -2
  98. package/dist/{chunk-F5VP6YCB.js → chunk-DCE6SQLA.js} +572 -155
  99. package/dist/chunk-DCE6SQLA.js.map +1 -0
  100. package/dist/{chunk-CUPFXL3J.js → chunk-DHRQHX36.js} +4 -4
  101. package/dist/chunk-DHRQHX36.js.map +1 -0
  102. package/dist/{chunk-GKFXUTJ2.js → chunk-DR7MCMPS.js} +981 -61
  103. package/dist/chunk-DR7MCMPS.js.map +1 -0
  104. package/dist/chunk-FP2373TW.js +149 -0
  105. package/dist/chunk-FP2373TW.js.map +1 -0
  106. package/dist/{chunk-RBBWYEFJ.js → chunk-G2WADRQ3.js} +1 -1
  107. package/dist/chunk-G7D6GZ5J.js +48 -0
  108. package/dist/chunk-G7D6GZ5J.js.map +1 -0
  109. package/dist/chunk-H7XKCNR6.js +60 -0
  110. package/dist/chunk-H7XKCNR6.js.map +1 -0
  111. package/dist/{chunk-VYM3VWOF.js → chunk-IM3JSE73.js} +966 -329
  112. package/dist/chunk-IM3JSE73.js.map +1 -0
  113. package/dist/chunk-IXEJRKCZ.js +18 -0
  114. package/dist/chunk-IXEJRKCZ.js.map +1 -0
  115. package/dist/chunk-IYY4MCPG.js +275 -0
  116. package/dist/chunk-IYY4MCPG.js.map +1 -0
  117. package/dist/{chunk-BK2EFTE2.js → chunk-JWSENLQI.js} +508 -28
  118. package/dist/chunk-JWSENLQI.js.map +1 -0
  119. package/dist/chunk-KNKUID7G.js +183 -0
  120. package/dist/chunk-KNKUID7G.js.map +1 -0
  121. package/dist/chunk-L2IO2QPY.js +2036 -0
  122. package/dist/chunk-L2IO2QPY.js.map +1 -0
  123. package/dist/{chunk-SPI27QT6.js → chunk-L5IIGA5V.js} +9 -4
  124. package/dist/chunk-L5IIGA5V.js.map +1 -0
  125. package/dist/{chunk-RGLL5SPU.js → chunk-LVYGDT5V.js} +56 -82
  126. package/dist/chunk-LVYGDT5V.js.map +1 -0
  127. package/dist/{chunk-ZAIM4TUE.js → chunk-LW2NMHDW.js} +46 -1
  128. package/dist/chunk-LW2NMHDW.js.map +1 -0
  129. package/dist/{chunk-3OGMS3PE.js → chunk-LZRYQK6L.js} +3 -2
  130. package/dist/chunk-LZRYQK6L.js.map +1 -0
  131. package/dist/chunk-MDYG7VI7.js +48 -0
  132. package/dist/chunk-MDYG7VI7.js.map +1 -0
  133. package/dist/chunk-MXC3AP5I.js +74 -0
  134. package/dist/chunk-MXC3AP5I.js.map +1 -0
  135. package/dist/{chunk-S3EEFKNY.js → chunk-N7X62G74.js} +26 -11
  136. package/dist/chunk-N7X62G74.js.map +1 -0
  137. package/dist/chunk-NN3TS5BM.js +147 -0
  138. package/dist/chunk-NN3TS5BM.js.map +1 -0
  139. package/dist/chunk-OA3L7BFR.js +183 -0
  140. package/dist/chunk-OA3L7BFR.js.map +1 -0
  141. package/dist/{chunk-LK6SGL53.js → chunk-OR64ZGRZ.js} +3 -2
  142. package/dist/chunk-OR64ZGRZ.js.map +1 -0
  143. package/dist/chunk-OZHRDTDX.js +240 -0
  144. package/dist/chunk-OZHRDTDX.js.map +1 -0
  145. package/dist/chunk-PCUKNJAZ.js +165 -0
  146. package/dist/chunk-PCUKNJAZ.js.map +1 -0
  147. package/dist/{chunk-6PFRXT4K.js → chunk-PFV5C235.js} +11 -6
  148. package/dist/chunk-PFV5C235.js.map +1 -0
  149. package/dist/chunk-PZ5AY32C.js +10 -0
  150. package/dist/chunk-PZ5AY32C.js.map +1 -0
  151. package/dist/{chunk-XZ2TIKGC.js → chunk-Q7FJ5ZHM.js} +30 -10
  152. package/dist/chunk-Q7FJ5ZHM.js.map +1 -0
  153. package/dist/{chunk-7I7FKFZH.js → chunk-R2L7SUX2.js} +6 -6
  154. package/dist/{chunk-JL2PU6AI.js → chunk-R2XRID2N.js} +2 -2
  155. package/dist/{chunk-WCLICCGB.js → chunk-RILIVK4O.js} +91 -4
  156. package/dist/chunk-RILIVK4O.js.map +1 -0
  157. package/dist/{chunk-C2EFFULQ.js → chunk-RK2Y4XOM.js} +163 -20
  158. package/dist/chunk-RK2Y4XOM.js.map +1 -0
  159. package/dist/{chunk-TP4FZJIZ.js → chunk-RULE4VG5.js} +5 -1
  160. package/dist/chunk-RULE4VG5.js.map +1 -0
  161. package/dist/{chunk-PVPWZSSI.js → chunk-SMA4IMHV.js} +19 -3
  162. package/dist/chunk-SMA4IMHV.js.map +1 -0
  163. package/dist/{chunk-WVVA7F5A.js → chunk-SS253RXF.js} +30 -16
  164. package/dist/chunk-SS253RXF.js.map +1 -0
  165. package/dist/chunk-TUFG6VXY.js +875 -0
  166. package/dist/chunk-TUFG6VXY.js.map +1 -0
  167. package/dist/chunk-TYEOAFH3.js +251 -0
  168. package/dist/chunk-TYEOAFH3.js.map +1 -0
  169. package/dist/chunk-UKJAGEXH.js +260 -0
  170. package/dist/chunk-UKJAGEXH.js.map +1 -0
  171. package/dist/{chunk-KVBLZUKV.js → chunk-USFPPRAF.js} +93 -3
  172. package/dist/chunk-USFPPRAF.js.map +1 -0
  173. package/dist/{chunk-EPQJM2GC.js → chunk-VTJVUHRK.js} +22 -36
  174. package/dist/chunk-VTJVUHRK.js.map +1 -0
  175. package/dist/{chunk-O5ETUNBT.js → chunk-VTU2B4VF.js} +7 -3
  176. package/dist/chunk-VTU2B4VF.js.map +1 -0
  177. package/dist/chunk-WIICJPET.js +45 -0
  178. package/dist/chunk-WIICJPET.js.map +1 -0
  179. package/dist/{chunk-VBVG2M5G.js → chunk-WPGJYVUH.js} +6 -2
  180. package/dist/chunk-WPGJYVUH.js.map +1 -0
  181. package/dist/{chunk-YNQKWQT4.js → chunk-WSZIHQBK.js} +31 -11
  182. package/dist/{chunk-YNQKWQT4.js.map → chunk-WSZIHQBK.js.map} +1 -1
  183. package/dist/{chunk-NZLQTHS5.js → chunk-WW3QQF4H.js} +4 -1
  184. package/dist/chunk-WW3QQF4H.js.map +1 -0
  185. package/dist/{chunk-FVA6TGI3.js → chunk-Y3WQ4ZWK.js} +42 -2
  186. package/dist/chunk-Y3WQ4ZWK.js.map +1 -0
  187. package/dist/chunk-YNJHCGDT.js +309 -0
  188. package/dist/chunk-YNJHCGDT.js.map +1 -0
  189. package/dist/{chunk-ALXMCZEU.js → chunk-Z2E7VW55.js} +6 -3
  190. package/dist/chunk-Z2E7VW55.js.map +1 -0
  191. package/dist/{chunk-INXV5JBT.js → chunk-ZGXSCMQN.js} +1992 -410
  192. package/dist/chunk-ZGXSCMQN.js.map +1 -0
  193. package/dist/{chunk-W6SL7OFG.js → chunk-ZTSE2ZJ6.js} +12 -2
  194. package/dist/{chunk-W6SL7OFG.js.map → chunk-ZTSE2ZJ6.js.map} +1 -1
  195. package/dist/chunking.js +1 -0
  196. package/dist/cipher-GVE2GQ5H.js +28 -0
  197. package/dist/cipher-GVE2GQ5H.js.map +1 -0
  198. package/dist/citations.js +1 -0
  199. package/dist/{cli-BkeRaYfk.d.ts → cli-x2APT9a6.d.ts} +26 -7
  200. package/dist/cli.d.ts +11 -6
  201. package/dist/cli.js +68 -34
  202. package/dist/codex-thread-key.js +1 -0
  203. package/dist/commitment-ledger.js +1 -0
  204. package/dist/compression-optimizer.js +1 -0
  205. package/dist/config.d.ts +2 -1
  206. package/dist/config.js +5 -2
  207. package/dist/connectors-cli-DFGtY2DB.d.ts +257 -0
  208. package/dist/connectors-cli.d.ts +2 -0
  209. package/dist/connectors-cli.js +22 -0
  210. package/dist/connectors-cli.js.map +1 -0
  211. package/dist/consolidation-operator.d.ts +65 -5
  212. package/dist/consolidation-operator.js +6 -1
  213. package/dist/consolidation-provenance-check.d.ts +1 -1
  214. package/dist/consolidation-provenance-check.js +3 -2
  215. package/dist/consolidation-undo.d.ts +1 -1
  216. package/dist/consolidation-undo.js +1 -0
  217. package/dist/consolidation-undo.js.map +1 -1
  218. package/dist/{contradiction-review-WIUBAR52.js → contradiction-review-5LTTVDQV.js} +2 -1
  219. package/dist/contradiction-review-5LTTVDQV.js.map +1 -0
  220. package/dist/{contradiction-scan-E3GJTI4F.js → contradiction-scan-3Z6YW7YA.js} +2 -1
  221. package/dist/{contradiction-scan-E3GJTI4F.js.map → contradiction-scan-3Z6YW7YA.js.map} +1 -1
  222. package/dist/cross-namespace-budget.js +1 -0
  223. package/dist/cue-anchors.js +1 -0
  224. package/dist/dashboard-runtime.js +1 -0
  225. package/dist/day-summary.js +1 -0
  226. package/dist/delinearize.js +1 -0
  227. package/dist/direct-answer-wiring.js +1 -0
  228. package/dist/direct-answer.js +1 -0
  229. package/dist/dreams-ledger-LR2NBAZE.js +286 -0
  230. package/dist/dreams-ledger-LR2NBAZE.js.map +1 -0
  231. package/dist/embedding-fallback.js +3 -1
  232. package/dist/{engine-F3GOXGE5.js → engine-ICC2DSQF.js} +10 -7
  233. package/dist/engine-ICC2DSQF.js.map +1 -0
  234. package/dist/entity-retrieval.d.ts +1 -1
  235. package/dist/entity-retrieval.js +9 -6
  236. package/dist/entity-schema.js +1 -0
  237. package/dist/evals.js +1 -0
  238. package/dist/evidence-pack.d.ts +16 -0
  239. package/dist/evidence-pack.js +8 -0
  240. package/dist/evidence-pack.js.map +1 -0
  241. package/dist/explicit-capture.d.ts +6 -4
  242. package/dist/explicit-capture.js +1 -0
  243. package/dist/extraction-judge-telemetry.js +1 -0
  244. package/dist/extraction-judge-training.js +1 -0
  245. package/dist/extraction-judge.js +1 -0
  246. package/dist/extraction.js +9 -8
  247. package/dist/fallback-llm.js +3 -2
  248. package/dist/first-start-migration-4MHQEOSD.js +263 -0
  249. package/dist/first-start-migration-4MHQEOSD.js.map +1 -0
  250. package/dist/forget-PLR6J5DN.js +69 -0
  251. package/dist/forget-PLR6J5DN.js.map +1 -0
  252. package/dist/framework-CyHYDcri.d.ts +153 -0
  253. package/dist/fs-utils-IRVUFB6G.js +30 -0
  254. package/dist/fs-utils-IRVUFB6G.js.map +1 -0
  255. package/dist/graph-dashboard-diff.js +1 -0
  256. package/dist/graph-dashboard-key.js +1 -0
  257. package/dist/graph-dashboard-parser.js +1 -0
  258. package/dist/graph-edge-decay-PWB63GRE.js +207 -0
  259. package/dist/graph-edge-decay-PWB63GRE.js.map +1 -0
  260. package/dist/graph-edge-reinforcement.d.ts +81 -0
  261. package/dist/graph-edge-reinforcement.js +24 -0
  262. package/dist/graph-edge-reinforcement.js.map +1 -0
  263. package/dist/graph-events.d.ts +87 -0
  264. package/dist/graph-events.js +14 -0
  265. package/dist/graph-events.js.map +1 -0
  266. package/dist/graph-recall.js +1 -0
  267. package/dist/graph-retrieval.js +1 -0
  268. package/dist/graph-snapshot.d.ts +112 -0
  269. package/dist/graph-snapshot.js +19 -0
  270. package/dist/graph-snapshot.js.map +1 -0
  271. package/dist/graph.d.ts +105 -7
  272. package/dist/graph.js +20 -3
  273. package/dist/harmonic-retrieval.js +1 -0
  274. package/dist/himem.js +1 -0
  275. package/dist/hygiene.js +1 -0
  276. package/dist/identity-continuity.js +1 -0
  277. package/dist/importance.js +1 -0
  278. package/dist/index.d.ts +562 -13
  279. package/dist/index.js +365 -96
  280. package/dist/index.js.map +1 -1
  281. package/dist/intent.js +1 -0
  282. package/dist/json-extract.js +1 -0
  283. package/dist/json-store.js +1 -0
  284. package/dist/kdf-7S6RWKLZ.js +26 -0
  285. package/dist/kdf-7S6RWKLZ.js.map +1 -0
  286. package/dist/legacy-hook-compat.js +1 -0
  287. package/dist/legacy-hook-compat.js.map +1 -1
  288. package/dist/lifecycle.js +1 -0
  289. package/dist/live-connectors-runner.d.ts +48 -0
  290. package/dist/live-connectors-runner.js +17 -0
  291. package/dist/live-connectors-runner.js.map +1 -0
  292. package/dist/local-llm.js +3 -2
  293. package/dist/logger.js +1 -0
  294. package/dist/memory-action-policy.js +1 -0
  295. package/dist/memory-cache.d.ts +2 -1
  296. package/dist/memory-cache.js +4 -1
  297. package/dist/memory-governance-KG52RITE.js +37 -0
  298. package/dist/memory-governance-KG52RITE.js.map +1 -0
  299. package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
  300. package/dist/memory-lifecycle-ledger-utils.js +4 -1
  301. package/dist/memory-projection-format.js +1 -0
  302. package/dist/{memory-projection-store-DeSXPh1j.d.ts → memory-projection-store-D3vBHS4J.d.ts} +1 -0
  303. package/dist/memory-projection-store.d.ts +1 -1
  304. package/dist/memory-projection-store.js +1 -0
  305. package/dist/memory-worth-bench.js +1 -0
  306. package/dist/memory-worth-bench.js.map +1 -1
  307. package/dist/memory-worth-filter.js +1 -0
  308. package/dist/memory-worth-outcomes.d.ts +1 -1
  309. package/dist/memory-worth-outcomes.js +1 -0
  310. package/dist/memory-worth.js +1 -0
  311. package/dist/metadata-FC3XPDRQ.js +21 -0
  312. package/dist/metadata-FC3XPDRQ.js.map +1 -0
  313. package/dist/migrate-from-identity-anchor-TTEDEJGX.js +8 -0
  314. package/dist/migrate-from-identity-anchor-TTEDEJGX.js.map +1 -0
  315. package/dist/model-registry.js +1 -0
  316. package/dist/models-json.js +1 -0
  317. package/dist/native-knowledge.js +1 -0
  318. package/dist/negative.js +1 -0
  319. package/dist/objective-state-writers.js +1 -0
  320. package/dist/objective-state-writers.js.map +1 -1
  321. package/dist/objective-state.js +1 -0
  322. package/dist/openai-chat-compat.js +1 -0
  323. package/dist/operator-toolkit.d.ts +46 -2
  324. package/dist/operator-toolkit.js +29 -17
  325. package/dist/opik-exporter.js +1 -0
  326. package/dist/opik-exporter.js.map +1 -1
  327. package/dist/{orchestrator-CmJ-NTdJ.d.ts → orchestrator-ChkesB8U.d.ts} +177 -13
  328. package/dist/orchestrator.d.ts +6 -4
  329. package/dist/orchestrator.js +58 -42
  330. package/dist/page-versioning.js +1 -0
  331. package/dist/path-RMTY5Y5A.js +9 -0
  332. package/dist/path-RMTY5Y5A.js.map +1 -0
  333. package/dist/patterns-cli.d.ts +160 -0
  334. package/dist/patterns-cli.js +29 -0
  335. package/dist/patterns-cli.js.map +1 -0
  336. package/dist/peers-6OSQ3NK6.js +44 -0
  337. package/dist/peers-6OSQ3NK6.js.map +1 -0
  338. package/dist/plugin-id.js +1 -0
  339. package/dist/policy-runtime.js +1 -0
  340. package/dist/{port-BADbLZU5.d.ts → port-hqGnoStS.d.ts} +6 -0
  341. package/dist/profiling.js +1 -0
  342. package/dist/purge-6ATBGT77.js +205 -0
  343. package/dist/purge-6ATBGT77.js.map +1 -0
  344. package/dist/qmd-recall-cache.d.ts +1 -1
  345. package/dist/qmd-recall-cache.js +1 -0
  346. package/dist/qmd.d.ts +2 -1
  347. package/dist/qmd.js +4 -3
  348. package/dist/reasoning-trace-recall.js +1 -0
  349. package/dist/reasoning-trace-types.js +1 -0
  350. package/dist/recall-audit-anomaly.js +1 -0
  351. package/dist/recall-audit.js +1 -0
  352. package/dist/recall-disclosure-escalation.d.ts +84 -0
  353. package/dist/recall-disclosure-escalation.js +14 -0
  354. package/dist/recall-disclosure-escalation.js.map +1 -0
  355. package/dist/recall-explain-renderer.js +4 -1
  356. package/dist/recall-mmr.js +1 -0
  357. package/dist/recall-qos.js +1 -0
  358. package/dist/recall-query-policy.js +1 -0
  359. package/dist/recall-state.d.ts +7 -0
  360. package/dist/recall-state.js +2 -1
  361. package/dist/recall-tag-filter.d.ts +56 -0
  362. package/dist/recall-tag-filter.js +14 -0
  363. package/dist/recall-tag-filter.js.map +1 -0
  364. package/dist/recall-tokenization.js +1 -0
  365. package/dist/recall-xray-cli.d.ts +9 -2
  366. package/dist/recall-xray-cli.js +9 -4
  367. package/dist/recall-xray-renderer.js +4 -1
  368. package/dist/recall-xray.d.ts +116 -2
  369. package/dist/recall-xray.js +9 -3
  370. package/dist/reconstruct.js +1 -0
  371. package/dist/release-changelog.js +2 -0
  372. package/dist/release-changelog.js.map +1 -1
  373. package/dist/relevance.js +1 -0
  374. package/dist/rerank.js +1 -0
  375. package/dist/{resolution-QBTDHTG7.js → resolution-YGIBORXI.js} +2 -1
  376. package/dist/{resolution-QBTDHTG7.js.map → resolution-YGIBORXI.js.map} +1 -1
  377. package/dist/resolve-auth-token.d.ts +51 -0
  378. package/dist/resolve-auth-token.js +12 -0
  379. package/dist/resolve-auth-token.js.map +1 -0
  380. package/dist/resolve-provider-secret.d.ts +13 -1
  381. package/dist/resolve-provider-secret.js +6 -1
  382. package/dist/resume-bundles.js +5 -4
  383. package/dist/retrieval-agents.d.ts +1 -1
  384. package/dist/retrieval-agents.js +1 -0
  385. package/dist/retrieval-tiers.js +1 -0
  386. package/dist/retrieval.js +1 -0
  387. package/dist/sanitize.js +1 -0
  388. package/dist/schemas.d.ts +15 -2
  389. package/dist/schemas.js +2 -1
  390. package/dist/sdk-compat.js +1 -0
  391. package/dist/sdk-compat.js.map +1 -1
  392. package/dist/secure-store-4R2GSO7S.js +156 -0
  393. package/dist/secure-store-4R2GSO7S.js.map +1 -0
  394. package/dist/semantic-chunking.js +1 -0
  395. package/dist/{semantic-consolidation-CxJU6MJk.d.ts → semantic-consolidation-ByBXb-sf.d.ts} +3 -3
  396. package/dist/semantic-consolidation.d.ts +2 -2
  397. package/dist/semantic-consolidation.js +12 -6
  398. package/dist/semantic-rule-promotion.d.ts +1 -1
  399. package/dist/semantic-rule-promotion.js +9 -6
  400. package/dist/semantic-rule-verifier.d.ts +1 -1
  401. package/dist/semantic-rule-verifier.js +9 -6
  402. package/dist/session-integrity.js +1 -0
  403. package/dist/session-observer-bands.js +1 -0
  404. package/dist/session-observer-state.js +1 -0
  405. package/dist/session-toggles.js +2 -0
  406. package/dist/session-toggles.js.map +1 -1
  407. package/dist/signal.js +1 -0
  408. package/dist/skills-registry.js +2 -0
  409. package/dist/skills-registry.js.map +1 -1
  410. package/dist/source-attribution.js +1 -0
  411. package/dist/state-NCHQ4TRG.js +8 -0
  412. package/dist/state-NCHQ4TRG.js.map +1 -0
  413. package/dist/state-store-3EH7HYIN.js +16 -0
  414. package/dist/state-store-3EH7HYIN.js.map +1 -0
  415. package/dist/storage.d.ts +76 -2
  416. package/dist/storage.js +8 -5
  417. package/dist/store-contract.js +1 -0
  418. package/dist/summarizer.js +6 -5
  419. package/dist/summary-snapshot.js +1 -0
  420. package/dist/temporal-index.js +1 -0
  421. package/dist/temporal-supersession.d.ts +1 -1
  422. package/dist/temporal-supersession.js +2 -1
  423. package/dist/temporal-validity.d.ts +52 -0
  424. package/dist/temporal-validity.js +14 -0
  425. package/dist/temporal-validity.js.map +1 -0
  426. package/dist/threading.js +1 -0
  427. package/dist/tier-migration.d.ts +2 -2
  428. package/dist/tier-migration.js +1 -0
  429. package/dist/tier-routing.js +1 -0
  430. package/dist/tier-stats-62ZVDFKS.js +152 -0
  431. package/dist/tier-stats-62ZVDFKS.js.map +1 -0
  432. package/dist/tmt.js +1 -0
  433. package/dist/tokens.js +3 -1
  434. package/dist/topics.js +1 -0
  435. package/dist/trace-C5ETWBEF.js +290 -0
  436. package/dist/trace-C5ETWBEF.js.map +1 -0
  437. package/dist/transcript.js +1 -0
  438. package/dist/trust-zones.js +1 -0
  439. package/dist/tui-RI7P6PBS.js +13 -0
  440. package/dist/tui-RI7P6PBS.js.map +1 -0
  441. package/dist/types-V3FJ26TF.js +30 -0
  442. package/dist/types-V3FJ26TF.js.map +1 -0
  443. package/dist/types.d.ts +634 -9
  444. package/dist/types.js +10 -3
  445. package/dist/utility-learner.js +1 -0
  446. package/dist/utility-runtime.js +1 -0
  447. package/dist/utility-telemetry.js +1 -0
  448. package/dist/verified-recall.js +9 -6
  449. package/dist/version-utils.js +1 -0
  450. package/dist/whitespace.js +1 -0
  451. package/dist/work-product-ledger.js +1 -0
  452. package/package.json +2 -1
  453. package/dist/access-service-Br8ZydTK.d.ts +0 -827
  454. package/dist/chunk-3OGMS3PE.js.map +0 -1
  455. package/dist/chunk-6PFRXT4K.js.map +0 -1
  456. package/dist/chunk-ALXMCZEU.js.map +0 -1
  457. package/dist/chunk-B5WXLVDY.js.map +0 -1
  458. package/dist/chunk-BGJGXLZ7.js.map +0 -1
  459. package/dist/chunk-BK2EFTE2.js.map +0 -1
  460. package/dist/chunk-C2EFFULQ.js.map +0 -1
  461. package/dist/chunk-CUPFXL3J.js.map +0 -1
  462. package/dist/chunk-DFTTJYSO.js.map +0 -1
  463. package/dist/chunk-EPQJM2GC.js.map +0 -1
  464. package/dist/chunk-F5VP6YCB.js.map +0 -1
  465. package/dist/chunk-FVA6TGI3.js.map +0 -1
  466. package/dist/chunk-GKFXUTJ2.js.map +0 -1
  467. package/dist/chunk-HK3FGIEW.js.map +0 -1
  468. package/dist/chunk-INXV5JBT.js.map +0 -1
  469. package/dist/chunk-KVBLZUKV.js.map +0 -1
  470. package/dist/chunk-LK6SGL53.js.map +0 -1
  471. package/dist/chunk-LTCGGW2D.js +0 -14
  472. package/dist/chunk-LTCGGW2D.js.map +0 -1
  473. package/dist/chunk-NZLQTHS5.js.map +0 -1
  474. package/dist/chunk-O5ETUNBT.js.map +0 -1
  475. package/dist/chunk-PVPWZSSI.js.map +0 -1
  476. package/dist/chunk-RGLL5SPU.js.map +0 -1
  477. package/dist/chunk-S3EEFKNY.js.map +0 -1
  478. package/dist/chunk-SPI27QT6.js.map +0 -1
  479. package/dist/chunk-TP4FZJIZ.js.map +0 -1
  480. package/dist/chunk-ULYOGL6R.js.map +0 -1
  481. package/dist/chunk-VBVG2M5G.js.map +0 -1
  482. package/dist/chunk-VDX363PS.js.map +0 -1
  483. package/dist/chunk-VYM3VWOF.js.map +0 -1
  484. package/dist/chunk-WCLICCGB.js.map +0 -1
  485. package/dist/chunk-WVVA7F5A.js.map +0 -1
  486. package/dist/chunk-X6GF3FX2.js +0 -26
  487. package/dist/chunk-X6GF3FX2.js.map +0 -1
  488. package/dist/chunk-XZ2TIKGC.js.map +0 -1
  489. package/dist/chunk-ZAIM4TUE.js.map +0 -1
  490. /package/dist/{contradiction-review-WIUBAR52.js.map → capsule-cli.js.map} +0 -0
  491. /package/dist/{engine-F3GOXGE5.js.map → capsule-crypto-5CYAGVC5.js.map} +0 -0
  492. /package/dist/{chunk-KUB6JU6H.js.map → chunk-47WOM4YW.js.map} +0 -0
  493. /package/dist/{chunk-ZEM3OK2K.js.map → chunk-B2TL6GA2.js.map} +0 -0
  494. /package/dist/{chunk-3GXCSUXR.js.map → chunk-CRU27Q4J.js.map} +0 -0
  495. /package/dist/{chunk-RBBWYEFJ.js.map → chunk-G2WADRQ3.js.map} +0 -0
  496. /package/dist/{chunk-7I7FKFZH.js.map → chunk-R2L7SUX2.js.map} +0 -0
  497. /package/dist/{chunk-JL2PU6AI.js.map → chunk-R2XRID2N.js.map} +0 -0
@@ -0,0 +1,260 @@
1
+ import {
2
+ DEFAULT_ARGON2ID_PARAMS,
3
+ DEFAULT_SCRYPT_PARAMS,
4
+ KDF_SALT_LENGTH
5
+ } from "./chunk-FP2373TW.js";
6
+
7
+ // src/secure-store/metadata.ts
8
+ var METADATA_FORMAT = "remnic.secure-store.metadata";
9
+ var METADATA_FORMAT_VERSION = 1;
10
+ function bytesToHex(bytes) {
11
+ return Buffer.from(bytes).toString("hex");
12
+ }
13
+ function hexToBytes(hex, expectedLength) {
14
+ if (typeof hex !== "string") {
15
+ throw new Error("hex field must be a string");
16
+ }
17
+ if (!/^[0-9a-f]*$/i.test(hex)) {
18
+ throw new Error("hex field must contain only hexadecimal characters");
19
+ }
20
+ if (hex.length % 2 !== 0) {
21
+ throw new Error("hex field must have even length");
22
+ }
23
+ const buf = Buffer.from(hex, "hex");
24
+ if (buf.length !== expectedLength) {
25
+ throw new Error(
26
+ `hex field decoded to ${buf.length} bytes, expected ${expectedLength}`
27
+ );
28
+ }
29
+ return buf;
30
+ }
31
+ function buildMetadata(options) {
32
+ const { algorithm, salt } = options;
33
+ if (!(salt instanceof Uint8Array) || salt.length !== KDF_SALT_LENGTH) {
34
+ throw new Error(
35
+ `salt must be ${KDF_SALT_LENGTH} bytes, got ${salt?.length ?? "non-buffer"}`
36
+ );
37
+ }
38
+ const createdAt = options.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
39
+ let kdf;
40
+ if (algorithm === "scrypt") {
41
+ const params = options.params ?? {
42
+ ...DEFAULT_SCRYPT_PARAMS
43
+ };
44
+ kdf = { algorithm: "scrypt", params, salt: bytesToHex(salt) };
45
+ } else if (algorithm === "argon2id") {
46
+ const params = options.params ?? {
47
+ ...DEFAULT_ARGON2ID_PARAMS
48
+ };
49
+ kdf = { algorithm: "argon2id", params, salt: bytesToHex(salt) };
50
+ } else {
51
+ throw new Error(`unknown KDF algorithm: ${algorithm}`);
52
+ }
53
+ const meta = {
54
+ format: METADATA_FORMAT,
55
+ formatVersion: METADATA_FORMAT_VERSION,
56
+ kdf,
57
+ createdAt
58
+ };
59
+ if (options.note !== void 0) {
60
+ meta.note = options.note;
61
+ }
62
+ return meta;
63
+ }
64
+ function serializeMetadata(meta) {
65
+ validateMetadata(meta);
66
+ const ordered = {
67
+ format: meta.format,
68
+ formatVersion: meta.formatVersion,
69
+ kdf: orderKdf(meta.kdf),
70
+ createdAt: meta.createdAt
71
+ };
72
+ if (meta.note !== void 0) {
73
+ ordered.note = meta.note;
74
+ }
75
+ return JSON.stringify(ordered, null, 2);
76
+ }
77
+ function orderKdf(kdf) {
78
+ if (kdf.algorithm === "scrypt") {
79
+ return {
80
+ algorithm: kdf.algorithm,
81
+ params: {
82
+ N: kdf.params.N,
83
+ r: kdf.params.r,
84
+ p: kdf.params.p,
85
+ keyLength: kdf.params.keyLength,
86
+ maxmem: kdf.params.maxmem
87
+ },
88
+ salt: kdf.salt
89
+ };
90
+ }
91
+ return {
92
+ algorithm: kdf.algorithm,
93
+ params: {
94
+ memoryKiB: kdf.params.memoryKiB,
95
+ iterations: kdf.params.iterations,
96
+ parallelism: kdf.params.parallelism,
97
+ keyLength: kdf.params.keyLength
98
+ },
99
+ salt: kdf.salt
100
+ };
101
+ }
102
+ function parseMetadata(json) {
103
+ if (typeof json !== "string") {
104
+ throw new Error("metadata input must be a string");
105
+ }
106
+ let parsed;
107
+ try {
108
+ parsed = JSON.parse(json);
109
+ } catch (e) {
110
+ const msg = e instanceof Error ? e.message : String(e);
111
+ throw new Error(`metadata is not valid JSON: ${msg}`);
112
+ }
113
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
114
+ throw new Error("metadata must be a JSON object");
115
+ }
116
+ const obj = parsed;
117
+ if (obj.format !== METADATA_FORMAT) {
118
+ throw new Error(
119
+ `unexpected metadata format: ${String(obj.format)} (expected ${METADATA_FORMAT})`
120
+ );
121
+ }
122
+ if (obj.formatVersion !== METADATA_FORMAT_VERSION) {
123
+ throw new Error(
124
+ `unsupported metadata formatVersion: ${String(obj.formatVersion)} (this build supports ${METADATA_FORMAT_VERSION})`
125
+ );
126
+ }
127
+ if (typeof obj.createdAt !== "string" || obj.createdAt.length === 0) {
128
+ throw new Error("metadata.createdAt must be a non-empty string");
129
+ }
130
+ if (obj.note !== void 0 && typeof obj.note !== "string") {
131
+ throw new Error("metadata.note must be a string when present");
132
+ }
133
+ const kdf = parseKdf(obj.kdf);
134
+ const meta = {
135
+ format: METADATA_FORMAT,
136
+ formatVersion: METADATA_FORMAT_VERSION,
137
+ kdf,
138
+ createdAt: obj.createdAt
139
+ };
140
+ if (typeof obj.note === "string") {
141
+ meta.note = obj.note;
142
+ }
143
+ validateMetadata(meta);
144
+ return meta;
145
+ }
146
+ function parseKdf(value) {
147
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
148
+ throw new Error("metadata.kdf must be an object");
149
+ }
150
+ const k = value;
151
+ if (k.algorithm !== "scrypt" && k.algorithm !== "argon2id") {
152
+ throw new Error(`metadata.kdf.algorithm must be 'scrypt' or 'argon2id', got ${String(k.algorithm)}`);
153
+ }
154
+ if (typeof k.salt !== "string") {
155
+ throw new Error("metadata.kdf.salt must be a hex string");
156
+ }
157
+ hexToBytes(k.salt, KDF_SALT_LENGTH);
158
+ if (typeof k.params !== "object" || k.params === null || Array.isArray(k.params)) {
159
+ throw new Error("metadata.kdf.params must be an object");
160
+ }
161
+ const params = k.params;
162
+ if (k.algorithm === "scrypt") {
163
+ const required = ["N", "r", "p", "keyLength", "maxmem"];
164
+ for (const key of required) {
165
+ if (typeof params[key] !== "number" || !Number.isFinite(params[key])) {
166
+ throw new Error(`metadata.kdf.params.${key} must be a finite number`);
167
+ }
168
+ }
169
+ return {
170
+ algorithm: "scrypt",
171
+ params: {
172
+ N: params.N,
173
+ r: params.r,
174
+ p: params.p,
175
+ keyLength: params.keyLength,
176
+ maxmem: params.maxmem
177
+ },
178
+ salt: k.salt
179
+ };
180
+ }
181
+ const required2 = [
182
+ "memoryKiB",
183
+ "iterations",
184
+ "parallelism",
185
+ "keyLength"
186
+ ];
187
+ for (const key of required2) {
188
+ if (typeof params[key] !== "number" || !Number.isFinite(params[key])) {
189
+ throw new Error(`metadata.kdf.params.${key} must be a finite number`);
190
+ }
191
+ }
192
+ return {
193
+ algorithm: "argon2id",
194
+ params: {
195
+ memoryKiB: params.memoryKiB,
196
+ iterations: params.iterations,
197
+ parallelism: params.parallelism,
198
+ keyLength: params.keyLength
199
+ },
200
+ salt: k.salt
201
+ };
202
+ }
203
+ function validateMetadata(meta) {
204
+ if (meta.format !== METADATA_FORMAT) {
205
+ throw new Error(`metadata.format must be ${METADATA_FORMAT}`);
206
+ }
207
+ if (meta.formatVersion !== METADATA_FORMAT_VERSION) {
208
+ throw new Error(`metadata.formatVersion must be ${METADATA_FORMAT_VERSION}`);
209
+ }
210
+ if (typeof meta.createdAt !== "string" || meta.createdAt.length === 0) {
211
+ throw new Error("metadata.createdAt must be a non-empty ISO-8601 string");
212
+ }
213
+ hexToBytes(meta.kdf.salt, KDF_SALT_LENGTH);
214
+ if (meta.kdf.algorithm === "scrypt") {
215
+ const { N, r, p, keyLength, maxmem } = meta.kdf.params;
216
+ if (!Number.isInteger(N) || N < 2 || N > 2 ** 30 || !Number.isInteger(Math.log2(N))) {
217
+ throw new Error("metadata.kdf.params.N must be a power of 2 in [2, 2^30]");
218
+ }
219
+ if (!Number.isInteger(r) || r < 1) {
220
+ throw new Error("metadata.kdf.params.r must be a positive integer");
221
+ }
222
+ if (!Number.isInteger(p) || p < 1) {
223
+ throw new Error("metadata.kdf.params.p must be a positive integer");
224
+ }
225
+ if (!Number.isInteger(keyLength) || keyLength !== 32) {
226
+ throw new Error("metadata.kdf.params.keyLength must be 32 (AES-256 requires a 32-byte key)");
227
+ }
228
+ if (!Number.isInteger(maxmem) || maxmem < 1024) {
229
+ throw new Error("metadata.kdf.params.maxmem must be a positive integer");
230
+ }
231
+ } else if (meta.kdf.algorithm === "argon2id") {
232
+ const { memoryKiB, iterations, parallelism, keyLength } = meta.kdf.params;
233
+ if (!Number.isInteger(memoryKiB) || memoryKiB < 8) {
234
+ throw new Error("metadata.kdf.params.memoryKiB must be \u2265 8");
235
+ }
236
+ if (!Number.isInteger(iterations) || iterations < 1) {
237
+ throw new Error("metadata.kdf.params.iterations must be a positive integer");
238
+ }
239
+ if (!Number.isInteger(parallelism) || parallelism < 1 || parallelism > 255) {
240
+ throw new Error("metadata.kdf.params.parallelism must be an integer in [1, 255]");
241
+ }
242
+ if (!Number.isInteger(keyLength) || keyLength !== 32) {
243
+ throw new Error("metadata.kdf.params.keyLength must be 32 (AES-256 requires a 32-byte key)");
244
+ }
245
+ }
246
+ }
247
+ function decodeMetadataSalt(meta) {
248
+ return hexToBytes(meta.kdf.salt, KDF_SALT_LENGTH);
249
+ }
250
+
251
+ export {
252
+ METADATA_FORMAT,
253
+ METADATA_FORMAT_VERSION,
254
+ buildMetadata,
255
+ serializeMetadata,
256
+ parseMetadata,
257
+ validateMetadata,
258
+ decodeMetadataSalt
259
+ };
260
+ //# sourceMappingURL=chunk-UKJAGEXH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/secure-store/metadata.ts"],"sourcesContent":["/**\n * Secure-store metadata file format.\n *\n * Issue #690 (PR 1/4) — pure data structure + serialize/parse helpers.\n * No I/O. The eventual `secure-store init` CLI (PR 2/4) will be the\n * surface that actually writes a metadata file to disk.\n *\n * Purpose\n * -------\n * When at-rest encryption is enabled, the memory directory needs a\n * stable record of:\n *\n * - which KDF algorithm was used to derive the master key,\n * - the algorithm parameters (so changing OWASP defaults later\n * doesn't break existing stores),\n * - the canonical salt for the master key,\n * - the metadata format version (so we can evolve the file).\n *\n * Crucially, the metadata file does **not** contain the master key,\n * the passphrase, or anything that would let an attacker decrypt\n * memories. It contains only the public parameters needed to\n * re-derive the same key from the same passphrase.\n *\n * On-disk shape\n * -------------\n * The file is JSON. All binary fields are encoded as lowercase hex\n * strings (chosen over base64 for readability when the file is\n * `cat`'d during incident response).\n *\n * {\n * \"format\": \"remnic.secure-store.metadata\",\n * \"formatVersion\": 1,\n * \"kdf\": {\n * \"algorithm\": \"argon2id\",\n * \"params\": { \"memoryKiB\": 65536, \"iterations\": 3, \"parallelism\": 4, \"keyLength\": 32 },\n * \"salt\": \"<32-hex-chars-for-16-bytes>\"\n * },\n * \"createdAt\": \"<ISO-8601 timestamp>\",\n * \"note\": \"<optional human-readable note>\"\n * }\n */\n\nimport {\n DEFAULT_ARGON2ID_PARAMS,\n DEFAULT_SCRYPT_PARAMS,\n KDF_SALT_LENGTH,\n type Argon2idParams,\n type KdfAlgorithm,\n type ScryptParams,\n} from \"./kdf.js\";\n\n/** Stable identifier so we can sniff the file shape without parsing JSON. */\nexport const METADATA_FORMAT = \"remnic.secure-store.metadata\" as const;\n\n/** Current metadata format version. Bump on breaking schema changes. */\nexport const METADATA_FORMAT_VERSION = 1 as const;\n\nexport interface SecureStoreMetadataKdfScrypt {\n algorithm: \"scrypt\";\n params: ScryptParams;\n /** Hex-encoded salt. Length must match `KDF_SALT_LENGTH` after decode. */\n salt: string;\n}\n\nexport interface SecureStoreMetadataKdfArgon2id {\n algorithm: \"argon2id\";\n params: Argon2idParams;\n salt: string;\n}\n\nexport type SecureStoreMetadataKdf =\n | SecureStoreMetadataKdfScrypt\n | SecureStoreMetadataKdfArgon2id;\n\nexport interface SecureStoreMetadata {\n format: typeof METADATA_FORMAT;\n formatVersion: number;\n kdf: SecureStoreMetadataKdf;\n /** ISO-8601 timestamp recorded at init time. */\n createdAt: string;\n /** Optional human-readable note. Never persist secrets here. */\n note?: string;\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString(\"hex\");\n}\n\nfunction hexToBytes(hex: string, expectedLength: number): Buffer {\n if (typeof hex !== \"string\") {\n throw new Error(\"hex field must be a string\");\n }\n if (!/^[0-9a-f]*$/i.test(hex)) {\n throw new Error(\"hex field must contain only hexadecimal characters\");\n }\n if (hex.length % 2 !== 0) {\n throw new Error(\"hex field must have even length\");\n }\n const buf = Buffer.from(hex, \"hex\");\n if (buf.length !== expectedLength) {\n throw new Error(\n `hex field decoded to ${buf.length} bytes, expected ${expectedLength}`,\n );\n }\n return buf;\n}\n\nexport interface BuildMetadataOptions {\n algorithm: KdfAlgorithm;\n salt: Uint8Array;\n /** Optional override; defaults to `DEFAULT_SCRYPT_PARAMS` / `DEFAULT_ARGON2ID_PARAMS`. */\n params?: ScryptParams | Argon2idParams;\n /** Optional ISO timestamp. Defaults to `new Date().toISOString()`. */\n createdAt?: string;\n /** Optional human-readable note. */\n note?: string;\n}\n\n/**\n * Build an in-memory `SecureStoreMetadata` object from the given\n * algorithm + salt. Pure: does not touch the filesystem or the clock\n * unless `createdAt` is omitted (in which case `new Date()` is read).\n */\nexport function buildMetadata(options: BuildMetadataOptions): SecureStoreMetadata {\n const { algorithm, salt } = options;\n if (!(salt instanceof Uint8Array) || salt.length !== KDF_SALT_LENGTH) {\n throw new Error(\n `salt must be ${KDF_SALT_LENGTH} bytes, got ${salt?.length ?? \"non-buffer\"}`,\n );\n }\n const createdAt = options.createdAt ?? new Date().toISOString();\n\n let kdf: SecureStoreMetadataKdf;\n if (algorithm === \"scrypt\") {\n const params = (options.params as ScryptParams | undefined) ?? {\n ...DEFAULT_SCRYPT_PARAMS,\n };\n kdf = { algorithm: \"scrypt\", params, salt: bytesToHex(salt) };\n } else if (algorithm === \"argon2id\") {\n const params = (options.params as Argon2idParams | undefined) ?? {\n ...DEFAULT_ARGON2ID_PARAMS,\n };\n kdf = { algorithm: \"argon2id\", params, salt: bytesToHex(salt) };\n } else {\n throw new Error(`unknown KDF algorithm: ${algorithm as string}`);\n }\n\n const meta: SecureStoreMetadata = {\n format: METADATA_FORMAT,\n formatVersion: METADATA_FORMAT_VERSION,\n kdf,\n createdAt,\n };\n if (options.note !== undefined) {\n meta.note = options.note;\n }\n return meta;\n}\n\n/**\n * Serialize metadata to a stable JSON string with sorted top-level\n * keys. Stable ordering matters because hash-based integrity checks\n * may eventually consume the serialized form.\n */\nexport function serializeMetadata(meta: SecureStoreMetadata): string {\n // Validate before serializing so we never write a malformed file.\n validateMetadata(meta);\n // JSON.stringify preserves insertion order; we construct the object\n // explicitly to lock the field order.\n const ordered: Record<string, unknown> = {\n format: meta.format,\n formatVersion: meta.formatVersion,\n kdf: orderKdf(meta.kdf),\n createdAt: meta.createdAt,\n };\n if (meta.note !== undefined) {\n ordered.note = meta.note;\n }\n return JSON.stringify(ordered, null, 2);\n}\n\nfunction orderKdf(kdf: SecureStoreMetadataKdf): Record<string, unknown> {\n if (kdf.algorithm === \"scrypt\") {\n return {\n algorithm: kdf.algorithm,\n params: {\n N: kdf.params.N,\n r: kdf.params.r,\n p: kdf.params.p,\n keyLength: kdf.params.keyLength,\n maxmem: kdf.params.maxmem,\n },\n salt: kdf.salt,\n };\n }\n return {\n algorithm: kdf.algorithm,\n params: {\n memoryKiB: kdf.params.memoryKiB,\n iterations: kdf.params.iterations,\n parallelism: kdf.params.parallelism,\n keyLength: kdf.params.keyLength,\n },\n salt: kdf.salt,\n };\n}\n\n/**\n * Parse a metadata JSON string. Throws on any structural problem.\n * Callers that need to migrate older formats should branch on\n * `formatVersion` *before* calling this; this function is strict\n * about the current version.\n */\nexport function parseMetadata(json: string): SecureStoreMetadata {\n if (typeof json !== \"string\") {\n throw new Error(\"metadata input must be a string\");\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(`metadata is not valid JSON: ${msg}`);\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(\"metadata must be a JSON object\");\n }\n const obj = parsed as Record<string, unknown>;\n if (obj.format !== METADATA_FORMAT) {\n throw new Error(\n `unexpected metadata format: ${String(obj.format)} (expected ${METADATA_FORMAT})`,\n );\n }\n if (obj.formatVersion !== METADATA_FORMAT_VERSION) {\n throw new Error(\n `unsupported metadata formatVersion: ${String(obj.formatVersion)} ` +\n `(this build supports ${METADATA_FORMAT_VERSION})`,\n );\n }\n if (typeof obj.createdAt !== \"string\" || obj.createdAt.length === 0) {\n throw new Error(\"metadata.createdAt must be a non-empty string\");\n }\n if (obj.note !== undefined && typeof obj.note !== \"string\") {\n throw new Error(\"metadata.note must be a string when present\");\n }\n const kdf = parseKdf(obj.kdf);\n const meta: SecureStoreMetadata = {\n format: METADATA_FORMAT,\n formatVersion: METADATA_FORMAT_VERSION,\n kdf,\n createdAt: obj.createdAt,\n };\n if (typeof obj.note === \"string\") {\n meta.note = obj.note;\n }\n validateMetadata(meta);\n return meta;\n}\n\nfunction parseKdf(value: unknown): SecureStoreMetadataKdf {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(\"metadata.kdf must be an object\");\n }\n const k = value as Record<string, unknown>;\n if (k.algorithm !== \"scrypt\" && k.algorithm !== \"argon2id\") {\n throw new Error(`metadata.kdf.algorithm must be 'scrypt' or 'argon2id', got ${String(k.algorithm)}`);\n }\n if (typeof k.salt !== \"string\") {\n throw new Error(\"metadata.kdf.salt must be a hex string\");\n }\n // Decode to validate length and hex shape; we don't need the bytes here.\n hexToBytes(k.salt, KDF_SALT_LENGTH);\n if (typeof k.params !== \"object\" || k.params === null || Array.isArray(k.params)) {\n throw new Error(\"metadata.kdf.params must be an object\");\n }\n const params = k.params as Record<string, unknown>;\n if (k.algorithm === \"scrypt\") {\n const required: (keyof ScryptParams)[] = [\"N\", \"r\", \"p\", \"keyLength\", \"maxmem\"];\n for (const key of required) {\n if (typeof params[key] !== \"number\" || !Number.isFinite(params[key] as number)) {\n throw new Error(`metadata.kdf.params.${key} must be a finite number`);\n }\n }\n return {\n algorithm: \"scrypt\",\n params: {\n N: params.N as number,\n r: params.r as number,\n p: params.p as number,\n keyLength: params.keyLength as number,\n maxmem: params.maxmem as number,\n },\n salt: k.salt,\n };\n }\n // argon2id\n const required2: (keyof Argon2idParams)[] = [\n \"memoryKiB\",\n \"iterations\",\n \"parallelism\",\n \"keyLength\",\n ];\n for (const key of required2) {\n if (typeof params[key] !== \"number\" || !Number.isFinite(params[key] as number)) {\n throw new Error(`metadata.kdf.params.${key} must be a finite number`);\n }\n }\n return {\n algorithm: \"argon2id\",\n params: {\n memoryKiB: params.memoryKiB as number,\n iterations: params.iterations as number,\n parallelism: params.parallelism as number,\n keyLength: params.keyLength as number,\n },\n salt: k.salt,\n };\n}\n\n/** Validate a metadata object's invariants. Throws on the first problem. */\nexport function validateMetadata(meta: SecureStoreMetadata): void {\n if (meta.format !== METADATA_FORMAT) {\n throw new Error(`metadata.format must be ${METADATA_FORMAT}`);\n }\n if (meta.formatVersion !== METADATA_FORMAT_VERSION) {\n throw new Error(`metadata.formatVersion must be ${METADATA_FORMAT_VERSION}`);\n }\n if (typeof meta.createdAt !== \"string\" || meta.createdAt.length === 0) {\n throw new Error(\"metadata.createdAt must be a non-empty ISO-8601 string\");\n }\n // Salt round-trip check.\n hexToBytes(meta.kdf.salt, KDF_SALT_LENGTH);\n if (meta.kdf.algorithm === \"scrypt\") {\n const { N, r, p, keyLength, maxmem } = meta.kdf.params;\n // Cursor Low + codex P2: bitwise `(N & (N - 1))` truncates to\n // 32-bit signed in JS, so for N >= 2**31 the check silently\n // wraps and accepts non-powers-of-two like `5 * 2**30`. Use\n // Math.log2 plus an upper bound at 2**30 so out-of-range\n // values are rejected loudly at metadata-load time rather than\n // locking up the KDF later.\n if (\n !Number.isInteger(N) ||\n N < 2 ||\n N > 2 ** 30 ||\n !Number.isInteger(Math.log2(N))\n ) {\n throw new Error(\"metadata.kdf.params.N must be a power of 2 in [2, 2^30]\");\n }\n if (!Number.isInteger(r) || r < 1) {\n throw new Error(\"metadata.kdf.params.r must be a positive integer\");\n }\n if (!Number.isInteger(p) || p < 1) {\n throw new Error(\"metadata.kdf.params.p must be a positive integer\");\n }\n // Codex P2: cipher.ts hard-requires a 32-byte AES-256 key\n // (`assertAesKey`). Accepting `keyLength: 16` here would parse\n // and validate cleanly but later fail at encrypt/decrypt time\n // — a latent runtime break. Reject anything other than 32 at\n // load time so the metadata file is the authoritative gate.\n if (!Number.isInteger(keyLength) || keyLength !== 32) {\n throw new Error(\"metadata.kdf.params.keyLength must be 32 (AES-256 requires a 32-byte key)\");\n }\n if (!Number.isInteger(maxmem) || maxmem < 1024) {\n throw new Error(\"metadata.kdf.params.maxmem must be a positive integer\");\n }\n } else if (meta.kdf.algorithm === \"argon2id\") {\n const { memoryKiB, iterations, parallelism, keyLength } = meta.kdf.params;\n if (!Number.isInteger(memoryKiB) || memoryKiB < 8) {\n throw new Error(\"metadata.kdf.params.memoryKiB must be ≥ 8\");\n }\n if (!Number.isInteger(iterations) || iterations < 1) {\n throw new Error(\"metadata.kdf.params.iterations must be a positive integer\");\n }\n if (!Number.isInteger(parallelism) || parallelism < 1 || parallelism > 255) {\n throw new Error(\"metadata.kdf.params.parallelism must be an integer in [1, 255]\");\n }\n // Codex P2: cipher.ts hard-requires a 32-byte AES-256 key\n // (`assertAesKey`). Accepting `keyLength: 16` here would parse\n // and validate cleanly but later fail at encrypt/decrypt time\n // — a latent runtime break. Reject anything other than 32 at\n // load time so the metadata file is the authoritative gate.\n if (!Number.isInteger(keyLength) || keyLength !== 32) {\n throw new Error(\"metadata.kdf.params.keyLength must be 32 (AES-256 requires a 32-byte key)\");\n }\n }\n}\n\n/**\n * Decode the salt field of a metadata object back into bytes.\n * Convenience helper so callers don't reach into the hex codec.\n */\nexport function decodeMetadataSalt(meta: SecureStoreMetadata): Buffer {\n return hexToBytes(meta.kdf.salt, KDF_SALT_LENGTH);\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,13 @@
1
+ import {
2
+ isRecallDisclosure
3
+ } from "./chunk-43EKP2UK.js";
4
+
1
5
  // src/recall-xray.ts
2
6
  import { randomUUID } from "crypto";
7
+ function estimateRecallTokens(text) {
8
+ if (typeof text !== "string" || text.length === 0) return 0;
9
+ return Math.ceil(text.length / 4);
10
+ }
3
11
  var RECALL_XRAY_SERVED_BY_VALUES = [
4
12
  "direct-answer",
5
13
  "hybrid",
@@ -19,7 +27,20 @@ function buildXraySnapshot(input) {
19
27
  const budgetChars = nonNegativeInt(input.budget?.chars);
20
28
  const budgetUsed = nonNegativeInt(input.budget?.used);
21
29
  const tierExplain = input.tierExplain && typeof input.tierExplain === "object" ? cloneTierExplain(input.tierExplain) : null;
22
- return {
30
+ let peerProfileInjection;
31
+ if (input.peerProfileInjection && typeof input.peerProfileInjection === "object") {
32
+ const raw = input.peerProfileInjection;
33
+ const peerId = nonEmptyString(raw.peerId);
34
+ if (peerId !== void 0) {
35
+ peerProfileInjection = {
36
+ peerId,
37
+ fieldsInjected: nonNegativeInt(raw.fieldsInjected)
38
+ };
39
+ }
40
+ } else if (input.peerProfileInjection === null) {
41
+ peerProfileInjection = null;
42
+ }
43
+ const out = {
23
44
  schemaVersion: "1",
24
45
  query: typeof input.query === "string" ? input.query : "",
25
46
  snapshotId: snapshotIdGenerator(),
@@ -32,6 +53,10 @@ function buildXraySnapshot(input) {
32
53
  namespace: nonEmptyString(input.namespace),
33
54
  traceId: nonEmptyString(input.traceId)
34
55
  };
56
+ if (peerProfileInjection !== void 0) {
57
+ out.peerProfileInjection = peerProfileInjection;
58
+ }
59
+ return out;
35
60
  }
36
61
  var RecallXrayBuilder = class {
37
62
  query;
@@ -43,6 +68,7 @@ var RecallXrayBuilder = class {
43
68
  filters = [];
44
69
  budgetChars = 0;
45
70
  budgetUsed = 0;
71
+ peerProfileInjection;
46
72
  constructor(opts) {
47
73
  this.query = typeof opts.query === "string" ? opts.query : "";
48
74
  this.sessionKey = nonEmptyString(opts.sessionKey);
@@ -62,6 +88,14 @@ var RecallXrayBuilder = class {
62
88
  this.budgetChars = nonNegativeInt(budget.chars);
63
89
  this.budgetUsed = nonNegativeInt(budget.used);
64
90
  }
91
+ /**
92
+ * Record peer-profile injection metadata for this recall snapshot
93
+ * (issue #679 completion). Pass `null` to explicitly record that no
94
+ * injection happened (feature enabled but no peer / no profile fields).
95
+ */
96
+ setPeerProfileInjection(injection) {
97
+ this.peerProfileInjection = injection;
98
+ }
65
99
  recordResult(result) {
66
100
  this.results.push(cloneResult(result));
67
101
  }
@@ -78,6 +112,7 @@ var RecallXrayBuilder = class {
78
112
  sessionKey: this.sessionKey,
79
113
  namespace: this.namespace,
80
114
  traceId: this.traceId,
115
+ peerProfileInjection: this.peerProfileInjection,
81
116
  now: opts.now,
82
117
  snapshotIdGenerator: opts.snapshotIdGenerator
83
118
  });
@@ -98,6 +133,25 @@ function cloneResult(result) {
98
133
  const path = typeof result.path === "string" ? result.path : "";
99
134
  const admittedBy = Array.isArray(result.admittedBy) ? result.admittedBy.filter((x) => typeof x === "string") : [];
100
135
  const graphPath = Array.isArray(result.graphPath) ? result.graphPath.filter((x) => typeof x === "string") : void 0;
136
+ let graphEdgeConfidences;
137
+ if (Array.isArray(result.graphEdgeConfidences) && graphPath && graphPath.length > 1) {
138
+ const expected = graphPath.length - 1;
139
+ const raw = result.graphEdgeConfidences;
140
+ if (raw.length === expected) {
141
+ const cleaned = [];
142
+ let allFinite = true;
143
+ for (const value of raw) {
144
+ if (typeof value !== "number" || !Number.isFinite(value)) {
145
+ allFinite = false;
146
+ break;
147
+ }
148
+ cleaned.push(Math.min(1, Math.max(0, value)));
149
+ }
150
+ if (allFinite) {
151
+ graphEdgeConfidences = cleaned;
152
+ }
153
+ }
154
+ }
101
155
  const auditEntryId = nonEmptyString(result.auditEntryId);
102
156
  const rejectedBy = nonEmptyString(result.rejectedBy);
103
157
  const scoreDecomposition = cloneScoreDecomposition(result.scoreDecomposition);
@@ -109,10 +163,40 @@ function cloneResult(result) {
109
163
  admittedBy
110
164
  };
111
165
  if (graphPath !== void 0) out.graphPath = graphPath;
166
+ if (graphEdgeConfidences !== void 0) {
167
+ out.graphEdgeConfidences = graphEdgeConfidences;
168
+ }
112
169
  if (auditEntryId !== void 0) out.auditEntryId = auditEntryId;
113
170
  if (rejectedBy !== void 0) out.rejectedBy = rejectedBy;
171
+ if (isRecallDisclosure(result.disclosure)) {
172
+ out.disclosure = result.disclosure;
173
+ }
174
+ if (typeof result.estimatedTokens === "number" && Number.isFinite(result.estimatedTokens) && result.estimatedTokens >= 0) {
175
+ out.estimatedTokens = Math.floor(result.estimatedTokens);
176
+ }
177
+ if (Array.isArray(result.tags)) {
178
+ const cleanedTags = result.tags.filter((t) => typeof t === "string").map((t) => t.trim()).filter((t) => t.length > 0);
179
+ if (cleanedTags.length > 0) {
180
+ out.tags = cleanedTags;
181
+ }
182
+ }
114
183
  return out;
115
184
  }
185
+ function summarizeDisclosureTokens(results) {
186
+ const summary = {
187
+ chunk: { count: 0, estimatedTokens: 0 },
188
+ section: { count: 0, estimatedTokens: 0 },
189
+ raw: { count: 0, estimatedTokens: 0 },
190
+ unspecified: { count: 0, estimatedTokens: 0 }
191
+ };
192
+ for (const result of results) {
193
+ const tokens = typeof result.estimatedTokens === "number" && Number.isFinite(result.estimatedTokens) && result.estimatedTokens >= 0 ? Math.floor(result.estimatedTokens) : 0;
194
+ const bucket = isRecallDisclosure(result.disclosure) ? result.disclosure : "unspecified";
195
+ summary[bucket].count += 1;
196
+ summary[bucket].estimatedTokens += tokens;
197
+ }
198
+ return summary;
199
+ }
116
200
  function cloneFilter(filter) {
117
201
  if (!filter || typeof filter !== "object") {
118
202
  throw new TypeError("RecallFilterTrace must be an object");
@@ -143,6 +227,10 @@ function cloneScoreDecomposition(value) {
143
227
  if (mmrPenalty !== void 0) out.mmrPenalty = mmrPenalty;
144
228
  const tierPrior = finiteNumber(value.tierPrior);
145
229
  if (tierPrior !== void 0) out.tierPrior = tierPrior;
230
+ const reinforcementBoost = finiteNumber(value.reinforcementBoost);
231
+ if (reinforcementBoost !== void 0 && reinforcementBoost > 0) {
232
+ out.reinforcementBoost = reinforcementBoost;
233
+ }
146
234
  return out;
147
235
  }
148
236
  function cloneTierExplain(tierExplain) {
@@ -165,9 +253,11 @@ function nonEmptyString(value) {
165
253
  }
166
254
 
167
255
  export {
256
+ estimateRecallTokens,
168
257
  RECALL_XRAY_SERVED_BY_VALUES,
169
258
  isRecallXrayServedBy,
170
259
  buildXraySnapshot,
171
- RecallXrayBuilder
260
+ RecallXrayBuilder,
261
+ summarizeDisclosureTokens
172
262
  };
173
- //# sourceMappingURL=chunk-KVBLZUKV.js.map
263
+ //# sourceMappingURL=chunk-USFPPRAF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/recall-xray.ts"],"sourcesContent":["/**\n * Recall X-ray snapshot schema (issue #570, PR 1).\n *\n * The X-ray surface is the unified, per-result attribution document that\n * merges the tier that served each memory, its score decomposition, any\n * graph path, an audit entry id, and the exact filter/eligibility ladder\n * that either admitted or rejected each candidate. This file defines the\n * schema and an in-memory builder + builder-state helper.\n *\n * Scope for PR 1 (this slice):\n * - Types only + pure builder functions (no IO, no rendering).\n * - Orchestrator plumbing captures a snapshot when the caller passes\n * `xrayCapture: true`. No behavior change when the flag is absent.\n * - NO new public surfaces here — CLI/HTTP/MCP land in later slices.\n *\n * The shared renderer lands in PR 2 at `recall-xray-renderer.ts`. Do not\n * fork formatting logic into other surfaces; extend the renderer.\n */\n\nimport { randomUUID } from \"node:crypto\";\n\nimport type { RecallDisclosure, RecallTierExplain } from \"./types.js\";\nimport { isRecallDisclosure } from \"./types.js\";\n\n/**\n * Estimate token cost of a payload at the rough ~4 chars/token English\n * heuristic. Non-negative integer; returns 0 for empty / null input.\n * Used by recall surfaces to attach `estimatedTokens` to X-ray results\n * (issue #677 PR 3/4). Identical to the private heuristic in\n * `chunking.ts`; kept self-contained here so X-ray callers don't pull\n * in chunking internals.\n */\nexport function estimateRecallTokens(text: string | null | undefined): number {\n if (typeof text !== \"string\" || text.length === 0) return 0;\n return Math.ceil(text.length / 4);\n}\n\n/**\n * Aggregated per-disclosure token spend summary, computed by the\n * renderer from a snapshot's results. Non-negative integers.\n */\nexport interface RecallXrayDisclosureSummary {\n chunk: { count: number; estimatedTokens: number };\n section: { count: number; estimatedTokens: number };\n raw: { count: number; estimatedTokens: number };\n /** Number of results without a recorded disclosure level. */\n unspecified: { count: number; estimatedTokens: number };\n}\n\n/**\n * Which retrieval source produced a given result. This is the X-ray\n * tier ladder called out in issue #570 and is *distinct* from the\n * `RetrievalTier` enum (which describes issue #518's tier-explain\n * block). Keeping the sets separate lets the two observability\n * surfaces evolve without conflating their vocabularies:\n *\n * - `RetrievalTier` — direct-answer eligibility ladder.\n * - `RecallXrayServedBy` — which source materialized each result.\n */\nexport type RecallXrayServedBy =\n | \"direct-answer\"\n | \"hybrid\"\n | \"graph\"\n | \"recent-scan\"\n | \"procedural\"\n | \"review-context\";\n\nexport const RECALL_XRAY_SERVED_BY_VALUES: readonly RecallXrayServedBy[] = [\n \"direct-answer\",\n \"hybrid\",\n \"graph\",\n \"recent-scan\",\n \"procedural\",\n \"review-context\",\n] as const;\n\nexport function isRecallXrayServedBy(\n value: unknown,\n): value is RecallXrayServedBy {\n return (\n typeof value === \"string\" &&\n (RECALL_XRAY_SERVED_BY_VALUES as readonly string[]).includes(value)\n );\n}\n\n/**\n * Score decomposition for a single X-ray result.\n *\n * All fields are optional because different tiers populate different\n * terms: `hybrid` reports vector + bm25 + mmr penalty, `direct-answer`\n * reports importance + tier prior, etc. The only guaranteed field is\n * `final`, which is the post-combination score used for ordering.\n */\nexport interface RecallXrayScoreDecomposition {\n vector?: number;\n bm25?: number;\n importance?: number;\n mmrPenalty?: number;\n tierPrior?: number;\n /** Additive boost from `reinforcement_count` frontmatter (issue #687 PR 3/4). */\n reinforcementBoost?: number;\n final: number;\n}\n\n/**\n * Per-result breakdown inside an X-ray snapshot.\n */\nexport interface RecallXrayResult {\n memoryId: string;\n path: string;\n servedBy: RecallXrayServedBy;\n scoreDecomposition: RecallXrayScoreDecomposition;\n graphPath?: string[];\n /**\n * Issue #681 PR 3/3 — per-edge confidence values aligned with\n * `graphPath`. When present, `graphEdgeConfidences[i]` is the\n * confidence of the edge between `graphPath[i]` and `graphPath[i+1]`,\n * so the array length is one less than `graphPath`. Legacy edges\n * without a recorded confidence render as `1.0`. Operators use this\n * to attribute floor-pruning and PageRank ranking decisions back to\n * specific edges. The renderer drops the line when the array is\n * empty or absent so legacy snapshots round-trip cleanly.\n */\n graphEdgeConfidences?: number[];\n auditEntryId?: string;\n /** Human-readable list of filters the candidate *passed*. */\n admittedBy: string[];\n /**\n * First filter that *would have* rejected the candidate, or undefined\n * when the candidate was admitted without a rejection trace. When\n * present, `admittedBy` may still contain filters the candidate passed\n * before the rejecting gate; consumers should render both.\n */\n rejectedBy?: string;\n /**\n * Disclosure depth used to render this result's payload (issue #677\n * PR 3/4). Mirrors the per-result disclosure already exposed in the\n * recall response so X-ray consumers can attribute token spend to\n * the depth that produced it.\n */\n disclosure?: RecallDisclosure;\n /**\n * Estimated token cost of the rendered payload at the chosen\n * disclosure depth. Non-negative integer. Computed by callers via\n * `estimateRecallTokens(text)`; the renderer aggregates these into\n * a per-disclosure summary so operators can see where their budget\n * went.\n */\n estimatedTokens?: number;\n /**\n * Free-form tags from the memory's YAML frontmatter (issue #689 PR 3/3).\n * Populated by the X-ray capture path when the caller passes a `tags`\n * filter so per-result tags are available alongside the filter trace\n * in `snapshot.filters`. Also populated without a filter when the\n * orchestrator decorates results via `xrayCapture: true` so all X-ray\n * consumers can inspect memory labels without a separate storage read.\n * Absent (not `[]`) when the frontmatter has no tags or the memory\n * could not be read.\n */\n tags?: string[];\n}\n\n/**\n * Trace entry for a filter the orchestrator evaluated during recall.\n * Captures the name of the filter, how many candidates it saw, and how\n * many it let through. Used by X-ray consumers to render the filter\n * ladder above the per-result breakdown.\n */\nexport interface RecallFilterTrace {\n name: string;\n considered: number;\n admitted: number;\n /** Optional human-readable reason for any rejections. */\n reason?: string;\n}\n\n/**\n * Peer-profile injection annotation (issue #679 completion).\n *\n * When `peerProfileRecallEnabled` is true and a peer is registered for\n * the session, the orchestrator injects a `## Peer Profile` section into\n * the recall context. This annotation records which peer was injected and\n * how many profile fields were included so operators can correlate\n * retrieval quality with peer-context enrichment.\n *\n * `null` means no peer profile was injected (peer not registered, feature\n * disabled, or peer has no profile fields).\n */\nexport interface RecallXrayPeerProfileInjection {\n /** The peer id whose profile was injected. */\n peerId: string;\n /**\n * Number of profile fields included after the `peerProfileRecallMaxFields`\n * cap was applied. Zero means the profile existed but had no fields.\n */\n fieldsInjected: number;\n}\n\n/**\n * The unified X-ray snapshot. CLI, HTTP, and MCP surfaces all render\n * this same shape through the shared renderer (CLAUDE.md rule 22).\n */\nexport interface RecallXraySnapshot {\n /** Stable v1 tag so downstream consumers can version-gate their parsers. */\n schemaVersion: \"1\";\n query: string;\n /** UUID minted per capture; unique across snapshots within a process. */\n snapshotId: string;\n /** Epoch milliseconds the snapshot was captured. */\n capturedAt: number;\n /**\n * Tier-explain block from issue #518, carried verbatim when present.\n * `null` means direct-answer tier did not run (disabled, or another\n * tier served the query).\n */\n tierExplain: RecallTierExplain | null;\n results: RecallXrayResult[];\n filters: RecallFilterTrace[];\n /**\n * Character budget accounting for the final assembled recall payload.\n * `used` is the rendered-context length; `chars` is the cap. Both are\n * non-negative integers in `[0, 2**31)`.\n */\n budget: { chars: number; used: number };\n /** Optional session-scope fields carried for downstream filtering. */\n sessionKey?: string;\n namespace?: string;\n traceId?: string;\n /**\n * Peer-profile injection metadata (issue #679 completion).\n * Non-null when `peerProfileRecallEnabled` is true and a peer profile\n * was successfully injected into this recall's context. `null` (or\n * absent) means no peer profile was injected.\n */\n peerProfileInjection?: RecallXrayPeerProfileInjection | null;\n}\n\n// ─── Builder ──────────────────────────────────────────────────────────────\n\nexport interface BuildXraySnapshotInput {\n query: string;\n tierExplain?: RecallTierExplain | null;\n results?: RecallXrayResult[];\n filters?: RecallFilterTrace[];\n budget?: { chars?: number; used?: number };\n sessionKey?: string;\n namespace?: string;\n traceId?: string;\n /** Peer-profile injection metadata (issue #679 completion). */\n peerProfileInjection?: RecallXrayPeerProfileInjection | null;\n /** Optional injected timestamp for deterministic tests. */\n now?: () => number;\n /** Optional injected id generator for deterministic tests. */\n snapshotIdGenerator?: () => string;\n}\n\n/**\n * Build a `RecallXraySnapshot` from explicit input fields. Pure\n * function; safe to call from anywhere. All array/object inputs are\n * shallow-copied so caller mutation after build cannot tear the\n * returned snapshot.\n */\nexport function buildXraySnapshot(\n input: BuildXraySnapshotInput,\n): RecallXraySnapshot {\n const now = input.now ?? Date.now;\n const snapshotIdGenerator = input.snapshotIdGenerator ?? randomUUID;\n\n const results = Array.isArray(input.results)\n ? input.results.map(cloneResult)\n : [];\n const filters = Array.isArray(input.filters)\n ? input.filters.map(cloneFilter)\n : [];\n\n const budgetChars = nonNegativeInt(input.budget?.chars);\n const budgetUsed = nonNegativeInt(input.budget?.used);\n\n const tierExplain =\n input.tierExplain && typeof input.tierExplain === \"object\"\n ? cloneTierExplain(input.tierExplain)\n : null;\n\n // Peer-profile injection annotation (issue #679 completion).\n // Deep-copy via structuredClone so the caller can't mutate the snapshot\n // after build. Accept null explicitly (no injection) or a valid object.\n let peerProfileInjection: RecallXrayPeerProfileInjection | null | undefined;\n if (input.peerProfileInjection && typeof input.peerProfileInjection === \"object\") {\n const raw = input.peerProfileInjection;\n const peerId = nonEmptyString(raw.peerId);\n if (peerId !== undefined) {\n peerProfileInjection = {\n peerId,\n fieldsInjected: nonNegativeInt(raw.fieldsInjected),\n };\n }\n } else if (input.peerProfileInjection === null) {\n peerProfileInjection = null;\n }\n\n const out: RecallXraySnapshot = {\n schemaVersion: \"1\",\n query: typeof input.query === \"string\" ? input.query : \"\",\n snapshotId: snapshotIdGenerator(),\n capturedAt: now(),\n tierExplain,\n results,\n filters,\n budget: { chars: budgetChars, used: budgetUsed },\n sessionKey: nonEmptyString(input.sessionKey),\n namespace: nonEmptyString(input.namespace),\n traceId: nonEmptyString(input.traceId),\n };\n if (peerProfileInjection !== undefined) {\n out.peerProfileInjection = peerProfileInjection;\n }\n return out;\n}\n\n/**\n * Mutable builder used by the orchestrator to accumulate X-ray fields\n * as recall progresses. Call `build()` to get the finalized\n * immutable-ish snapshot. All inputs are validated at insert time so\n * a malformed entry cannot poison the snapshot later.\n */\nexport class RecallXrayBuilder {\n private readonly query: string;\n private readonly sessionKey: string | undefined;\n private namespace: string | undefined;\n private traceId: string | undefined;\n private tierExplain: RecallTierExplain | null = null;\n private readonly results: RecallXrayResult[] = [];\n private readonly filters: RecallFilterTrace[] = [];\n private budgetChars = 0;\n private budgetUsed = 0;\n private peerProfileInjection: RecallXrayPeerProfileInjection | null | undefined;\n\n constructor(opts: {\n query: string;\n sessionKey?: string;\n namespace?: string;\n traceId?: string;\n }) {\n this.query = typeof opts.query === \"string\" ? opts.query : \"\";\n this.sessionKey = nonEmptyString(opts.sessionKey);\n this.namespace = nonEmptyString(opts.namespace);\n this.traceId = nonEmptyString(opts.traceId);\n }\n\n setNamespace(namespace: string | undefined): void {\n this.namespace = nonEmptyString(namespace);\n }\n\n setTraceId(traceId: string | undefined): void {\n this.traceId = nonEmptyString(traceId);\n }\n\n setTierExplain(tierExplain: RecallTierExplain | null | undefined): void {\n this.tierExplain =\n tierExplain && typeof tierExplain === \"object\"\n ? cloneTierExplain(tierExplain)\n : null;\n }\n\n setBudget(budget: { chars?: number; used?: number }): void {\n this.budgetChars = nonNegativeInt(budget.chars);\n this.budgetUsed = nonNegativeInt(budget.used);\n }\n\n /**\n * Record peer-profile injection metadata for this recall snapshot\n * (issue #679 completion). Pass `null` to explicitly record that no\n * injection happened (feature enabled but no peer / no profile fields).\n */\n setPeerProfileInjection(\n injection: RecallXrayPeerProfileInjection | null,\n ): void {\n this.peerProfileInjection = injection;\n }\n\n recordResult(result: RecallXrayResult): void {\n this.results.push(cloneResult(result));\n }\n\n recordFilter(filter: RecallFilterTrace): void {\n this.filters.push(cloneFilter(filter));\n }\n\n build(opts: {\n now?: () => number;\n snapshotIdGenerator?: () => string;\n } = {}): RecallXraySnapshot {\n return buildXraySnapshot({\n query: this.query,\n tierExplain: this.tierExplain,\n results: this.results,\n filters: this.filters,\n budget: { chars: this.budgetChars, used: this.budgetUsed },\n sessionKey: this.sessionKey,\n namespace: this.namespace,\n traceId: this.traceId,\n peerProfileInjection: this.peerProfileInjection,\n now: opts.now,\n snapshotIdGenerator: opts.snapshotIdGenerator,\n });\n }\n}\n\n// ─── Internals ────────────────────────────────────────────────────────────\n\nfunction cloneResult(result: RecallXrayResult): RecallXrayResult {\n if (!result || typeof result !== \"object\") {\n throw new TypeError(\"RecallXrayResult must be an object\");\n }\n if (!isRecallXrayServedBy(result.servedBy)) {\n throw new TypeError(\n `RecallXrayResult.servedBy must be one of ${RECALL_XRAY_SERVED_BY_VALUES.join(\n \", \",\n )}; got ${JSON.stringify(result.servedBy)}`,\n );\n }\n const memoryId = typeof result.memoryId === \"string\" ? result.memoryId : \"\";\n const path = typeof result.path === \"string\" ? result.path : \"\";\n const admittedBy = Array.isArray(result.admittedBy)\n ? result.admittedBy.filter((x): x is string => typeof x === \"string\")\n : [];\n const graphPath = Array.isArray(result.graphPath)\n ? result.graphPath.filter((x): x is string => typeof x === \"string\")\n : undefined;\n // Issue #681 PR 3/3 — per-edge confidences alongside graph path.\n // Each entry is clamped into [0, 1]; the array is rejected wholesale\n // when alignment cannot be verified so downstream surfaces can rely\n // on `graphEdgeConfidences[i]` describing the edge between\n // `graphPath[i]` and `graphPath[i+1]`.\n //\n // Cursor review (#735): the input array length MUST match\n // `graphPath.length - 1` *before* any per-element filtering. The\n // earlier implementation skipped non-finite entries via `continue`\n // and then length-checked the cleaned array — that would silently\n // shift surviving values to earlier positions. Example: input\n // `[0.5, NaN, 0.7]` for a 3-edge path would collapse to\n // `[0.5, 0.7]`, length-check would pass against `expected = 2`, and\n // the renderer would mis-attribute `0.7` to edge B→C when it really\n // came from edge C→D. Reject on either size mismatch or any\n // non-finite entry so misalignment is impossible.\n let graphEdgeConfidences: number[] | undefined;\n if (Array.isArray(result.graphEdgeConfidences) && graphPath && graphPath.length > 1) {\n const expected = graphPath.length - 1;\n const raw = result.graphEdgeConfidences;\n if (raw.length === expected) {\n const cleaned: number[] = [];\n let allFinite = true;\n for (const value of raw) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n allFinite = false;\n break;\n }\n cleaned.push(Math.min(1, Math.max(0, value)));\n }\n if (allFinite) {\n graphEdgeConfidences = cleaned;\n }\n }\n }\n const auditEntryId = nonEmptyString(result.auditEntryId);\n const rejectedBy = nonEmptyString(result.rejectedBy);\n const scoreDecomposition = cloneScoreDecomposition(result.scoreDecomposition);\n const out: RecallXrayResult = {\n memoryId,\n path,\n servedBy: result.servedBy,\n scoreDecomposition,\n admittedBy,\n };\n if (graphPath !== undefined) out.graphPath = graphPath;\n if (graphEdgeConfidences !== undefined) {\n out.graphEdgeConfidences = graphEdgeConfidences;\n }\n if (auditEntryId !== undefined) out.auditEntryId = auditEntryId;\n if (rejectedBy !== undefined) out.rejectedBy = rejectedBy;\n // Disclosure + token telemetry (issue #677 PR 3/4). Only attach when\n // present and well-formed; unknown disclosure values are dropped so a\n // bad caller can't poison downstream renderers. Uses the shared\n // `isRecallDisclosure` guard so adding a fourth disclosure level\n // requires touching only `types.ts`.\n if (isRecallDisclosure(result.disclosure)) {\n out.disclosure = result.disclosure;\n }\n if (\n typeof result.estimatedTokens === \"number\" &&\n Number.isFinite(result.estimatedTokens) &&\n result.estimatedTokens >= 0\n ) {\n out.estimatedTokens = Math.floor(result.estimatedTokens);\n }\n // Tags from frontmatter (issue #689 PR 3/3). Normalize identically to\n // the recall-surface path: trim and drop empty strings so consumers can\n // compare tags directly without a secondary normalization step.\n if (Array.isArray(result.tags)) {\n const cleanedTags = result.tags\n .filter((t): t is string => typeof t === \"string\")\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n if (cleanedTags.length > 0) {\n out.tags = cleanedTags;\n }\n }\n return out;\n}\n\n/**\n * Summarize per-disclosure token spend across an X-ray snapshot's\n * results. Pure helper — used by the markdown renderer to print a\n * \"per-disclosure token spend\" line and exposed for tests / surfaces.\n */\nexport function summarizeDisclosureTokens(\n results: ReadonlyArray<RecallXrayResult>,\n): RecallXrayDisclosureSummary {\n const summary: RecallXrayDisclosureSummary = {\n chunk: { count: 0, estimatedTokens: 0 },\n section: { count: 0, estimatedTokens: 0 },\n raw: { count: 0, estimatedTokens: 0 },\n unspecified: { count: 0, estimatedTokens: 0 },\n };\n for (const result of results) {\n const tokens =\n typeof result.estimatedTokens === \"number\" &&\n Number.isFinite(result.estimatedTokens) &&\n result.estimatedTokens >= 0\n ? Math.floor(result.estimatedTokens)\n : 0;\n const bucket = isRecallDisclosure(result.disclosure)\n ? result.disclosure\n : \"unspecified\";\n summary[bucket].count += 1;\n summary[bucket].estimatedTokens += tokens;\n }\n return summary;\n}\n\nfunction cloneFilter(filter: RecallFilterTrace): RecallFilterTrace {\n if (!filter || typeof filter !== \"object\") {\n throw new TypeError(\"RecallFilterTrace must be an object\");\n }\n const out: RecallFilterTrace = {\n name: typeof filter.name === \"string\" ? filter.name : \"\",\n considered: nonNegativeInt(filter.considered),\n admitted: nonNegativeInt(filter.admitted),\n };\n const reason = nonEmptyString(filter.reason);\n if (reason !== undefined) out.reason = reason;\n return out;\n}\n\nfunction cloneScoreDecomposition(\n value: RecallXrayScoreDecomposition | undefined,\n): RecallXrayScoreDecomposition {\n if (!value || typeof value !== \"object\") {\n return { final: 0 };\n }\n const out: RecallXrayScoreDecomposition = {\n final: finiteNumber(value.final) ?? 0,\n };\n const vector = finiteNumber(value.vector);\n if (vector !== undefined) out.vector = vector;\n const bm25 = finiteNumber(value.bm25);\n if (bm25 !== undefined) out.bm25 = bm25;\n const importance = finiteNumber(value.importance);\n if (importance !== undefined) out.importance = importance;\n const mmrPenalty = finiteNumber(value.mmrPenalty);\n if (mmrPenalty !== undefined) out.mmrPenalty = mmrPenalty;\n const tierPrior = finiteNumber(value.tierPrior);\n if (tierPrior !== undefined) out.tierPrior = tierPrior;\n const reinforcementBoost = finiteNumber(value.reinforcementBoost);\n if (reinforcementBoost !== undefined && reinforcementBoost > 0) {\n out.reinforcementBoost = reinforcementBoost;\n }\n return out;\n}\n\nfunction cloneTierExplain(tierExplain: RecallTierExplain): RecallTierExplain {\n // Use structuredClone so future RecallTierExplain additions do not\n // silently share references through hand-enumerated fields. The\n // payload is JSON-shaped.\n return structuredClone(tierExplain);\n}\n\nfunction nonNegativeInt(value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 0;\n if (value <= 0) return 0;\n return Math.floor(value);\n}\n\nfunction finiteNumber(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n return value;\n}\n\nfunction nonEmptyString(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n return trimmed;\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,3 @@
1
- import {
2
- resolveHomeDir
3
- } from "./chunk-MARWOCVP.js";
4
1
  import {
5
2
  validateRouteTarget
6
3
  } from "./chunk-2LGMW3DJ.js";
@@ -139,19 +136,9 @@ function validateReplayTurn(turn, index) {
139
136
  return issues;
140
137
  }
141
138
 
142
- // src/utils/path.ts
143
- import path from "path";
144
- function expandTildePath(p) {
145
- if (p === "~") return resolveHomeDir();
146
- if (p.startsWith("~/") || p.startsWith("~\\")) {
147
- return path.join(resolveHomeDir(), p.slice(2));
148
- }
149
- return p;
150
- }
151
-
152
139
  // src/routing/store.ts
153
140
  import { lstat, mkdir, readFile, realpath, rename, rm, stat, writeFile } from "fs/promises";
154
- import path2 from "path";
141
+ import path from "path";
155
142
  import { createHash } from "crypto";
156
143
  function defaultState() {
157
144
  return {
@@ -170,14 +157,14 @@ function stableRuleId(rule) {
170
157
  return `route-${createHash("sha256").update(seed).digest("hex").slice(0, 12)}`;
171
158
  }
172
159
  function resolveStatePath(memoryDir, stateFile) {
173
- const root = path2.resolve(memoryDir);
174
- const defaultPath = path2.join(root, "state", "routing-rules.json");
175
- if (path2.isAbsolute(stateFile)) {
176
- const absolute = path2.resolve(stateFile);
177
- return absolute.startsWith(root + path2.sep) ? absolute : defaultPath;
160
+ const root = path.resolve(memoryDir);
161
+ const defaultPath = path.join(root, "state", "routing-rules.json");
162
+ if (path.isAbsolute(stateFile)) {
163
+ const absolute = path.resolve(stateFile);
164
+ return absolute.startsWith(root + path.sep) ? absolute : defaultPath;
178
165
  }
179
- const resolved = path2.resolve(root, stateFile);
180
- return resolved.startsWith(root + path2.sep) ? resolved : defaultPath;
166
+ const resolved = path.resolve(root, stateFile);
167
+ return resolved.startsWith(root + path.sep) ? resolved : defaultPath;
181
168
  }
182
169
  function normalizeRule(rule, options) {
183
170
  if (!rule || typeof rule !== "object") return null;
@@ -210,7 +197,7 @@ var RoutingRulesStore = class {
210
197
  lockPath;
211
198
  writeQueue = Promise.resolve();
212
199
  constructor(memoryDir, stateFile = "state/routing-rules.json") {
213
- this.memoryRoot = path2.resolve(memoryDir);
200
+ this.memoryRoot = path.resolve(memoryDir);
214
201
  this.statePath = resolveStatePath(memoryDir, stateFile);
215
202
  this.lockPath = `${this.statePath}.lock`;
216
203
  }
@@ -316,7 +303,7 @@ var RoutingRulesStore = class {
316
303
  const timeoutMs = 5e3;
317
304
  let unexpectedLockError = null;
318
305
  await this.assertStatePathScoped();
319
- await mkdir(path2.dirname(this.lockPath), { recursive: true });
306
+ await mkdir(path.dirname(this.lockPath), { recursive: true });
320
307
  while (Date.now() - start < timeoutMs) {
321
308
  try {
322
309
  await mkdir(this.lockPath);
@@ -351,12 +338,12 @@ var RoutingRulesStore = class {
351
338
  async assertStatePathScoped() {
352
339
  await mkdir(this.memoryRoot, { recursive: true });
353
340
  const canonicalRoot = await realpath(this.memoryRoot);
354
- const canonicalParent = await this.canonicalizePathWithoutCreating(path2.dirname(this.statePath));
355
- const canonicalStatePath = path2.join(canonicalParent, path2.basename(this.statePath));
341
+ const canonicalParent = await this.canonicalizePathWithoutCreating(path.dirname(this.statePath));
342
+ const canonicalStatePath = path.join(canonicalParent, path.basename(this.statePath));
356
343
  if (!this.isPathInside(canonicalRoot, canonicalStatePath)) {
357
344
  throw new Error(`routing rules state path escaped memoryDir: ${canonicalStatePath}`);
358
345
  }
359
- await mkdir(path2.dirname(this.statePath), { recursive: true });
346
+ await mkdir(path.dirname(this.statePath), { recursive: true });
360
347
  try {
361
348
  const stateStats = await lstat(this.statePath);
362
349
  if (stateStats.isSymbolicLink()) {
@@ -373,28 +360,28 @@ var RoutingRulesStore = class {
373
360
  }
374
361
  }
375
362
  isPathInside(root, candidate) {
376
- const normalizedRoot = path2.resolve(root);
377
- const normalizedCandidate = path2.resolve(candidate);
363
+ const normalizedRoot = path.resolve(root);
364
+ const normalizedCandidate = path.resolve(candidate);
378
365
  if (normalizedCandidate === normalizedRoot) return true;
379
- if (normalizedRoot === path2.parse(normalizedRoot).root) {
366
+ if (normalizedRoot === path.parse(normalizedRoot).root) {
380
367
  return normalizedCandidate.startsWith(normalizedRoot);
381
368
  }
382
- return normalizedCandidate.startsWith(`${normalizedRoot}${path2.sep}`);
369
+ return normalizedCandidate.startsWith(`${normalizedRoot}${path.sep}`);
383
370
  }
384
371
  async canonicalizePathWithoutCreating(targetPath) {
385
- const absoluteTarget = path2.resolve(targetPath);
372
+ const absoluteTarget = path.resolve(targetPath);
386
373
  let probe = absoluteTarget;
387
374
  while (true) {
388
375
  try {
389
376
  const canonicalProbe = await realpath(probe);
390
- const remainder = path2.relative(probe, absoluteTarget);
391
- return path2.resolve(canonicalProbe, remainder);
377
+ const remainder = path.relative(probe, absoluteTarget);
378
+ return path.resolve(canonicalProbe, remainder);
392
379
  } catch (err) {
393
380
  const code = err.code;
394
381
  if (code !== "ENOENT") {
395
382
  throw err;
396
383
  }
397
- const parent = path2.dirname(probe);
384
+ const parent = path.dirname(probe);
398
385
  if (parent === probe) {
399
386
  return absoluteTarget;
400
387
  }
@@ -411,7 +398,6 @@ export {
411
398
  normalizeReplaySessionKey,
412
399
  parseIsoTimestamp,
413
400
  validateReplayTurn,
414
- expandTildePath,
415
401
  RoutingRulesStore
416
402
  };
417
- //# sourceMappingURL=chunk-EPQJM2GC.js.map
403
+ //# sourceMappingURL=chunk-VTJVUHRK.js.map