@remnic/core 1.1.11 → 1.1.13

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 (1462) hide show
  1. package/README.md +3 -3
  2. package/dist/access-cli.d.ts +2 -1
  3. package/dist/access-cli.js +293 -104
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +31 -62
  6. package/dist/access-http.js +53 -35
  7. package/dist/access-mcp.d.ts +31 -8
  8. package/dist/access-mcp.js +45 -34
  9. package/dist/access-schema.d.ts +197 -14
  10. package/dist/access-schema.js +16 -5
  11. package/dist/access-service-DcCDmNYC.d.ts +1542 -0
  12. package/dist/access-service.d.ts +30 -9
  13. package/dist/access-service.js +42 -32
  14. package/dist/action-confidence.d.ts +83 -0
  15. package/dist/action-confidence.js +22 -0
  16. package/dist/active-memory-bridge.d.ts +1 -1
  17. package/dist/active-memory-bridge.js +2 -2
  18. package/dist/active-recall.d.ts +1 -1
  19. package/dist/active-recall.js +11 -3
  20. package/dist/active-recall.js.map +1 -1
  21. package/dist/adapters/claude-code.d.ts +24 -0
  22. package/dist/adapters/claude-code.js +9 -0
  23. package/dist/adapters/codex.d.ts +25 -0
  24. package/dist/adapters/codex.js +9 -0
  25. package/dist/adapters/hermes.d.ts +35 -0
  26. package/dist/adapters/hermes.js +9 -0
  27. package/dist/adapters/index.d.ts +6 -0
  28. package/dist/adapters/index.js +26 -0
  29. package/dist/adapters/registry.d.ts +20 -0
  30. package/dist/adapters/registry.js +13 -0
  31. package/dist/adapters/replit.d.ts +28 -0
  32. package/dist/adapters/replit.js +9 -0
  33. package/dist/adapters/types.d.ts +43 -0
  34. package/dist/adapters/types.js +8 -0
  35. package/dist/behavior-learner.d.ts +1 -1
  36. package/dist/behavior-signals.d.ts +1 -1
  37. package/dist/bootstrap.d.ts +23 -6
  38. package/dist/boxes.d.ts +7 -0
  39. package/dist/boxes.js +1 -1
  40. package/dist/briefing.d.ts +5 -3
  41. package/dist/briefing.js +10 -7
  42. package/dist/buffer-surprise-report.d.ts +1 -1
  43. package/dist/buffer-surprise-report.js +1 -1
  44. package/dist/buffer.d.ts +18 -4
  45. package/dist/buffer.js +1 -1
  46. package/dist/calibration.d.ts +1 -1
  47. package/dist/calibration.js +6 -6
  48. package/dist/capsule-cli.d.ts +4 -4
  49. package/dist/capsule-cli.js +1 -1
  50. package/dist/capsule-crypto-5CYAGVC5.js +18 -0
  51. package/dist/capsule-merge-4MGKE7C5.js +189 -0
  52. package/dist/causal-behavior.d.ts +9 -29
  53. package/dist/causal-behavior.js +6 -3
  54. package/dist/causal-behavior.js.map +1 -1
  55. package/dist/causal-chain.js +3 -2
  56. package/dist/causal-consolidation.d.ts +2 -2
  57. package/dist/causal-consolidation.js +28 -17
  58. package/dist/causal-consolidation.js.map +1 -1
  59. package/dist/causal-retrieval.js +3 -3
  60. package/dist/causal-trajectory.js +1 -1
  61. package/dist/chunk-25MQ7IHJ.js +427 -0
  62. package/dist/chunk-25MQ7IHJ.js.map +1 -0
  63. package/dist/chunk-2F2W355T.js +256 -0
  64. package/dist/chunk-2F2W355T.js.map +1 -0
  65. package/dist/chunk-2KI4QFHU.js +228 -0
  66. package/dist/chunk-2KI4QFHU.js.map +1 -0
  67. package/dist/chunk-2PRQG7PV.js +86 -0
  68. package/dist/chunk-2PRQG7PV.js.map +1 -0
  69. package/dist/chunk-2QR3XXIC.js +2272 -0
  70. package/dist/chunk-2QR3XXIC.js.map +1 -0
  71. package/dist/chunk-2WWLHTZY.js +121 -0
  72. package/dist/chunk-326G7DJK.js +2185 -0
  73. package/dist/chunk-326G7DJK.js.map +1 -0
  74. package/dist/chunk-34DQE4KF.js +174 -0
  75. package/dist/chunk-34DQE4KF.js.map +1 -0
  76. package/dist/chunk-3APJ5EVB.js +601 -0
  77. package/dist/chunk-3APJ5EVB.js.map +1 -0
  78. package/dist/chunk-3HPAPHUK.js +51 -0
  79. package/dist/chunk-3HPAPHUK.js.map +1 -0
  80. package/dist/chunk-3JXBXXM2.js +69 -0
  81. package/dist/chunk-3JXBXXM2.js.map +1 -0
  82. package/dist/chunk-3KW65B36.js +681 -0
  83. package/dist/chunk-3KW65B36.js.map +1 -0
  84. package/dist/chunk-3UXOZBHV.js +20 -0
  85. package/dist/chunk-3UXOZBHV.js.map +1 -0
  86. package/dist/chunk-3VAL7ZL2.js +266 -0
  87. package/dist/chunk-3VAL7ZL2.js.map +1 -0
  88. package/dist/chunk-3Y4P7RXM.js +31 -0
  89. package/dist/chunk-3Y4P7RXM.js.map +1 -0
  90. package/dist/chunk-47VWKCAF.js +273 -0
  91. package/dist/chunk-47VWKCAF.js.map +1 -0
  92. package/dist/chunk-4CRG46BG.js +271 -0
  93. package/dist/chunk-4RA3C3EV.js +60 -0
  94. package/dist/chunk-4RA3C3EV.js.map +1 -0
  95. package/dist/chunk-5375UYTQ.js +914 -0
  96. package/dist/chunk-5375UYTQ.js.map +1 -0
  97. package/dist/chunk-56K5QLHX.js +506 -0
  98. package/dist/chunk-56K5QLHX.js.map +1 -0
  99. package/dist/chunk-5NXIJZFX.js +180 -0
  100. package/dist/chunk-5NXIJZFX.js.map +1 -0
  101. package/dist/chunk-5RGLBDQF.js +596 -0
  102. package/dist/chunk-5RGLBDQF.js.map +1 -0
  103. package/dist/chunk-5UZXUTVO.js +9 -0
  104. package/dist/chunk-5UZXUTVO.js.map +1 -0
  105. package/dist/chunk-65PG43EQ.js +105 -0
  106. package/dist/chunk-65PG43EQ.js.map +1 -0
  107. package/dist/chunk-66DHUKLO.js +57 -0
  108. package/dist/chunk-66DHUKLO.js.map +1 -0
  109. package/dist/chunk-6FC5EGNV.js +46 -0
  110. package/dist/chunk-6FC5EGNV.js.map +1 -0
  111. package/dist/chunk-6H2TESSP.js +62 -0
  112. package/dist/chunk-6H2TESSP.js.map +1 -0
  113. package/dist/chunk-6LVVDPJ4.js +32 -0
  114. package/dist/chunk-6LVVDPJ4.js.map +1 -0
  115. package/dist/chunk-6NKAQ74D.js +2237 -0
  116. package/dist/chunk-6NKAQ74D.js.map +1 -0
  117. package/dist/chunk-6RVI47ZR.js +159 -0
  118. package/dist/chunk-6RVI47ZR.js.map +1 -0
  119. package/dist/chunk-7AAT6G4Q.js +5117 -0
  120. package/dist/chunk-7AAT6G4Q.js.map +1 -0
  121. package/dist/chunk-7DTASS5T.js +29 -0
  122. package/dist/chunk-7DTASS5T.js.map +1 -0
  123. package/dist/chunk-7IASACLB.js +596 -0
  124. package/dist/chunk-7MNMYOFP.js +32 -0
  125. package/dist/chunk-7MNMYOFP.js.map +1 -0
  126. package/dist/chunk-7N4KAIGN.js +133 -0
  127. package/dist/chunk-7N4KAIGN.js.map +1 -0
  128. package/dist/chunk-7OZ53EXP.js +101 -0
  129. package/dist/chunk-7OZ53EXP.js.map +1 -0
  130. package/dist/chunk-7XYTQGCC.js +134 -0
  131. package/dist/chunk-7XYTQGCC.js.map +1 -0
  132. package/dist/chunk-A2XUIMJ3.js +341 -0
  133. package/dist/chunk-A2XUIMJ3.js.map +1 -0
  134. package/dist/chunk-AC5LO7IU.js +308 -0
  135. package/dist/chunk-AC5LO7IU.js.map +1 -0
  136. package/dist/chunk-AGZQD76C.js +201 -0
  137. package/dist/chunk-AGZQD76C.js.map +1 -0
  138. package/dist/chunk-AH2JUU6X.js +336 -0
  139. package/dist/chunk-AH2JUU6X.js.map +1 -0
  140. package/dist/chunk-APO3DCMU.js +361 -0
  141. package/dist/chunk-APO3DCMU.js.map +1 -0
  142. package/dist/chunk-BFBF3XEF.js +283 -0
  143. package/dist/chunk-BFBF3XEF.js.map +1 -0
  144. package/dist/chunk-BJ3KMYTB.js +1974 -0
  145. package/dist/chunk-BJ3KMYTB.js.map +1 -0
  146. package/dist/chunk-C5BCH4ZS.js +317 -0
  147. package/dist/chunk-C5BCH4ZS.js.map +1 -0
  148. package/dist/chunk-CHEL3SKB.js +6758 -0
  149. package/dist/chunk-CHEL3SKB.js.map +1 -0
  150. package/dist/chunk-CQZRLNMV.js +1491 -0
  151. package/dist/chunk-CQZRLNMV.js.map +1 -0
  152. package/dist/chunk-D46YSIYX.js +892 -0
  153. package/dist/chunk-D46YSIYX.js.map +1 -0
  154. package/dist/chunk-DB5A3NHS.js +906 -0
  155. package/dist/chunk-DB5A3NHS.js.map +1 -0
  156. package/dist/chunk-DINWEURR.js +648 -0
  157. package/dist/chunk-DINWEURR.js.map +1 -0
  158. package/dist/chunk-DK5LDEQM.js +530 -0
  159. package/dist/chunk-DK5LDEQM.js.map +1 -0
  160. package/dist/chunk-DOM4GKSW.js +34 -0
  161. package/dist/chunk-DOM4GKSW.js.map +1 -0
  162. package/dist/chunk-EDTHC6UD.js +1075 -0
  163. package/dist/chunk-EDTHC6UD.js.map +1 -0
  164. package/dist/chunk-EFJ3MQ4V.js +721 -0
  165. package/dist/chunk-EHRTFRWW.js +89 -0
  166. package/dist/chunk-EHRTFRWW.js.map +1 -0
  167. package/dist/chunk-FAJ7FZYM.js +11 -0
  168. package/dist/chunk-FAJ7FZYM.js.map +1 -0
  169. package/dist/chunk-FBYESMQ2.js +570 -0
  170. package/dist/chunk-FBYESMQ2.js.map +1 -0
  171. package/dist/chunk-FDU6HUUL.js +147 -0
  172. package/dist/chunk-FF4KLI5W.js +99 -0
  173. package/dist/chunk-FF4KLI5W.js.map +1 -0
  174. package/dist/chunk-FIT6DMX6.js +310 -0
  175. package/dist/chunk-FIT6DMX6.js.map +1 -0
  176. package/dist/chunk-FJ43PRLT.js +272 -0
  177. package/dist/chunk-FJ43PRLT.js.map +1 -0
  178. package/dist/chunk-FKFMOY3N.js +32 -0
  179. package/dist/chunk-FKFMOY3N.js.map +1 -0
  180. package/dist/chunk-FLTNHQK6.js +262 -0
  181. package/dist/chunk-FLTNHQK6.js.map +1 -0
  182. package/dist/chunk-GA454ALV.js +12436 -0
  183. package/dist/chunk-GA454ALV.js.map +1 -0
  184. package/dist/chunk-GGKRUQOO.js +228 -0
  185. package/dist/chunk-GIF42EW3.js +63 -0
  186. package/dist/chunk-GIF42EW3.js.map +1 -0
  187. package/dist/chunk-GL6I6MEQ.js +647 -0
  188. package/dist/chunk-H3ME6L6D.js +709 -0
  189. package/dist/chunk-H3ME6L6D.js.map +1 -0
  190. package/dist/chunk-HHLLAQGZ.js +1 -0
  191. package/dist/chunk-HXXBL2KD.js +2040 -0
  192. package/dist/chunk-I5V2VDIW.js +219 -0
  193. package/dist/chunk-I5V2VDIW.js.map +1 -0
  194. package/dist/chunk-I6K5FBRQ.js +35 -0
  195. package/dist/chunk-I6K5FBRQ.js.map +1 -0
  196. package/dist/chunk-ICRIXAP2.js +121 -0
  197. package/dist/chunk-ICRIXAP2.js.map +1 -0
  198. package/dist/chunk-J4EB7DNW.js +11 -0
  199. package/dist/chunk-J4EB7DNW.js.map +1 -0
  200. package/dist/chunk-JLFA7DQG.js +62 -0
  201. package/dist/chunk-JLFA7DQG.js.map +1 -0
  202. package/dist/chunk-KJTKLXTH.js +9 -0
  203. package/dist/chunk-KJTKLXTH.js.map +1 -0
  204. package/dist/chunk-KLAO5DGL.js +917 -0
  205. package/dist/chunk-KLAO5DGL.js.map +1 -0
  206. package/dist/chunk-KNKUID7G.js +183 -0
  207. package/dist/chunk-KOSORCJG.js +624 -0
  208. package/dist/chunk-KOSORCJG.js.map +1 -0
  209. package/dist/chunk-KUJVMMZQ.js +1262 -0
  210. package/dist/chunk-KUJVMMZQ.js.map +1 -0
  211. package/dist/chunk-LCR46JY5.js +123 -0
  212. package/dist/chunk-LCR46JY5.js.map +1 -0
  213. package/dist/chunk-LLQ2LLWF.js +148 -0
  214. package/dist/chunk-LLQ2LLWF.js.map +1 -0
  215. package/dist/chunk-LPMVBPA3.js +236 -0
  216. package/dist/chunk-LT3NLYSI.js +50 -0
  217. package/dist/chunk-LT3NLYSI.js.map +1 -0
  218. package/dist/chunk-LUDTDZLK.js +287 -0
  219. package/dist/chunk-LUDTDZLK.js.map +1 -0
  220. package/dist/chunk-M23FSH32.js +3963 -0
  221. package/dist/chunk-M23FSH32.js.map +1 -0
  222. package/dist/chunk-MC26UJIM.js +118 -0
  223. package/dist/chunk-ME6ESPZU.js +119 -0
  224. package/dist/chunk-ME6ESPZU.js.map +1 -0
  225. package/dist/chunk-MGKYQQYF.js +272 -0
  226. package/dist/chunk-MGKYQQYF.js.map +1 -0
  227. package/dist/chunk-MJFNCJXV.js +66 -0
  228. package/dist/chunk-MJFNCJXV.js.map +1 -0
  229. package/dist/chunk-MSWG7JI6.js +237 -0
  230. package/dist/chunk-MSWG7JI6.js.map +1 -0
  231. package/dist/chunk-MT25YHYH.js +141 -0
  232. package/dist/chunk-MT25YHYH.js.map +1 -0
  233. package/dist/chunk-MT4HVDUZ.js +53 -0
  234. package/dist/chunk-MY6TPVXW.js +219 -0
  235. package/dist/chunk-N2D6GXBM.js +267 -0
  236. package/dist/chunk-N2D6GXBM.js.map +1 -0
  237. package/dist/chunk-NJ3MJQZX.js +46 -0
  238. package/dist/chunk-NJ3MJQZX.js.map +1 -0
  239. package/dist/chunk-NMZY542O.js +335 -0
  240. package/dist/chunk-NMZY542O.js.map +1 -0
  241. package/dist/chunk-NNVTUXEB.js +23 -0
  242. package/dist/chunk-NZL6GGQE.js +375 -0
  243. package/dist/chunk-NZL6GGQE.js.map +1 -0
  244. package/dist/chunk-OAZ5MFUB.js +4124 -0
  245. package/dist/chunk-OAZ5MFUB.js.map +1 -0
  246. package/dist/chunk-OIGNEXKZ.js +237 -0
  247. package/dist/chunk-OIGNEXKZ.js.map +1 -0
  248. package/dist/chunk-OZKZ2TRP.js +3729 -0
  249. package/dist/chunk-OZKZ2TRP.js.map +1 -0
  250. package/dist/chunk-P4NEIHUT.js +108 -0
  251. package/dist/chunk-P7FMDTKL.js +103 -0
  252. package/dist/chunk-P7FMDTKL.js.map +1 -0
  253. package/dist/chunk-PD6O7AXF.js +110 -0
  254. package/dist/chunk-PD6O7AXF.js.map +1 -0
  255. package/dist/chunk-PHK3HARR.js +32 -0
  256. package/dist/chunk-PHK3HARR.js.map +1 -0
  257. package/dist/chunk-PIRJPV5T.js +98 -0
  258. package/dist/chunk-PIRJPV5T.js.map +1 -0
  259. package/dist/chunk-PK7H5L6Y.js +159 -0
  260. package/dist/chunk-PK7H5L6Y.js.map +1 -0
  261. package/dist/chunk-PR5FBTFU.js +233 -0
  262. package/dist/chunk-PR5FBTFU.js.map +1 -0
  263. package/dist/chunk-PU63GXWS.js +174 -0
  264. package/dist/chunk-PU63GXWS.js.map +1 -0
  265. package/dist/chunk-PYPOFEMK.js +294 -0
  266. package/dist/chunk-PYPOFEMK.js.map +1 -0
  267. package/dist/chunk-PZIAX57I.js +124 -0
  268. package/dist/chunk-PZIAX57I.js.map +1 -0
  269. package/dist/chunk-Q7P4WJDP.js +26 -0
  270. package/dist/chunk-Q7P4WJDP.js.map +1 -0
  271. package/dist/chunk-QDZ2RLEC.js +908 -0
  272. package/dist/chunk-QDZ2RLEC.js.map +1 -0
  273. package/dist/chunk-QQUAB63I.js +63 -0
  274. package/dist/chunk-QQUAB63I.js.map +1 -0
  275. package/dist/chunk-QRNI5JBH.js +18 -0
  276. package/dist/chunk-RHY3HH7P.js +601 -0
  277. package/dist/chunk-RHY3HH7P.js.map +1 -0
  278. package/dist/chunk-RK6F44Y6.js +84 -0
  279. package/dist/chunk-RK6F44Y6.js.map +1 -0
  280. package/dist/chunk-RRF5UOBJ.js +91 -0
  281. package/dist/chunk-RXDLTSWT.js +124 -0
  282. package/dist/chunk-RXDLTSWT.js.map +1 -0
  283. package/dist/chunk-RYED3SPJ.js +42 -0
  284. package/dist/chunk-RYED3SPJ.js.map +1 -0
  285. package/dist/chunk-S7KDBTWT.js +106 -0
  286. package/dist/chunk-S7KDBTWT.js.map +1 -0
  287. package/dist/chunk-SEDEKFYQ.js +1 -0
  288. package/dist/chunk-SOAU2OE2.js +125 -0
  289. package/dist/chunk-SOAU2OE2.js.map +1 -0
  290. package/dist/chunk-TECVW3JP.js +36 -0
  291. package/dist/chunk-TECVW3JP.js.map +1 -0
  292. package/dist/chunk-TFO23QT4.js +88 -0
  293. package/dist/chunk-TFO23QT4.js.map +1 -0
  294. package/dist/chunk-TK4UEOSK.js +76 -0
  295. package/dist/chunk-TK4UEOSK.js.map +1 -0
  296. package/dist/chunk-TKWGAOLV.js +122 -0
  297. package/dist/chunk-TKWGAOLV.js.map +1 -0
  298. package/dist/chunk-TMM4S4IJ.js +597 -0
  299. package/dist/chunk-TMM4S4IJ.js.map +1 -0
  300. package/dist/chunk-TMQLARTH.js +188 -0
  301. package/dist/chunk-TMQLARTH.js.map +1 -0
  302. package/dist/chunk-TPDBFYEG.js +130 -0
  303. package/dist/chunk-TPDBFYEG.js.map +1 -0
  304. package/dist/chunk-TPMQ3G6Z.js +145 -0
  305. package/dist/chunk-TPMQ3G6Z.js.map +1 -0
  306. package/dist/chunk-TZOLIGIG.js +61 -0
  307. package/dist/chunk-TZOLIGIG.js.map +1 -0
  308. package/dist/chunk-U3PN77QT.js +113 -0
  309. package/dist/chunk-U3WSW6PZ.js +277 -0
  310. package/dist/chunk-U4SCL7B7.js +640 -0
  311. package/dist/chunk-U4SCL7B7.js.map +1 -0
  312. package/dist/chunk-UWK5OXUJ.js +156 -0
  313. package/dist/chunk-UWK5OXUJ.js.map +1 -0
  314. package/dist/chunk-UWVJF25J.js +74 -0
  315. package/dist/chunk-UXHQAFNA.js +1317 -0
  316. package/dist/chunk-UXHQAFNA.js.map +1 -0
  317. package/dist/chunk-V5OCT34X.js +1 -0
  318. package/dist/chunk-V5OCT34X.js.map +1 -0
  319. package/dist/chunk-VLXA6PI2.js +304 -0
  320. package/dist/chunk-VLXA6PI2.js.map +1 -0
  321. package/dist/chunk-VNO6ZJ35.js +500 -0
  322. package/dist/chunk-VNO6ZJ35.js.map +1 -0
  323. package/dist/chunk-VW676BEI.js +827 -0
  324. package/dist/chunk-VW676BEI.js.map +1 -0
  325. package/dist/chunk-VWT3F4IV.js +2161 -0
  326. package/dist/chunk-VWT3F4IV.js.map +1 -0
  327. package/dist/chunk-W3LR522O.js +2296 -0
  328. package/dist/chunk-W3LR522O.js.map +1 -0
  329. package/dist/chunk-W4L6CZKA.js +96 -0
  330. package/dist/chunk-W4L6CZKA.js.map +1 -0
  331. package/dist/chunk-W4RVMTHR.js +372 -0
  332. package/dist/chunk-W4RVMTHR.js.map +1 -0
  333. package/dist/chunk-WEHSQBFR.js +188 -0
  334. package/dist/chunk-WEHSQBFR.js.map +1 -0
  335. package/dist/chunk-WELDCG6C.js +380 -0
  336. package/dist/chunk-WELDCG6C.js.map +1 -0
  337. package/dist/chunk-WZYKANL3.js +2800 -0
  338. package/dist/chunk-WZYKANL3.js.map +1 -0
  339. package/dist/chunk-XIG5PDM7.js +48 -0
  340. package/dist/chunk-XJNBEDFE.js +193 -0
  341. package/dist/chunk-XJNBEDFE.js.map +1 -0
  342. package/dist/chunk-XVVIG67A.js +291 -0
  343. package/dist/chunk-XVVIG67A.js.map +1 -0
  344. package/dist/chunk-XVZ7B3HG.js +135 -0
  345. package/dist/chunk-YBPYIAA5.js +73 -0
  346. package/dist/chunk-YBPYIAA5.js.map +1 -0
  347. package/dist/chunk-Z734BLO3.js +21 -0
  348. package/dist/chunk-Z734BLO3.js.map +1 -0
  349. package/dist/chunk-ZKSK55RC.js +269 -0
  350. package/dist/chunk-ZKSK55RC.js.map +1 -0
  351. package/dist/chunk-ZTFCYYEZ.js +69 -0
  352. package/dist/chunk-ZTFCYYEZ.js.map +1 -0
  353. package/dist/chunk-ZY2MNJR6.js +329 -0
  354. package/dist/chunk-ZY2MNJR6.js.map +1 -0
  355. package/dist/cli-D3VpkVwB.d.ts +1136 -0
  356. package/dist/cli.d.ts +42 -10
  357. package/dist/cli.js +121 -58
  358. package/dist/codex-cli-fallback.d.ts +1 -0
  359. package/dist/codex-cli-fallback.js +1 -1
  360. package/dist/commitment-ledger.js +1 -1
  361. package/dist/compat/checks.d.ts +5 -0
  362. package/dist/compat/checks.js +11 -0
  363. package/dist/compat/checks.js.map +1 -0
  364. package/dist/compat/types.d.ts +30 -0
  365. package/dist/compat/types.js +1 -0
  366. package/dist/compat/types.js.map +1 -0
  367. package/dist/compounding/engine.d.ts +221 -0
  368. package/dist/compounding/engine.js +32 -0
  369. package/dist/compounding/engine.js.map +1 -0
  370. package/dist/compounding/preference-consolidator.d.ts +92 -0
  371. package/dist/compounding/preference-consolidator.js +553 -0
  372. package/dist/compounding/preference-consolidator.js.map +1 -0
  373. package/dist/compression-optimizer.d.ts +1 -1
  374. package/dist/config.d.ts +5 -3
  375. package/dist/config.js +9 -4
  376. package/dist/conflict-policy-DyJ2wd-h.d.ts +4 -0
  377. package/dist/connectors/codex-materialize-runner.d.ts +64 -0
  378. package/dist/connectors/codex-materialize-runner.js +33 -0
  379. package/dist/connectors/codex-materialize-runner.js.map +1 -0
  380. package/dist/connectors/codex-materialize.d.ts +195 -0
  381. package/dist/connectors/codex-materialize.js +38 -0
  382. package/dist/connectors/codex-materialize.js.map +1 -0
  383. package/dist/connectors/index.d.ts +444 -0
  384. package/dist/connectors/index.js +115 -0
  385. package/dist/connectors/index.js.map +1 -0
  386. package/dist/connectors-cli-CwbyjGR7.d.ts +257 -0
  387. package/dist/connectors-cli.d.ts +1 -1
  388. package/dist/consolidation-provenance-check.d.ts +4 -2
  389. package/dist/consolidation-undo.d.ts +4 -2
  390. package/dist/contradiction/index.d.ts +258 -0
  391. package/dist/contradiction/index.js +43 -0
  392. package/dist/contradiction/index.js.map +1 -0
  393. package/dist/contradiction-review-ATP4S6IC.js +30 -0
  394. package/dist/contradiction-review-ATP4S6IC.js.map +1 -0
  395. package/dist/contradiction-scan-5A4IDZV5.js +13 -0
  396. package/dist/contradiction-scan-5A4IDZV5.js.map +1 -0
  397. package/dist/conversation-index/backend.d.ts +97 -0
  398. package/dist/conversation-index/backend.js +13 -0
  399. package/dist/conversation-index/backend.js.map +1 -0
  400. package/dist/conversation-index/chunker.d.ts +16 -0
  401. package/dist/conversation-index/chunker.js +8 -0
  402. package/dist/conversation-index/chunker.js.map +1 -0
  403. package/dist/conversation-index/cleanup.d.ts +11 -0
  404. package/dist/conversation-index/cleanup.js +9 -0
  405. package/dist/conversation-index/cleanup.js.map +1 -0
  406. package/dist/conversation-index/faiss-adapter.d.ts +6 -0
  407. package/dist/conversation-index/faiss-adapter.js +16 -0
  408. package/dist/conversation-index/faiss-adapter.js.map +1 -0
  409. package/dist/conversation-index/indexer.d.ts +23 -0
  410. package/dist/conversation-index/indexer.js +15 -0
  411. package/dist/conversation-index/indexer.js.map +1 -0
  412. package/dist/conversation-index/search.d.ts +6 -0
  413. package/dist/conversation-index/search.js +11 -0
  414. package/dist/conversation-index/search.js.map +1 -0
  415. package/dist/day-summary.d.ts +1 -1
  416. package/dist/delinearize.d.ts +1 -1
  417. package/dist/direct-answer-wiring.d.ts +1 -1
  418. package/dist/direct-answer-wiring.js +1 -1
  419. package/dist/direct-answer.d.ts +1 -1
  420. package/dist/embedding-fallback.d.ts +1 -1
  421. package/dist/embedding-fallback.js +2 -2
  422. package/dist/enrichment/index.d.ts +163 -0
  423. package/dist/enrichment/index.js +18 -0
  424. package/dist/enrichment/index.js.map +1 -0
  425. package/dist/entity-retrieval.d.ts +4 -2
  426. package/dist/entity-retrieval.js +9 -6
  427. package/dist/entity-schema.d.ts +1 -1
  428. package/dist/evals.js +1 -1
  429. package/dist/event-order-recall.d.ts +17 -0
  430. package/dist/event-order-recall.js +11 -0
  431. package/dist/event-order-recall.js.map +1 -0
  432. package/dist/evidence-pack.d.ts +3 -1
  433. package/dist/evidence-pack.js +5 -3
  434. package/dist/explicit-capture.d.ts +23 -6
  435. package/dist/explicit-capture.js +2 -2
  436. package/dist/explicit-cue-recall.d.ts +4 -1
  437. package/dist/explicit-cue-recall.js +4 -2
  438. package/dist/extraction-judge-telemetry.d.ts +1 -1
  439. package/dist/extraction-judge-training.d.ts +1 -1
  440. package/dist/extraction-judge-training.js +1 -1
  441. package/dist/extraction-judge.d.ts +1 -1
  442. package/dist/extraction.d.ts +1 -1
  443. package/dist/extraction.js +11 -10
  444. package/dist/faiss-adapter-CzPghc4C.d.ts +70 -0
  445. package/dist/fallback-llm.d.ts +4 -1
  446. package/dist/fallback-llm.js +6 -6
  447. package/dist/focused-list-recall.d.ts +17 -0
  448. package/dist/focused-list-recall.js +11 -0
  449. package/dist/focused-list-recall.js.map +1 -0
  450. package/dist/graph-edge-decay-5DI5GUNL.js +207 -0
  451. package/dist/identity-continuity.d.ts +1 -1
  452. package/dist/importance.d.ts +1 -1
  453. package/dist/index-DJ9QWMw-.d.ts +35 -0
  454. package/dist/index.d.ts +107 -715
  455. package/dist/index.js +657 -2611
  456. package/dist/index.js.map +1 -1
  457. package/dist/intent.d.ts +1 -1
  458. package/dist/intent.js +1 -1
  459. package/dist/lcm/archive.d.ts +89 -0
  460. package/dist/lcm/archive.js +12 -0
  461. package/dist/lcm/archive.js.map +1 -0
  462. package/dist/lcm/dag.d.ts +48 -0
  463. package/dist/lcm/dag.js +8 -0
  464. package/dist/lcm/dag.js.map +1 -0
  465. package/dist/lcm/engine.d.ts +116 -0
  466. package/dist/lcm/engine.js +20 -0
  467. package/dist/lcm/engine.js.map +1 -0
  468. package/dist/lcm/index.d.ts +12 -0
  469. package/dist/lcm/index.js +44 -0
  470. package/dist/lcm/index.js.map +1 -0
  471. package/dist/lcm/queue.d.ts +62 -0
  472. package/dist/lcm/queue.js +8 -0
  473. package/dist/lcm/queue.js.map +1 -0
  474. package/dist/lcm/recall.d.ts +20 -0
  475. package/dist/lcm/recall.js +8 -0
  476. package/dist/lcm/recall.js.map +1 -0
  477. package/dist/lcm/schema.d.ts +16 -0
  478. package/dist/lcm/schema.js +14 -0
  479. package/dist/lcm/schema.js.map +1 -0
  480. package/dist/lcm/summarizer.d.ts +38 -0
  481. package/dist/lcm/summarizer.js +12 -0
  482. package/dist/lcm/summarizer.js.map +1 -0
  483. package/dist/lcm/tools.d.ts +29 -0
  484. package/dist/lcm/tools.js +8 -0
  485. package/dist/lcm/tools.js.map +1 -0
  486. package/dist/lifecycle.d.ts +1 -1
  487. package/dist/live-connectors-runner.d.ts +1 -1
  488. package/dist/live-connectors-runner.js +5 -5
  489. package/dist/local-llm.d.ts +8 -4
  490. package/dist/local-llm.js +3 -3
  491. package/dist/maintenance/archive-observations.d.ts +18 -0
  492. package/dist/maintenance/archive-observations.js +8 -0
  493. package/dist/maintenance/archive-observations.js.map +1 -0
  494. package/dist/maintenance/backup-stamp.d.ts +3 -0
  495. package/dist/maintenance/backup-stamp.js +8 -0
  496. package/dist/maintenance/backup-stamp.js.map +1 -0
  497. package/dist/maintenance/memory-governance-cron.d.ts +85 -0
  498. package/dist/maintenance/memory-governance-cron.js +22 -0
  499. package/dist/maintenance/memory-governance-cron.js.map +1 -0
  500. package/dist/maintenance/memory-governance.d.ts +137 -0
  501. package/dist/maintenance/memory-governance.js +40 -0
  502. package/dist/maintenance/memory-governance.js.map +1 -0
  503. package/dist/maintenance/migrate-observations.d.ts +18 -0
  504. package/dist/maintenance/migrate-observations.js +9 -0
  505. package/dist/maintenance/migrate-observations.js.map +1 -0
  506. package/dist/maintenance/observation-ledger-utils.d.ts +10 -0
  507. package/dist/maintenance/observation-ledger-utils.js +10 -0
  508. package/dist/maintenance/observation-ledger-utils.js.map +1 -0
  509. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +15 -0
  510. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +28 -0
  511. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js.map +1 -0
  512. package/dist/maintenance/rebuild-memory-projection.d.ts +77 -0
  513. package/dist/maintenance/rebuild-memory-projection.js +35 -0
  514. package/dist/maintenance/rebuild-memory-projection.js.map +1 -0
  515. package/dist/maintenance/rebuild-observations.d.ts +17 -0
  516. package/dist/maintenance/rebuild-observations.js +9 -0
  517. package/dist/maintenance/rebuild-observations.js.map +1 -0
  518. package/dist/mcp-memory-inspector-app.d.ts +124 -0
  519. package/dist/mcp-memory-inspector-app.js +20 -0
  520. package/dist/mcp-memory-inspector-app.js.map +1 -0
  521. package/dist/memory-action-policy.d.ts +1 -1
  522. package/dist/memory-cache.d.ts +1 -1
  523. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  524. package/dist/memory-projection-store.d.ts +108 -3
  525. package/dist/memory-projection-store.js +2 -1
  526. package/dist/memory-provenance.d.ts +57 -0
  527. package/dist/memory-provenance.js +13 -0
  528. package/dist/memory-provenance.js.map +1 -0
  529. package/dist/memory-worth-outcomes.d.ts +4 -2
  530. package/dist/migrate/from-engram.d.ts +24 -0
  531. package/dist/migrate/from-engram.js +12 -0
  532. package/dist/migrate/from-engram.js.map +1 -0
  533. package/dist/models-json.d.ts +1 -1
  534. package/dist/namespaces/migrate.d.ts +50 -0
  535. package/dist/namespaces/migrate.js +50 -0
  536. package/dist/namespaces/migrate.js.map +1 -0
  537. package/dist/namespaces/principal.d.ts +17 -0
  538. package/dist/namespaces/principal.js +16 -0
  539. package/dist/namespaces/principal.js.map +1 -0
  540. package/dist/namespaces/search.d.ts +46 -0
  541. package/dist/namespaces/search.js +28 -0
  542. package/dist/namespaces/search.js.map +1 -0
  543. package/dist/namespaces/storage.d.ts +32 -0
  544. package/dist/namespaces/storage.js +28 -0
  545. package/dist/namespaces/storage.js.map +1 -0
  546. package/dist/native-knowledge.d.ts +1 -1
  547. package/dist/network/tailscale.d.ts +41 -0
  548. package/dist/network/tailscale.js +9 -0
  549. package/dist/network/tailscale.js.map +1 -0
  550. package/dist/network/webdav.d.ts +39 -0
  551. package/dist/network/webdav.js +10 -0
  552. package/dist/network/webdav.js.map +1 -0
  553. package/dist/objective-state-writers.d.ts +1 -1
  554. package/dist/objective-state-writers.js +2 -2
  555. package/dist/operator-toolkit.d.ts +4 -2
  556. package/dist/operator-toolkit.js +35 -17
  557. package/dist/opik-exporter.js +2 -2
  558. package/dist/opik-exporter.js.map +1 -1
  559. package/dist/orchestrator-DuWl9Hwx.d.ts +1244 -0
  560. package/dist/orchestrator.d.ts +24 -7
  561. package/dist/orchestrator.js +107 -65
  562. package/dist/path-MR5JPYOP.js +9 -0
  563. package/dist/path-MR5JPYOP.js.map +1 -0
  564. package/dist/patterns-cli.d.ts +1 -1
  565. package/dist/policy-runtime.d.ts +1 -1
  566. package/dist/qmd-recall-cache.d.ts +2 -2
  567. package/dist/qmd.d.ts +103 -4
  568. package/dist/qmd.js +23 -5
  569. package/dist/recall-disclosure-escalation.d.ts +1 -1
  570. package/dist/recall-explain-renderer.d.ts +3 -1
  571. package/dist/recall-explain-renderer.js +5 -3
  572. package/dist/recall-state.d.ts +1 -1
  573. package/dist/recall-tag-filter.d.ts +3 -1
  574. package/dist/recall-xray-cli.d.ts +3 -1
  575. package/dist/recall-xray-cli.js +6 -4
  576. package/dist/recall-xray-renderer.d.ts +3 -1
  577. package/dist/recall-xray-renderer.js +5 -3
  578. package/dist/recall-xray.d.ts +8 -1
  579. package/dist/recall-xray.js +4 -2
  580. package/dist/replay/normalizers/chatgpt.d.ts +6 -0
  581. package/dist/replay/normalizers/chatgpt.js +11 -0
  582. package/dist/replay/normalizers/chatgpt.js.map +1 -0
  583. package/dist/replay/normalizers/claude.d.ts +6 -0
  584. package/dist/replay/normalizers/claude.js +11 -0
  585. package/dist/replay/normalizers/claude.js.map +1 -0
  586. package/dist/replay/normalizers/openclaw.d.ts +6 -0
  587. package/dist/replay/normalizers/openclaw.js +11 -0
  588. package/dist/replay/normalizers/openclaw.js.map +1 -0
  589. package/dist/replay/normalizers/shared.d.ts +16 -0
  590. package/dist/replay/normalizers/shared.js +14 -0
  591. package/dist/replay/normalizers/shared.js.map +1 -0
  592. package/dist/replay/runner.d.ts +35 -0
  593. package/dist/replay/runner.js +16 -0
  594. package/dist/replay/runner.js.map +1 -0
  595. package/dist/replay/types.d.ts +57 -0
  596. package/dist/replay/types.js +19 -0
  597. package/dist/replay/types.js.map +1 -0
  598. package/dist/resolution-B7FNQSSP.js +12 -0
  599. package/dist/resolution-B7FNQSSP.js.map +1 -0
  600. package/dist/resolve-auth-token.d.ts +1 -1
  601. package/dist/resolve-provider-secret.js +2 -2
  602. package/dist/response-guidance-recall.d.ts +18 -0
  603. package/dist/response-guidance-recall.js +11 -0
  604. package/dist/response-guidance-recall.js.map +1 -0
  605. package/dist/resume-bundles.js +7 -5
  606. package/dist/retrieval-agents.d.ts +2 -2
  607. package/dist/retrieval-tiers.d.ts +1 -1
  608. package/dist/routing/engine.d.ts +35 -0
  609. package/dist/routing/engine.js +16 -0
  610. package/dist/routing/engine.js.map +1 -0
  611. package/dist/routing/store.d.ts +27 -0
  612. package/dist/routing/store.js +10 -0
  613. package/dist/routing/store.js.map +1 -0
  614. package/dist/runtime/better-sqlite.d.ts +8 -0
  615. package/dist/runtime/better-sqlite.js +10 -0
  616. package/dist/runtime/better-sqlite.js.map +1 -0
  617. package/dist/runtime/child-process.d.ts +32 -0
  618. package/dist/runtime/child-process.js +10 -0
  619. package/dist/runtime/child-process.js.map +1 -0
  620. package/dist/runtime/env.d.ts +5 -0
  621. package/dist/runtime/env.js +12 -0
  622. package/dist/runtime/env.js.map +1 -0
  623. package/dist/sdk-compat.js +1 -1
  624. package/dist/search/document-scanner.d.ts +22 -0
  625. package/dist/search/document-scanner.js +8 -0
  626. package/dist/search/document-scanner.js.map +1 -0
  627. package/dist/search/embed-helper.d.ts +35 -0
  628. package/dist/search/embed-helper.js +9 -0
  629. package/dist/search/embed-helper.js.map +1 -0
  630. package/dist/search/factory.d.ts +32 -0
  631. package/dist/search/factory.js +29 -0
  632. package/dist/search/factory.js.map +1 -0
  633. package/dist/search/index.d.ts +15 -0
  634. package/dist/search/index.js +50 -0
  635. package/dist/search/index.js.map +1 -0
  636. package/dist/search/lancedb-backend.d.ts +51 -0
  637. package/dist/search/lancedb-backend.js +10 -0
  638. package/dist/search/lancedb-backend.js.map +1 -0
  639. package/dist/search/meilisearch-backend.d.ts +48 -0
  640. package/dist/search/meilisearch-backend.js +10 -0
  641. package/dist/search/meilisearch-backend.js.map +1 -0
  642. package/dist/search/noop-backend.d.ts +26 -0
  643. package/dist/search/noop-backend.js +8 -0
  644. package/dist/search/noop-backend.js.map +1 -0
  645. package/dist/search/orama-backend.d.ts +53 -0
  646. package/dist/search/orama-backend.js +10 -0
  647. package/dist/search/orama-backend.js.map +1 -0
  648. package/dist/search/port.d.ts +61 -0
  649. package/dist/search/port.js +1 -0
  650. package/dist/search/port.js.map +1 -0
  651. package/dist/search/remote-backend.d.ts +39 -0
  652. package/dist/search/remote-backend.js +9 -0
  653. package/dist/search/remote-backend.js.map +1 -0
  654. package/dist/secure-store/index.d.ts +890 -0
  655. package/dist/secure-store/index.js +156 -0
  656. package/dist/secure-store/index.js.map +1 -0
  657. package/dist/semantic-VwGI14Ok.d.ts +69 -0
  658. package/dist/semantic-consolidation-4HkHWgeI.d.ts +180 -0
  659. package/dist/semantic-consolidation.d.ts +3 -3
  660. package/dist/semantic-consolidation.js +15 -8
  661. package/dist/semantic-rule-promotion.js +9 -6
  662. package/dist/semantic-rule-verifier.d.ts +1 -1
  663. package/dist/semantic-rule-verifier.js +10 -7
  664. package/dist/session-observer-bands.d.ts +1 -1
  665. package/dist/session-observer-state.d.ts +1 -1
  666. package/dist/shared-context/manager.d.ts +131 -0
  667. package/dist/shared-context/manager.js +15 -0
  668. package/dist/shared-context/manager.js.map +1 -0
  669. package/dist/signal.d.ts +1 -1
  670. package/dist/skills-registry.js +13 -1
  671. package/dist/skills-registry.js.map +1 -1
  672. package/dist/state-store-VZU2IA53.js +16 -0
  673. package/dist/state-store-VZU2IA53.js.map +1 -0
  674. package/dist/storage-paths.d.ts +9 -0
  675. package/dist/storage-paths.js +20 -0
  676. package/dist/storage-paths.js.map +1 -0
  677. package/dist/storage.d.ts +6 -2
  678. package/dist/storage.js +8 -5
  679. package/dist/summarizer.d.ts +6 -1
  680. package/dist/summarizer.js +11 -10
  681. package/dist/summary-snapshot.d.ts +1 -1
  682. package/dist/summary-snapshot.js +2 -1
  683. package/dist/surfaces/dreams.d.ts +16 -0
  684. package/dist/surfaces/dreams.js +282 -0
  685. package/dist/surfaces/dreams.js.map +1 -0
  686. package/dist/surfaces/heartbeat.d.ts +17 -0
  687. package/dist/surfaces/heartbeat.js +265 -0
  688. package/dist/surfaces/heartbeat.js.map +1 -0
  689. package/dist/targeted-fact-recall.d.ts +17 -0
  690. package/dist/targeted-fact-recall.js +11 -0
  691. package/dist/targeted-fact-recall.js.map +1 -0
  692. package/dist/telemetry-transcript.d.ts +7 -0
  693. package/dist/telemetry-transcript.js +16 -0
  694. package/dist/telemetry-transcript.js.map +1 -0
  695. package/dist/temporal-supersession.d.ts +4 -2
  696. package/dist/temporal-supersession.js +2 -1
  697. package/dist/temporal-validity.d.ts +1 -1
  698. package/dist/threading.d.ts +6 -1
  699. package/dist/threading.js +2 -1
  700. package/dist/tier-migration.d.ts +5 -3
  701. package/dist/tier-routing.d.ts +1 -1
  702. package/dist/tokens.js +2 -2
  703. package/dist/topics.d.ts +1 -1
  704. package/dist/transcript.d.ts +16 -2
  705. package/dist/transcript.js +2 -1
  706. package/dist/transfer/autodetect.d.ts +4 -0
  707. package/dist/transfer/autodetect.js +15 -0
  708. package/dist/transfer/autodetect.js.map +1 -0
  709. package/dist/transfer/backup.d.ts +21 -0
  710. package/dist/transfer/backup.js +17 -0
  711. package/dist/transfer/backup.js.map +1 -0
  712. package/dist/transfer/capsule-export.d.ts +113 -0
  713. package/dist/transfer/capsule-export.js +19 -0
  714. package/dist/transfer/capsule-export.js.map +1 -0
  715. package/dist/transfer/capsule-import.d.ts +124 -0
  716. package/dist/transfer/capsule-import.js +16 -0
  717. package/dist/transfer/capsule-import.js.map +1 -0
  718. package/dist/transfer/constants.d.ts +13 -0
  719. package/dist/transfer/constants.js +12 -0
  720. package/dist/transfer/constants.js.map +1 -0
  721. package/dist/transfer/export-json.d.ts +11 -0
  722. package/dist/transfer/export-json.js +11 -0
  723. package/dist/transfer/export-json.js.map +1 -0
  724. package/dist/transfer/export-md.d.ts +10 -0
  725. package/dist/transfer/export-md.js +13 -0
  726. package/dist/transfer/export-md.js.map +1 -0
  727. package/dist/transfer/export-sqlite.d.ts +9 -0
  728. package/dist/transfer/export-sqlite.js +12 -0
  729. package/dist/transfer/export-sqlite.js.map +1 -0
  730. package/dist/transfer/fs-utils.d.ts +61 -0
  731. package/dist/transfer/fs-utils.js +40 -0
  732. package/dist/transfer/fs-utils.js.map +1 -0
  733. package/dist/transfer/import-json.d.ts +16 -0
  734. package/dist/transfer/import-json.js +13 -0
  735. package/dist/transfer/import-json.js.map +1 -0
  736. package/dist/transfer/import-md.d.ts +14 -0
  737. package/dist/transfer/import-md.js +11 -0
  738. package/dist/transfer/import-md.js.map +1 -0
  739. package/dist/transfer/import-sqlite.d.ts +14 -0
  740. package/dist/transfer/import-sqlite.js +12 -0
  741. package/dist/transfer/import-sqlite.js.map +1 -0
  742. package/dist/transfer/sqlite-schema.d.ts +4 -0
  743. package/dist/transfer/sqlite-schema.js +10 -0
  744. package/dist/transfer/sqlite-schema.js.map +1 -0
  745. package/dist/transfer/types.d.ts +916 -0
  746. package/dist/transfer/types.js +30 -0
  747. package/dist/transfer/types.js.map +1 -0
  748. package/dist/trust-zones.d.ts +3 -2
  749. package/dist/trust-zones.js +1 -1
  750. package/dist/types.d.ts +88 -3
  751. package/dist/types.js +1 -1
  752. package/dist/user-model.d.ts +37 -0
  753. package/dist/user-model.js +28 -0
  754. package/dist/user-model.js.map +1 -0
  755. package/dist/utility-runtime.d.ts +1 -1
  756. package/dist/verified-recall.js +11 -8
  757. package/dist/work/board.d.ts +43 -0
  758. package/dist/work/board.js +14 -0
  759. package/dist/work/board.js.map +1 -0
  760. package/dist/work/boundary.d.ts +8 -0
  761. package/dist/work/boundary.js +14 -0
  762. package/dist/work/boundary.js.map +1 -0
  763. package/dist/work/storage.d.ts +39 -0
  764. package/dist/work/storage.js +11 -0
  765. package/dist/work/storage.js.map +1 -0
  766. package/dist/work/types.d.ts +75 -0
  767. package/dist/work/types.js +1 -0
  768. package/dist/work/types.js.map +1 -0
  769. package/package.json +2767 -6
  770. package/scripts/faiss_index.py +816 -0
  771. package/scripts/faiss_requirements.txt +3 -0
  772. package/skills/remnic-entities/SKILL.md +51 -0
  773. package/skills/remnic-memory-workflow/SKILL.md +61 -0
  774. package/skills/remnic-recall/SKILL.md +51 -0
  775. package/skills/remnic-remember/SKILL.md +56 -0
  776. package/skills/remnic-search/SKILL.md +51 -0
  777. package/skills/remnic-status/SKILL.md +51 -0
  778. package/src/abort-error.test.ts +49 -0
  779. package/src/abort-error.ts +46 -0
  780. package/src/abstraction-nodes.ts +162 -0
  781. package/src/access-audit.test.ts +178 -0
  782. package/src/access-audit.ts +125 -0
  783. package/src/access-cli.test.ts +439 -0
  784. package/src/access-cli.ts +438 -0
  785. package/src/access-http.test.ts +225 -0
  786. package/src/access-http.ts +1899 -0
  787. package/src/access-idempotency.ts +232 -0
  788. package/src/access-mcp.test.ts +568 -0
  789. package/src/access-mcp.ts +3056 -0
  790. package/src/access-schema-pi.test.ts +60 -0
  791. package/src/access-schema.ts +522 -0
  792. package/src/access-service-namespace.test.ts +123 -0
  793. package/src/access-service.ts +5629 -0
  794. package/src/action-confidence.test.ts +206 -0
  795. package/src/action-confidence.ts +466 -0
  796. package/src/active-memory-bridge.test.ts +285 -0
  797. package/src/active-memory-bridge.ts +217 -0
  798. package/src/active-recall.test.ts +484 -0
  799. package/src/active-recall.ts +459 -0
  800. package/src/adapters/claude-code.ts +56 -0
  801. package/src/adapters/codex.ts +57 -0
  802. package/src/adapters/hermes.ts +64 -0
  803. package/src/adapters/index.ts +6 -0
  804. package/src/adapters/registry.ts +41 -0
  805. package/src/adapters/replit.ts +55 -0
  806. package/src/adapters/types.ts +51 -0
  807. package/src/behavior-learner.ts +144 -0
  808. package/src/behavior-signals.ts +73 -0
  809. package/src/binary-lifecycle/backend.ts +117 -0
  810. package/src/binary-lifecycle/index.ts +35 -0
  811. package/src/binary-lifecycle/manifest.ts +79 -0
  812. package/src/binary-lifecycle/pipeline.ts +352 -0
  813. package/src/binary-lifecycle/scanner.ts +89 -0
  814. package/src/binary-lifecycle/types.ts +89 -0
  815. package/src/bootstrap.ts +178 -0
  816. package/src/boxes.ts +521 -0
  817. package/src/briefing.test.ts +1535 -0
  818. package/src/briefing.ts +1382 -0
  819. package/src/buffer-session.test.ts +443 -0
  820. package/src/buffer-surprise-report.ts +176 -0
  821. package/src/buffer-surprise-telemetry.test.ts +606 -0
  822. package/src/buffer-surprise-trigger.test.ts +766 -0
  823. package/src/buffer-surprise.test.ts +339 -0
  824. package/src/buffer-surprise.ts +203 -0
  825. package/src/buffer.ts +900 -0
  826. package/src/bulk-import/cli-command.test.ts +204 -0
  827. package/src/bulk-import/index.ts +34 -0
  828. package/src/bulk-import/pipeline.test.ts +445 -0
  829. package/src/bulk-import/pipeline.ts +178 -0
  830. package/src/bulk-import/registry.test.ts +151 -0
  831. package/src/bulk-import/registry.ts +72 -0
  832. package/src/bulk-import/types.test.ts +272 -0
  833. package/src/bulk-import/types.ts +145 -0
  834. package/src/calibration.ts +394 -0
  835. package/src/capsule-cli.test.ts +398 -0
  836. package/src/capsule-cli.ts +565 -0
  837. package/src/causal-behavior.ts +308 -0
  838. package/src/causal-chain.ts +419 -0
  839. package/src/causal-consolidation.ts +370 -0
  840. package/src/causal-retrieval.ts +286 -0
  841. package/src/causal-trajectory-graph.ts +60 -0
  842. package/src/causal-trajectory.ts +303 -0
  843. package/src/chunking.ts +220 -0
  844. package/src/citations.ts +232 -0
  845. package/src/cli.ts +9403 -0
  846. package/src/codex-cli-fallback.ts +162 -0
  847. package/src/codex-thread-key.ts +1 -0
  848. package/src/coding/access-coding-context.test.ts +197 -0
  849. package/src/coding/coding-branch-scope.test.ts +281 -0
  850. package/src/coding/coding-namespace.test.ts +360 -0
  851. package/src/coding/coding-namespace.ts +412 -0
  852. package/src/coding/coding-orchestrator.test.ts +249 -0
  853. package/src/coding/git-context.test.ts +507 -0
  854. package/src/coding/git-context.ts +336 -0
  855. package/src/coding/mcp-set-coding-context.test.ts +174 -0
  856. package/src/coding/review-context.test.ts +316 -0
  857. package/src/coding/review-context.ts +349 -0
  858. package/src/coding/wire-coding-context.test.ts +468 -0
  859. package/src/commitment-ledger.test.ts +78 -0
  860. package/src/commitment-ledger.ts +337 -0
  861. package/src/compat/checks.test.ts +206 -0
  862. package/src/compat/checks.ts +716 -0
  863. package/src/compat/types.ts +33 -0
  864. package/src/compounding/engine.ts +1686 -0
  865. package/src/compounding/preference-consolidator.ts +778 -0
  866. package/src/compression-optimizer.ts +312 -0
  867. package/src/config.test.ts +930 -0
  868. package/src/config.ts +3807 -0
  869. package/src/connectors/codex/instructions.md +160 -0
  870. package/src/connectors/codex/resources/namespace-cheatsheet.md +48 -0
  871. package/src/connectors/codex-marketplace.ts +500 -0
  872. package/src/connectors/codex-materialize-runner.ts +212 -0
  873. package/src/connectors/codex-materialize.ts +983 -0
  874. package/src/connectors/coerce.ts +62 -0
  875. package/src/connectors/index.test.ts +1570 -0
  876. package/src/connectors/index.ts +3222 -0
  877. package/src/connectors/live/framework.ts +164 -0
  878. package/src/connectors/live/github.test.ts +1218 -0
  879. package/src/connectors/live/github.ts +1068 -0
  880. package/src/connectors/live/gmail.test.ts +1706 -0
  881. package/src/connectors/live/gmail.ts +1293 -0
  882. package/src/connectors/live/google-drive.test.ts +696 -0
  883. package/src/connectors/live/google-drive.ts +724 -0
  884. package/src/connectors/live/index.ts +101 -0
  885. package/src/connectors/live/live-connectors.test.ts +689 -0
  886. package/src/connectors/live/notion.test.ts +1109 -0
  887. package/src/connectors/live/notion.ts +978 -0
  888. package/src/connectors/live/registry.ts +103 -0
  889. package/src/connectors/live/state-store.ts +399 -0
  890. package/src/connectors/live/transient-errors.ts +150 -0
  891. package/src/connectors/weclone-installer.test.ts +850 -0
  892. package/src/connectors-cli.ts +513 -0
  893. package/src/console/state.test.ts +224 -0
  894. package/src/console/state.ts +514 -0
  895. package/src/console/trace.test.ts +813 -0
  896. package/src/console/trace.ts +603 -0
  897. package/src/console/tui.test.ts +582 -0
  898. package/src/console/tui.ts +508 -0
  899. package/src/consolidation-operator.ts +182 -0
  900. package/src/consolidation-provenance-check.ts +551 -0
  901. package/src/consolidation-undo.ts +718 -0
  902. package/src/contradiction/contradiction-judge.test.ts +189 -0
  903. package/src/contradiction/contradiction-judge.ts +333 -0
  904. package/src/contradiction/contradiction-review.ts +574 -0
  905. package/src/contradiction/contradiction-scan.ts +504 -0
  906. package/src/contradiction/contradiction.test.ts +2230 -0
  907. package/src/contradiction/index.ts +37 -0
  908. package/src/contradiction/resolution.ts +383 -0
  909. package/src/conversation-index/backend.ts +323 -0
  910. package/src/conversation-index/chunker.ts +47 -0
  911. package/src/conversation-index/cleanup.ts +53 -0
  912. package/src/conversation-index/faiss-adapter.ts +384 -0
  913. package/src/conversation-index/indexer.test.ts +164 -0
  914. package/src/conversation-index/indexer.ts +192 -0
  915. package/src/conversation-index/search.ts +37 -0
  916. package/src/cross-namespace-budget.test.ts +275 -0
  917. package/src/cross-namespace-budget.ts +365 -0
  918. package/src/cue-anchors.ts +163 -0
  919. package/src/curation/index.ts +544 -0
  920. package/src/dashboard-runtime.ts +337 -0
  921. package/src/day-summary.ts +122 -0
  922. package/src/dedup/index.ts +330 -0
  923. package/src/dedup/semantic.test.ts +1577 -0
  924. package/src/dedup/semantic.ts +148 -0
  925. package/src/delinearize.ts +193 -0
  926. package/src/direct-answer-wiring.test.ts +473 -0
  927. package/src/direct-answer-wiring.ts +180 -0
  928. package/src/direct-answer.test.ts +484 -0
  929. package/src/direct-answer.ts +273 -0
  930. package/src/embedding-fallback.ts +565 -0
  931. package/src/enrichment/audit.ts +89 -0
  932. package/src/enrichment/index.ts +27 -0
  933. package/src/enrichment/pipeline.ts +197 -0
  934. package/src/enrichment/provider-registry.ts +85 -0
  935. package/src/enrichment/types.ts +100 -0
  936. package/src/enrichment/web-search-provider.ts +63 -0
  937. package/src/entity-retrieval.ts +774 -0
  938. package/src/entity-schema.ts +239 -0
  939. package/src/evals.ts +1312 -0
  940. package/src/event-order-recall.test.ts +4164 -0
  941. package/src/event-order-recall.ts +2802 -0
  942. package/src/evidence-pack.test.ts +89 -0
  943. package/src/evidence-pack.ts +388 -0
  944. package/src/explicit-capture.ts +530 -0
  945. package/src/explicit-cue-recall.test.ts +3019 -0
  946. package/src/explicit-cue-recall.ts +5545 -0
  947. package/src/extraction-judge-telemetry.ts +234 -0
  948. package/src/extraction-judge-training.ts +221 -0
  949. package/src/extraction-judge.ts +846 -0
  950. package/src/extraction-timeout.test.ts +265 -0
  951. package/src/extraction.ts +2719 -0
  952. package/src/fallback-llm.test.ts +1060 -0
  953. package/src/fallback-llm.ts +918 -0
  954. package/src/focused-list-recall.test.ts +734 -0
  955. package/src/focused-list-recall.ts +1160 -0
  956. package/src/graph-dashboard-diff.ts +35 -0
  957. package/src/graph-dashboard-key.ts +5 -0
  958. package/src/graph-dashboard-parser.ts +104 -0
  959. package/src/graph-edge-reinforcement.ts +192 -0
  960. package/src/graph-events.ts +151 -0
  961. package/src/graph-recall.test.ts +164 -0
  962. package/src/graph-recall.ts +189 -0
  963. package/src/graph-retrieval.test.ts +809 -0
  964. package/src/graph-retrieval.ts +823 -0
  965. package/src/graph-snapshot.ts +329 -0
  966. package/src/graph.ts +813 -0
  967. package/src/harmonic-retrieval.ts +223 -0
  968. package/src/himem.ts +154 -0
  969. package/src/hygiene.ts +87 -0
  970. package/src/identity-continuity.ts +333 -0
  971. package/src/importance.ts +328 -0
  972. package/src/importers/base.test.ts +294 -0
  973. package/src/importers/base.ts +436 -0
  974. package/src/importers/index.ts +21 -0
  975. package/src/index.ts +1204 -0
  976. package/src/intent.ts +154 -0
  977. package/src/json-extract.ts +85 -0
  978. package/src/json-store.ts +42 -0
  979. package/src/lcm/archive.ts +617 -0
  980. package/src/lcm/dag.ts +199 -0
  981. package/src/lcm/engine.ts +645 -0
  982. package/src/lcm/index.ts +7 -0
  983. package/src/lcm/queue.test.ts +178 -0
  984. package/src/lcm/queue.ts +200 -0
  985. package/src/lcm/recall.ts +117 -0
  986. package/src/lcm/schema.ts +154 -0
  987. package/src/lcm/summarizer.ts +235 -0
  988. package/src/lcm/tools.ts +191 -0
  989. package/src/lcm-engine.test.ts +660 -0
  990. package/src/legacy-hook-compat.test.ts +20 -0
  991. package/src/legacy-hook-compat.ts +45 -0
  992. package/src/lifecycle.ts +289 -0
  993. package/src/live-connectors-runner.ts +385 -0
  994. package/src/local-llm-qos.test.ts +303 -0
  995. package/src/local-llm-thinking.test.ts +292 -0
  996. package/src/local-llm.ts +1464 -0
  997. package/src/logger.ts +49 -0
  998. package/src/maintenance/archive-observations.ts +147 -0
  999. package/src/maintenance/backup-stamp.ts +3 -0
  1000. package/src/maintenance/dreams-ledger.ts +516 -0
  1001. package/src/maintenance/first-start-migration.ts +362 -0
  1002. package/src/maintenance/forget.test.ts +206 -0
  1003. package/src/maintenance/forget.ts +126 -0
  1004. package/src/maintenance/graph-edge-decay.test.ts +409 -0
  1005. package/src/maintenance/graph-edge-decay.ts +394 -0
  1006. package/src/maintenance/memory-governance-cron.ts +447 -0
  1007. package/src/maintenance/memory-governance.ts +1039 -0
  1008. package/src/maintenance/migrate-observations.ts +216 -0
  1009. package/src/maintenance/observation-ledger-utils.ts +54 -0
  1010. package/src/maintenance/pattern-reinforcement.test.ts +875 -0
  1011. package/src/maintenance/pattern-reinforcement.ts +369 -0
  1012. package/src/maintenance/purge.ts +334 -0
  1013. package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +78 -0
  1014. package/src/maintenance/rebuild-memory-projection.ts +1234 -0
  1015. package/src/maintenance/rebuild-observations.ts +178 -0
  1016. package/src/maintenance/tier-stats.test.ts +378 -0
  1017. package/src/maintenance/tier-stats.ts +222 -0
  1018. package/src/mcp-memory-inspector-app.ts +421 -0
  1019. package/src/memory-action-policy.ts +80 -0
  1020. package/src/memory-cache.ts +208 -0
  1021. package/src/memory-extension/claude-code-publisher.ts +51 -0
  1022. package/src/memory-extension/codex-publisher.ts +149 -0
  1023. package/src/memory-extension/hermes-publisher.ts +51 -0
  1024. package/src/memory-extension/index.ts +100 -0
  1025. package/src/memory-extension/shared-instructions.ts +133 -0
  1026. package/src/memory-extension/types.ts +86 -0
  1027. package/src/memory-extension-host/host-discovery.ts +276 -0
  1028. package/src/memory-extension-host/index.ts +14 -0
  1029. package/src/memory-extension-host/render-extensions-block.ts +73 -0
  1030. package/src/memory-extension-host/types.ts +21 -0
  1031. package/src/memory-lifecycle-ledger-utils.ts +116 -0
  1032. package/src/memory-projection-format.ts +11 -0
  1033. package/src/memory-projection-store.ts +951 -0
  1034. package/src/memory-provenance.test.ts +196 -0
  1035. package/src/memory-provenance.ts +484 -0
  1036. package/src/memory-worth-bench.test.ts +71 -0
  1037. package/src/memory-worth-bench.ts +265 -0
  1038. package/src/memory-worth-filter.test.ts +209 -0
  1039. package/src/memory-worth-filter.ts +204 -0
  1040. package/src/memory-worth-frontmatter.test.ts +311 -0
  1041. package/src/memory-worth-outcomes.test.ts +316 -0
  1042. package/src/memory-worth-outcomes.ts +286 -0
  1043. package/src/memory-worth.test.ts +317 -0
  1044. package/src/memory-worth.ts +215 -0
  1045. package/src/message-parts/index.ts +806 -0
  1046. package/src/message-parts/message-parts.test.ts +421 -0
  1047. package/src/migrate/from-engram.ts +789 -0
  1048. package/src/model-registry.ts +313 -0
  1049. package/src/models-json.ts +76 -0
  1050. package/src/namespaces/migrate.ts +187 -0
  1051. package/src/namespaces/path.ts +25 -0
  1052. package/src/namespaces/principal.test.ts +195 -0
  1053. package/src/namespaces/principal.ts +86 -0
  1054. package/src/namespaces/search.test.ts +105 -0
  1055. package/src/namespaces/search.ts +233 -0
  1056. package/src/namespaces/storage.ts +74 -0
  1057. package/src/native-knowledge.ts +1823 -0
  1058. package/src/negative.ts +72 -0
  1059. package/src/network/tailscale.ts +179 -0
  1060. package/src/network/webdav.ts +385 -0
  1061. package/src/objective-state-writers.ts +951 -0
  1062. package/src/objective-state.ts +320 -0
  1063. package/src/onboarding/index.ts +529 -0
  1064. package/src/openai-chat-compat.ts +56 -0
  1065. package/src/operator-toolkit.ts +2132 -0
  1066. package/src/opik-exporter.test.ts +72 -0
  1067. package/src/opik-exporter.ts +587 -0
  1068. package/src/orchestrator-extraction-queue.test.ts +197 -0
  1069. package/src/orchestrator-flush.test.ts +1171 -0
  1070. package/src/orchestrator-pattern-reinforcement.test.ts +128 -0
  1071. package/src/orchestrator-source-attribution.test.ts +701 -0
  1072. package/src/orchestrator.ts +16368 -0
  1073. package/src/page-versioning.ts +450 -0
  1074. package/src/patterns-cli.ts +574 -0
  1075. package/src/peers/index.ts +54 -0
  1076. package/src/peers/migrate-from-identity-anchor.test.ts +291 -0
  1077. package/src/peers/migrate-from-identity-anchor.ts +350 -0
  1078. package/src/peers/peers.test.ts +419 -0
  1079. package/src/peers/profile-reasoner.ts +694 -0
  1080. package/src/peers/storage.ts +1350 -0
  1081. package/src/peers/types.ts +138 -0
  1082. package/src/plugin-id.ts +84 -0
  1083. package/src/policy-runtime.ts +209 -0
  1084. package/src/procedural/procedure-miner.ts +150 -0
  1085. package/src/procedural/procedure-recall.ts +93 -0
  1086. package/src/procedural/procedure-stats.ts +213 -0
  1087. package/src/procedural/procedure-types.ts +132 -0
  1088. package/src/procedural/reinforcement-core.test.ts +132 -0
  1089. package/src/procedural/reinforcement-core.ts +73 -0
  1090. package/src/profiling.test.ts +263 -0
  1091. package/src/profiling.ts +435 -0
  1092. package/src/projection/index.ts +398 -0
  1093. package/src/qmd-recall-cache.test.ts +138 -0
  1094. package/src/qmd-recall-cache.ts +111 -0
  1095. package/src/qmd.test.ts +257 -0
  1096. package/src/qmd.ts +2614 -0
  1097. package/src/reasoning-trace-recall.ts +201 -0
  1098. package/src/reasoning-trace-types.ts +235 -0
  1099. package/src/recall-audit-anomaly.test.ts +246 -0
  1100. package/src/recall-audit-anomaly.ts +297 -0
  1101. package/src/recall-audit.test.ts +51 -0
  1102. package/src/recall-audit.ts +72 -0
  1103. package/src/recall-budget-config.test.ts +87 -0
  1104. package/src/recall-disclosure-escalation.test.ts +196 -0
  1105. package/src/recall-disclosure-escalation.ts +158 -0
  1106. package/src/recall-disclosure-shaping.test.ts +146 -0
  1107. package/src/recall-disclosure.test.ts +214 -0
  1108. package/src/recall-explain-renderer.test.ts +140 -0
  1109. package/src/recall-explain-renderer.ts +356 -0
  1110. package/src/recall-mmr.test.ts +808 -0
  1111. package/src/recall-mmr.ts +607 -0
  1112. package/src/recall-qos.test.ts +85 -0
  1113. package/src/recall-qos.ts +82 -0
  1114. package/src/recall-query-policy.ts +221 -0
  1115. package/src/recall-state.test.ts +233 -0
  1116. package/src/recall-state.ts +456 -0
  1117. package/src/recall-tag-filter.ts +143 -0
  1118. package/src/recall-tokenization.ts +35 -0
  1119. package/src/recall-xray-cli.test.ts +118 -0
  1120. package/src/recall-xray-cli.ts +100 -0
  1121. package/src/recall-xray-disclosure-telemetry.test.ts +183 -0
  1122. package/src/recall-xray-renderer.test.ts +539 -0
  1123. package/src/recall-xray-renderer.ts +487 -0
  1124. package/src/recall-xray.test.ts +503 -0
  1125. package/src/recall-xray.ts +621 -0
  1126. package/src/reconstruct.ts +41 -0
  1127. package/src/release-changelog.ts +35 -0
  1128. package/src/relevance.ts +67 -0
  1129. package/src/replay/normalizers/chatgpt.ts +133 -0
  1130. package/src/replay/normalizers/claude.ts +102 -0
  1131. package/src/replay/normalizers/openclaw.ts +119 -0
  1132. package/src/replay/normalizers/shared.ts +69 -0
  1133. package/src/replay/runner.ts +197 -0
  1134. package/src/replay/types.ts +143 -0
  1135. package/src/rerank.test.ts +48 -0
  1136. package/src/rerank.ts +176 -0
  1137. package/src/resolve-auth-token.test.ts +226 -0
  1138. package/src/resolve-auth-token.ts +151 -0
  1139. package/src/resolve-provider-secret.test.ts +187 -0
  1140. package/src/resolve-provider-secret.ts +410 -0
  1141. package/src/response-guidance-recall.test.ts +3952 -0
  1142. package/src/response-guidance-recall.ts +4431 -0
  1143. package/src/resume-bundles.ts +415 -0
  1144. package/src/retrieval-agents.ts +623 -0
  1145. package/src/retrieval-tiers.ts +25 -0
  1146. package/src/retrieval.ts +104 -0
  1147. package/src/review/index.test.ts +201 -0
  1148. package/src/review/index.ts +536 -0
  1149. package/src/routing/engine.ts +162 -0
  1150. package/src/routing/store.ts +321 -0
  1151. package/src/runtime/better-sqlite.test.ts +32 -0
  1152. package/src/runtime/better-sqlite.ts +76 -0
  1153. package/src/runtime/child-process.ts +67 -0
  1154. package/src/runtime/env.ts +48 -0
  1155. package/src/sanitize.ts +58 -0
  1156. package/src/schemas.ts +449 -0
  1157. package/src/sdk-compat.ts +87 -0
  1158. package/src/search/document-scanner.ts +96 -0
  1159. package/src/search/embed-helper.ts +142 -0
  1160. package/src/search/factory.ts +189 -0
  1161. package/src/search/index.ts +10 -0
  1162. package/src/search/lancedb-backend.ts +342 -0
  1163. package/src/search/meilisearch-backend.ts +232 -0
  1164. package/src/search/noop-backend.ts +57 -0
  1165. package/src/search/orama-backend.ts +358 -0
  1166. package/src/search/port.ts +86 -0
  1167. package/src/search/remote-backend.ts +124 -0
  1168. package/src/secure-store/cipher.ts +271 -0
  1169. package/src/secure-store/cli-handlers.ts +355 -0
  1170. package/src/secure-store/cli-renderer.ts +131 -0
  1171. package/src/secure-store/header.ts +373 -0
  1172. package/src/secure-store/index.ts +137 -0
  1173. package/src/secure-store/kdf.ts +263 -0
  1174. package/src/secure-store/keyring.ts +106 -0
  1175. package/src/secure-store/metadata.ts +394 -0
  1176. package/src/secure-store/passphrase-reader.ts +252 -0
  1177. package/src/secure-store/secure-fs.ts +571 -0
  1178. package/src/secure-store/secure-store.test.ts +755 -0
  1179. package/src/semantic-chunking.ts +545 -0
  1180. package/src/semantic-consolidation.test.ts +182 -0
  1181. package/src/semantic-consolidation.ts +432 -0
  1182. package/src/semantic-rule-promotion.ts +183 -0
  1183. package/src/semantic-rule-verifier.ts +160 -0
  1184. package/src/session-integrity.ts +569 -0
  1185. package/src/session-observer-bands.ts +11 -0
  1186. package/src/session-observer-state.ts +346 -0
  1187. package/src/session-toggles.test.ts +96 -0
  1188. package/src/session-toggles.ts +159 -0
  1189. package/src/shared-context/manager.ts +810 -0
  1190. package/src/signal.ts +84 -0
  1191. package/src/skills-registry.test.ts +277 -0
  1192. package/src/skills-registry.ts +120 -0
  1193. package/src/source-attribution-roundtrip.test.ts +215 -0
  1194. package/src/source-attribution.test.ts +1425 -0
  1195. package/src/source-attribution.ts +639 -0
  1196. package/src/spaces/index.ts +627 -0
  1197. package/src/storage-paths.ts +117 -0
  1198. package/src/storage.ts +6657 -0
  1199. package/src/store-contract.ts +55 -0
  1200. package/src/summarizer.ts +844 -0
  1201. package/src/summary-snapshot.test.ts +681 -0
  1202. package/src/summary-snapshot.ts +238 -0
  1203. package/src/surfaces/dreams.test.ts +394 -0
  1204. package/src/surfaces/dreams.ts +346 -0
  1205. package/src/surfaces/heartbeat.test.ts +415 -0
  1206. package/src/surfaces/heartbeat.ts +325 -0
  1207. package/src/sync/index.ts +308 -0
  1208. package/src/targeted-fact-recall.test.ts +1694 -0
  1209. package/src/targeted-fact-recall.ts +2905 -0
  1210. package/src/taxonomy/default-taxonomy.ts +87 -0
  1211. package/src/taxonomy/index.ts +26 -0
  1212. package/src/taxonomy/resolver-doc-generator.ts +57 -0
  1213. package/src/taxonomy/resolver.ts +184 -0
  1214. package/src/taxonomy/taxonomy-loader.ts +186 -0
  1215. package/src/taxonomy/types.ts +48 -0
  1216. package/src/telemetry-transcript.ts +70 -0
  1217. package/src/temporal-index.ts +890 -0
  1218. package/src/temporal-supersession.test.ts +2703 -0
  1219. package/src/temporal-supersession.ts +493 -0
  1220. package/src/temporal-validity.test.ts +448 -0
  1221. package/src/temporal-validity.ts +123 -0
  1222. package/src/threading.ts +395 -0
  1223. package/src/tier-migration.ts +124 -0
  1224. package/src/tier-routing.ts +102 -0
  1225. package/src/tmt.ts +462 -0
  1226. package/src/tokens.test.ts +178 -0
  1227. package/src/tokens.ts +279 -0
  1228. package/src/topics.ts +147 -0
  1229. package/src/training-export/cli-date-validation.test.ts +258 -0
  1230. package/src/training-export/converter.test.ts +452 -0
  1231. package/src/training-export/converter.ts +319 -0
  1232. package/src/training-export/date-parse.ts +117 -0
  1233. package/src/training-export/index.ts +26 -0
  1234. package/src/training-export/registry.test.ts +85 -0
  1235. package/src/training-export/registry.ts +57 -0
  1236. package/src/training-export/types.ts +31 -0
  1237. package/src/transcript.ts +1179 -0
  1238. package/src/transfer/autodetect.ts +30 -0
  1239. package/src/transfer/backup.ts +138 -0
  1240. package/src/transfer/capsule-crypto.ts +485 -0
  1241. package/src/transfer/capsule-encrypt.test.ts +690 -0
  1242. package/src/transfer/capsule-export.ts +543 -0
  1243. package/src/transfer/capsule-fork.ts +375 -0
  1244. package/src/transfer/capsule-import.ts +564 -0
  1245. package/src/transfer/capsule-merge.ts +433 -0
  1246. package/src/transfer/conflict-policy.ts +16 -0
  1247. package/src/transfer/constants.ts +13 -0
  1248. package/src/transfer/exclusions.ts +37 -0
  1249. package/src/transfer/export-json.ts +65 -0
  1250. package/src/transfer/export-md.ts +59 -0
  1251. package/src/transfer/export-sqlite.ts +52 -0
  1252. package/src/transfer/fs-utils.ts +269 -0
  1253. package/src/transfer/import-json.ts +108 -0
  1254. package/src/transfer/import-md.ts +84 -0
  1255. package/src/transfer/import-sqlite.ts +100 -0
  1256. package/src/transfer/integrity.ts +71 -0
  1257. package/src/transfer/sqlite-schema.ts +16 -0
  1258. package/src/transfer/types.ts +297 -0
  1259. package/src/trust-zones.ts +1186 -0
  1260. package/src/types.ts +3074 -0
  1261. package/src/user-model.test.ts +124 -0
  1262. package/src/user-model.ts +162 -0
  1263. package/src/utility-learner.ts +353 -0
  1264. package/src/utility-runtime.ts +88 -0
  1265. package/src/utility-telemetry.ts +215 -0
  1266. package/src/utils/category-dir.ts +44 -0
  1267. package/src/utils/errno.ts +6 -0
  1268. package/src/utils/iso-timestamp.test.ts +37 -0
  1269. package/src/utils/iso-timestamp.ts +164 -0
  1270. package/src/utils/path.ts +26 -0
  1271. package/src/verified-recall.ts +138 -0
  1272. package/src/version-utils.test.ts +10 -0
  1273. package/src/version-utils.ts +9 -0
  1274. package/src/whitespace.ts +10 -0
  1275. package/src/work/board.ts +359 -0
  1276. package/src/work/boundary.ts +107 -0
  1277. package/src/work/storage.ts +436 -0
  1278. package/src/work/types.ts +82 -0
  1279. package/src/work-product-ledger.ts +265 -0
  1280. package/dist/access-service-BkXt3di1.d.ts +0 -2039
  1281. package/dist/capsule-crypto-SJS5VVAP.js +0 -18
  1282. package/dist/capsule-export-LLEVB2RG.js +0 -17
  1283. package/dist/capsule-import-UW45R2MZ.js +0 -16
  1284. package/dist/capsule-merge-DI7PNQ2H.js +0 -189
  1285. package/dist/chunk-2LGMW3DJ.js +0 -111
  1286. package/dist/chunk-2YMTO4ZJ.js +0 -265
  1287. package/dist/chunk-2YMTO4ZJ.js.map +0 -1
  1288. package/dist/chunk-363MWCD3.js +0 -9683
  1289. package/dist/chunk-363MWCD3.js.map +0 -1
  1290. package/dist/chunk-36CTNQY7.js +0 -1554
  1291. package/dist/chunk-36CTNQY7.js.map +0 -1
  1292. package/dist/chunk-457A4P3L.js +0 -119
  1293. package/dist/chunk-457A4P3L.js.map +0 -1
  1294. package/dist/chunk-4DXC6HQQ.js +0 -1837
  1295. package/dist/chunk-4DXC6HQQ.js.map +0 -1
  1296. package/dist/chunk-4IS4SXIQ.js +0 -2040
  1297. package/dist/chunk-57QNCUEZ.js +0 -1914
  1298. package/dist/chunk-57QNCUEZ.js.map +0 -1
  1299. package/dist/chunk-6AUUAZEX.js +0 -150
  1300. package/dist/chunk-6AUUAZEX.js.map +0 -1
  1301. package/dist/chunk-6TBWYBJ3.js +0 -236
  1302. package/dist/chunk-6XA7UN4Z.js +0 -135
  1303. package/dist/chunk-6Z6UH6TK.js +0 -2129
  1304. package/dist/chunk-6Z6UH6TK.js.map +0 -1
  1305. package/dist/chunk-74EMIVE4.js +0 -329
  1306. package/dist/chunk-74EMIVE4.js.map +0 -1
  1307. package/dist/chunk-74WWN7ZW.js +0 -82
  1308. package/dist/chunk-74WWN7ZW.js.map +0 -1
  1309. package/dist/chunk-767ODGE6.js +0 -183
  1310. package/dist/chunk-A4ACKWIW.js +0 -289
  1311. package/dist/chunk-A4ACKWIW.js.map +0 -1
  1312. package/dist/chunk-ASAITVLA.js +0 -64
  1313. package/dist/chunk-ASAITVLA.js.map +0 -1
  1314. package/dist/chunk-C5HUWVH2.js +0 -891
  1315. package/dist/chunk-C5HUWVH2.js.map +0 -1
  1316. package/dist/chunk-D54LZC5L.js +0 -147
  1317. package/dist/chunk-DF3RVK3X.js +0 -119
  1318. package/dist/chunk-DF3RVK3X.js.map +0 -1
  1319. package/dist/chunk-E6K4NIEU.js +0 -747
  1320. package/dist/chunk-E6K4NIEU.js.map +0 -1
  1321. package/dist/chunk-EEQLFRUM.js +0 -89
  1322. package/dist/chunk-EQINRHYR.js +0 -672
  1323. package/dist/chunk-EQINRHYR.js.map +0 -1
  1324. package/dist/chunk-ETOW6ACV.js +0 -158
  1325. package/dist/chunk-ETOW6ACV.js.map +0 -1
  1326. package/dist/chunk-EYNQTST2.js +0 -721
  1327. package/dist/chunk-FYIYMQ5N.js +0 -221
  1328. package/dist/chunk-FYIYMQ5N.js.map +0 -1
  1329. package/dist/chunk-G2WADRQ3.js +0 -219
  1330. package/dist/chunk-G4SK7DSQ.js +0 -121
  1331. package/dist/chunk-GGD5W7TB.js +0 -105
  1332. package/dist/chunk-GGD5W7TB.js.map +0 -1
  1333. package/dist/chunk-GVPWB7EY.js +0 -390
  1334. package/dist/chunk-GVPWB7EY.js.map +0 -1
  1335. package/dist/chunk-HJYHRE4S.js +0 -647
  1336. package/dist/chunk-I6BQZSML.js +0 -1451
  1337. package/dist/chunk-I6BQZSML.js.map +0 -1
  1338. package/dist/chunk-IBX3VFOM.js +0 -446
  1339. package/dist/chunk-IBX3VFOM.js.map +0 -1
  1340. package/dist/chunk-IXEJRKCZ.js +0 -18
  1341. package/dist/chunk-JBMSGZEQ.js +0 -441
  1342. package/dist/chunk-JBMSGZEQ.js.map +0 -1
  1343. package/dist/chunk-JRNQ3RNA.js +0 -284
  1344. package/dist/chunk-JRNQ3RNA.js.map +0 -1
  1345. package/dist/chunk-K6WK37A6.js +0 -865
  1346. package/dist/chunk-K6WK37A6.js.map +0 -1
  1347. package/dist/chunk-KBYWQWSB.js +0 -271
  1348. package/dist/chunk-KUHRUM6B.js +0 -14397
  1349. package/dist/chunk-KUHRUM6B.js.map +0 -1
  1350. package/dist/chunk-KWBPHZUU.js +0 -83
  1351. package/dist/chunk-KWBPHZUU.js.map +0 -1
  1352. package/dist/chunk-LIO5X3CM.js +0 -596
  1353. package/dist/chunk-MARWOCVP.js +0 -48
  1354. package/dist/chunk-MCC6KDQF.js +0 -5095
  1355. package/dist/chunk-MCC6KDQF.js.map +0 -1
  1356. package/dist/chunk-N5AKDXAI.js +0 -74
  1357. package/dist/chunk-NN3LPQ5D.js +0 -936
  1358. package/dist/chunk-NN3LPQ5D.js.map +0 -1
  1359. package/dist/chunk-O4XJUPSF.js +0 -533
  1360. package/dist/chunk-O4XJUPSF.js.map +0 -1
  1361. package/dist/chunk-OA3L7BFR.js +0 -183
  1362. package/dist/chunk-OA3L7BFR.js.map +0 -1
  1363. package/dist/chunk-OR64ZGRZ.js +0 -23
  1364. package/dist/chunk-P73JTV34.js +0 -275
  1365. package/dist/chunk-P73JTV34.js.map +0 -1
  1366. package/dist/chunk-P77UEOU2.js +0 -1521
  1367. package/dist/chunk-P77UEOU2.js.map +0 -1
  1368. package/dist/chunk-PB5KW5PL.js +0 -118
  1369. package/dist/chunk-PHNGXFQ6.js +0 -623
  1370. package/dist/chunk-PHNGXFQ6.js.map +0 -1
  1371. package/dist/chunk-QIGOEM65.js +0 -228
  1372. package/dist/chunk-RXTFCYQF.js +0 -108
  1373. package/dist/chunk-S2JJBLJG.js +0 -2101
  1374. package/dist/chunk-S2JJBLJG.js.map +0 -1
  1375. package/dist/chunk-S3IP6R6K.js +0 -219
  1376. package/dist/chunk-S3IP6R6K.js.map +0 -1
  1377. package/dist/chunk-SRBJUAMP.js +0 -403
  1378. package/dist/chunk-SRBJUAMP.js.map +0 -1
  1379. package/dist/chunk-URB2WSKZ.js +0 -350
  1380. package/dist/chunk-URB2WSKZ.js.map +0 -1
  1381. package/dist/chunk-VQXK37XA.js +0 -26
  1382. package/dist/chunk-VQXK37XA.js.map +0 -1
  1383. package/dist/chunk-VTU2B4VF.js +0 -146
  1384. package/dist/chunk-VTU2B4VF.js.map +0 -1
  1385. package/dist/chunk-VX2IUQFE.js +0 -613
  1386. package/dist/chunk-VX2IUQFE.js.map +0 -1
  1387. package/dist/chunk-WGK4VHGP.js +0 -4292
  1388. package/dist/chunk-WGK4VHGP.js.map +0 -1
  1389. package/dist/chunk-WTFWLUSX.js +0 -827
  1390. package/dist/chunk-WTFWLUSX.js.map +0 -1
  1391. package/dist/chunk-XJKFSSDW.js +0 -726
  1392. package/dist/chunk-XJKFSSDW.js.map +0 -1
  1393. package/dist/chunk-XMHBH5H6.js +0 -283
  1394. package/dist/chunk-XMHBH5H6.js.map +0 -1
  1395. package/dist/chunk-XMVFHBHT.js +0 -277
  1396. package/dist/chunk-Y5KDIOKF.js +0 -2403
  1397. package/dist/chunk-Y5KDIOKF.js.map +0 -1
  1398. package/dist/chunk-YNB73F22.js +0 -137
  1399. package/dist/chunk-YNB73F22.js.map +0 -1
  1400. package/dist/chunk-Z2E7VW55.js +0 -335
  1401. package/dist/chunk-Z2E7VW55.js.map +0 -1
  1402. package/dist/chunk-Z5S5HNGY.js +0 -2280
  1403. package/dist/chunk-Z5S5HNGY.js.map +0 -1
  1404. package/dist/chunk-ZL4S7ARC.js +0 -53
  1405. package/dist/chunk-ZTSE2ZJ6.js +0 -190
  1406. package/dist/chunk-ZTSE2ZJ6.js.map +0 -1
  1407. package/dist/cli-Cvy2SNhF.d.ts +0 -1259
  1408. package/dist/codex-materialize-CQlLTzke.d.ts +0 -139
  1409. package/dist/connectors-cli-DFGtY2DB.d.ts +0 -257
  1410. package/dist/contradiction-review-5LTTVDQV.js +0 -22
  1411. package/dist/contradiction-scan-3Z6YW7YA.js +0 -413
  1412. package/dist/contradiction-scan-3Z6YW7YA.js.map +0 -1
  1413. package/dist/engine-FOC3IJLA.js +0 -28
  1414. package/dist/fs-utils-IRVUFB6G.js +0 -30
  1415. package/dist/graph-edge-decay-PWB63GRE.js +0 -207
  1416. package/dist/index-1qIcnbG1.d.ts +0 -34
  1417. package/dist/memory-governance-F3QOJGEY.js +0 -37
  1418. package/dist/memory-projection-store-CY8TU40w.d.ts +0 -222
  1419. package/dist/orchestrator-AOQMo7QI.d.ts +0 -1784
  1420. package/dist/path-RMTY5Y5A.js +0 -9
  1421. package/dist/port-B6VEDIkC.d.ts +0 -53
  1422. package/dist/resolution-YGIBORXI.js +0 -101
  1423. package/dist/resolution-YGIBORXI.js.map +0 -1
  1424. package/dist/secure-store-4R2GSO7S.js +0 -156
  1425. package/dist/semantic-consolidation-ByBXb-sf.d.ts +0 -180
  1426. package/dist/state-store-3EH7HYIN.js +0 -16
  1427. package/dist/types-V3FJ26TF.js +0 -30
  1428. /package/dist/{capsule-crypto-SJS5VVAP.js.map → action-confidence.js.map} +0 -0
  1429. /package/dist/{capsule-export-LLEVB2RG.js.map → adapters/claude-code.js.map} +0 -0
  1430. /package/dist/{capsule-import-UW45R2MZ.js.map → adapters/codex.js.map} +0 -0
  1431. /package/dist/{contradiction-review-5LTTVDQV.js.map → adapters/hermes.js.map} +0 -0
  1432. /package/dist/{engine-FOC3IJLA.js.map → adapters/index.js.map} +0 -0
  1433. /package/dist/{fs-utils-IRVUFB6G.js.map → adapters/registry.js.map} +0 -0
  1434. /package/dist/{memory-governance-F3QOJGEY.js.map → adapters/replit.js.map} +0 -0
  1435. /package/dist/{path-RMTY5Y5A.js.map → adapters/types.js.map} +0 -0
  1436. /package/dist/{secure-store-4R2GSO7S.js.map → capsule-crypto-5CYAGVC5.js.map} +0 -0
  1437. /package/dist/{capsule-merge-DI7PNQ2H.js.map → capsule-merge-4MGKE7C5.js.map} +0 -0
  1438. /package/dist/{chunk-G4SK7DSQ.js.map → chunk-2WWLHTZY.js.map} +0 -0
  1439. /package/dist/{chunk-KBYWQWSB.js.map → chunk-4CRG46BG.js.map} +0 -0
  1440. /package/dist/{chunk-LIO5X3CM.js.map → chunk-7IASACLB.js.map} +0 -0
  1441. /package/dist/{chunk-EYNQTST2.js.map → chunk-EFJ3MQ4V.js.map} +0 -0
  1442. /package/dist/{chunk-D54LZC5L.js.map → chunk-FDU6HUUL.js.map} +0 -0
  1443. /package/dist/{chunk-QIGOEM65.js.map → chunk-GGKRUQOO.js.map} +0 -0
  1444. /package/dist/{chunk-HJYHRE4S.js.map → chunk-GL6I6MEQ.js.map} +0 -0
  1445. /package/dist/{state-store-3EH7HYIN.js.map → chunk-HHLLAQGZ.js.map} +0 -0
  1446. /package/dist/{chunk-4IS4SXIQ.js.map → chunk-HXXBL2KD.js.map} +0 -0
  1447. /package/dist/{chunk-767ODGE6.js.map → chunk-KNKUID7G.js.map} +0 -0
  1448. /package/dist/{chunk-6TBWYBJ3.js.map → chunk-LPMVBPA3.js.map} +0 -0
  1449. /package/dist/{chunk-PB5KW5PL.js.map → chunk-MC26UJIM.js.map} +0 -0
  1450. /package/dist/{chunk-ZL4S7ARC.js.map → chunk-MT4HVDUZ.js.map} +0 -0
  1451. /package/dist/{chunk-G2WADRQ3.js.map → chunk-MY6TPVXW.js.map} +0 -0
  1452. /package/dist/{chunk-OR64ZGRZ.js.map → chunk-NNVTUXEB.js.map} +0 -0
  1453. /package/dist/{chunk-RXTFCYQF.js.map → chunk-P4NEIHUT.js.map} +0 -0
  1454. /package/dist/{chunk-IXEJRKCZ.js.map → chunk-QRNI5JBH.js.map} +0 -0
  1455. /package/dist/{chunk-EEQLFRUM.js.map → chunk-RRF5UOBJ.js.map} +0 -0
  1456. /package/dist/{types-V3FJ26TF.js.map → chunk-SEDEKFYQ.js.map} +0 -0
  1457. /package/dist/{chunk-2LGMW3DJ.js.map → chunk-U3PN77QT.js.map} +0 -0
  1458. /package/dist/{chunk-XMVFHBHT.js.map → chunk-U3WSW6PZ.js.map} +0 -0
  1459. /package/dist/{chunk-N5AKDXAI.js.map → chunk-UWVJF25J.js.map} +0 -0
  1460. /package/dist/{chunk-MARWOCVP.js.map → chunk-XIG5PDM7.js.map} +0 -0
  1461. /package/dist/{chunk-6XA7UN4Z.js.map → chunk-XVZ7B3HG.js.map} +0 -0
  1462. /package/dist/{graph-edge-decay-PWB63GRE.js.map → graph-edge-decay-5DI5GUNL.js.map} +0 -0
@@ -0,0 +1,1382 @@
1
+ /**
2
+ * Daily Context Briefing (Issue #370)
3
+ *
4
+ * Produces a focused "here is what matters right now" briefing by
5
+ * cross-referencing active entities, recent facts, open commitments,
6
+ * LLM-generated follow-ups, and an optional calendar source.
7
+ *
8
+ * The module exposes:
9
+ * - `parseBriefingWindow(token)` — CLI-friendly window parser.
10
+ * - `buildBriefing(options)` — core builder that returns markdown + JSON.
11
+ * - `FileCalendarSource` — stub CalendarSource implementation that reads
12
+ * a local ICS or JSON file.
13
+ *
14
+ * ALL OpenAI usage in this module goes through the Responses API. Chat
15
+ * Completions is never used.
16
+ */
17
+
18
+ import { readFile } from "node:fs/promises";
19
+ import os from "node:os";
20
+ import path from "node:path";
21
+ import { log } from "./logger.js";
22
+ import { normalizeEntityName, StorageManager } from "./storage.js";
23
+ import { readEnvVar, resolveHomeDir } from "./runtime/env.js";
24
+ import type {
25
+ BriefingActiveThread,
26
+ BriefingCalendarSourceError,
27
+ BriefingFocus,
28
+ BriefingFollowup,
29
+ BriefingOpenCommitment,
30
+ BriefingRecentEntity,
31
+ BriefingResult,
32
+ BriefingSections,
33
+ CalendarEvent,
34
+ CalendarSource,
35
+ EntityFile,
36
+ MemoryFile,
37
+ } from "./types.js";
38
+
39
+ // ──────────────────────────────────────────────────────────────────────────
40
+ // Window parsing
41
+ // ──────────────────────────────────────────────────────────────────────────
42
+
43
+ /** Allowed values for the briefing format flag/field. */
44
+ export const BRIEFING_FORMAT_ALLOWED = ["markdown", "json"] as const;
45
+
46
+ /**
47
+ * Default model used for the Responses API follow-up generation call.
48
+ * Mirrors the extraction engine default in config.ts — keep in sync.
49
+ */
50
+ export const BRIEFING_FOLLOWUP_DEFAULT_MODEL = "gpt-5.5";
51
+ export type BriefingFormatValue = typeof BRIEFING_FORMAT_ALLOWED[number];
52
+
53
+ /**
54
+ * Validate a user-supplied `--format` flag value.
55
+ * Returns `null` when the value is valid (or `undefined`, meaning the flag
56
+ * was not supplied and the caller should fall back to the configured default).
57
+ * Returns an error message string when the value is explicitly invalid.
58
+ */
59
+ export function validateBriefingFormat(value: string | undefined): string | null {
60
+ if (value === undefined) return null;
61
+ if ((BRIEFING_FORMAT_ALLOWED as readonly string[]).includes(value)) return null;
62
+ return `Invalid --format value: "${value}". Accepted: ${BRIEFING_FORMAT_ALLOWED.join(", ")}.`;
63
+ }
64
+
65
+ /** Parsed briefing lookback window. */
66
+ export interface ParsedBriefingWindow {
67
+ /** Start of the window (inclusive). */
68
+ from: Date;
69
+ /** End of the window (exclusive). */
70
+ to: Date;
71
+ /** Human-readable label. */
72
+ label: string;
73
+ }
74
+
75
+ const DAY_MS = 24 * 60 * 60 * 1000;
76
+
77
+ /**
78
+ * Maximum allowed lookback offset in milliseconds (100 years).
79
+ * Anything beyond this is almost certainly a typo or abuse — and would
80
+ * overflow to `Invalid Date` for sufficiently large values anyway.
81
+ */
82
+ const MAX_WINDOW_MS = 100 * 365 * DAY_MS;
83
+
84
+ /**
85
+ * Parse a CLI-friendly window token into a concrete date range.
86
+ *
87
+ * Accepted forms (case-insensitive):
88
+ * - `yesterday` — the previous UTC calendar day.
89
+ * - `today` — the current UTC calendar day so far.
90
+ * - `NNh` — last N hours (e.g. `24h`, `48h`).
91
+ * - `NNd` — last N calendar days (e.g. `3d`, `7d`).
92
+ * - `NNw` — last N weeks (e.g. `1w`, `2w`).
93
+ *
94
+ * Returns `null` for invalid tokens so callers can surface a clean error.
95
+ */
96
+ export function parseBriefingWindow(
97
+ token: string,
98
+ now: Date = new Date(),
99
+ ): ParsedBriefingWindow | null {
100
+ const raw = typeof token === "string" ? token.trim().toLowerCase() : "";
101
+ if (raw.length === 0) return null;
102
+
103
+ if (raw === "yesterday") {
104
+ const startOfToday = startOfUtcDay(now);
105
+ const from = new Date(startOfToday.getTime() - DAY_MS);
106
+ return { from, to: startOfToday, label: "yesterday" };
107
+ }
108
+
109
+ if (raw === "today") {
110
+ return { from: startOfUtcDay(now), to: now, label: "today" };
111
+ }
112
+
113
+ const match = raw.match(/^(\d+)\s*(h|d|w)$/);
114
+ if (!match) return null;
115
+ const value = parseInt(match[1], 10);
116
+ if (!Number.isFinite(value) || value <= 0) return null;
117
+ const unit = match[2];
118
+ let ms = 0;
119
+ if (unit === "h") ms = value * 60 * 60 * 1000;
120
+ else if (unit === "d") ms = value * DAY_MS;
121
+ else if (unit === "w") ms = value * 7 * DAY_MS;
122
+ if (ms === 0) return null;
123
+ // Reject values that exceed the 100-year cap or would overflow to Invalid Date.
124
+ if (ms > MAX_WINDOW_MS || !Number.isFinite(ms)) return null;
125
+ const from = new Date(now.getTime() - ms);
126
+ if (!Number.isFinite(from.getTime())) return null;
127
+ return {
128
+ from,
129
+ to: now,
130
+ label: `last ${value}${unit}`,
131
+ };
132
+ }
133
+
134
+ function startOfUtcDay(date: Date): Date {
135
+ const d = new Date(date.getTime());
136
+ d.setUTCHours(0, 0, 0, 0);
137
+ return d;
138
+ }
139
+
140
+ // ──────────────────────────────────────────────────────────────────────────
141
+ // Focus filter
142
+ // ──────────────────────────────────────────────────────────────────────────
143
+
144
+ /**
145
+ * Parse a CLI `--focus` string into a structured focus filter.
146
+ *
147
+ * Accepted forms:
148
+ * - `person:Jane Doe`
149
+ * - `project:remnic-core`
150
+ * - `topic:retrieval`
151
+ *
152
+ * If no prefix is supplied, falls back to `topic:<value>`.
153
+ */
154
+ export function parseBriefingFocus(token: string | undefined): BriefingFocus | null {
155
+ if (typeof token !== "string") return null;
156
+ const trimmed = token.trim();
157
+ if (trimmed.length === 0) return null;
158
+ const [maybeType, ...rest] = trimmed.split(":");
159
+ if (rest.length === 0) {
160
+ return { type: "topic", value: maybeType };
161
+ }
162
+ const rawType = maybeType.toLowerCase();
163
+ if (rawType === "person" || rawType === "project" || rawType === "topic") {
164
+ const value = rest.join(":").trim();
165
+ if (value.length === 0) return null;
166
+ return { type: rawType, value };
167
+ }
168
+ return { type: "topic", value: trimmed };
169
+ }
170
+
171
+ /**
172
+ * Decide whether a memory/entity matches the given focus filter.
173
+ * Purely deterministic — no LLM, case-insensitive substring match across
174
+ * the most useful surfaces.
175
+ *
176
+ * For typed focus (`person:`, `project:`, `entity:`) we attribute via the
177
+ * canonical-id path below to avoid the substring leak fixed in #682 PR 2/3
178
+ * R-10 (`Alice-Test` substring-hitting `person-alice-test-a1`).
179
+ *
180
+ * For untyped (`topic`) focus there is no type to canonicalize against, so
181
+ * we keep `entityRef` in the raw haystack — otherwise memories that link to
182
+ * an entity only via `frontmatter.entityRef` (no body / tag mention) would
183
+ * silently drop out of an untyped focus filter (codex P2 review on #695).
184
+ */
185
+ export function focusMatchesMemory(memory: MemoryFile, focus: BriefingFocus): boolean {
186
+ const needle = focus.value.toLowerCase();
187
+ const entityRef = (memory.frontmatter.entityRef ?? "").toLowerCase();
188
+
189
+ // Raw substring match across content and tags. For untyped (`topic`)
190
+ // focus, also include the entityRef so memories linked only via the
191
+ // frontmatter ref still match. For typed focus we deliberately
192
+ // exclude entityRef here and route through the canonical-id path
193
+ // below (see comment above).
194
+ const rawHaystackParts = [
195
+ memory.content,
196
+ ...(memory.frontmatter.tags ?? []),
197
+ ];
198
+ if (focus.type === "topic" && entityRef) {
199
+ rawHaystackParts.push(entityRef);
200
+ }
201
+ const rawHaystack = rawHaystackParts.join(" ").toLowerCase();
202
+ if (rawHaystack.includes(needle)) return true;
203
+
204
+ // Canonical-id match (#682 PR 2/3 R-10). Normalize BOTH sides through
205
+ // `normalizeEntityName` so:
206
+ // - `entityRef === slug` exact comparison no longer fails when the
207
+ // stored ref is in a non-canonical form (e.g. `person:Alice-Test`
208
+ // vs. `person-alice-test`) — both normalize to the same canonical id.
209
+ // - `entityRef.includes(slug)` substring matching is replaced by
210
+ // equality, so similarly-prefixed entities like
211
+ // `person-alice-test-a1` no longer match a focus on
212
+ // `person:Alice-Test`.
213
+ // This also handles the type-prefix-in-name case the cursor reviewer
214
+ // flagged: `normalizeEntityName` strips a duplicate type prefix so
215
+ // `Project-Alpha` of type `project` canonicalizes to `project-alpha`,
216
+ // and a focus on `project:Project-Alpha` does the same.
217
+ if (!entityRef) return false;
218
+ const focusCanonical = normalizeEntityName(focus.value, focus.type);
219
+ // Strip a leading `<type><delimiter>` prefix from a non-canonical
220
+ // entityRef before normalizing — `normalizeEntityName` only strips
221
+ // `<type>-` so other valid verbatim formats (`person:Alice-Test`,
222
+ // `person/alice-test`, `person_alice_test`, `person Alice Test`)
223
+ // would otherwise double up the type prefix and miss the canonical
224
+ // comparison. Codex P2 review on #695: memory writes persist
225
+ // entityRef strings as provided, so any non-alphanumeric delimiter
226
+ // after the type token must be tolerated here.
227
+ let refForNormalize = entityRef;
228
+ const typeDelimMatch = refForNormalize.match(
229
+ new RegExp(`^${focus.type}[^a-z0-9]+`, "i"),
230
+ );
231
+ if (typeDelimMatch) {
232
+ refForNormalize = refForNormalize.slice(typeDelimMatch[0].length);
233
+ }
234
+ const refCanonical = normalizeEntityName(refForNormalize, focus.type);
235
+ return refCanonical === focusCanonical;
236
+ }
237
+
238
+ export function focusMatchesEntity(entity: EntityFile, focus: BriefingFocus): boolean {
239
+ const needle = focus.value.toLowerCase();
240
+ if (focus.type === "person" && entity.type.toLowerCase() !== "person") return false;
241
+ if (focus.type === "project" && entity.type.toLowerCase() !== "project") return false;
242
+ const haystack = [
243
+ entity.name,
244
+ entity.synthesis || entity.summary || "",
245
+ ...entity.facts,
246
+ ...(entity.aliases ?? []),
247
+ ...(entity.structuredSections ?? []).flatMap((section) => [section.title, ...section.facts]),
248
+ ]
249
+ .join(" ")
250
+ .toLowerCase();
251
+ return haystack.includes(needle);
252
+ }
253
+
254
+ // ──────────────────────────────────────────────────────────────────────────
255
+ // Calendar source
256
+ // ──────────────────────────────────────────────────────────────────────────
257
+
258
+ /**
259
+ * Stub `CalendarSource` backed by a single local file. Supports:
260
+ * - JSON files containing an array of `CalendarEvent` records, OR a wrapper
261
+ * `{ events: CalendarEvent[] }` object.
262
+ * - Minimal ICS (`.ics`) files — extracts `VEVENT` blocks with `SUMMARY`,
263
+ * `DTSTART`, `DTEND`, `LOCATION`, `DESCRIPTION`, `UID`.
264
+ *
265
+ * Real calendar integrations (Google, iCloud, Microsoft) can plug into the
266
+ * same `CalendarSource` interface later.
267
+ */
268
+ export class FileCalendarSource implements CalendarSource {
269
+ constructor(private readonly filePath: string) {}
270
+
271
+ async eventsForDate(dateIso: string): Promise<CalendarEvent[]> {
272
+ let raw: string;
273
+ try {
274
+ raw = await readFile(this.filePath, "utf-8");
275
+ } catch (err) {
276
+ log.warn(`briefing: calendar source unreadable at ${this.filePath}: ${err}`);
277
+ return [];
278
+ }
279
+
280
+ const events = this.filePath.toLowerCase().endsWith(".ics")
281
+ ? parseIcsEvents(raw)
282
+ : parseJsonEvents(raw);
283
+
284
+ return events.filter((event) => eventFallsOnDate(event, dateIso));
285
+ }
286
+ }
287
+
288
+ function parseJsonEvents(raw: string): CalendarEvent[] {
289
+ try {
290
+ const parsed = JSON.parse(raw) as unknown;
291
+ const arr = Array.isArray(parsed)
292
+ ? parsed
293
+ : parsed && typeof parsed === "object" && Array.isArray((parsed as { events?: unknown }).events)
294
+ ? ((parsed as { events: unknown[] }).events)
295
+ : [];
296
+ const events: CalendarEvent[] = [];
297
+ for (const entry of arr) {
298
+ if (!entry || typeof entry !== "object") continue;
299
+ const e = entry as Record<string, unknown>;
300
+ const id = typeof e.id === "string" ? e.id : typeof e.uid === "string" ? e.uid : cryptoRandomId();
301
+ const title = typeof e.title === "string" ? e.title : typeof e.summary === "string" ? e.summary : "";
302
+ const start = typeof e.start === "string" ? e.start : typeof e.dtstart === "string" ? e.dtstart : "";
303
+ if (!title || !start) continue;
304
+ events.push({
305
+ id,
306
+ title,
307
+ start,
308
+ end: typeof e.end === "string" ? e.end : typeof e.dtend === "string" ? e.dtend : undefined,
309
+ location: typeof e.location === "string" ? e.location : undefined,
310
+ notes: typeof e.notes === "string" ? e.notes : typeof e.description === "string" ? e.description : undefined,
311
+ });
312
+ }
313
+ return events;
314
+ } catch (err) {
315
+ log.warn(`briefing: calendar JSON parse failed: ${err}`);
316
+ return [];
317
+ }
318
+ }
319
+
320
+ interface IcsParsedLine {
321
+ property: string;
322
+ params: Record<string, string>;
323
+ value: string;
324
+ }
325
+
326
+ /**
327
+ * Parse a single ICS content line into its property, parameters, and value.
328
+ * Returns null if the line is not a well-formed property line.
329
+ *
330
+ * Example:
331
+ * `DTSTART;TZID=America/New_York:20260411T233000`
332
+ * → { property: "DTSTART", params: { TZID: "America/New_York" }, value: "20260411T233000" }
333
+ */
334
+ function parseIcsLine(line: string): IcsParsedLine | null {
335
+ // Find the first `:` outside of any parameter value. Per RFC 5545 parameter
336
+ // values may be quoted, but the minimal-parser use case here only needs to
337
+ // handle unquoted TZID values.
338
+ const colonIdx = line.indexOf(":");
339
+ if (colonIdx <= 0) return null;
340
+ const head = line.slice(0, colonIdx);
341
+ const value = line.slice(colonIdx + 1).trim();
342
+ // Head is of the form `PROPERTY[;PARAM=val[;PARAM=val]]`.
343
+ const headParts = head.split(";");
344
+ const property = headParts[0]!.toUpperCase();
345
+ if (!/^[A-Z0-9-]+$/.test(property)) return null;
346
+ const params: Record<string, string> = {};
347
+ for (let i = 1; i < headParts.length; i++) {
348
+ const segment = headParts[i]!;
349
+ const eqIdx = segment.indexOf("=");
350
+ if (eqIdx <= 0) continue;
351
+ const name = segment.slice(0, eqIdx).toUpperCase();
352
+ let val = segment.slice(eqIdx + 1);
353
+ // Strip surrounding quotes if present (RFC 5545 §3.1).
354
+ if (val.startsWith('"') && val.endsWith('"') && val.length >= 2) {
355
+ val = val.slice(1, -1);
356
+ }
357
+ params[name] = val;
358
+ }
359
+ return { property, params, value };
360
+ }
361
+
362
+ interface IcsDateField {
363
+ raw: string;
364
+ params: Record<string, string>;
365
+ }
366
+
367
+ /** @internal — exported for testing only. */
368
+ export function parseIcsEvents(raw: string): CalendarEvent[] {
369
+ const events: CalendarEvent[] = [];
370
+ // RFC 5545 §3.1 line unfolding: a CRLF (now \n) followed by a single
371
+ // whitespace character (space or tab) is a fold — remove both characters
372
+ // to join the continuation onto the preceding logical line. This MUST
373
+ // happen after normalising CRLF → \n and BEFORE splitting on \n.
374
+ const normalized = raw.replace(/\r\n/g, "\n").replace(/\n[ \t]/g, "");
375
+ const blocks = normalized.split(/BEGIN:VEVENT/i).slice(1);
376
+ for (const block of blocks) {
377
+ const endIdx = block.search(/END:VEVENT/i);
378
+ const body = endIdx === -1 ? block : block.slice(0, endIdx);
379
+ const simpleFields: Record<string, string> = {};
380
+ const dateFields: Record<string, IcsDateField> = {};
381
+ for (const line of body.split("\n")) {
382
+ const parsed = parseIcsLine(line);
383
+ if (!parsed) continue;
384
+ const { property, params, value } = parsed;
385
+ if (property === "DTSTART" || property === "DTEND") {
386
+ if (dateFields[property] === undefined) {
387
+ dateFields[property] = { raw: value, params };
388
+ }
389
+ } else if (simpleFields[property] === undefined) {
390
+ simpleFields[property] = value;
391
+ }
392
+ }
393
+ const title = simpleFields.SUMMARY;
394
+ const dtstart = dateFields.DTSTART;
395
+ if (!title || !dtstart) continue;
396
+ const dtend = dateFields.DTEND;
397
+ events.push({
398
+ id: simpleFields.UID ?? cryptoRandomId(),
399
+ title,
400
+ start: normalizeIcsDate(dtstart.raw, dtstart.params),
401
+ end: dtend ? normalizeIcsDate(dtend.raw, dtend.params) : undefined,
402
+ location: simpleFields.LOCATION,
403
+ notes: simpleFields.DESCRIPTION,
404
+ });
405
+ }
406
+ return events;
407
+ }
408
+
409
+ /**
410
+ * Normalise an ICS date/datetime value (optionally with a `TZID` parameter)
411
+ * into an ISO 8601 string that downstream code can compare unambiguously.
412
+ *
413
+ * Behaviour:
414
+ * - `20260411T150000Z` → `2026-04-11T15:00:00Z`
415
+ * - `20260411` → `2026-04-11T00:00:00Z` (date-only events are day-boundaries)
416
+ * - `20260411T150000` (floating, no Z, no TZID) → `2026-04-11T15:00:00` (floating)
417
+ * - `20260411T233000` with `TZID=America/New_York` → `2026-04-12T03:30:00Z`
418
+ * (applies the zone offset at that wallclock time; DST-aware via Intl)
419
+ * - Unknown TZID falls back to UTC with a logged warning (conservative:
420
+ * the event still appears, but on the UTC date).
421
+ */
422
+ function normalizeIcsDate(value: string, params: Record<string, string> = {}): string {
423
+ // Date-time with explicit Z suffix (UTC).
424
+ if (/^\d{8}T\d{6}Z$/.test(value)) {
425
+ const y = value.slice(0, 4);
426
+ const m = value.slice(4, 6);
427
+ const d = value.slice(6, 8);
428
+ const hh = value.slice(9, 11);
429
+ const mm = value.slice(11, 13);
430
+ const ss = value.slice(13, 15);
431
+ return `${y}-${m}-${d}T${hh}:${mm}:${ss}Z`;
432
+ }
433
+ // Date-time without Z: may be floating or zoned via TZID.
434
+ if (/^\d{8}T\d{6}$/.test(value)) {
435
+ const y = value.slice(0, 4);
436
+ const m = value.slice(4, 6);
437
+ const d = value.slice(6, 8);
438
+ const hh = value.slice(9, 11);
439
+ const mm = value.slice(11, 13);
440
+ const ss = value.slice(13, 15);
441
+ const local = `${y}-${m}-${d}T${hh}:${mm}:${ss}`;
442
+ const tzid = params.TZID;
443
+ if (tzid) {
444
+ const utcIso = icsWallclockToUtc(local, tzid);
445
+ if (utcIso) return utcIso;
446
+ log.warn(
447
+ `briefing: unsupported TZID "${tzid}" — treating as UTC for ${local}`,
448
+ );
449
+ return `${local}Z`;
450
+ }
451
+ // No TZID → floating. Downstream compares the date slice directly.
452
+ return local;
453
+ }
454
+ // Date-only (all-day event). Date-only values carry no TZID per RFC 5545.
455
+ if (/^\d{8}$/.test(value)) {
456
+ return `${value.slice(0, 4)}-${value.slice(4, 6)}-${value.slice(6, 8)}T00:00:00Z`;
457
+ }
458
+ return value;
459
+ }
460
+
461
+ /**
462
+ * Convert a wallclock local datetime in a named IANA timezone to a UTC ISO
463
+ * string. Returns null if the timezone is unsupported by the runtime.
464
+ *
465
+ * Implementation note: this is the standard "invert the formatter" technique.
466
+ * We treat the local wallclock as though it were UTC, ask the runtime what
467
+ * time that instant shows in the target zone, and the delta is the zone's
468
+ * offset at that wallclock moment (DST-aware).
469
+ */
470
+ function icsWallclockToUtc(local: string, tzid: string): string | null {
471
+ const match = local.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})$/);
472
+ if (!match) return null;
473
+ const [, y, mo, d, hh, mm, ss] = match;
474
+ // Treat the wallclock as UTC for the first probe.
475
+ const naiveUtcMs = Date.UTC(
476
+ Number(y),
477
+ Number(mo) - 1,
478
+ Number(d),
479
+ Number(hh),
480
+ Number(mm),
481
+ Number(ss),
482
+ );
483
+ if (!Number.isFinite(naiveUtcMs)) return null;
484
+
485
+ let formatter: Intl.DateTimeFormat;
486
+ try {
487
+ formatter = new Intl.DateTimeFormat("en-US", {
488
+ timeZone: tzid,
489
+ year: "numeric",
490
+ month: "2-digit",
491
+ day: "2-digit",
492
+ hour: "2-digit",
493
+ minute: "2-digit",
494
+ second: "2-digit",
495
+ hour12: false,
496
+ });
497
+ } catch {
498
+ return null;
499
+ }
500
+
501
+ const zonedMs = zonedFormatToMs(formatter, new Date(naiveUtcMs));
502
+ if (zonedMs === null) return null;
503
+ // Offset = naiveUtc − zonedAtNaiveUtc (positive for zones east of UTC).
504
+ const offsetMs = naiveUtcMs - zonedMs;
505
+ // Apply the offset once to land on the real UTC instant.
506
+ const realUtcMs = naiveUtcMs + offsetMs;
507
+ // Second pass: offsets can differ when the wallclock crosses a DST boundary.
508
+ const zonedMs2 = zonedFormatToMs(formatter, new Date(realUtcMs));
509
+ if (zonedMs2 !== null) {
510
+ const offsetMs2 = realUtcMs - zonedMs2;
511
+ if (offsetMs2 !== offsetMs) {
512
+ return new Date(naiveUtcMs + offsetMs2).toISOString();
513
+ }
514
+ }
515
+ return new Date(realUtcMs).toISOString();
516
+ }
517
+
518
+ /**
519
+ * Format a Date in the given timezone and return the absolute ms timestamp
520
+ * of that wallclock time interpreted as if it were UTC. Used only by
521
+ * `icsWallclockToUtc` to compute zone offsets.
522
+ */
523
+ function zonedFormatToMs(formatter: Intl.DateTimeFormat, date: Date): number | null {
524
+ const parts = formatter.formatToParts(date);
525
+ const get = (type: string): string | undefined =>
526
+ parts.find((p) => p.type === type)?.value;
527
+ const y = get("year");
528
+ const mo = get("month");
529
+ const d = get("day");
530
+ const hh = get("hour");
531
+ const mm = get("minute");
532
+ const ss = get("second");
533
+ if (!y || !mo || !d || !hh || !mm || !ss) return null;
534
+ // RFC 5545 / Intl edge-case: some runtimes return `hour: "24"` for midnight
535
+ // while keeping the same calendar day (instead of returning hour=0 with the
536
+ // next day). Passing 24 straight to Date.UTC would roll the date forward by
537
+ // one day, producing a 24-hour-skewed offset in icsWallclockToUtc and
538
+ // shifting TZID midnight events to the wrong briefing day. Normalise to 0
539
+ // and leave the date component unchanged.
540
+ const normalizedHour = Number(hh) === 24 ? 0 : Number(hh);
541
+ const ms = Date.UTC(Number(y), Number(mo) - 1, Number(d), normalizedHour, Number(mm), Number(ss));
542
+ return Number.isFinite(ms) ? ms : null;
543
+ }
544
+
545
+ /**
546
+ * Returns true when `isoStr` has an explicit UTC or numeric offset suffix
547
+ * (Z, ±HH:MM, or ±HHMM). Floating datetimes produced by `normalizeIcsDate`
548
+ * have no such suffix.
549
+ */
550
+ function isoHasTimezone(isoStr: string): boolean {
551
+ return /(Z|[+-]\d{2}:?\d{2})$/.test(isoStr);
552
+ }
553
+
554
+ /**
555
+ * Parse an ISO datetime string (UTC-aware or floating) to milliseconds since
556
+ * epoch, or `null` if the string is not a valid datetime.
557
+ *
558
+ * - UTC / offset-aware strings are passed directly to `new Date()`.
559
+ * - Floating strings (no timezone suffix) are interpreted as UTC so that
560
+ * interval arithmetic uses the same epoch base as UTC-aware strings.
561
+ * The caller is responsible for using the correct date-boundary constants.
562
+ */
563
+ function isoToMs(isoStr: string): number | null {
564
+ if (!isoStr) return null;
565
+ let src = isoStr;
566
+ if (!isoHasTimezone(src)) {
567
+ // Treat floating time as UTC for interval math (append Z).
568
+ src = src + "Z";
569
+ }
570
+ const ms = new Date(src).getTime();
571
+ return Number.isFinite(ms) ? ms : null;
572
+ }
573
+
574
+ /** @internal — exported for testing only. */
575
+ export function eventFallsOnDate(event: CalendarEvent, dateIso: string): boolean {
576
+ const target = dateIso.slice(0, 10);
577
+ const start = event.start;
578
+
579
+ // Floating ICS datetime (no Z, no offset): `normalizeIcsDate` produces
580
+ // "YYYY-MM-DDTHH:MM:SS" with no timezone. Passing this to `new Date()`
581
+ // causes ECMAScript to parse it as local time, which then round-trips
582
+ // through UTC via `toISOString()` and can shift the calendar date.
583
+ // For floating times we compare date portions directly (no epoch arithmetic).
584
+ const startIsFloating = !isoHasTimezone(start);
585
+
586
+ if (startIsFloating) {
587
+ // Validate the start timestamp with the same rigour applied to end:
588
+ // 1. Shape check — must match the ISO-8601 date or datetime pattern.
589
+ // 2. Real-date check — round-trip through UTC to reject impossible dates
590
+ // like "2026-02-30" that JavaScript silently auto-corrects.
591
+ // 3. Time-component check — reject out-of-range hours/minutes/seconds
592
+ // (e.g. "2026-04-11T25:99:00") that JavaScript rolls over to a
593
+ // different day, which would cause the event to be matched against
594
+ // unrelated calendar dates.
595
+ // If start fails any check we skip the event entirely — there is no usable
596
+ // start date to fall back on.
597
+ const startShapeOk =
598
+ typeof start === "string" &&
599
+ /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?)?$/.test(start);
600
+ if (!startShapeOk) {
601
+ log.debug(`briefing: skipping calendar event with invalid start value: ${JSON.stringify(start)}`);
602
+ return false;
603
+ }
604
+ const startDateStr = start.slice(0, 10);
605
+ const startDateProbe = new Date(startDateStr + "T00:00:00Z");
606
+ if (
607
+ Number.isNaN(startDateProbe.getTime()) ||
608
+ startDateProbe.toISOString().slice(0, 10) !== startDateStr
609
+ ) {
610
+ log.warn(
611
+ `briefing: skipping calendar event "${event.title}" with impossible start date ${JSON.stringify(startDateStr)}`,
612
+ );
613
+ return false;
614
+ }
615
+ const startRawTime = start.indexOf("T") !== -1 ? start.slice(start.indexOf("T") + 1) : "";
616
+ if (startRawTime !== "") {
617
+ const startTimeParts = startRawTime.split(":").map(Number);
618
+ const shh = startTimeParts[0] ?? 0;
619
+ const smm = startTimeParts[1] ?? 0;
620
+ const sss = Math.floor(startTimeParts[2] ?? 0);
621
+ if (shh > 23 || smm > 59 || sss > 59) {
622
+ log.warn(
623
+ `briefing: skipping calendar event "${event.title}" with out-of-range start time ${JSON.stringify(startRawTime)}`,
624
+ );
625
+ return false;
626
+ }
627
+ }
628
+
629
+ const startDate = startDateStr;
630
+ const end = event.end;
631
+
632
+ // Point event (no end) — simple date prefix comparison.
633
+ if (!end) return startDate === target;
634
+
635
+ // Validate that end is a recognisable ISO-8601 date/datetime string before
636
+ // slicing it for lexicographic comparison. A malformed end (e.g. a JSON
637
+ // feed emitting "end": "invalid") would otherwise produce a non-date prefix
638
+ // from `end.slice(0, 10)` and cause the event to appear on unrelated days.
639
+ // Fallback: treat the event as a single-day event starting on startDate.
640
+ const endIsValid =
641
+ typeof end === "string" &&
642
+ /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?)?$/.test(end);
643
+ if (!endIsValid) {
644
+ log.warn(
645
+ `briefing: event "${event.title}" has malformed end timestamp ${JSON.stringify(end)}; treating as single-day event at ${startDate}`,
646
+ );
647
+ // Render the event but only on its start date.
648
+ return startDate === target;
649
+ }
650
+
651
+ // UhLh: Reject impossible calendar dates that pass the regex (e.g. "2026-99-99").
652
+ // The regex only validates the *shape* of the string — it accepts month 99 and
653
+ // day 99. We must additionally verify the date is real by constructing a UTC
654
+ // Date and checking that the ISO round-trip matches the input prefix. If the
655
+ // date is impossible, Date will auto-correct it (e.g. "2026-01-99" becomes some
656
+ // later date), so the round-trip will differ. Fall back to single-day semantics.
657
+ const endDate = end.slice(0, 10);
658
+ const endDateProbe = new Date(endDate + "T00:00:00Z");
659
+ if (
660
+ Number.isNaN(endDateProbe.getTime()) ||
661
+ endDateProbe.toISOString().slice(0, 10) !== endDate
662
+ ) {
663
+ log.warn(
664
+ `briefing: event "${event.title}" has impossible end date ${JSON.stringify(endDate)}; treating as single-day event at ${startDate}`,
665
+ );
666
+ return startDate === target;
667
+ }
668
+
669
+ // Validate the time components of the end timestamp when present.
670
+ // The regex above only checks the shape (e.g. two digits for hour) but does
671
+ // not enforce numeric ranges. A value like "2026-04-11T25:99:99" passes the
672
+ // regex and the date-round-trip check above yet carries an impossible time.
673
+ // JavaScript's Date constructor silently rolls such values over to a later
674
+ // date, which would make the event bleed into unrelated days. Extract the
675
+ // individual time fields and reject anything outside the valid range.
676
+ const rawTime = end.indexOf("T") !== -1 ? end.slice(end.indexOf("T") + 1) : "";
677
+ if (rawTime !== "") {
678
+ const timeParts = rawTime.split(":").map(Number);
679
+ const hh = timeParts[0] ?? 0;
680
+ const mm = timeParts[1] ?? 0;
681
+ // Seconds may carry a fractional component; floor to get the integer part.
682
+ const ss = Math.floor(timeParts[2] ?? 0);
683
+ const timeIsValid = hh <= 23 && mm <= 59 && ss <= 59;
684
+ if (!timeIsValid) {
685
+ log.warn(
686
+ `briefing: event "${event.title}" has out-of-range end time ${JSON.stringify(rawTime)}; treating as single-day event at ${startDate}`,
687
+ );
688
+ return startDate === target;
689
+ }
690
+ }
691
+
692
+ // Span event: include if [start, end) overlaps the target calendar day.
693
+ //
694
+ // We can't use pure YYYY-MM-DD lexicographic comparison because a
695
+ // same-day event (`start=2026-04-11T14:30`, `end=2026-04-11T15:00`)
696
+ // has `startDate === endDate === "2026-04-11"`, and a `target < endDate`
697
+ // check would wrongly exclude it. A cross-day event ending at
698
+ // `2026-04-12T00:00:00` (exact midnight) also needs the end day to be
699
+ // treated as exclusive per half-open `[start, end)` semantics.
700
+ //
701
+ // Decide whether the end day is still active on the end date by looking
702
+ // at the time portion: if the end time is strictly after midnight, the
703
+ // event is still running at the start of the end day and should include
704
+ // it; if the end time is exactly midnight, the event ends precisely at
705
+ // the boundary and the end day is excluded. Within-day spans always
706
+ // have a non-zero end time and so correctly include their own date.
707
+ //
708
+ // UhLg: A date-only end value (no "T" separator) produces an empty
709
+ // endTime string. The regex above does not match empty string, so
710
+ // endAtExactMidnight would be false and the event would incorrectly
711
+ // appear on the end date. Date-only end values carry [start, end)
712
+ // semantics (the end date is exclusive), so we treat them as midnight.
713
+ const endTime = end.slice(11); // "HH:MM", "HH:MM:SS", "HH:MM:SS.mmm", or "" (date-only)
714
+ // Treat any end time that is exactly midnight — or absent (date-only) — as
715
+ // day-exclusive per [start, end) semantics.
716
+ // Cases covered:
717
+ // "" — date-only end (UhLg fix: exclusive like midnight)
718
+ // "00:00" — HH:MM form (valid floating-time ISO value, no seconds)
719
+ // "00:00:00" — HH:MM:SS form
720
+ // "00:00:00.000..." — with fractional seconds (any number of trailing zeros)
721
+ // A bare `>` string comparison incorrectly treats "00:00:00.000" as > "00:00:00"
722
+ // because the fractional suffix makes the string lexicographically longer.
723
+ const endIsDateOnly = endTime === "";
724
+ const endAtExactMidnight = endIsDateOnly || /^00(:00){1,2}(\.0+)?$/.test(endTime);
725
+ const endActiveOnEndDay = !endAtExactMidnight;
726
+ if (endActiveOnEndDay) {
727
+ return startDate <= target && target <= endDate;
728
+ }
729
+ return startDate <= target && target < endDate;
730
+ }
731
+
732
+ // UTC or offset-aware ISO string: parse and normalise to UTC milliseconds,
733
+ // then check whether the event's [start, end) interval overlaps the target
734
+ // UTC day [dayStart, dayEnd).
735
+ const startMs = isoToMs(start);
736
+ if (startMs === null) {
737
+ log.debug(`briefing: skipping calendar event with invalid start value: ${JSON.stringify(start)}`);
738
+ return false;
739
+ }
740
+
741
+ // Boundaries of the target UTC day (half-open: [dayStart, dayEnd)).
742
+ const dayStart = Date.UTC(
743
+ Number(target.slice(0, 4)),
744
+ Number(target.slice(5, 7)) - 1,
745
+ Number(target.slice(8, 10)),
746
+ );
747
+ const dayEnd = dayStart + 86_400_000; // +24 h
748
+
749
+ const end = event.end;
750
+ if (!end) {
751
+ // Point event: included iff start falls within [dayStart, dayEnd).
752
+ return startMs >= dayStart && startMs < dayEnd;
753
+ }
754
+
755
+ const endMs = isoToMs(end);
756
+ if (endMs === null) {
757
+ // Unparseable end — fall back to point-event semantics.
758
+ return startMs >= dayStart && startMs < dayEnd;
759
+ }
760
+
761
+ // Interval event: overlaps day iff start < dayEnd AND end > dayStart.
762
+ // Using strict > for end so that an event ending exactly at midnight
763
+ // (dayEnd of previous day) is NOT counted on the next day.
764
+ return startMs < dayEnd && endMs > dayStart;
765
+ }
766
+
767
+ function cryptoRandomId(): string {
768
+ // Keep dependency-free: Math.random is fine for synthetic fixture IDs.
769
+ return `evt-${Math.random().toString(36).slice(2, 10)}`;
770
+ }
771
+
772
+ // ──────────────────────────────────────────────────────────────────────────
773
+ // buildBriefing
774
+ // ──────────────────────────────────────────────────────────────────────────
775
+
776
+ /** Dependency-injection hook for LLM follow-up generation (used in tests). */
777
+ export type BriefingFollowupGenerator = (
778
+ prompt: {
779
+ sections: BriefingSections;
780
+ windowLabel: string;
781
+ maxFollowups: number;
782
+ },
783
+ ) => Promise<BriefingFollowup[]>;
784
+
785
+ /** Options accepted by `buildBriefing`. */
786
+ export interface BuildBriefingOptions {
787
+ /** Workspace-scoped storage. Tests pass a temp dir. */
788
+ storage: StorageManager;
789
+ /** Parsed window. If omitted, a default 1-day window is used. */
790
+ window?: ParsedBriefingWindow;
791
+ /** Optional focus filter. */
792
+ focus?: BriefingFocus | null;
793
+ /** Optional namespace hint for logging. */
794
+ namespace?: string;
795
+ /** Calendar source. Section omitted entirely when undefined. */
796
+ calendarSource?: CalendarSource;
797
+ /** Maximum LLM follow-ups (0 to disable the section). */
798
+ maxFollowups?: number;
799
+ /** Whether the module is allowed to invoke the Responses API. */
800
+ allowLlm?: boolean;
801
+ /** OpenAI API key. If absent the follow-up section is gracefully omitted. */
802
+ openaiApiKey?: string;
803
+ /** OpenAI-compatible base URL (for Azure or proxied endpoints). */
804
+ openaiBaseUrl?: string;
805
+ /** Model id for the Responses call. */
806
+ model?: string;
807
+ /** Injected follow-up generator. Overrides real LLM call (tests). */
808
+ followupGenerator?: BriefingFollowupGenerator;
809
+ /** Injected "now" — makes tests deterministic. */
810
+ now?: Date;
811
+ }
812
+
813
+ const MAX_ACTIVE_THREADS = 8;
814
+ const MAX_RECENT_ENTITIES = 8;
815
+ const MAX_OPEN_COMMITMENTS = 8;
816
+
817
+ /**
818
+ * Build the daily context briefing.
819
+ *
820
+ * Never throws on LLM failures — the suggested follow-ups section is simply
821
+ * omitted and `followupsUnavailableReason` is set.
822
+ */
823
+ export async function buildBriefing(options: BuildBriefingOptions): Promise<BriefingResult> {
824
+ const now = options.now ?? new Date();
825
+ const window = options.window ?? defaultWindow(now);
826
+ const maxFollowups = clampFollowups(options.maxFollowups);
827
+ const focus = options.focus ?? null;
828
+
829
+ const [allMemories, allEntities] = await Promise.all([
830
+ safeReadMemories(options.storage),
831
+ safeReadEntities(options.storage),
832
+ ]);
833
+
834
+ const memoriesInWindow = filterMemoriesByWindow(allMemories, window);
835
+ const focusedMemories = focus
836
+ ? memoriesInWindow.filter((m) => focusMatchesMemory(m, focus))
837
+ : memoriesInWindow;
838
+
839
+ const activeThreads = buildActiveThreads(focusedMemories);
840
+ const recentEntities = buildRecentEntities(allEntities, window, focus);
841
+ // TODO(#370): openCommitments only covers memories inside the lookback window.
842
+ // Still-open commitments (pending tag, commitment category) that pre-date the
843
+ // window are silently omitted. A separate query over allMemories filtered to
844
+ // open-status entries would surface these. Deferred to avoid scope creep here.
845
+ const openCommitments = buildOpenCommitments(focusedMemories);
846
+
847
+ const calendarLoadResult = options.calendarSource
848
+ ? await loadTodayCalendar(options.calendarSource, now)
849
+ : undefined;
850
+
851
+ const calendarSourceErrors: BriefingCalendarSourceError[] =
852
+ calendarLoadResult?.error ? [calendarLoadResult.error] : [];
853
+
854
+ const sectionsBase: BriefingSections = {
855
+ activeThreads,
856
+ recentEntities,
857
+ openCommitments,
858
+ suggestedFollowups: [],
859
+ todayCalendar: calendarLoadResult?.events,
860
+ };
861
+
862
+ let followups: BriefingFollowup[] = [];
863
+ let followupsUnavailableReason: string | undefined;
864
+
865
+ if (maxFollowups === 0 || options.allowLlm === false) {
866
+ followupsUnavailableReason = "LLM follow-ups disabled by configuration";
867
+ } else if (!options.openaiApiKey && !options.followupGenerator) {
868
+ followupsUnavailableReason = "OPENAI_API_KEY not configured";
869
+ } else {
870
+ try {
871
+ const generator = options.followupGenerator ?? buildOpenAiFollowupGenerator({
872
+ apiKey: options.openaiApiKey!,
873
+ model: options.model ?? BRIEFING_FOLLOWUP_DEFAULT_MODEL,
874
+ baseURL: options.openaiBaseUrl,
875
+ });
876
+ const generated = await generator({
877
+ sections: sectionsBase,
878
+ windowLabel: window.label,
879
+ maxFollowups,
880
+ });
881
+ followups = generated.slice(0, maxFollowups);
882
+ } catch (err) {
883
+ const errMsg = stringifyError(err);
884
+ const modelName = options.model ?? BRIEFING_FOLLOWUP_DEFAULT_MODEL;
885
+ // Detect "model not found / invalid" errors from the Responses API and
886
+ // produce a user-friendly message that surfaces the problematic identifier.
887
+ if (
888
+ /model/i.test(errMsg) &&
889
+ (/not found/i.test(errMsg) || /does not exist/i.test(errMsg) || /invalid/i.test(errMsg))
890
+ ) {
891
+ followupsUnavailableReason =
892
+ `configured follow-up model '${modelName}' is not available in the Responses API`;
893
+ } else {
894
+ followupsUnavailableReason = `LLM follow-ups failed: ${errMsg}`;
895
+ }
896
+ log.warn(`briefing: ${followupsUnavailableReason}`);
897
+ }
898
+ }
899
+
900
+ const sections: BriefingSections = {
901
+ ...sectionsBase,
902
+ suggestedFollowups: followups,
903
+ };
904
+
905
+ const windowIso = { from: window.from.toISOString(), to: window.to.toISOString() };
906
+ const markdown = renderBriefingMarkdown({
907
+ sections,
908
+ windowLabel: window.label,
909
+ focus,
910
+ followupsUnavailableReason,
911
+ generatedAt: now,
912
+ namespace: options.namespace,
913
+ });
914
+
915
+ const json: Record<string, unknown> = {
916
+ generatedAt: now.toISOString(),
917
+ window: windowIso,
918
+ focus,
919
+ namespace: options.namespace ?? null,
920
+ sections,
921
+ followupsUnavailableReason: followupsUnavailableReason ?? null,
922
+ calendarSourceErrors: calendarSourceErrors.length > 0 ? calendarSourceErrors : null,
923
+ };
924
+
925
+ const result: BriefingResult = {
926
+ markdown,
927
+ json,
928
+ sections,
929
+ followupsUnavailableReason,
930
+ window: windowIso,
931
+ };
932
+
933
+ if (calendarSourceErrors.length > 0) {
934
+ result.calendarSourceErrors = calendarSourceErrors;
935
+ }
936
+
937
+ return result;
938
+ }
939
+
940
+ function clampFollowups(value: number | undefined): number {
941
+ if (typeof value !== "number" || !Number.isFinite(value)) return 5;
942
+ return Math.max(0, Math.min(10, Math.floor(value)));
943
+ }
944
+
945
+ function defaultWindow(now: Date): ParsedBriefingWindow {
946
+ const parsed = parseBriefingWindow("yesterday", now);
947
+ if (parsed) return parsed;
948
+ return { from: new Date(now.getTime() - DAY_MS), to: now, label: "yesterday" };
949
+ }
950
+
951
+ async function safeReadMemories(storage: StorageManager): Promise<MemoryFile[]> {
952
+ try {
953
+ return await storage.readAllMemories();
954
+ } catch (err) {
955
+ log.warn(`briefing: readAllMemories failed: ${err}`);
956
+ return [];
957
+ }
958
+ }
959
+
960
+ async function safeReadEntities(storage: StorageManager): Promise<EntityFile[]> {
961
+ try {
962
+ return await storage.readAllEntityFiles();
963
+ } catch (err) {
964
+ log.warn(`briefing: readAllEntityFiles failed: ${err}`);
965
+ return [];
966
+ }
967
+ }
968
+
969
+ function memoryTimestamp(memory: MemoryFile): number {
970
+ const raw = memory.frontmatter.updated || memory.frontmatter.created;
971
+ if (!raw) return 0;
972
+ const t = Date.parse(raw);
973
+ return Number.isFinite(t) ? t : 0;
974
+ }
975
+
976
+ /** @internal — exported for testing only. */
977
+ export function filterMemoriesByWindow(memories: MemoryFile[], window: ParsedBriefingWindow): MemoryFile[] {
978
+ const fromMs = window.from.getTime();
979
+ const toMs = window.to.getTime();
980
+ return memories.filter((m) => {
981
+ // Exclude explicitly retired statuses so commitments overridden within the
982
+ // window don't appear as open. In addition to `superseded` / `archived`
983
+ // (temporal retirement), also exclude `rejected` and `quarantined`, which
984
+ // come from governance/disposition workflows: those memories have been
985
+ // explicitly marked unsafe or invalid and must NOT flow into active
986
+ // threads, open commitments, or follow-up generation, even if they
987
+ // fall within the briefing window. Surfacing them would reintroduce
988
+ // quarantined content into downstream automation as actionable context.
989
+ //
990
+ // `pending_review` memories are awaiting human review — not invalidated —
991
+ // and must be included so reviewers see them in the briefing.
992
+ const status = m.frontmatter.status;
993
+ if (
994
+ status === "superseded" ||
995
+ status === "archived" ||
996
+ status === "rejected" ||
997
+ status === "quarantined" ||
998
+ status === "forgotten"
999
+ ) {
1000
+ return false;
1001
+ }
1002
+ const ts = memoryTimestamp(m);
1003
+ return ts >= fromMs && ts < toMs;
1004
+ });
1005
+ }
1006
+
1007
+ /** @internal — exported for testing only. */
1008
+ export function buildActiveThreads(memories: MemoryFile[]): BriefingActiveThread[] {
1009
+ const buckets = new Map<string, BriefingActiveThread>();
1010
+ for (const memory of memories) {
1011
+ const threadKey = extractThreadKey(memory);
1012
+ const updatedAt = memory.frontmatter.updated || memory.frontmatter.created || "";
1013
+ const existing = buckets.get(threadKey);
1014
+ if (!existing || updatedAt > existing.updatedAt) {
1015
+ buckets.set(threadKey, {
1016
+ id: threadKey,
1017
+ title: summarizeContentTitle(memory),
1018
+ updatedAt,
1019
+ // Always derive reason from the newest memory so the description
1020
+ // reflects the most-recent activity type, not the first memory seen.
1021
+ reason: describeReason(memory),
1022
+ });
1023
+ }
1024
+ }
1025
+ return Array.from(buckets.values())
1026
+ .sort((a, b) => {
1027
+ if (a.updatedAt > b.updatedAt) return -1;
1028
+ if (a.updatedAt < b.updatedAt) return 1;
1029
+ // Tiebreaker: lexicographic order by id ensures a deterministic, stable
1030
+ // result when multiple threads share the same updatedAt timestamp (e.g.
1031
+ // after a batch extraction run).
1032
+ return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
1033
+ })
1034
+ .slice(0, MAX_ACTIVE_THREADS);
1035
+ }
1036
+
1037
+ function extractThreadKey(memory: MemoryFile): string {
1038
+ const entityRef = memory.frontmatter.entityRef?.trim();
1039
+ if (entityRef) return `entity:${entityRef}`;
1040
+ const tags = memory.frontmatter.tags ?? [];
1041
+ const topicTag = tags.find((t) => t.startsWith("topic:"));
1042
+ if (topicTag) return topicTag;
1043
+ if (tags.length > 0) return `tag:${tags[0]}`;
1044
+ return `memory:${memory.frontmatter.id}`;
1045
+ }
1046
+
1047
+ function summarizeContentTitle(memory: MemoryFile): string {
1048
+ const firstLine = (memory.content || "").split("\n").find((line) => line.trim().length > 0) ?? "";
1049
+ const trimmed = firstLine.trim();
1050
+ if (trimmed.length === 0) return memory.frontmatter.id;
1051
+ return trimmed.length > 120 ? `${trimmed.slice(0, 117)}...` : trimmed;
1052
+ }
1053
+
1054
+ function describeReason(memory: MemoryFile): string {
1055
+ const cat = memory.frontmatter.category;
1056
+ if (cat === "commitment") return "open commitment";
1057
+ if (cat === "decision") return "recent decision";
1058
+ if (cat === "correction") return "recent correction";
1059
+ return "recent activity";
1060
+ }
1061
+
1062
+ /** @internal — exported for testing only. */
1063
+ export function buildRecentEntities(
1064
+ entities: EntityFile[],
1065
+ window: ParsedBriefingWindow,
1066
+ focus: BriefingFocus | null,
1067
+ ): BriefingRecentEntity[] {
1068
+ const fromMs = window.from.getTime();
1069
+ const scored: BriefingRecentEntity[] = [];
1070
+ const now = window.to;
1071
+ for (const entity of entities) {
1072
+ if (focus && !focusMatchesEntity(entity, focus)) continue;
1073
+ const toMs = window.to.getTime();
1074
+ const updatedMs = entity.updated ? Date.parse(entity.updated) : 0;
1075
+ if (!Number.isFinite(updatedMs) || updatedMs < fromMs || updatedMs >= toMs) continue;
1076
+ const score = StorageManager.scoreEntity(entity, now);
1077
+ scored.push({
1078
+ name: entity.name,
1079
+ type: entity.type,
1080
+ updatedAt: entity.updated,
1081
+ score: Number(score.toFixed(4)),
1082
+ summary: entity.synthesis || entity.summary,
1083
+ });
1084
+ }
1085
+ return scored
1086
+ .sort((a, b) => {
1087
+ const scoreDiff = b.score - a.score;
1088
+ if (scoreDiff !== 0) return scoreDiff;
1089
+ if (a.updatedAt > b.updatedAt) return -1;
1090
+ if (a.updatedAt < b.updatedAt) return 1;
1091
+ return 0;
1092
+ })
1093
+ .slice(0, MAX_RECENT_ENTITIES);
1094
+ }
1095
+
1096
+ function buildOpenCommitments(memories: MemoryFile[]): BriefingOpenCommitment[] {
1097
+ const commitments: BriefingOpenCommitment[] = [];
1098
+
1099
+ for (const memory of memories) {
1100
+ const tags = memory.frontmatter.tags ?? [];
1101
+ const isPending = tags.some((t) => t.toLowerCase() === "pending");
1102
+ const isCommitment = memory.frontmatter.category === "commitment";
1103
+ const isUnresolvedQuestion = /(?:\?$|\bfollow[- ]up\b|\btodo\b)/i.test(memory.content);
1104
+
1105
+ if (isPending || isCommitment || isUnresolvedQuestion) {
1106
+ const kind: BriefingOpenCommitment["kind"] = isCommitment
1107
+ ? "commitment"
1108
+ : isUnresolvedQuestion
1109
+ ? "question"
1110
+ : "pending_memory";
1111
+ commitments.push({
1112
+ id: memory.frontmatter.id,
1113
+ kind,
1114
+ text: summarizeContentTitle(memory),
1115
+ source: memory.frontmatter.source,
1116
+ createdAt: memory.frontmatter.created,
1117
+ });
1118
+ }
1119
+ }
1120
+
1121
+ return commitments
1122
+ .sort((a, b) => {
1123
+ // Missing timestamps sort last (highest comparator value).
1124
+ if (!a.createdAt && !b.createdAt) return 0;
1125
+ if (!a.createdAt) return 1;
1126
+ if (!b.createdAt) return -1;
1127
+ if (a.createdAt > b.createdAt) return -1;
1128
+ if (a.createdAt < b.createdAt) return 1;
1129
+ return 0;
1130
+ })
1131
+ .slice(0, MAX_OPEN_COMMITMENTS);
1132
+ }
1133
+
1134
+ interface CalendarLoadResult {
1135
+ events: CalendarEvent[] | undefined;
1136
+ error: BriefingCalendarSourceError | undefined;
1137
+ }
1138
+
1139
+ async function loadTodayCalendar(
1140
+ source: CalendarSource,
1141
+ now: Date,
1142
+ ): Promise<CalendarLoadResult> {
1143
+ const sourceLabel = (source as { filePath?: string }).filePath ?? "calendar";
1144
+ try {
1145
+ const dateIso = now.toISOString().slice(0, 10);
1146
+ const events = await source.eventsForDate(dateIso);
1147
+ // Return the events array (possibly empty for a legitimately empty calendar).
1148
+ // An empty array is distinct from `undefined`: empty means "source responded
1149
+ // with no events today"; undefined means "source failed".
1150
+ return { events, error: undefined };
1151
+ } catch (err) {
1152
+ const message = err instanceof Error ? err.message : String(err);
1153
+ log.warn(`briefing: calendar source error (${sourceLabel}): ${message}`);
1154
+ // Return undefined events (not []) to signal an error so callers can
1155
+ // distinguish "no events today" from "the calendar source threw".
1156
+ return {
1157
+ events: undefined,
1158
+ error: { source: sourceLabel, error: message },
1159
+ };
1160
+ }
1161
+ }
1162
+
1163
+ // ──────────────────────────────────────────────────────────────────────────
1164
+ // Follow-ups (Responses API)
1165
+ // ──────────────────────────────────────────────────────────────────────────
1166
+
1167
+ function buildOpenAiFollowupGenerator(cfg: {
1168
+ apiKey: string;
1169
+ model: string;
1170
+ baseURL?: string;
1171
+ }): BriefingFollowupGenerator {
1172
+ return async ({ sections, windowLabel, maxFollowups }) => {
1173
+ // Lazy import keeps the module dependency-free when LLM path is unused.
1174
+ const { OpenAI } = (await import("openai")) as {
1175
+ OpenAI: new (opts: { apiKey: string; baseURL?: string }) => unknown;
1176
+ };
1177
+ const clientOpts: { apiKey: string; baseURL?: string } = { apiKey: cfg.apiKey };
1178
+ if (cfg.baseURL) clientOpts.baseURL = cfg.baseURL;
1179
+ const client = new OpenAI(clientOpts) as {
1180
+ responses: {
1181
+ create: (args: {
1182
+ model: string;
1183
+ instructions: string;
1184
+ input: string;
1185
+ max_output_tokens?: number;
1186
+ }) => Promise<{ output_text?: string }>;
1187
+ };
1188
+ };
1189
+
1190
+ const prompt = buildFollowupPrompt(sections, windowLabel, maxFollowups);
1191
+ const response = await client.responses.create({
1192
+ model: cfg.model,
1193
+ instructions: FOLLOWUP_INSTRUCTIONS,
1194
+ input: prompt,
1195
+ max_output_tokens: 512,
1196
+ });
1197
+
1198
+ const text = typeof response.output_text === "string" ? response.output_text : "";
1199
+ return parseFollowupResponse(text, maxFollowups);
1200
+ };
1201
+ }
1202
+
1203
+ const FOLLOWUP_INSTRUCTIONS = `You suggest short follow-up prompts for a daily context briefing.
1204
+ Return strict JSON of the form { "followups": [{ "text": "...", "rationale": "..." }] }.
1205
+ Rules:
1206
+ - Never invent facts absent from the input.
1207
+ - Keep each "text" under 140 characters.
1208
+ - Prefer concrete, action-oriented phrasing.
1209
+ - Omit duplicates. Avoid filler.`;
1210
+
1211
+ function buildFollowupPrompt(
1212
+ sections: BriefingSections,
1213
+ windowLabel: string,
1214
+ maxFollowups: number,
1215
+ ): string {
1216
+ const lines: string[] = [];
1217
+ lines.push(`Window: ${windowLabel}`);
1218
+ lines.push(`Desired follow-ups: ${maxFollowups}`);
1219
+ lines.push("");
1220
+ lines.push("Active threads:");
1221
+ for (const t of sections.activeThreads) lines.push(`- ${t.title} (${t.reason})`);
1222
+ lines.push("");
1223
+ lines.push("Recent entities:");
1224
+ for (const e of sections.recentEntities) lines.push(`- ${e.name} [${e.type}]`);
1225
+ lines.push("");
1226
+ lines.push("Open commitments:");
1227
+ for (const c of sections.openCommitments) lines.push(`- [${c.kind}] ${c.text}`);
1228
+ return lines.join("\n");
1229
+ }
1230
+
1231
+ function parseFollowupResponse(raw: string, max: number): BriefingFollowup[] {
1232
+ // JSON.parse throws on invalid JSON — let the caller catch it so the outer
1233
+ // try/catch in buildBriefing can set followupsUnavailableReason rather than
1234
+ // silently returning an empty array that masks the parse failure.
1235
+ const parsed = JSON.parse(raw) as unknown;
1236
+ if (!parsed || typeof parsed !== "object") {
1237
+ throw new Error(`LLM returned non-object JSON: ${typeof parsed}`);
1238
+ }
1239
+ const arr = (parsed as { followups?: unknown }).followups;
1240
+ if (!Array.isArray(arr)) {
1241
+ throw new Error(`LLM response missing "followups" array`);
1242
+ }
1243
+ const out: BriefingFollowup[] = [];
1244
+ for (const entry of arr) {
1245
+ if (!entry || typeof entry !== "object") continue;
1246
+ const text = (entry as Record<string, unknown>).text;
1247
+ if (typeof text !== "string" || text.trim().length === 0) continue;
1248
+ const rationale = (entry as Record<string, unknown>).rationale;
1249
+ out.push({
1250
+ text: text.trim(),
1251
+ rationale: typeof rationale === "string" ? rationale.trim() : undefined,
1252
+ });
1253
+ if (out.length >= max) break;
1254
+ }
1255
+ return out;
1256
+ }
1257
+
1258
+ function stringifyError(err: unknown): string {
1259
+ if (err instanceof Error) return err.message;
1260
+ return String(err);
1261
+ }
1262
+
1263
+ // ──────────────────────────────────────────────────────────────────────────
1264
+ // Markdown rendering
1265
+ // ──────────────────────────────────────────────────────────────────────────
1266
+
1267
+ interface RenderContext {
1268
+ sections: BriefingSections;
1269
+ windowLabel: string;
1270
+ focus: BriefingFocus | null;
1271
+ followupsUnavailableReason?: string;
1272
+ generatedAt: Date;
1273
+ namespace?: string;
1274
+ }
1275
+
1276
+ export function renderBriefingMarkdown(ctx: RenderContext): string {
1277
+ const lines: string[] = [];
1278
+ lines.push(`# Daily Context Briefing`);
1279
+ lines.push("");
1280
+ lines.push(`_Generated ${ctx.generatedAt.toISOString()} (window: ${ctx.windowLabel})_`);
1281
+ if (ctx.focus) {
1282
+ lines.push(`_Focus: ${ctx.focus.type}:${ctx.focus.value}_`);
1283
+ }
1284
+ if (ctx.namespace) {
1285
+ lines.push(`_Namespace: ${ctx.namespace}_`);
1286
+ }
1287
+ lines.push("");
1288
+
1289
+ lines.push(`## Active threads`);
1290
+ if (ctx.sections.activeThreads.length === 0) {
1291
+ lines.push(`_No active threads in window._`);
1292
+ } else {
1293
+ for (const t of ctx.sections.activeThreads) {
1294
+ lines.push(`- **${t.title}** — ${t.reason} (updated ${t.updatedAt})`);
1295
+ }
1296
+ }
1297
+ lines.push("");
1298
+
1299
+ lines.push(`## Recent entities`);
1300
+ if (ctx.sections.recentEntities.length === 0) {
1301
+ lines.push(`_No entities updated in window._`);
1302
+ } else {
1303
+ for (const e of ctx.sections.recentEntities) {
1304
+ const summary = e.summary ? ` — ${e.summary}` : "";
1305
+ lines.push(`- **${e.name}** (${e.type}, score ${e.score})${summary}`);
1306
+ }
1307
+ }
1308
+ lines.push("");
1309
+
1310
+ lines.push(`## Open commitments`);
1311
+ if (ctx.sections.openCommitments.length === 0) {
1312
+ lines.push(`_No open commitments detected._`);
1313
+ } else {
1314
+ for (const c of ctx.sections.openCommitments) {
1315
+ lines.push(`- [${c.kind}] ${c.text}`);
1316
+ }
1317
+ }
1318
+ lines.push("");
1319
+
1320
+ lines.push(`## Suggested follow-ups`);
1321
+ if (ctx.followupsUnavailableReason) {
1322
+ lines.push(`_Unavailable: ${ctx.followupsUnavailableReason}_`);
1323
+ } else if (ctx.sections.suggestedFollowups.length === 0) {
1324
+ lines.push(`_No follow-ups suggested._`);
1325
+ } else {
1326
+ for (const f of ctx.sections.suggestedFollowups) {
1327
+ const rationale = f.rationale ? ` _(${f.rationale})_` : "";
1328
+ lines.push(`- ${f.text}${rationale}`);
1329
+ }
1330
+ }
1331
+ lines.push("");
1332
+
1333
+ if (ctx.sections.todayCalendar !== undefined) {
1334
+ lines.push(`## Today's calendar`);
1335
+ if (ctx.sections.todayCalendar.length === 0) {
1336
+ lines.push(`_No events on the calendar today._`);
1337
+ } else {
1338
+ for (const ev of ctx.sections.todayCalendar) {
1339
+ const end = ev.end ? ` → ${ev.end}` : "";
1340
+ const loc = ev.location ? ` @ ${ev.location}` : "";
1341
+ lines.push(`- **${ev.title}** (${ev.start}${end})${loc}`);
1342
+ }
1343
+ }
1344
+ lines.push("");
1345
+ }
1346
+
1347
+ return lines.join("\n").trimEnd() + "\n";
1348
+ }
1349
+
1350
+ // ──────────────────────────────────────────────────────────────────────────
1351
+ // Save helpers
1352
+ // ──────────────────────────────────────────────────────────────────────────
1353
+
1354
+ /**
1355
+ * Resolve the directory where `--save` writes dated briefings.
1356
+ * Respects the following precedence:
1357
+ * 1. explicit `configOverride` argument
1358
+ * 2. `$REMNIC_HOME/briefings/`
1359
+ * 3. `$HOME/.remnic/briefings/`
1360
+ */
1361
+ export function resolveBriefingSaveDir(
1362
+ configOverride: string | null | undefined,
1363
+ env?: NodeJS.ProcessEnv,
1364
+ ): string {
1365
+ if (typeof configOverride === "string" && configOverride.trim().length > 0) {
1366
+ return path.resolve(configOverride.trim());
1367
+ }
1368
+ const remnicHome = (env === undefined ? readEnvVar("REMNIC_HOME") : env.REMNIC_HOME)?.trim();
1369
+ if (remnicHome && remnicHome.length > 0) {
1370
+ return path.join(remnicHome, "briefings");
1371
+ }
1372
+ const home = env === undefined
1373
+ ? resolveHomeDir()
1374
+ : env.HOME ?? env.USERPROFILE ?? os.homedir();
1375
+ return path.join(home, ".remnic", "briefings");
1376
+ }
1377
+
1378
+ /** Format the dated filename for a given briefing. */
1379
+ export function briefingFilename(date: Date, format: "markdown" | "json" = "markdown"): string {
1380
+ const day = date.toISOString().slice(0, 10);
1381
+ return format === "json" ? `${day}.json` : `${day}.md`;
1382
+ }