@remnic/core 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) hide show
  1. package/dist/abort-error.js +1 -0
  2. package/dist/abstraction-nodes.js +1 -0
  3. package/dist/access-audit.js +1 -0
  4. package/dist/access-cli.js +70 -45
  5. package/dist/access-cli.js.map +1 -1
  6. package/dist/access-http.d.ts +50 -5
  7. package/dist/access-http.js +37 -15
  8. package/dist/access-idempotency.js +1 -0
  9. package/dist/access-mcp.d.ts +10 -5
  10. package/dist/access-mcp.js +36 -13
  11. package/dist/access-schema.d.ts +133 -13
  12. package/dist/access-schema.js +20 -1
  13. package/dist/access-service-_AEUMVyX.d.ts +1981 -0
  14. package/dist/access-service.d.ts +11 -6
  15. package/dist/access-service.js +38 -14
  16. package/dist/active-memory-bridge.js +1 -0
  17. package/dist/active-recall.js +1 -0
  18. package/dist/active-recall.js.map +1 -1
  19. package/dist/behavior-learner.js +1 -0
  20. package/dist/behavior-learner.js.map +1 -1
  21. package/dist/behavior-signals.js +1 -0
  22. package/dist/bootstrap.d.ts +6 -4
  23. package/dist/bootstrap.js +1 -0
  24. package/dist/boxes.js +1 -0
  25. package/dist/briefing.d.ts +9 -5
  26. package/dist/briefing.js +9 -6
  27. package/dist/buffer-surprise-report.js +1 -0
  28. package/dist/buffer-surprise.js +1 -0
  29. package/dist/buffer.d.ts +1 -1
  30. package/dist/buffer.js +1 -0
  31. package/dist/calibration.d.ts +8 -1
  32. package/dist/calibration.js +10 -2
  33. package/dist/calibration.js.map +1 -1
  34. package/dist/capsule-cli.d.ts +137 -0
  35. package/dist/capsule-cli.js +34 -0
  36. package/dist/capsule-crypto-5CYAGVC5.js +18 -0
  37. package/dist/capsule-export-NZQPOTQ4.js +17 -0
  38. package/dist/capsule-export-NZQPOTQ4.js.map +1 -0
  39. package/dist/capsule-import-SDCUXLEV.js +16 -0
  40. package/dist/capsule-import-SDCUXLEV.js.map +1 -0
  41. package/dist/capsule-merge-DI7PNQ2H.js +189 -0
  42. package/dist/capsule-merge-DI7PNQ2H.js.map +1 -0
  43. package/dist/causal-behavior.js +1 -0
  44. package/dist/causal-behavior.js.map +1 -1
  45. package/dist/causal-chain.js +1 -0
  46. package/dist/causal-consolidation.js +11 -8
  47. package/dist/causal-consolidation.js.map +1 -1
  48. package/dist/causal-retrieval.js +2 -1
  49. package/dist/causal-retrieval.js.map +1 -1
  50. package/dist/causal-trajectory-graph.js +4 -1
  51. package/dist/causal-trajectory-graph.js.map +1 -1
  52. package/dist/causal-trajectory.js +2 -1
  53. package/dist/chunk-2LSZVONP.js +67 -0
  54. package/dist/chunk-2LSZVONP.js.map +1 -0
  55. package/dist/chunk-32KD5IHZ.js +245 -0
  56. package/dist/chunk-32KD5IHZ.js.map +1 -0
  57. package/dist/{chunk-VDX363PS.js → chunk-34F3PLWZ.js} +10 -3
  58. package/dist/chunk-34F3PLWZ.js.map +1 -0
  59. package/dist/chunk-3KIS4VGT.js +228 -0
  60. package/dist/chunk-3KIS4VGT.js.map +1 -0
  61. package/dist/chunk-3LCWFNVS.js +350 -0
  62. package/dist/chunk-3LCWFNVS.js.map +1 -0
  63. package/dist/chunk-43EKP2UK.js +26 -0
  64. package/dist/chunk-43EKP2UK.js.map +1 -0
  65. package/dist/chunk-457A4P3L.js +119 -0
  66. package/dist/chunk-457A4P3L.js.map +1 -0
  67. package/dist/{chunk-TMYO7B5P.js → chunk-47WOM4YW.js} +2 -2
  68. package/dist/{chunk-OC5OXUQ4.js → chunk-4PLGJRBV.js} +653 -17
  69. package/dist/chunk-4PLGJRBV.js.map +1 -0
  70. package/dist/{chunk-PVICZTKG.js → chunk-55FXRRSJ.js} +5 -5
  71. package/dist/{chunk-PVICZTKG.js.map → chunk-55FXRRSJ.js.map} +1 -1
  72. package/dist/{chunk-ULYOGL6R.js → chunk-5HRY2WRF.js} +7 -3
  73. package/dist/chunk-5HRY2WRF.js.map +1 -0
  74. package/dist/chunk-6TBWYBJ3.js +236 -0
  75. package/dist/chunk-6TBWYBJ3.js.map +1 -0
  76. package/dist/chunk-74EMIVE4.js +329 -0
  77. package/dist/chunk-74EMIVE4.js.map +1 -0
  78. package/dist/chunk-74WWN7ZW.js +82 -0
  79. package/dist/chunk-74WWN7ZW.js.map +1 -0
  80. package/dist/{chunk-6YJHX2DL.js → chunk-7GCMLT7J.js} +242 -22
  81. package/dist/chunk-7GCMLT7J.js.map +1 -0
  82. package/dist/chunk-A6XUJE5D.js +126 -0
  83. package/dist/chunk-A6XUJE5D.js.map +1 -0
  84. package/dist/chunk-AJA46VX5.js +393 -0
  85. package/dist/chunk-AJA46VX5.js.map +1 -0
  86. package/dist/{chunk-UWB5LMWY.js → chunk-AKUCB2OG.js} +525 -24
  87. package/dist/chunk-AKUCB2OG.js.map +1 -0
  88. package/dist/chunk-ASIQZXYO.js +277 -0
  89. package/dist/chunk-ASIQZXYO.js.map +1 -0
  90. package/dist/{chunk-DG6YMRDC.js → chunk-B2TL6GA2.js} +2 -2
  91. package/dist/chunk-BJMBJZ2Y.js +290 -0
  92. package/dist/chunk-BJMBJZ2Y.js.map +1 -0
  93. package/dist/chunk-BT7NVCML.js +79 -0
  94. package/dist/chunk-BT7NVCML.js.map +1 -0
  95. package/dist/chunk-CK5NTM2S.js +454 -0
  96. package/dist/chunk-CK5NTM2S.js.map +1 -0
  97. package/dist/{chunk-AYXIPSZO.js → chunk-CRU27Q4J.js} +2 -2
  98. package/dist/{chunk-F5VP6YCB.js → chunk-DCE6SQLA.js} +572 -155
  99. package/dist/chunk-DCE6SQLA.js.map +1 -0
  100. package/dist/{chunk-CUPFXL3J.js → chunk-DHRQHX36.js} +4 -4
  101. package/dist/chunk-DHRQHX36.js.map +1 -0
  102. package/dist/{chunk-STGWEHYR.js → chunk-DR7MCMPS.js} +981 -61
  103. package/dist/chunk-DR7MCMPS.js.map +1 -0
  104. package/dist/chunk-FP2373TW.js +149 -0
  105. package/dist/chunk-FP2373TW.js.map +1 -0
  106. package/dist/{chunk-RBBWYEFJ.js → chunk-G2WADRQ3.js} +1 -1
  107. package/dist/chunk-G7D6GZ5J.js +48 -0
  108. package/dist/chunk-G7D6GZ5J.js.map +1 -0
  109. package/dist/chunk-H7XKCNR6.js +60 -0
  110. package/dist/chunk-H7XKCNR6.js.map +1 -0
  111. package/dist/{chunk-3YGHKTBF.js → chunk-IM3JSE73.js} +953 -322
  112. package/dist/chunk-IM3JSE73.js.map +1 -0
  113. package/dist/chunk-IXEJRKCZ.js +18 -0
  114. package/dist/chunk-IXEJRKCZ.js.map +1 -0
  115. package/dist/chunk-IYY4MCPG.js +275 -0
  116. package/dist/chunk-IYY4MCPG.js.map +1 -0
  117. package/dist/{chunk-BECYBZLX.js → chunk-JWSENLQI.js} +502 -22
  118. package/dist/chunk-JWSENLQI.js.map +1 -0
  119. package/dist/chunk-KNKUID7G.js +183 -0
  120. package/dist/chunk-KNKUID7G.js.map +1 -0
  121. package/dist/chunk-L2IO2QPY.js +2036 -0
  122. package/dist/chunk-L2IO2QPY.js.map +1 -0
  123. package/dist/{chunk-SPI27QT6.js → chunk-L5IIGA5V.js} +9 -4
  124. package/dist/chunk-L5IIGA5V.js.map +1 -0
  125. package/dist/{chunk-XXVWLXSG.js → chunk-LVYGDT5V.js} +56 -82
  126. package/dist/chunk-LVYGDT5V.js.map +1 -0
  127. package/dist/{chunk-ZAIM4TUE.js → chunk-LW2NMHDW.js} +46 -1
  128. package/dist/chunk-LW2NMHDW.js.map +1 -0
  129. package/dist/{chunk-3OGMS3PE.js → chunk-LZRYQK6L.js} +3 -2
  130. package/dist/chunk-LZRYQK6L.js.map +1 -0
  131. package/dist/chunk-MDYG7VI7.js +48 -0
  132. package/dist/chunk-MDYG7VI7.js.map +1 -0
  133. package/dist/chunk-MXC3AP5I.js +74 -0
  134. package/dist/chunk-MXC3AP5I.js.map +1 -0
  135. package/dist/{chunk-DIXB44VE.js → chunk-N7X62G74.js} +25 -10
  136. package/dist/chunk-N7X62G74.js.map +1 -0
  137. package/dist/chunk-NN3TS5BM.js +147 -0
  138. package/dist/chunk-NN3TS5BM.js.map +1 -0
  139. package/dist/chunk-OA3L7BFR.js +183 -0
  140. package/dist/chunk-OA3L7BFR.js.map +1 -0
  141. package/dist/chunk-OZHRDTDX.js +240 -0
  142. package/dist/chunk-OZHRDTDX.js.map +1 -0
  143. package/dist/chunk-PCUKNJAZ.js +165 -0
  144. package/dist/chunk-PCUKNJAZ.js.map +1 -0
  145. package/dist/{chunk-6PFRXT4K.js → chunk-PFV5C235.js} +11 -6
  146. package/dist/chunk-PFV5C235.js.map +1 -0
  147. package/dist/chunk-PZ5AY32C.js +10 -0
  148. package/dist/chunk-PZ5AY32C.js.map +1 -0
  149. package/dist/{chunk-Y7R2XJ5Q.js → chunk-Q7FJ5ZHM.js} +6 -2
  150. package/dist/chunk-Q7FJ5ZHM.js.map +1 -0
  151. package/dist/{chunk-NBVAS5MT.js → chunk-R2L7SUX2.js} +6 -6
  152. package/dist/{chunk-WCLICCGB.js → chunk-RILIVK4O.js} +91 -4
  153. package/dist/chunk-RILIVK4O.js.map +1 -0
  154. package/dist/{chunk-C2EFFULQ.js → chunk-RK2Y4XOM.js} +163 -20
  155. package/dist/chunk-RK2Y4XOM.js.map +1 -0
  156. package/dist/{chunk-TP4FZJIZ.js → chunk-RULE4VG5.js} +5 -1
  157. package/dist/chunk-RULE4VG5.js.map +1 -0
  158. package/dist/{chunk-PVPWZSSI.js → chunk-SMA4IMHV.js} +19 -3
  159. package/dist/chunk-SMA4IMHV.js.map +1 -0
  160. package/dist/{chunk-L7IXWRYE.js → chunk-SS253RXF.js} +22 -13
  161. package/dist/chunk-SS253RXF.js.map +1 -0
  162. package/dist/chunk-TUFG6VXY.js +875 -0
  163. package/dist/chunk-TUFG6VXY.js.map +1 -0
  164. package/dist/chunk-TYEOAFH3.js +251 -0
  165. package/dist/chunk-TYEOAFH3.js.map +1 -0
  166. package/dist/chunk-UKJAGEXH.js +260 -0
  167. package/dist/chunk-UKJAGEXH.js.map +1 -0
  168. package/dist/{chunk-KVBLZUKV.js → chunk-USFPPRAF.js} +93 -3
  169. package/dist/chunk-USFPPRAF.js.map +1 -0
  170. package/dist/{chunk-GA5P7RST.js → chunk-VTJVUHRK.js} +22 -36
  171. package/dist/chunk-VTJVUHRK.js.map +1 -0
  172. package/dist/chunk-WIICJPET.js +45 -0
  173. package/dist/chunk-WIICJPET.js.map +1 -0
  174. package/dist/{chunk-VBVG2M5G.js → chunk-WPGJYVUH.js} +6 -2
  175. package/dist/chunk-WPGJYVUH.js.map +1 -0
  176. package/dist/{chunk-4HQS2HPX.js → chunk-WSZIHQBK.js} +29 -9
  177. package/dist/{chunk-4HQS2HPX.js.map → chunk-WSZIHQBK.js.map} +1 -1
  178. package/dist/{chunk-NZLQTHS5.js → chunk-WW3QQF4H.js} +4 -1
  179. package/dist/chunk-WW3QQF4H.js.map +1 -0
  180. package/dist/{chunk-FVA6TGI3.js → chunk-Y3WQ4ZWK.js} +42 -2
  181. package/dist/chunk-Y3WQ4ZWK.js.map +1 -0
  182. package/dist/chunk-YNJHCGDT.js +309 -0
  183. package/dist/chunk-YNJHCGDT.js.map +1 -0
  184. package/dist/{chunk-LOIMBRDE.js → chunk-ZGXSCMQN.js} +1993 -411
  185. package/dist/chunk-ZGXSCMQN.js.map +1 -0
  186. package/dist/{chunk-W6SL7OFG.js → chunk-ZTSE2ZJ6.js} +12 -2
  187. package/dist/{chunk-W6SL7OFG.js.map → chunk-ZTSE2ZJ6.js.map} +1 -1
  188. package/dist/chunking.js +1 -0
  189. package/dist/cipher-GVE2GQ5H.js +28 -0
  190. package/dist/cipher-GVE2GQ5H.js.map +1 -0
  191. package/dist/citations.js +1 -0
  192. package/dist/{cli-BkeRaYfk.d.ts → cli-x2APT9a6.d.ts} +26 -7
  193. package/dist/cli.d.ts +11 -6
  194. package/dist/cli.js +67 -33
  195. package/dist/codex-thread-key.js +1 -0
  196. package/dist/commitment-ledger.js +1 -0
  197. package/dist/compression-optimizer.js +1 -0
  198. package/dist/config.d.ts +2 -1
  199. package/dist/config.js +4 -1
  200. package/dist/connectors-cli-DFGtY2DB.d.ts +257 -0
  201. package/dist/connectors-cli.d.ts +2 -0
  202. package/dist/connectors-cli.js +22 -0
  203. package/dist/connectors-cli.js.map +1 -0
  204. package/dist/consolidation-operator.d.ts +65 -5
  205. package/dist/consolidation-operator.js +6 -1
  206. package/dist/consolidation-provenance-check.d.ts +1 -1
  207. package/dist/consolidation-provenance-check.js +3 -2
  208. package/dist/consolidation-undo.d.ts +1 -1
  209. package/dist/consolidation-undo.js +1 -0
  210. package/dist/consolidation-undo.js.map +1 -1
  211. package/dist/{contradiction-review-WIUBAR52.js → contradiction-review-5LTTVDQV.js} +2 -1
  212. package/dist/contradiction-review-5LTTVDQV.js.map +1 -0
  213. package/dist/{contradiction-scan-E3GJTI4F.js → contradiction-scan-3Z6YW7YA.js} +2 -1
  214. package/dist/{contradiction-scan-E3GJTI4F.js.map → contradiction-scan-3Z6YW7YA.js.map} +1 -1
  215. package/dist/cross-namespace-budget.js +1 -0
  216. package/dist/cue-anchors.js +1 -0
  217. package/dist/dashboard-runtime.js +1 -0
  218. package/dist/day-summary.js +1 -0
  219. package/dist/delinearize.js +1 -0
  220. package/dist/direct-answer-wiring.js +1 -0
  221. package/dist/direct-answer.js +1 -0
  222. package/dist/dreams-ledger-LR2NBAZE.js +286 -0
  223. package/dist/dreams-ledger-LR2NBAZE.js.map +1 -0
  224. package/dist/embedding-fallback.js +1 -0
  225. package/dist/{engine-72LSIWQP.js → engine-ICC2DSQF.js} +10 -7
  226. package/dist/engine-ICC2DSQF.js.map +1 -0
  227. package/dist/entity-retrieval.d.ts +1 -1
  228. package/dist/entity-retrieval.js +9 -6
  229. package/dist/entity-schema.js +1 -0
  230. package/dist/evals.js +1 -0
  231. package/dist/evidence-pack.d.ts +16 -0
  232. package/dist/evidence-pack.js +8 -0
  233. package/dist/evidence-pack.js.map +1 -0
  234. package/dist/explicit-capture.d.ts +6 -4
  235. package/dist/explicit-capture.js +1 -0
  236. package/dist/extraction-judge-telemetry.js +1 -0
  237. package/dist/extraction-judge-training.js +1 -0
  238. package/dist/extraction-judge.js +1 -0
  239. package/dist/extraction.js +7 -6
  240. package/dist/fallback-llm.js +3 -2
  241. package/dist/first-start-migration-4MHQEOSD.js +263 -0
  242. package/dist/first-start-migration-4MHQEOSD.js.map +1 -0
  243. package/dist/forget-PLR6J5DN.js +69 -0
  244. package/dist/forget-PLR6J5DN.js.map +1 -0
  245. package/dist/framework-CyHYDcri.d.ts +153 -0
  246. package/dist/fs-utils-IRVUFB6G.js +30 -0
  247. package/dist/fs-utils-IRVUFB6G.js.map +1 -0
  248. package/dist/graph-dashboard-diff.js +1 -0
  249. package/dist/graph-dashboard-key.js +1 -0
  250. package/dist/graph-dashboard-parser.js +1 -0
  251. package/dist/graph-edge-decay-PWB63GRE.js +207 -0
  252. package/dist/graph-edge-decay-PWB63GRE.js.map +1 -0
  253. package/dist/graph-edge-reinforcement.d.ts +81 -0
  254. package/dist/graph-edge-reinforcement.js +24 -0
  255. package/dist/graph-edge-reinforcement.js.map +1 -0
  256. package/dist/graph-events.d.ts +87 -0
  257. package/dist/graph-events.js +14 -0
  258. package/dist/graph-events.js.map +1 -0
  259. package/dist/graph-recall.js +1 -0
  260. package/dist/graph-retrieval.js +1 -0
  261. package/dist/graph-snapshot.d.ts +112 -0
  262. package/dist/graph-snapshot.js +19 -0
  263. package/dist/graph-snapshot.js.map +1 -0
  264. package/dist/graph.d.ts +105 -7
  265. package/dist/graph.js +20 -3
  266. package/dist/harmonic-retrieval.js +1 -0
  267. package/dist/himem.js +1 -0
  268. package/dist/hygiene.js +1 -0
  269. package/dist/identity-continuity.js +1 -0
  270. package/dist/importance.js +1 -0
  271. package/dist/index.d.ts +562 -13
  272. package/dist/index.js +329 -67
  273. package/dist/index.js.map +1 -1
  274. package/dist/intent.js +1 -0
  275. package/dist/json-extract.js +1 -0
  276. package/dist/json-store.js +1 -0
  277. package/dist/kdf-7S6RWKLZ.js +26 -0
  278. package/dist/kdf-7S6RWKLZ.js.map +1 -0
  279. package/dist/legacy-hook-compat.js +1 -0
  280. package/dist/legacy-hook-compat.js.map +1 -1
  281. package/dist/lifecycle.js +1 -0
  282. package/dist/live-connectors-runner.d.ts +48 -0
  283. package/dist/live-connectors-runner.js +17 -0
  284. package/dist/live-connectors-runner.js.map +1 -0
  285. package/dist/local-llm.js +1 -0
  286. package/dist/logger.js +1 -0
  287. package/dist/memory-action-policy.js +1 -0
  288. package/dist/memory-cache.d.ts +2 -1
  289. package/dist/memory-cache.js +4 -1
  290. package/dist/memory-governance-KG52RITE.js +37 -0
  291. package/dist/memory-governance-KG52RITE.js.map +1 -0
  292. package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
  293. package/dist/memory-lifecycle-ledger-utils.js +4 -1
  294. package/dist/memory-projection-format.js +1 -0
  295. package/dist/{memory-projection-store-DeSXPh1j.d.ts → memory-projection-store-D3vBHS4J.d.ts} +1 -0
  296. package/dist/memory-projection-store.d.ts +1 -1
  297. package/dist/memory-projection-store.js +1 -0
  298. package/dist/memory-worth-bench.js +1 -0
  299. package/dist/memory-worth-bench.js.map +1 -1
  300. package/dist/memory-worth-filter.js +1 -0
  301. package/dist/memory-worth-outcomes.d.ts +1 -1
  302. package/dist/memory-worth-outcomes.js +1 -0
  303. package/dist/memory-worth.js +1 -0
  304. package/dist/metadata-FC3XPDRQ.js +21 -0
  305. package/dist/metadata-FC3XPDRQ.js.map +1 -0
  306. package/dist/migrate-from-identity-anchor-TTEDEJGX.js +8 -0
  307. package/dist/migrate-from-identity-anchor-TTEDEJGX.js.map +1 -0
  308. package/dist/model-registry.js +1 -0
  309. package/dist/models-json.js +1 -0
  310. package/dist/native-knowledge.js +1 -0
  311. package/dist/negative.js +1 -0
  312. package/dist/objective-state-writers.js +1 -0
  313. package/dist/objective-state-writers.js.map +1 -1
  314. package/dist/objective-state.js +1 -0
  315. package/dist/openai-chat-compat.js +1 -0
  316. package/dist/operator-toolkit.d.ts +46 -2
  317. package/dist/operator-toolkit.js +28 -16
  318. package/dist/opik-exporter.js +1 -0
  319. package/dist/opik-exporter.js.map +1 -1
  320. package/dist/{orchestrator-CmJ-NTdJ.d.ts → orchestrator-ChkesB8U.d.ts} +177 -13
  321. package/dist/orchestrator.d.ts +6 -4
  322. package/dist/orchestrator.js +55 -39
  323. package/dist/page-versioning.js +1 -0
  324. package/dist/path-RMTY5Y5A.js +9 -0
  325. package/dist/path-RMTY5Y5A.js.map +1 -0
  326. package/dist/patterns-cli.d.ts +160 -0
  327. package/dist/patterns-cli.js +29 -0
  328. package/dist/patterns-cli.js.map +1 -0
  329. package/dist/peers-6OSQ3NK6.js +44 -0
  330. package/dist/peers-6OSQ3NK6.js.map +1 -0
  331. package/dist/plugin-id.js +1 -0
  332. package/dist/policy-runtime.js +1 -0
  333. package/dist/{port-BADbLZU5.d.ts → port-hqGnoStS.d.ts} +6 -0
  334. package/dist/profiling.js +1 -0
  335. package/dist/purge-6ATBGT77.js +205 -0
  336. package/dist/purge-6ATBGT77.js.map +1 -0
  337. package/dist/qmd-recall-cache.d.ts +1 -1
  338. package/dist/qmd-recall-cache.js +1 -0
  339. package/dist/qmd.d.ts +2 -1
  340. package/dist/qmd.js +4 -3
  341. package/dist/reasoning-trace-recall.js +1 -0
  342. package/dist/reasoning-trace-types.js +1 -0
  343. package/dist/recall-audit-anomaly.js +1 -0
  344. package/dist/recall-audit.js +1 -0
  345. package/dist/recall-disclosure-escalation.d.ts +84 -0
  346. package/dist/recall-disclosure-escalation.js +14 -0
  347. package/dist/recall-disclosure-escalation.js.map +1 -0
  348. package/dist/recall-explain-renderer.js +4 -1
  349. package/dist/recall-mmr.js +1 -0
  350. package/dist/recall-qos.js +1 -0
  351. package/dist/recall-query-policy.js +1 -0
  352. package/dist/recall-state.d.ts +7 -0
  353. package/dist/recall-state.js +2 -1
  354. package/dist/recall-tag-filter.d.ts +56 -0
  355. package/dist/recall-tag-filter.js +14 -0
  356. package/dist/recall-tag-filter.js.map +1 -0
  357. package/dist/recall-tokenization.js +1 -0
  358. package/dist/recall-xray-cli.d.ts +9 -2
  359. package/dist/recall-xray-cli.js +9 -4
  360. package/dist/recall-xray-renderer.js +4 -1
  361. package/dist/recall-xray.d.ts +116 -2
  362. package/dist/recall-xray.js +9 -3
  363. package/dist/reconstruct.js +1 -0
  364. package/dist/release-changelog.js +2 -0
  365. package/dist/release-changelog.js.map +1 -1
  366. package/dist/relevance.js +1 -0
  367. package/dist/rerank.js +1 -0
  368. package/dist/{resolution-QBTDHTG7.js → resolution-YGIBORXI.js} +2 -1
  369. package/dist/{resolution-QBTDHTG7.js.map → resolution-YGIBORXI.js.map} +1 -1
  370. package/dist/resolve-auth-token.d.ts +51 -0
  371. package/dist/resolve-auth-token.js +12 -0
  372. package/dist/resolve-auth-token.js.map +1 -0
  373. package/dist/resolve-provider-secret.d.ts +9 -1
  374. package/dist/resolve-provider-secret.js +4 -1
  375. package/dist/resume-bundles.js +4 -3
  376. package/dist/retrieval-agents.d.ts +1 -1
  377. package/dist/retrieval-agents.js +1 -0
  378. package/dist/retrieval-tiers.js +1 -0
  379. package/dist/retrieval.js +1 -0
  380. package/dist/sanitize.js +1 -0
  381. package/dist/schemas.d.ts +37 -24
  382. package/dist/schemas.js +2 -1
  383. package/dist/sdk-compat.js +1 -0
  384. package/dist/sdk-compat.js.map +1 -1
  385. package/dist/secure-store-4R2GSO7S.js +156 -0
  386. package/dist/secure-store-4R2GSO7S.js.map +1 -0
  387. package/dist/semantic-chunking.js +1 -0
  388. package/dist/{semantic-consolidation-CxJU6MJk.d.ts → semantic-consolidation-ByBXb-sf.d.ts} +3 -3
  389. package/dist/semantic-consolidation.d.ts +2 -2
  390. package/dist/semantic-consolidation.js +11 -6
  391. package/dist/semantic-rule-promotion.d.ts +1 -1
  392. package/dist/semantic-rule-promotion.js +9 -6
  393. package/dist/semantic-rule-verifier.d.ts +1 -1
  394. package/dist/semantic-rule-verifier.js +9 -6
  395. package/dist/session-integrity.js +1 -0
  396. package/dist/session-observer-bands.js +1 -0
  397. package/dist/session-observer-state.js +1 -0
  398. package/dist/session-toggles.js +2 -0
  399. package/dist/session-toggles.js.map +1 -1
  400. package/dist/signal.js +1 -0
  401. package/dist/skills-registry.js +2 -0
  402. package/dist/skills-registry.js.map +1 -1
  403. package/dist/source-attribution.js +1 -0
  404. package/dist/state-NCHQ4TRG.js +8 -0
  405. package/dist/state-NCHQ4TRG.js.map +1 -0
  406. package/dist/state-store-3EH7HYIN.js +16 -0
  407. package/dist/state-store-3EH7HYIN.js.map +1 -0
  408. package/dist/storage.d.ts +76 -2
  409. package/dist/storage.js +8 -5
  410. package/dist/store-contract.js +1 -0
  411. package/dist/summarizer.js +5 -4
  412. package/dist/summary-snapshot.js +1 -0
  413. package/dist/temporal-index.js +1 -0
  414. package/dist/temporal-supersession.d.ts +1 -1
  415. package/dist/temporal-supersession.js +2 -1
  416. package/dist/temporal-validity.d.ts +52 -0
  417. package/dist/temporal-validity.js +14 -0
  418. package/dist/temporal-validity.js.map +1 -0
  419. package/dist/threading.js +1 -0
  420. package/dist/tier-migration.d.ts +2 -2
  421. package/dist/tier-migration.js +1 -0
  422. package/dist/tier-routing.js +1 -0
  423. package/dist/tier-stats-62ZVDFKS.js +152 -0
  424. package/dist/tier-stats-62ZVDFKS.js.map +1 -0
  425. package/dist/tmt.js +1 -0
  426. package/dist/tokens.js +1 -0
  427. package/dist/topics.js +1 -0
  428. package/dist/trace-C5ETWBEF.js +290 -0
  429. package/dist/trace-C5ETWBEF.js.map +1 -0
  430. package/dist/transcript.js +1 -0
  431. package/dist/trust-zones.js +1 -0
  432. package/dist/tui-RI7P6PBS.js +13 -0
  433. package/dist/tui-RI7P6PBS.js.map +1 -0
  434. package/dist/types-V3FJ26TF.js +30 -0
  435. package/dist/types-V3FJ26TF.js.map +1 -0
  436. package/dist/types.d.ts +634 -9
  437. package/dist/types.js +10 -3
  438. package/dist/utility-learner.js +1 -0
  439. package/dist/utility-runtime.js +1 -0
  440. package/dist/utility-telemetry.js +1 -0
  441. package/dist/verified-recall.js +9 -6
  442. package/dist/version-utils.js +1 -0
  443. package/dist/whitespace.js +1 -0
  444. package/dist/work-product-ledger.js +1 -0
  445. package/package.json +2 -1
  446. package/dist/access-service-Br8ZydTK.d.ts +0 -827
  447. package/dist/chunk-3OGMS3PE.js.map +0 -1
  448. package/dist/chunk-3YGHKTBF.js.map +0 -1
  449. package/dist/chunk-6PFRXT4K.js.map +0 -1
  450. package/dist/chunk-6YJHX2DL.js.map +0 -1
  451. package/dist/chunk-BECYBZLX.js.map +0 -1
  452. package/dist/chunk-C2EFFULQ.js.map +0 -1
  453. package/dist/chunk-CUPFXL3J.js.map +0 -1
  454. package/dist/chunk-DIXB44VE.js.map +0 -1
  455. package/dist/chunk-F5VP6YCB.js.map +0 -1
  456. package/dist/chunk-FVA6TGI3.js.map +0 -1
  457. package/dist/chunk-GA5P7RST.js.map +0 -1
  458. package/dist/chunk-KVBLZUKV.js.map +0 -1
  459. package/dist/chunk-L7IXWRYE.js.map +0 -1
  460. package/dist/chunk-LOIMBRDE.js.map +0 -1
  461. package/dist/chunk-LTCGGW2D.js +0 -14
  462. package/dist/chunk-LTCGGW2D.js.map +0 -1
  463. package/dist/chunk-NZLQTHS5.js.map +0 -1
  464. package/dist/chunk-OC5OXUQ4.js.map +0 -1
  465. package/dist/chunk-PVPWZSSI.js.map +0 -1
  466. package/dist/chunk-SPI27QT6.js.map +0 -1
  467. package/dist/chunk-STGWEHYR.js.map +0 -1
  468. package/dist/chunk-TP4FZJIZ.js.map +0 -1
  469. package/dist/chunk-ULYOGL6R.js.map +0 -1
  470. package/dist/chunk-UWB5LMWY.js.map +0 -1
  471. package/dist/chunk-VBVG2M5G.js.map +0 -1
  472. package/dist/chunk-VDX363PS.js.map +0 -1
  473. package/dist/chunk-WCLICCGB.js.map +0 -1
  474. package/dist/chunk-X6GF3FX2.js +0 -26
  475. package/dist/chunk-X6GF3FX2.js.map +0 -1
  476. package/dist/chunk-XXVWLXSG.js.map +0 -1
  477. package/dist/chunk-Y7R2XJ5Q.js.map +0 -1
  478. package/dist/chunk-ZAIM4TUE.js.map +0 -1
  479. /package/dist/{contradiction-review-WIUBAR52.js.map → capsule-cli.js.map} +0 -0
  480. /package/dist/{engine-72LSIWQP.js.map → capsule-crypto-5CYAGVC5.js.map} +0 -0
  481. /package/dist/{chunk-TMYO7B5P.js.map → chunk-47WOM4YW.js.map} +0 -0
  482. /package/dist/{chunk-DG6YMRDC.js.map → chunk-B2TL6GA2.js.map} +0 -0
  483. /package/dist/{chunk-AYXIPSZO.js.map → chunk-CRU27Q4J.js.map} +0 -0
  484. /package/dist/{chunk-RBBWYEFJ.js.map → chunk-G2WADRQ3.js.map} +0 -0
  485. /package/dist/{chunk-NBVAS5MT.js.map → chunk-R2L7SUX2.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/entity-retrieval.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { sanitizeMemoryContent } from \"./sanitize.js\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { collectNativeKnowledgeChunks, type NativeKnowledgeChunk } from \"./native-knowledge.js\";\nimport { compareEntityTimestamps, normalizeEntityName, type StorageManager } from \"./storage.js\";\nimport { normalizeEntityText, resolveRequestedEntitySectionKeys } from \"./entity-schema.js\";\nimport type { EntityStructuredSection, MemoryFile, PluginConfig, TranscriptEntry } from \"./types.js\";\n\nconst ENTITY_INDEX_VERSION = 3;\nconst RECENT_TRANSCRIPT_LOOKBACK_HOURS = 24;\nconst INSTRUCTION_LIKE_RE = /\\b(always|never|must|should|remember to|do not|don't|process|workflow|template|checklist|instruction)\\b/i;\nconst METADATA_WRAPPER_RE = /^(source|context|metadata|notes?):/i;\nconst ENTITY_PRONOUN_RE = /\\b(he|him|his|she|her|they|them|their|it|its)\\b/i;\n\ntype EntityQueryMode = \"direct\" | \"timeline\" | \"follow_up\";\n\ntype EntityMentionIndexEntry = {\n canonicalId: string;\n name: string;\n type: string;\n aliases: string[];\n summary?: string;\n facts: string[];\n timelineFacts: string[];\n structuredSections: EntityStructuredSection[];\n timeline: Array<{\n timestamp: string;\n text: string;\n source?: string;\n sessionKey?: string;\n principal?: string;\n }>;\n relationships: Array<{ target: string; label: string }>;\n activity: Array<{ date: string; note: string }>;\n factCount: number;\n memorySnippets: string[];\n nativeChunks: Array<{\n chunkId: string;\n title: string;\n sourceKind: NativeKnowledgeChunk[\"sourceKind\"];\n sourcePath: string;\n snippet: string;\n derivedDate?: string;\n }>;\n};\n\ntype EntityMentionIndex = {\n version: number;\n updatedAt: string;\n entities: EntityMentionIndexEntry[];\n};\n\ntype EntityCandidate = {\n entry: EntityMentionIndexEntry;\n alias: string;\n score: number;\n source: \"query\" | \"recent_turn\";\n};\n\ntype EntityHintSnippet = {\n text: string;\n score: number;\n kind: \"summary\" | \"fact\" | \"section\" | \"relationship\" | \"activity\" | \"memory\" | \"native\";\n};\n\nexport interface BuildEntityRecallSectionOptions {\n config: PluginConfig;\n storage: StorageManager;\n query: string;\n recallNamespaces?: string[];\n recentTurns: number;\n maxHints: number;\n maxSupportingFacts: number;\n maxRelatedEntities: number;\n maxChars: number;\n transcriptEntries: TranscriptEntry[];\n}\n\nfunction tokenize(value: string): string[] {\n return normalizeEntityText(value).split(/\\s+/).filter((token) => token.length >= 2);\n}\n\nfunction uniqueStrings(values: string[]): string[] {\n return [...new Set(values.map((value) => value.trim()).filter((value) => value.length > 0))];\n}\n\nfunction containsPhrase(haystack: string, needle: string): boolean {\n if (!needle) return false;\n const escaped = needle.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(`(^|\\\\b)${escaped}(\\\\b|$)`, \"i\").test(haystack);\n}\n\nfunction compactLine(value: string, maxLength: number = 220): string {\n const normalized = value.replace(/\\s+/g, \" \").trim();\n if (normalized.length <= maxLength) return normalized;\n return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;\n}\n\nfunction dedupeHintSnippetsByText(snippets: EntityHintSnippet[]): EntityHintSnippet[] {\n const seen = new Set<string>();\n const result: EntityHintSnippet[] = [];\n for (const snippet of snippets) {\n const key = normalizeEntityText(snippet.text);\n if (seen.has(key)) continue;\n seen.add(key);\n result.push(snippet);\n }\n return result;\n}\n\nfunction relationLine(entry: EntityMentionIndexEntry, relationship: { target: string; label: string }): string {\n const normalizedLabel = relationship.label.replace(/\\s+/g, \" \").trim();\n if (normalizedLabel.length === 0) return `${entry.name} is connected to ${relationship.target}`;\n return `${entry.name} ${normalizedLabel} ${relationship.target}`;\n}\n\nfunction detectEntityQueryMode(query: string): EntityQueryMode | null {\n const normalized = normalizeEntityText(query);\n if (!normalized) return null;\n if (\n /^(what about|and what about|how about|what happened (with|to) (he|him|his|she|her|they|them|their|it|its)|did (he|she|they|it)|is (he|she|they|it)|was (he|she|they|it))\\b/.test(normalized)\n ) {\n return \"follow_up\";\n }\n if (\n /^(who is|who s|what do we know about|what does|tell me about|what can you tell me about|what s new with|what happened with|what happened to|status of|where is|how is)\\b/.test(normalized)\n ) {\n if (/^what does\\b/.test(normalized)) {\n if (/^what does (?:this|that|it|the|a|an|my|our|your|their)\\b/.test(normalized)) {\n return null;\n }\n if (\n /^what does [a-z0-9-]+ (?:error|warning|exception|failure|stack|trace|code|message|log)\\b/.test(normalized)\n && /\\b(mean|means|indicate|indicates|imply|implies)\\b/.test(normalized)\n ) {\n return null;\n }\n }\n return /what happened|what s new|status of|how is|where is/.test(normalized) ? \"timeline\" : \"direct\";\n }\n if (ENTITY_PRONOUN_RE.test(normalized) && normalized.split(/\\s+/).length <= 8) {\n return \"follow_up\";\n }\n return null;\n}\n\nfunction scoreAliasMatch(query: string, alias: string): number {\n const normalizedQuery = normalizeEntityText(query);\n const normalizedAlias = normalizeEntityText(alias);\n if (!normalizedAlias) return 0;\n if (normalizedQuery === normalizedAlias) return 10;\n if (containsPhrase(normalizedQuery, normalizedAlias)) return 8 + Math.min(normalizedAlias.split(/\\s+/).length, 3);\n const queryTokens = new Set(tokenize(normalizedQuery));\n const aliasTokens = tokenize(normalizedAlias);\n const overlap = aliasTokens.filter((token) => queryTokens.has(token)).length;\n if (overlap === 0) return 0;\n return overlap;\n}\n\nfunction isLikelyInstructionLike(value: string): boolean {\n return INSTRUCTION_LIKE_RE.test(value) || METADATA_WRAPPER_RE.test(value);\n}\n\nfunction sanitizeEntityFact(fact: string): string {\n const sanitized = sanitizeMemoryContent(fact);\n const clean = sanitized.text.trim();\n if (!clean) return \"\";\n if (INSTRUCTION_LIKE_RE.test(clean) && clean.length > 100) return \"\";\n return clean;\n}\n\nfunction scoreHintSnippet(snippet: EntityHintSnippet, queryTokens: string[]): EntityHintSnippet | null {\n const normalized = normalizeEntityText(snippet.text);\n if (!normalized) return null;\n const scored = { ...snippet };\n if (isLikelyInstructionLike(scored.text) && scored.kind !== \"summary\") {\n scored.score -= 3;\n }\n const overlap = queryTokens.filter((token) => normalized.includes(token)).length;\n scored.score += overlap * 2;\n if (METADATA_WRAPPER_RE.test(scored.text)) scored.score -= 2;\n if (scored.text.length <= 160) scored.score += 1;\n return scored.score > 0 ? scored : null;\n}\n\nfunction sortTimelineEntriesDesc(\n left: EntityMentionIndexEntry[\"timeline\"][number],\n right: EntityMentionIndexEntry[\"timeline\"][number],\n): number {\n const timestampOrder = compareEntityTimestamps(right.timestamp, left.timestamp);\n if (timestampOrder !== 0) {\n return timestampOrder;\n }\n return right.text.localeCompare(left.text);\n}\n\nfunction jaccardSimilarity(a: string, b: string): number {\n const aTokens = new Set(tokenize(a));\n const bTokens = new Set(tokenize(b));\n if (aTokens.size === 0 || bTokens.size === 0) return 0;\n let intersection = 0;\n for (const token of aTokens) {\n if (bTokens.has(token)) intersection += 1;\n }\n const union = new Set([...aTokens, ...bTokens]).size;\n return union === 0 ? 0 : intersection / union;\n}\n\nfunction buildAliasIndex(entries: EntityMentionIndexEntry[]): Map<string, EntityMentionIndexEntry[]> {\n const index = new Map<string, EntityMentionIndexEntry[]>();\n for (const entry of entries) {\n const aliases = uniqueStrings([entry.name, ...entry.aliases]).map(normalizeEntityText).filter(Boolean);\n for (const alias of aliases) {\n const existing = index.get(alias) ?? [];\n existing.push(entry);\n index.set(alias, existing);\n }\n }\n return index;\n}\n\nasync function readNativeChunks(\n config: PluginConfig,\n recallNamespaces?: string[],\n): Promise<NativeKnowledgeChunk[]> {\n if (!config.nativeKnowledge?.enabled) return [];\n return collectNativeKnowledgeChunks({\n workspaceDir: config.workspaceDir,\n memoryDir: config.memoryDir,\n config: config.nativeKnowledge,\n recallNamespaces: config.namespacesEnabled ? recallNamespaces : undefined,\n defaultNamespace: config.defaultNamespace,\n }).catch(() => []);\n}\n\nfunction entityIndexStatePath(storage: StorageManager): string {\n return path.join(storage.dir, \"state\", \"entity-mention-index.json\");\n}\n\nasync function readEntityIndexState(storage: StorageManager): Promise<EntityMentionIndex | null> {\n const raw = await readFile(entityIndexStatePath(storage), \"utf-8\").catch(() => \"\");\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw) as Partial<EntityMentionIndex>;\n if (parsed.version !== ENTITY_INDEX_VERSION || !Array.isArray(parsed.entities)) return null;\n return parsed as EntityMentionIndex;\n } catch {\n return null;\n }\n}\n\nasync function writeEntityIndexState(storage: StorageManager, index: EntityMentionIndex): Promise<void> {\n const statePath = entityIndexStatePath(storage);\n await mkdir(path.dirname(statePath), { recursive: true });\n const nextContent = JSON.stringify(index, null, 2) + \"\\n\";\n const currentContent = await readFile(statePath, \"utf-8\").catch(() => \"\");\n if (currentContent === nextContent) return;\n await writeFile(statePath, nextContent, \"utf-8\");\n}\n\nfunction nativePseudoCanonicalId(chunk: NativeKnowledgeChunk): string {\n return `native:${createHash(\"sha256\").update(chunk.sourcePath).digest(\"hex\").slice(0, 12)}`;\n}\n\nfunction createPseudoNativeEntry(chunk: NativeKnowledgeChunk): EntityMentionIndexEntry {\n const canonicalId = nativePseudoCanonicalId(chunk);\n return {\n canonicalId,\n name: chunk.title,\n type: chunk.sourceKind,\n aliases: uniqueStrings(chunk.aliases ?? []),\n facts: [],\n structuredSections: [],\n timelineFacts: [],\n timeline: [],\n relationships: [],\n activity: [],\n factCount: 0,\n memorySnippets: [],\n nativeChunks: [\n {\n chunkId: chunk.chunkId,\n title: chunk.title,\n sourceKind: chunk.sourceKind,\n sourcePath: chunk.sourcePath,\n snippet: compactLine(chunk.content, 180),\n derivedDate: chunk.derivedDate,\n },\n ],\n };\n}\n\nfunction mergeNativeChunk(entry: EntityMentionIndexEntry, chunk: NativeKnowledgeChunk): void {\n const existing = entry.nativeChunks.find((item) => item.chunkId === chunk.chunkId);\n if (existing) return;\n entry.nativeChunks.push({\n chunkId: chunk.chunkId,\n title: chunk.title,\n sourceKind: chunk.sourceKind,\n sourcePath: chunk.sourcePath,\n snippet: compactLine(chunk.content, 180),\n derivedDate: chunk.derivedDate,\n });\n entry.aliases = uniqueStrings([...entry.aliases, ...(chunk.aliases ?? [])]);\n}\n\nasync function buildEntityMentionIndex(\n storage: StorageManager,\n config: PluginConfig,\n recallNamespaces?: string[],\n): Promise<EntityMentionIndex> {\n const [previousIndex, entityFiles, memories, nativeChunks] = await Promise.all([\n readEntityIndexState(storage),\n storage.readAllEntityFiles(),\n storage.readAllMemories(),\n readNativeChunks(config, recallNamespaces),\n ]);\n\n const entities = new Map<string, EntityMentionIndexEntry>();\n for (const entity of entityFiles) {\n const canonicalId = normalizeEntityName(entity.name, entity.type);\n const sanitizedFacts = entity.facts.map((fact) => sanitizeEntityFact(fact)).filter(Boolean).map((fact) => compactLine(fact, 180));\n const sanitizedTimelineFacts = entity.timeline\n .map((entry) => sanitizeEntityFact(entry.text))\n .filter(Boolean)\n .map((fact) => compactLine(fact, 180));\n entities.set(canonicalId, {\n canonicalId,\n name: entity.name,\n type: entity.type,\n aliases: uniqueStrings(entity.aliases),\n summary: entity.synthesis?.trim() || entity.summary?.trim() || undefined,\n facts: sanitizedFacts,\n timelineFacts: uniqueStrings(sanitizedTimelineFacts),\n structuredSections: (entity.structuredSections ?? []).map((section) => ({\n key: section.key,\n title: section.title,\n facts: section.facts\n .map((fact) => sanitizeEntityFact(fact))\n .filter(Boolean)\n .map((fact) => compactLine(fact, 180)),\n })).filter((section) => section.facts.length > 0),\n timeline: entity.timeline.map((entry) => ({ ...entry })),\n relationships: entity.relationships.map((relationship) => ({ ...relationship })),\n activity: entity.activity.map((activity) => ({ ...activity })),\n factCount: sanitizedFacts.length,\n memorySnippets: [],\n nativeChunks: [],\n });\n }\n\n for (const memory of memories) {\n const entityRef = typeof memory.frontmatter.entityRef === \"string\" ? memory.frontmatter.entityRef : \"\";\n if (!entityRef) continue;\n const entry = entities.get(entityRef);\n if (!entry) continue;\n const snippet = await readMemorySnippet(memory);\n if (!entry.memorySnippets.includes(snippet)) {\n entry.memorySnippets.push(snippet);\n }\n }\n\n const aliasIndex = buildAliasIndex([...entities.values()]);\n for (const chunk of nativeChunks) {\n const existingPseudo = entities.get(nativePseudoCanonicalId(chunk));\n if (existingPseudo) {\n mergeNativeChunk(existingPseudo, chunk);\n continue;\n }\n const candidateAliases = uniqueStrings([chunk.title, ...(chunk.aliases ?? [])]).map(normalizeEntityText).filter(Boolean);\n let matched = false;\n for (const alias of candidateAliases) {\n for (const entry of aliasIndex.get(alias) ?? []) {\n mergeNativeChunk(entry, chunk);\n matched = true;\n }\n }\n if (matched) continue;\n const pseudoEntry = createPseudoNativeEntry(chunk);\n entities.set(pseudoEntry.canonicalId, pseudoEntry);\n }\n\n const sortedEntities = [...entities.values()].sort((left, right) => left.name.localeCompare(right.name));\n const previousEntities = previousIndex ? JSON.stringify(previousIndex.entities) : \"\";\n const nextEntities = JSON.stringify(sortedEntities);\n const index: EntityMentionIndex = {\n version: ENTITY_INDEX_VERSION,\n updatedAt:\n previousIndex && previousEntities === nextEntities\n ? previousIndex.updatedAt\n : new Date().toISOString(),\n entities: sortedEntities,\n };\n await writeEntityIndexState(storage, index);\n return index;\n}\n\nfunction resolveExplicitCandidates(\n index: EntityMentionIndex,\n query: string,\n): EntityCandidate[] {\n const candidates: EntityCandidate[] = [];\n for (const entry of index.entities) {\n const aliases = uniqueStrings([entry.name, ...entry.aliases]);\n let bestAlias = \"\";\n let bestScore = 0;\n for (const alias of aliases) {\n const score = scoreAliasMatch(query, alias);\n if (score > bestScore) {\n bestAlias = alias;\n bestScore = score;\n }\n }\n if (bestScore <= 0) continue;\n candidates.push({ entry, alias: bestAlias, score: bestScore, source: \"query\" });\n }\n return candidates.sort((left, right) => right.score - left.score);\n}\n\nfunction resolveRecentTurnCandidates(\n index: EntityMentionIndex,\n transcriptEntries: TranscriptEntry[],\n recentTurns: number,\n): EntityCandidate[] {\n if (recentTurns <= 0 || transcriptEntries.length === 0) return [];\n const recentEntries = transcriptEntries.slice(-recentTurns);\n const candidates = new Map<string, EntityCandidate>();\n for (let indexOffset = recentEntries.length - 1; indexOffset >= 0; indexOffset -= 1) {\n const turn = recentEntries[indexOffset];\n const recencyBoost = recentEntries.length - indexOffset;\n const roleWeight = turn.role === \"user\" ? 2 : turn.role === \"assistant\" ? -1 : 0;\n for (const entry of index.entities) {\n const aliases = uniqueStrings([entry.name, ...entry.aliases]);\n for (const alias of aliases) {\n const score = scoreAliasMatch(turn.content, alias);\n if (score <= 0) continue;\n const current = candidates.get(entry.canonicalId);\n const weightedScore = score + Math.max(0, 6 - recencyBoost) + roleWeight;\n if (!current || weightedScore > current.score) {\n candidates.set(entry.canonicalId, {\n entry,\n alias,\n score: weightedScore,\n source: \"recent_turn\",\n });\n }\n }\n }\n }\n return [...candidates.values()].sort((left, right) => right.score - left.score);\n}\n\nasync function readMemorySnippet(memory: MemoryFile): Promise<string> {\n const content = memory.content.replace(/\\s+/g, \" \").trim();\n return compactLine(content, 180);\n}\n\nasync function buildHintSnippets(\n entry: EntityMentionIndexEntry,\n queryTokens: string[],\n mode: EntityQueryMode,\n maxSupportingFacts: number,\n requestedSectionKeys: Set<string>,\n): Promise<EntityHintSnippet[]> {\n const snippets: EntityHintSnippet[] = [];\n const aliasTokens = new Set(tokenize(uniqueStrings([entry.name, ...entry.aliases]).join(\" \")));\n if (entry.summary) {\n snippets.push({ text: compactLine(entry.summary, 180), score: 10, kind: \"summary\" });\n }\n\n if (requestedSectionKeys.size > 0) {\n for (const section of entry.structuredSections) {\n if (!requestedSectionKeys.has(normalizeEntityText(section.key).replace(/\\s+/g, \"_\"))) continue;\n for (const fact of section.facts) {\n snippets.push({ text: fact, score: mode === \"direct\" ? 8 : 9, kind: \"section\" });\n }\n }\n } else {\n for (const fact of entry.timelineFacts) {\n snippets.push({ text: fact, score: mode === \"direct\" ? 6 : 7, kind: \"fact\" });\n }\n for (const section of entry.structuredSections) {\n for (const fact of section.facts) {\n const normalizedFact = normalizeEntityText(fact);\n const hasNonAliasQueryOverlap = queryTokens.some((token) =>\n !aliasTokens.has(token) && normalizedFact.includes(token)\n );\n if (entry.timelineFacts.length > 0 && !hasNonAliasQueryOverlap) {\n continue;\n }\n snippets.push({ text: fact, score: mode === \"direct\" ? 6 : 7, kind: \"fact\" });\n }\n }\n if (entry.timelineFacts.length === 0 && entry.structuredSections.length === 0) {\n for (const fact of entry.facts) {\n if (!fact.trim()) continue;\n snippets.push({ text: fact, score: mode === \"direct\" ? 6 : 7, kind: \"fact\" });\n }\n }\n }\n\n if (requestedSectionKeys.size === 0) {\n for (const relationship of entry.relationships) {\n snippets.push({\n text: compactLine(relationLine(entry, relationship), 180),\n score: mode === \"direct\" && entry.type.toLowerCase() === \"person\" ? 6 : 4,\n kind: \"relationship\",\n });\n }\n\n for (const activity of entry.activity) {\n snippets.push({\n text: compactLine(`${activity.date}: ${activity.note}`, 180),\n score: 4,\n kind: \"activity\",\n });\n }\n\n for (const memorySnippet of entry.memorySnippets.slice(0, Math.min(maxSupportingFacts, 4))) {\n snippets.push({\n text: memorySnippet,\n score: 5,\n kind: \"memory\",\n });\n }\n\n for (const chunk of entry.nativeChunks) {\n snippets.push({\n text: compactLine(chunk.snippet, 180),\n score: 3,\n kind: \"native\",\n });\n }\n }\n\n const deduped = new Map<string, EntityHintSnippet>();\n for (const snippet of snippets) {\n const scored = scoreHintSnippet(snippet, queryTokens);\n if (!scored) continue;\n const normalized = normalizeEntityText(scored.text);\n const existing = deduped.get(normalized);\n if (!existing || scored.score > existing.score) deduped.set(normalized, scored);\n }\n\n return [...deduped.values()]\n .filter((snippet) => snippet.score > 0)\n .sort((left, right) => right.score - left.score)\n .slice(0, maxSupportingFacts);\n}\n\nfunction summarizeUncertainty(snippets: EntityHintSnippet[]): string | null {\n const direct = snippets.filter((snippet) =>\n snippet.kind === \"summary\"\n || snippet.kind === \"fact\"\n || snippet.kind === \"section\"\n || snippet.kind === \"memory\"\n );\n if (direct.length < 2) return null;\n for (let index = 0; index < direct.length; index += 1) {\n for (let compare = index + 1; compare < direct.length; compare += 1) {\n if (jaccardSimilarity(direct[index].text, direct[compare].text) < 0.2) {\n return \"Evidence is mixed across stored facts; treat the hints below as partial and verify before answering definitively.\";\n }\n }\n }\n return null;\n}\n\nfunction formatEntityHintSection(\n candidates: Array<{\n candidate: EntityCandidate;\n snippets: EntityHintSnippet[];\n uncertainty: string | null;\n }>,\n queryTokens: string[],\n mode: EntityQueryMode,\n maxRelatedEntities: number,\n maxChars: number,\n): string | null {\n if (candidates.length === 0) return null;\n const lines: string[] = [\"## entity_answer_hints\", \"\"];\n for (const { candidate, snippets, uncertainty } of candidates) {\n const hasSummary = Boolean(candidate.entry.summary?.trim());\n const preferredTopSnippets = hasSummary\n ? snippets.filter((snippet) => snippet.kind !== \"fact\")\n : snippets;\n let topSnippets = (\n preferredTopSnippets.length > 0 ? preferredTopSnippets : snippets\n ).slice(0, 3);\n const buildTimelineSnippets = (seedExcludedTexts: Set<string>): EntityHintSnippet[] => {\n const explicitTimelinePool = dedupeHintSnippetsByText(\n (candidate.entry.timeline ?? [])\n .slice()\n .sort(sortTimelineEntriesDesc)\n .map((entry) => sanitizeEntityFact(entry.text))\n .filter(Boolean)\n .map((text) => scoreHintSnippet({\n text: compactLine(text, 180),\n score: 7,\n kind: \"activity\" as const,\n }, queryTokens))\n .filter((snippet): snippet is EntityHintSnippet => snippet !== null)\n .filter((snippet) => !seedExcludedTexts.has(normalizeEntityText(snippet.text))),\n ).slice(0, 2);\n const activityTimelinePool = dedupeHintSnippetsByText(\n snippets\n .filter((snippet) => (\n snippet.kind === \"activity\" || snippet.kind === \"memory\"\n ) && !seedExcludedTexts.has(normalizeEntityText(snippet.text))),\n ).slice(0, 2);\n return explicitTimelinePool.length > 0\n ? explicitTimelinePool\n : activityTimelinePool.length > 0\n ? activityTimelinePool\n : dedupeHintSnippetsByText(\n snippets\n .filter((snippet) => (\n snippet.kind === \"fact\" || snippet.kind === \"summary\"\n ) && !seedExcludedTexts.has(normalizeEntityText(snippet.text))),\n ).slice(0, 2);\n };\n const baseTopSnippetTexts = new Set(topSnippets.map((snippet) => normalizeEntityText(snippet.text)));\n const timelinePool = mode !== \"direct\" ? buildTimelineSnippets(baseTopSnippetTexts) : [];\n if (mode !== \"direct\" && hasSummary && topSnippets.length < 2) {\n if (timelinePool.length > 0) {\n topSnippets = [...topSnippets, timelinePool[0]!].slice(0, 3);\n }\n }\n const topSnippetTexts = new Set(topSnippets.map((snippet) => normalizeEntityText(snippet.text)));\n lines.push(`- target: ${candidate.entry.name} (${candidate.entry.type})`);\n if (candidate.source === \"recent_turn\") {\n lines.push(`- resolution: carried forward from recent turns via alias \"${candidate.alias}\"`);\n } else {\n lines.push(`- resolution: matched alias \"${candidate.alias}\" in the query`);\n }\n if (uncertainty) lines.push(`- uncertainty: ${uncertainty}`);\n if (topSnippets.length > 0) {\n lines.push(\"- likely answer:\");\n for (const snippet of topSnippets) {\n lines.push(` - ${snippet.text}`);\n }\n }\n if (mode !== \"direct\") {\n const fallbackTimeline = timelinePool.filter(\n (snippet) => !topSnippetTexts.has(normalizeEntityText(snippet.text)),\n );\n if (fallbackTimeline.length > 0) {\n lines.push(\"- recent timeline:\");\n for (const snippet of fallbackTimeline) {\n lines.push(` - ${snippet.text}`);\n }\n }\n }\n const related = candidate.entry.relationships.slice(0, maxRelatedEntities).map((relationship) => relationship.target);\n if (related.length > 0) {\n lines.push(`- related entities: ${related.join(\", \")}`);\n }\n lines.push(`- support counts: facts=${candidate.entry.factCount}, memories=${candidate.entry.memorySnippets.length}, native=${candidate.entry.nativeChunks.length}`);\n lines.push(\"\");\n }\n\n let result = lines.join(\"\\n\");\n if (result.length > maxChars) {\n result = `${result.slice(0, Math.max(0, maxChars - 15)).trimEnd()}\\n\\n...(trimmed)\\n`;\n }\n return result.trim().length > 0 ? result.trimEnd() : null;\n}\n\nexport async function buildEntityRecallSection(options: BuildEntityRecallSectionOptions): Promise<string | null> {\n const mode = detectEntityQueryMode(options.query);\n if (!mode) return null;\n\n const index = await buildEntityMentionIndex(options.storage, options.config, options.recallNamespaces);\n if (index.entities.length === 0) return null;\n\n const explicitCandidates = resolveExplicitCandidates(index, options.query);\n const candidates = explicitCandidates.length > 0\n ? explicitCandidates\n : resolveRecentTurnCandidates(index, options.transcriptEntries, options.recentTurns);\n\n if (candidates.length === 0) return null;\n\n const queryTokens = tokenize(options.query);\n const candidateLimit = explicitCandidates.length === 0 && mode === \"follow_up\"\n ? 1\n : options.maxHints;\n const rankedCandidates = candidates.slice(0, candidateLimit);\n const enriched = await Promise.all(\n rankedCandidates.map(async (candidate) => {\n const requestedSectionKeys = new Set(\n resolveRequestedEntitySectionKeys(\n options.query,\n candidate.entry.type,\n candidate.entry.structuredSections,\n options.config.entitySchemas,\n ),\n );\n const snippets = await buildHintSnippets(\n candidate.entry,\n queryTokens,\n mode,\n options.maxSupportingFacts,\n requestedSectionKeys,\n );\n return {\n candidate,\n snippets,\n uncertainty: summarizeUncertainty(snippets),\n };\n }),\n );\n\n const section = formatEntityHintSection(enriched, queryTokens, mode, options.maxRelatedEntities, options.maxChars);\n if (!section) return null;\n return section;\n}\n\nexport async function readRecentEntityTranscriptEntries(\n transcriptEntriesPromise: Promise<TranscriptEntry[]>,\n recentTurns: number,\n): Promise<TranscriptEntry[]> {\n if (recentTurns <= 0) return [];\n const transcriptEntries = await transcriptEntriesPromise.catch(() => []);\n if (transcriptEntries.length === 0) return [];\n return transcriptEntries.slice(-Math.max(1, recentTurns * 2));\n}\n\nexport const entityIndexVersion = ENTITY_INDEX_VERSION;\nexport const entityRecentTranscriptLookbackHours = RECENT_TRANSCRIPT_LOOKBACK_HOURS;\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/iso-timestamp.ts","../src/replay/types.ts","../src/utils/path.ts","../src/routing/store.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Shared ISO-8601 / RFC 3339 timestamp validation helpers.\n//\n// Two public entry points — a strict UTC-only parser used by the replay\n// pipeline, and a more permissive parser used by bulk-import adapters that\n// need to preserve source timezone offsets. Both share date-component,\n// offset-range, and round-trip validation so they cannot silently diverge.\n// ---------------------------------------------------------------------------\n\n// UTC-only: `...Z`, 0 or 3 fractional digits (replay canonical form).\nconst ISO_UTC_TIMESTAMP_RE =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$/;\n\n// Lenient: variable-precision fractional seconds and `Z` or `[+-]HH:MM` offset.\nconst ISO_OFFSET_TIMESTAMP_RE =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/;\n\n/**\n * Validate the date/time components of an ISO timestamp string.\n * Catches overflowed dates like Feb 31 that `Date.parse` silently normalizes.\n */\nfunction validateDateComponents(isoString: string): boolean {\n const match = isoString.match(\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})/,\n );\n if (!match) return false;\n const [, yStr, mStr, dStr, hStr, minStr, sStr] = match;\n const y = Number(yStr);\n const m = Number(mStr);\n const d = Number(dStr);\n const h = Number(hStr);\n const min = Number(minStr);\n const s = Number(sStr);\n if (m < 1 || m > 12) return false;\n if (d < 1 || d > 31) return false;\n if (h > 23 || min > 59 || s > 59) return false;\n // Validate day for the specific month (using Date(y, m, 0) to get days).\n const daysInMonth = new Date(y, m, 0).getDate();\n if (d > daysInMonth) return false;\n return true;\n}\n\n/**\n * Validate the timezone offset range if present.\n * Max offset is +/-14:00 per ISO 8601; minute part must be 0-59.\n */\nfunction validateOffset(isoString: string): boolean {\n const offsetMatch = isoString.match(/([+-])(\\d{2}):(\\d{2})$/);\n if (!offsetMatch) return true; // `Z` form, no offset to validate.\n const oh = Number(offsetMatch[2]);\n const om = Number(offsetMatch[3]);\n if (oh > 14 || om > 59) return false;\n // +14:00 is max; offsets like +14:30 are invalid.\n if (oh === 14 && om > 0) return false;\n return true;\n}\n\n/**\n * Normalize a `Z`-suffixed ISO timestamp to exactly three fractional digits so\n * the round-trip comparison against `Date.prototype.toISOString()` succeeds\n * regardless of input precision (or absence of a fractional part).\n */\nfunction normalizeUtcForComparison(value: string): string {\n const fracMatch = value.match(/\\.(\\d+)Z$/);\n if (fracMatch) {\n const ms = (fracMatch[1] + \"000\").slice(0, 3);\n return value.replace(/\\.\\d+Z$/, `.${ms}Z`);\n }\n return value.replace(/Z$/, \".000Z\");\n}\n\n/**\n * Strict UTC-only parser — accepts `YYYY-MM-DDTHH:MM:SS[.sss]Z`.\n * Returns milliseconds since epoch, or `null` if invalid.\n */\nexport function parseIsoUtcTimestamp(value: string): number | null {\n if (typeof value !== \"string\" || !ISO_UTC_TIMESTAMP_RE.test(value)) {\n return null;\n }\n const ts = Date.parse(value);\n if (!Number.isFinite(ts)) return null;\n if (!validateDateComponents(value)) return null;\n const roundTrip = new Date(ts).toISOString();\n if (roundTrip !== normalizeUtcForComparison(value)) return null;\n return ts;\n}\n\n/**\n * Lenient parser — accepts variable-precision fractional seconds and either\n * a `Z` suffix or a `[+-]HH:MM` offset. Returns milliseconds since epoch, or\n * `null` if the string is not a well-formed RFC 3339 timestamp.\n */\nexport function parseIsoOffsetTimestamp(value: string): number | null {\n if (typeof value !== \"string\" || !ISO_OFFSET_TIMESTAMP_RE.test(value)) {\n return null;\n }\n const ts = Date.parse(value);\n if (!Number.isFinite(ts)) return null;\n if (!validateDateComponents(value)) return null;\n if (!validateOffset(value)) return null;\n // For UTC timestamps (ending in `Z`), verify with a round-trip so that\n // overflowed UTC calendar dates cannot slip through.\n if (value.endsWith(\"Z\")) {\n const roundTrip = new Date(ts).toISOString();\n if (roundTrip !== normalizeUtcForComparison(value)) return null;\n }\n return ts;\n}\n","import { parseIsoUtcTimestamp } from \"../utils/iso-timestamp.js\";\n\nexport type ReplaySource = \"openclaw\" | \"claude\" | \"chatgpt\";\nexport type ReplayRole = \"user\" | \"assistant\";\n\nexport interface ReplayTurn {\n source: ReplaySource;\n sessionKey: string;\n role: ReplayRole;\n content: string;\n timestamp: string;\n externalId?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ReplayWarning {\n code: string;\n message: string;\n index?: number;\n}\n\nexport interface ReplayValidationIssue {\n code: string;\n message: string;\n index?: number;\n}\n\nexport interface ReplayParseOptions {\n from?: string;\n to?: string;\n defaultSessionKey?: string;\n strict?: boolean;\n}\n\nexport interface ReplayParseResult {\n turns: ReplayTurn[];\n warnings: ReplayWarning[];\n}\n\nexport interface ReplayNormalizer {\n source: ReplaySource;\n parse(input: unknown, options?: ReplayParseOptions): Promise<ReplayParseResult> | ReplayParseResult;\n}\n\nconst VALID_SOURCES: ReadonlySet<string> = new Set([\"openclaw\", \"claude\", \"chatgpt\"]);\nconst VALID_ROLES: ReadonlySet<string> = new Set([\"user\", \"assistant\"]);\nexport const REPLAY_UNKNOWN_SESSION_KEY = \"replay:unknown\";\n\nexport function isReplaySource(value: unknown): value is ReplaySource {\n return typeof value === \"string\" && VALID_SOURCES.has(value);\n}\n\nexport function isReplayRole(value: unknown): value is ReplayRole {\n return typeof value === \"string\" && VALID_ROLES.has(value);\n}\n\nexport function normalizeReplaySessionKey(value: unknown): string {\n if (typeof value !== \"string\") return REPLAY_UNKNOWN_SESSION_KEY;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : REPLAY_UNKNOWN_SESSION_KEY;\n}\n\n/**\n * Strict UTC-only ISO-8601 parser used by the replay pipeline.\n *\n * Delegates to the shared parser in `utils/iso-timestamp.ts` — do not\n * reimplement locally; extend that helper instead. Replay intentionally\n * rejects timezone-offset timestamps to keep canonical form consistent\n * across recorded transcripts.\n */\nexport function parseIsoTimestamp(value: string): number | null {\n return parseIsoUtcTimestamp(value);\n}\n\nexport function validateReplayTurn(turn: ReplayTurn, index?: number): ReplayValidationIssue[] {\n const issues: ReplayValidationIssue[] = [];\n if (!turn || typeof turn !== \"object\") {\n issues.push({\n code: \"turn.invalid\",\n message: \"Replay turn must be an object.\",\n index,\n });\n return issues;\n }\n\n if (!isReplayRole(turn.role)) {\n issues.push({\n code: \"turn.role.invalid\",\n message: `Replay role must be 'user' or 'assistant', received '${String(turn.role)}'.`,\n index,\n });\n }\n\n if (!isReplaySource(turn.source)) {\n issues.push({\n code: \"turn.source.invalid\",\n message: `Replay source must be 'openclaw', 'claude', or 'chatgpt', received '${String(turn.source)}'.`,\n index,\n });\n }\n\n if (!turn.sessionKey || typeof turn.sessionKey !== \"string\" || turn.sessionKey.trim().length === 0) {\n issues.push({\n code: \"turn.sessionKey.invalid\",\n message: \"Replay sessionKey is required.\",\n index,\n });\n }\n\n if (!turn.content || typeof turn.content !== \"string\" || turn.content.trim().length === 0) {\n issues.push({\n code: \"turn.content.invalid\",\n message: \"Replay content must be a non-empty string.\",\n index,\n });\n }\n\n if (!turn.timestamp || typeof turn.timestamp !== \"string\" || parseIsoTimestamp(turn.timestamp) === null) {\n issues.push({\n code: \"turn.timestamp.invalid\",\n message: `Replay timestamp must be a valid ISO timestamp, received '${String(turn.timestamp)}'.`,\n index,\n });\n }\n\n return issues;\n}\n","/**\n * Shared path helpers. CLAUDE.md #17 requires consistent `~` expansion across\n * every user-facing path input, but Node's `fs` does not expand `~`, so every\n * call site must go through this helper.\n */\n\nimport path from \"node:path\";\n\nimport { resolveHomeDir } from \"../runtime/env.js\";\n\n/**\n * Expand a leading `~` or `~/…` to the resolved home directory.\n *\n * Leaves paths without a leading `~` unchanged — including absolute paths,\n * relative paths, and paths that contain `~` in the middle.\n *\n * Accepts both `~/` (POSIX) and `~\\` (Windows) as separators so call sites\n * don't have to branch on platform.\n */\nexport function expandTildePath(p: string): string {\n if (p === \"~\") return resolveHomeDir();\n if (p.startsWith(\"~/\") || p.startsWith(\"~\\\\\")) {\n return path.join(resolveHomeDir(), p.slice(2));\n }\n return p;\n}\n","import { lstat, mkdir, readFile, realpath, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { log } from \"../logger.js\";\nimport { validateRouteTarget, type RouteRule, type RoutingEngineOptions } from \"./engine.js\";\n\ntype RoutingRulesState = {\n version: 1;\n updatedAt: string;\n rules: RouteRule[];\n};\n\nfunction defaultState(): RoutingRulesState {\n return {\n version: 1,\n updatedAt: new Date(0).toISOString(),\n rules: [],\n };\n}\n\nfunction stableRuleId(rule: Pick<RouteRule, \"patternType\" | \"pattern\" | \"priority\" | \"target\">): string {\n const seed = JSON.stringify({\n patternType: rule.patternType,\n pattern: rule.pattern.trim(),\n priority: rule.priority,\n target: rule.target,\n });\n return `route-${createHash(\"sha256\").update(seed).digest(\"hex\").slice(0, 12)}`;\n}\n\nfunction resolveStatePath(memoryDir: string, stateFile: string): string {\n const root = path.resolve(memoryDir);\n const defaultPath = path.join(root, \"state\", \"routing-rules.json\");\n if (path.isAbsolute(stateFile)) {\n const absolute = path.resolve(stateFile);\n return absolute.startsWith(root + path.sep) ? absolute : defaultPath;\n }\n const resolved = path.resolve(root, stateFile);\n return resolved.startsWith(root + path.sep) ? resolved : defaultPath;\n}\n\nfunction normalizeRule(rule: RouteRule, options?: RoutingEngineOptions): RouteRule | null {\n if (!rule || typeof rule !== \"object\") return null;\n if (rule.enabled === false) return null;\n if (rule.patternType !== \"keyword\" && rule.patternType !== \"regex\") return null;\n if (typeof rule.pattern !== \"string\" || rule.pattern.trim().length === 0) return null;\n if (typeof rule.priority !== \"number\" || !Number.isFinite(rule.priority)) return null;\n\n const targetValidation = validateRouteTarget(rule.target, options);\n if (!targetValidation.ok || !targetValidation.target) return null;\n\n const normalizedPriority = Math.trunc(rule.priority);\n const normalizedTarget = targetValidation.target;\n const id = typeof rule.id === \"string\" && rule.id.trim().length > 0\n ? rule.id.trim()\n : stableRuleId({\n patternType: rule.patternType,\n pattern: rule.pattern.trim(),\n priority: normalizedPriority,\n target: normalizedTarget,\n });\n return {\n id,\n patternType: rule.patternType,\n pattern: rule.pattern.trim(),\n priority: normalizedPriority,\n target: normalizedTarget,\n enabled: true,\n };\n}\n\nexport class RoutingRulesStore {\n private readonly memoryRoot: string;\n private readonly statePath: string;\n private readonly lockPath: string;\n private writeQueue: Promise<void> = Promise.resolve();\n\n constructor(memoryDir: string, stateFile = \"state/routing-rules.json\") {\n this.memoryRoot = path.resolve(memoryDir);\n this.statePath = resolveStatePath(memoryDir, stateFile);\n this.lockPath = `${this.statePath}.lock`;\n }\n\n async read(options?: RoutingEngineOptions): Promise<RouteRule[]> {\n try {\n const persisted = await this.readPersistedRules();\n return persisted\n .map((rule) => normalizeRule(rule, options))\n .filter((rule): rule is RouteRule => rule !== null);\n } catch {\n return [];\n }\n }\n\n async write(rules: RouteRule[], options?: RoutingEngineOptions): Promise<RouteRule[]> {\n return this.withWriteLock(async () => this.writeNormalized(rules, options));\n }\n\n async upsert(rule: RouteRule, options?: RoutingEngineOptions): Promise<RouteRule[]> {\n return this.withWriteLock(async () => {\n const existing = await this.readPersistedRules();\n const normalized = normalizeRule(rule, options);\n if (!normalized) return existing;\n\n const next = existing.filter((entry) => entry.id !== normalized.id);\n next.push(normalized);\n return this.writeNormalized(next);\n });\n }\n\n async removeByPattern(pattern: string): Promise<RouteRule[]> {\n return this.withWriteLock(async () => {\n const trimmed = pattern.trim();\n const existing = await this.readPersistedRules();\n const next = existing.filter((entry) => entry.pattern !== trimmed);\n if (next.length === existing.length) return existing;\n return this.writeNormalized(next);\n });\n }\n\n async reset(): Promise<void> {\n await this.withWriteLock(async () => {\n const payload = defaultState();\n await this.assertStatePathScoped();\n await writeFile(this.statePath, JSON.stringify(payload, null, 2), \"utf-8\");\n });\n }\n\n private dedupeById(rules: RouteRule[]): RouteRule[] {\n const byId = new Map<string, RouteRule>();\n for (const rule of rules) {\n byId.set(rule.id, rule);\n }\n return Array.from(byId.values());\n }\n\n private async readPersistedRules(): Promise<RouteRule[]> {\n try {\n await this.assertStatePathScoped();\n const raw = await readFile(this.statePath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<RoutingRulesState>;\n if (!parsed || typeof parsed !== \"object\" || !Array.isArray(parsed.rules)) return [];\n const normalized = parsed.rules\n .map((rule) => normalizeRule(rule))\n .filter((rule): rule is RouteRule => rule !== null);\n return this.dedupeById(normalized);\n } catch {\n return [];\n }\n }\n\n private async writeNormalized(rules: RouteRule[], options?: RoutingEngineOptions): Promise<RouteRule[]> {\n const normalized = this.dedupeById(\n rules\n .map((rule) => normalizeRule(rule, options))\n .filter((rule): rule is RouteRule => rule !== null),\n );\n\n const payload: RoutingRulesState = {\n version: 1,\n updatedAt: new Date().toISOString(),\n rules: normalized,\n };\n\n const tmpPath = `${this.statePath}.tmp-${process.pid}-${Date.now()}`;\n try {\n await this.assertStatePathScoped();\n await writeFile(tmpPath, JSON.stringify(payload, null, 2), \"utf-8\");\n await rename(tmpPath, this.statePath);\n } catch (err) {\n log.debug(`routing rules write failed: ${err}`);\n throw err;\n } finally {\n await rm(tmpPath, { force: true }).catch(() => {});\n }\n\n return normalized;\n }\n\n private async withWriteLock<T>(op: () => Promise<T>): Promise<T> {\n const previous = this.writeQueue;\n let release: () => void = () => {};\n this.writeQueue = new Promise<void>((resolve) => {\n release = resolve;\n });\n await previous;\n let unlock: (() => Promise<void>) | null = null;\n try {\n unlock = await this.acquireFileLock();\n return await op();\n } finally {\n if (unlock) await unlock();\n release();\n }\n }\n\n private async acquireFileLock(): Promise<() => Promise<void>> {\n const start = Date.now();\n const staleMs = 30_000;\n const timeoutMs = 5_000;\n let unexpectedLockError: unknown = null;\n await this.assertStatePathScoped();\n await mkdir(path.dirname(this.lockPath), { recursive: true });\n\n while (Date.now() - start < timeoutMs) {\n try {\n await mkdir(this.lockPath);\n return async () => {\n try {\n await rm(this.lockPath, { recursive: true, force: true });\n } catch {\n // Fail-open: lock cleanup should not fail writes.\n }\n };\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") {\n unexpectedLockError = err;\n break;\n }\n try {\n const lockStat = await stat(this.lockPath);\n if (Date.now() - lockStat.mtimeMs > staleMs) {\n await rm(this.lockPath, { recursive: true, force: true });\n continue;\n }\n } catch {\n // Lock may have been released between stat/rm attempts.\n }\n await new Promise((resolve) => setTimeout(resolve, 25));\n }\n }\n\n if (unexpectedLockError) {\n throw unexpectedLockError;\n }\n throw new Error(`routing rules lock acquisition timed out after ${timeoutMs}ms`);\n }\n\n private async assertStatePathScoped(): Promise<void> {\n await mkdir(this.memoryRoot, { recursive: true });\n const canonicalRoot = await realpath(this.memoryRoot);\n const canonicalParent = await this.canonicalizePathWithoutCreating(path.dirname(this.statePath));\n const canonicalStatePath = path.join(canonicalParent, path.basename(this.statePath));\n if (!this.isPathInside(canonicalRoot, canonicalStatePath)) {\n throw new Error(`routing rules state path escaped memoryDir: ${canonicalStatePath}`);\n }\n await mkdir(path.dirname(this.statePath), { recursive: true });\n try {\n const stateStats = await lstat(this.statePath);\n if (stateStats.isSymbolicLink()) {\n const canonicalFile = await realpath(this.statePath);\n if (!this.isPathInside(canonicalRoot, canonicalFile)) {\n throw new Error(`routing rules state symlink escaped memoryDir: ${canonicalFile}`);\n }\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\") {\n throw err;\n }\n }\n }\n\n private isPathInside(root: string, candidate: string): boolean {\n const normalizedRoot = path.resolve(root);\n const normalizedCandidate = path.resolve(candidate);\n if (normalizedCandidate === normalizedRoot) return true;\n if (normalizedRoot === path.parse(normalizedRoot).root) {\n return normalizedCandidate.startsWith(normalizedRoot);\n }\n return normalizedCandidate.startsWith(`${normalizedRoot}${path.sep}`);\n }\n\n private async canonicalizePathWithoutCreating(targetPath: string): Promise<string> {\n const absoluteTarget = path.resolve(targetPath);\n let probe = absoluteTarget;\n while (true) {\n try {\n const canonicalProbe = await realpath(probe);\n const remainder = path.relative(probe, absoluteTarget);\n return path.resolve(canonicalProbe, remainder);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\") {\n throw err;\n }\n const parent = path.dirname(probe);\n if (parent === probe) {\n return absoluteTarget;\n }\n probe = parent;\n }\n }\n }\n}\n"],"mappings":"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","names":["path","path"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/recall-xray.ts"],"sourcesContent":["/**\n * Recall X-ray snapshot schema (issue #570, PR 1).\n *\n * The X-ray surface is the unified, per-result attribution document that\n * merges the tier that served each memory, its score decomposition, any\n * graph path, an audit entry id, and the exact filter/eligibility ladder\n * that either admitted or rejected each candidate. This file defines the\n * schema and an in-memory builder + builder-state helper.\n *\n * Scope for PR 1 (this slice):\n * - Types only + pure builder functions (no IO, no rendering).\n * - Orchestrator plumbing captures a snapshot when the caller passes\n * `xrayCapture: true`. No behavior change when the flag is absent.\n * - NO new public surfaces here — CLI/HTTP/MCP land in later slices.\n *\n * The shared renderer lands in PR 2 at `recall-xray-renderer.ts`. Do not\n * fork formatting logic into other surfaces; extend the renderer.\n */\n\nimport { randomUUID } from \"node:crypto\";\n\nimport type { RecallTierExplain } from \"./types.js\";\n\n/**\n * Which retrieval source produced a given result. This is the X-ray\n * tier ladder called out in issue #570 and is *distinct* from the\n * `RetrievalTier` enum (which describes issue #518's tier-explain\n * block). Keeping the sets separate lets the two observability\n * surfaces evolve without conflating their vocabularies:\n *\n * - `RetrievalTier` — direct-answer eligibility ladder.\n * - `RecallXrayServedBy` — which source materialized each result.\n */\nexport type RecallXrayServedBy =\n | \"direct-answer\"\n | \"hybrid\"\n | \"graph\"\n | \"recent-scan\"\n | \"procedural\"\n | \"review-context\";\n\nexport const RECALL_XRAY_SERVED_BY_VALUES: readonly RecallXrayServedBy[] = [\n \"direct-answer\",\n \"hybrid\",\n \"graph\",\n \"recent-scan\",\n \"procedural\",\n \"review-context\",\n] as const;\n\nexport function isRecallXrayServedBy(\n value: unknown,\n): value is RecallXrayServedBy {\n return (\n typeof value === \"string\" &&\n (RECALL_XRAY_SERVED_BY_VALUES as readonly string[]).includes(value)\n );\n}\n\n/**\n * Score decomposition for a single X-ray result.\n *\n * All fields are optional because different tiers populate different\n * terms: `hybrid` reports vector + bm25 + mmr penalty, `direct-answer`\n * reports importance + tier prior, etc. The only guaranteed field is\n * `final`, which is the post-combination score used for ordering.\n */\nexport interface RecallXrayScoreDecomposition {\n vector?: number;\n bm25?: number;\n importance?: number;\n mmrPenalty?: number;\n tierPrior?: number;\n final: number;\n}\n\n/**\n * Per-result breakdown inside an X-ray snapshot.\n */\nexport interface RecallXrayResult {\n memoryId: string;\n path: string;\n servedBy: RecallXrayServedBy;\n scoreDecomposition: RecallXrayScoreDecomposition;\n graphPath?: string[];\n auditEntryId?: string;\n /** Human-readable list of filters the candidate *passed*. */\n admittedBy: string[];\n /**\n * First filter that *would have* rejected the candidate, or undefined\n * when the candidate was admitted without a rejection trace. When\n * present, `admittedBy` may still contain filters the candidate passed\n * before the rejecting gate; consumers should render both.\n */\n rejectedBy?: string;\n}\n\n/**\n * Trace entry for a filter the orchestrator evaluated during recall.\n * Captures the name of the filter, how many candidates it saw, and how\n * many it let through. Used by X-ray consumers to render the filter\n * ladder above the per-result breakdown.\n */\nexport interface RecallFilterTrace {\n name: string;\n considered: number;\n admitted: number;\n /** Optional human-readable reason for any rejections. */\n reason?: string;\n}\n\n/**\n * The unified X-ray snapshot. CLI, HTTP, and MCP surfaces all render\n * this same shape through the shared renderer (CLAUDE.md rule 22).\n */\nexport interface RecallXraySnapshot {\n /** Stable v1 tag so downstream consumers can version-gate their parsers. */\n schemaVersion: \"1\";\n query: string;\n /** UUID minted per capture; unique across snapshots within a process. */\n snapshotId: string;\n /** Epoch milliseconds the snapshot was captured. */\n capturedAt: number;\n /**\n * Tier-explain block from issue #518, carried verbatim when present.\n * `null` means direct-answer tier did not run (disabled, or another\n * tier served the query).\n */\n tierExplain: RecallTierExplain | null;\n results: RecallXrayResult[];\n filters: RecallFilterTrace[];\n /**\n * Character budget accounting for the final assembled recall payload.\n * `used` is the rendered-context length; `chars` is the cap. Both are\n * non-negative integers in `[0, 2**31)`.\n */\n budget: { chars: number; used: number };\n /** Optional session-scope fields carried for downstream filtering. */\n sessionKey?: string;\n namespace?: string;\n traceId?: string;\n}\n\n// ─── Builder ──────────────────────────────────────────────────────────────\n\nexport interface BuildXraySnapshotInput {\n query: string;\n tierExplain?: RecallTierExplain | null;\n results?: RecallXrayResult[];\n filters?: RecallFilterTrace[];\n budget?: { chars?: number; used?: number };\n sessionKey?: string;\n namespace?: string;\n traceId?: string;\n /** Optional injected timestamp for deterministic tests. */\n now?: () => number;\n /** Optional injected id generator for deterministic tests. */\n snapshotIdGenerator?: () => string;\n}\n\n/**\n * Build a `RecallXraySnapshot` from explicit input fields. Pure\n * function; safe to call from anywhere. All array/object inputs are\n * shallow-copied so caller mutation after build cannot tear the\n * returned snapshot.\n */\nexport function buildXraySnapshot(\n input: BuildXraySnapshotInput,\n): RecallXraySnapshot {\n const now = input.now ?? Date.now;\n const snapshotIdGenerator = input.snapshotIdGenerator ?? randomUUID;\n\n const results = Array.isArray(input.results)\n ? input.results.map(cloneResult)\n : [];\n const filters = Array.isArray(input.filters)\n ? input.filters.map(cloneFilter)\n : [];\n\n const budgetChars = nonNegativeInt(input.budget?.chars);\n const budgetUsed = nonNegativeInt(input.budget?.used);\n\n const tierExplain =\n input.tierExplain && typeof input.tierExplain === \"object\"\n ? cloneTierExplain(input.tierExplain)\n : null;\n\n return {\n schemaVersion: \"1\",\n query: typeof input.query === \"string\" ? input.query : \"\",\n snapshotId: snapshotIdGenerator(),\n capturedAt: now(),\n tierExplain,\n results,\n filters,\n budget: { chars: budgetChars, used: budgetUsed },\n sessionKey: nonEmptyString(input.sessionKey),\n namespace: nonEmptyString(input.namespace),\n traceId: nonEmptyString(input.traceId),\n };\n}\n\n/**\n * Mutable builder used by the orchestrator to accumulate X-ray fields\n * as recall progresses. Call `build()` to get the finalized\n * immutable-ish snapshot. All inputs are validated at insert time so\n * a malformed entry cannot poison the snapshot later.\n */\nexport class RecallXrayBuilder {\n private readonly query: string;\n private readonly sessionKey: string | undefined;\n private namespace: string | undefined;\n private traceId: string | undefined;\n private tierExplain: RecallTierExplain | null = null;\n private readonly results: RecallXrayResult[] = [];\n private readonly filters: RecallFilterTrace[] = [];\n private budgetChars = 0;\n private budgetUsed = 0;\n\n constructor(opts: {\n query: string;\n sessionKey?: string;\n namespace?: string;\n traceId?: string;\n }) {\n this.query = typeof opts.query === \"string\" ? opts.query : \"\";\n this.sessionKey = nonEmptyString(opts.sessionKey);\n this.namespace = nonEmptyString(opts.namespace);\n this.traceId = nonEmptyString(opts.traceId);\n }\n\n setNamespace(namespace: string | undefined): void {\n this.namespace = nonEmptyString(namespace);\n }\n\n setTraceId(traceId: string | undefined): void {\n this.traceId = nonEmptyString(traceId);\n }\n\n setTierExplain(tierExplain: RecallTierExplain | null | undefined): void {\n this.tierExplain =\n tierExplain && typeof tierExplain === \"object\"\n ? cloneTierExplain(tierExplain)\n : null;\n }\n\n setBudget(budget: { chars?: number; used?: number }): void {\n this.budgetChars = nonNegativeInt(budget.chars);\n this.budgetUsed = nonNegativeInt(budget.used);\n }\n\n recordResult(result: RecallXrayResult): void {\n this.results.push(cloneResult(result));\n }\n\n recordFilter(filter: RecallFilterTrace): void {\n this.filters.push(cloneFilter(filter));\n }\n\n build(opts: {\n now?: () => number;\n snapshotIdGenerator?: () => string;\n } = {}): RecallXraySnapshot {\n return buildXraySnapshot({\n query: this.query,\n tierExplain: this.tierExplain,\n results: this.results,\n filters: this.filters,\n budget: { chars: this.budgetChars, used: this.budgetUsed },\n sessionKey: this.sessionKey,\n namespace: this.namespace,\n traceId: this.traceId,\n now: opts.now,\n snapshotIdGenerator: opts.snapshotIdGenerator,\n });\n }\n}\n\n// ─── Internals ────────────────────────────────────────────────────────────\n\nfunction cloneResult(result: RecallXrayResult): RecallXrayResult {\n if (!result || typeof result !== \"object\") {\n throw new TypeError(\"RecallXrayResult must be an object\");\n }\n if (!isRecallXrayServedBy(result.servedBy)) {\n throw new TypeError(\n `RecallXrayResult.servedBy must be one of ${RECALL_XRAY_SERVED_BY_VALUES.join(\n \", \",\n )}; got ${JSON.stringify(result.servedBy)}`,\n );\n }\n const memoryId = typeof result.memoryId === \"string\" ? result.memoryId : \"\";\n const path = typeof result.path === \"string\" ? result.path : \"\";\n const admittedBy = Array.isArray(result.admittedBy)\n ? result.admittedBy.filter((x): x is string => typeof x === \"string\")\n : [];\n const graphPath = Array.isArray(result.graphPath)\n ? result.graphPath.filter((x): x is string => typeof x === \"string\")\n : undefined;\n const auditEntryId = nonEmptyString(result.auditEntryId);\n const rejectedBy = nonEmptyString(result.rejectedBy);\n const scoreDecomposition = cloneScoreDecomposition(result.scoreDecomposition);\n const out: RecallXrayResult = {\n memoryId,\n path,\n servedBy: result.servedBy,\n scoreDecomposition,\n admittedBy,\n };\n if (graphPath !== undefined) out.graphPath = graphPath;\n if (auditEntryId !== undefined) out.auditEntryId = auditEntryId;\n if (rejectedBy !== undefined) out.rejectedBy = rejectedBy;\n return out;\n}\n\nfunction cloneFilter(filter: RecallFilterTrace): RecallFilterTrace {\n if (!filter || typeof filter !== \"object\") {\n throw new TypeError(\"RecallFilterTrace must be an object\");\n }\n const out: RecallFilterTrace = {\n name: typeof filter.name === \"string\" ? filter.name : \"\",\n considered: nonNegativeInt(filter.considered),\n admitted: nonNegativeInt(filter.admitted),\n };\n const reason = nonEmptyString(filter.reason);\n if (reason !== undefined) out.reason = reason;\n return out;\n}\n\nfunction cloneScoreDecomposition(\n value: RecallXrayScoreDecomposition | undefined,\n): RecallXrayScoreDecomposition {\n if (!value || typeof value !== \"object\") {\n return { final: 0 };\n }\n const out: RecallXrayScoreDecomposition = {\n final: finiteNumber(value.final) ?? 0,\n };\n const vector = finiteNumber(value.vector);\n if (vector !== undefined) out.vector = vector;\n const bm25 = finiteNumber(value.bm25);\n if (bm25 !== undefined) out.bm25 = bm25;\n const importance = finiteNumber(value.importance);\n if (importance !== undefined) out.importance = importance;\n const mmrPenalty = finiteNumber(value.mmrPenalty);\n if (mmrPenalty !== undefined) out.mmrPenalty = mmrPenalty;\n const tierPrior = finiteNumber(value.tierPrior);\n if (tierPrior !== undefined) out.tierPrior = tierPrior;\n return out;\n}\n\nfunction cloneTierExplain(tierExplain: RecallTierExplain): RecallTierExplain {\n // Use structuredClone so future RecallTierExplain additions do not\n // silently share references through hand-enumerated fields. The\n // payload is JSON-shaped.\n return structuredClone(tierExplain);\n}\n\nfunction nonNegativeInt(value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 0;\n if (value <= 0) return 0;\n return Math.floor(value);\n}\n\nfunction finiteNumber(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n return value;\n}\n\nfunction nonEmptyString(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n return trimmed;\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/briefing.ts"],"sourcesContent":["/**\n * Daily Context Briefing (Issue #370)\n *\n * Produces a focused \"here is what matters right now\" briefing by\n * cross-referencing active entities, recent facts, open commitments,\n * LLM-generated follow-ups, and an optional calendar source.\n *\n * The module exposes:\n * - `parseBriefingWindow(token)` — CLI-friendly window parser.\n * - `buildBriefing(options)` — core builder that returns markdown + JSON.\n * - `FileCalendarSource` — stub CalendarSource implementation that reads\n * a local ICS or JSON file.\n *\n * ALL OpenAI usage in this module goes through the Responses API. Chat\n * Completions is never used.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { log } from \"./logger.js\";\nimport { StorageManager } from \"./storage.js\";\nimport { readEnvVar, resolveHomeDir } from \"./runtime/env.js\";\nimport type {\n BriefingActiveThread,\n BriefingCalendarSourceError,\n BriefingFocus,\n BriefingFollowup,\n BriefingOpenCommitment,\n BriefingRecentEntity,\n BriefingResult,\n BriefingSections,\n CalendarEvent,\n CalendarSource,\n EntityFile,\n MemoryFile,\n} from \"./types.js\";\n\n// ──────────────────────────────────────────────────────────────────────────\n// Window parsing\n// ──────────────────────────────────────────────────────────────────────────\n\n/** Allowed values for the briefing format flag/field. */\nexport const BRIEFING_FORMAT_ALLOWED = [\"markdown\", \"json\"] as const;\n\n/**\n * Default model used for the Responses API follow-up generation call.\n * Mirrors the extraction engine default in config.ts — keep in sync.\n */\nexport const BRIEFING_FOLLOWUP_DEFAULT_MODEL = \"gpt-5.2\";\nexport type BriefingFormatValue = typeof BRIEFING_FORMAT_ALLOWED[number];\n\n/**\n * Validate a user-supplied `--format` flag value.\n * Returns `null` when the value is valid (or `undefined`, meaning the flag\n * was not supplied and the caller should fall back to the configured default).\n * Returns an error message string when the value is explicitly invalid.\n */\nexport function validateBriefingFormat(value: string | undefined): string | null {\n if (value === undefined) return null;\n if ((BRIEFING_FORMAT_ALLOWED as readonly string[]).includes(value)) return null;\n return `Invalid --format value: \"${value}\". Accepted: ${BRIEFING_FORMAT_ALLOWED.join(\", \")}.`;\n}\n\n/** Parsed briefing lookback window. */\nexport interface ParsedBriefingWindow {\n /** Start of the window (inclusive). */\n from: Date;\n /** End of the window (exclusive). */\n to: Date;\n /** Human-readable label. */\n label: string;\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\n/**\n * Maximum allowed lookback offset in milliseconds (100 years).\n * Anything beyond this is almost certainly a typo or abuse — and would\n * overflow to `Invalid Date` for sufficiently large values anyway.\n */\nconst MAX_WINDOW_MS = 100 * 365 * DAY_MS;\n\n/**\n * Parse a CLI-friendly window token into a concrete date range.\n *\n * Accepted forms (case-insensitive):\n * - `yesterday` — the previous UTC calendar day.\n * - `today` — the current UTC calendar day so far.\n * - `NNh` — last N hours (e.g. `24h`, `48h`).\n * - `NNd` — last N calendar days (e.g. `3d`, `7d`).\n * - `NNw` — last N weeks (e.g. `1w`, `2w`).\n *\n * Returns `null` for invalid tokens so callers can surface a clean error.\n */\nexport function parseBriefingWindow(\n token: string,\n now: Date = new Date(),\n): ParsedBriefingWindow | null {\n const raw = typeof token === \"string\" ? token.trim().toLowerCase() : \"\";\n if (raw.length === 0) return null;\n\n if (raw === \"yesterday\") {\n const startOfToday = startOfUtcDay(now);\n const from = new Date(startOfToday.getTime() - DAY_MS);\n return { from, to: startOfToday, label: \"yesterday\" };\n }\n\n if (raw === \"today\") {\n return { from: startOfUtcDay(now), to: now, label: \"today\" };\n }\n\n const match = raw.match(/^(\\d+)\\s*(h|d|w)$/);\n if (!match) return null;\n const value = parseInt(match[1], 10);\n if (!Number.isFinite(value) || value <= 0) return null;\n const unit = match[2];\n let ms = 0;\n if (unit === \"h\") ms = value * 60 * 60 * 1000;\n else if (unit === \"d\") ms = value * DAY_MS;\n else if (unit === \"w\") ms = value * 7 * DAY_MS;\n if (ms === 0) return null;\n // Reject values that exceed the 100-year cap or would overflow to Invalid Date.\n if (ms > MAX_WINDOW_MS || !Number.isFinite(ms)) return null;\n const from = new Date(now.getTime() - ms);\n if (!Number.isFinite(from.getTime())) return null;\n return {\n from,\n to: now,\n label: `last ${value}${unit}`,\n };\n}\n\nfunction startOfUtcDay(date: Date): Date {\n const d = new Date(date.getTime());\n d.setUTCHours(0, 0, 0, 0);\n return d;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Focus filter\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Parse a CLI `--focus` string into a structured focus filter.\n *\n * Accepted forms:\n * - `person:Jane Doe`\n * - `project:remnic-core`\n * - `topic:retrieval`\n *\n * If no prefix is supplied, falls back to `topic:<value>`.\n */\nexport function parseBriefingFocus(token: string | undefined): BriefingFocus | null {\n if (typeof token !== \"string\") return null;\n const trimmed = token.trim();\n if (trimmed.length === 0) return null;\n const [maybeType, ...rest] = trimmed.split(\":\");\n if (rest.length === 0) {\n return { type: \"topic\", value: maybeType };\n }\n const rawType = maybeType.toLowerCase();\n if (rawType === \"person\" || rawType === \"project\" || rawType === \"topic\") {\n const value = rest.join(\":\").trim();\n if (value.length === 0) return null;\n return { type: rawType, value };\n }\n return { type: \"topic\", value: trimmed };\n}\n\n/**\n * Derive the slugged form of a typed focus value that mirrors how entityRefs\n * are constructed (lowercased, non-alphanumeric runs → hyphens, prefixed with\n * the focus type). Example: `person:Jane Doe` → `\"person-jane-doe\"`.\n *\n * This lets `focusMatchesMemory` match against `entityRef` even when the\n * focus value was supplied with spaces/capitals that the slug normalised away.\n */\nfunction focusToEntityRefSlug(focus: BriefingFocus): string {\n const sluggedValue = focus.value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n return `${focus.type}-${sluggedValue}`;\n}\n\n/**\n * Decide whether a memory/entity matches the given focus filter.\n * Purely deterministic — no LLM, case-insensitive substring match across\n * the most useful surfaces.\n *\n * For `entityRef` matching we also check the slugged form of the typed focus\n * (e.g. `person:Jane Doe` → `\"person-jane-doe\"`) because entityRefs are stored\n * in normalised slug form and a raw substring match on `\"Jane Doe\"` would never\n * hit `\"person-jane-doe\"`.\n */\nexport function focusMatchesMemory(memory: MemoryFile, focus: BriefingFocus): boolean {\n const needle = focus.value.toLowerCase();\n const entityRef = (memory.frontmatter.entityRef ?? \"\").toLowerCase();\n\n // Raw substring match across content and tags (preserves existing behaviour).\n const rawHaystack = [\n memory.content,\n entityRef,\n ...(memory.frontmatter.tags ?? []),\n ]\n .join(\" \")\n .toLowerCase();\n if (rawHaystack.includes(needle)) return true;\n\n // Slug match: check whether the entityRef contains the slugged focus value.\n // This catches typed focus tokens like `person:Jane Doe` whose slug form\n // `\"person-jane-doe\"` matches an entityRef but the raw value never would.\n const slug = focusToEntityRefSlug(focus);\n return entityRef.includes(slug);\n}\n\nexport function focusMatchesEntity(entity: EntityFile, focus: BriefingFocus): boolean {\n const needle = focus.value.toLowerCase();\n if (focus.type === \"person\" && entity.type.toLowerCase() !== \"person\") return false;\n if (focus.type === \"project\" && entity.type.toLowerCase() !== \"project\") return false;\n const haystack = [\n entity.name,\n entity.synthesis || entity.summary || \"\",\n ...entity.facts,\n ...(entity.aliases ?? []),\n ...(entity.structuredSections ?? []).flatMap((section) => [section.title, ...section.facts]),\n ]\n .join(\" \")\n .toLowerCase();\n return haystack.includes(needle);\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Calendar source\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Stub `CalendarSource` backed by a single local file. Supports:\n * - JSON files containing an array of `CalendarEvent` records, OR a wrapper\n * `{ events: CalendarEvent[] }` object.\n * - Minimal ICS (`.ics`) files — extracts `VEVENT` blocks with `SUMMARY`,\n * `DTSTART`, `DTEND`, `LOCATION`, `DESCRIPTION`, `UID`.\n *\n * Real calendar integrations (Google, iCloud, Microsoft) can plug into the\n * same `CalendarSource` interface later.\n */\nexport class FileCalendarSource implements CalendarSource {\n constructor(private readonly filePath: string) {}\n\n async eventsForDate(dateIso: string): Promise<CalendarEvent[]> {\n let raw: string;\n try {\n raw = await readFile(this.filePath, \"utf-8\");\n } catch (err) {\n log.warn(`briefing: calendar source unreadable at ${this.filePath}: ${err}`);\n return [];\n }\n\n const events = this.filePath.toLowerCase().endsWith(\".ics\")\n ? parseIcsEvents(raw)\n : parseJsonEvents(raw);\n\n return events.filter((event) => eventFallsOnDate(event, dateIso));\n }\n}\n\nfunction parseJsonEvents(raw: string): CalendarEvent[] {\n try {\n const parsed = JSON.parse(raw) as unknown;\n const arr = Array.isArray(parsed)\n ? parsed\n : parsed && typeof parsed === \"object\" && Array.isArray((parsed as { events?: unknown }).events)\n ? ((parsed as { events: unknown[] }).events)\n : [];\n const events: CalendarEvent[] = [];\n for (const entry of arr) {\n if (!entry || typeof entry !== \"object\") continue;\n const e = entry as Record<string, unknown>;\n const id = typeof e.id === \"string\" ? e.id : typeof e.uid === \"string\" ? e.uid : cryptoRandomId();\n const title = typeof e.title === \"string\" ? e.title : typeof e.summary === \"string\" ? e.summary : \"\";\n const start = typeof e.start === \"string\" ? e.start : typeof e.dtstart === \"string\" ? e.dtstart : \"\";\n if (!title || !start) continue;\n events.push({\n id,\n title,\n start,\n end: typeof e.end === \"string\" ? e.end : typeof e.dtend === \"string\" ? e.dtend : undefined,\n location: typeof e.location === \"string\" ? e.location : undefined,\n notes: typeof e.notes === \"string\" ? e.notes : typeof e.description === \"string\" ? e.description : undefined,\n });\n }\n return events;\n } catch (err) {\n log.warn(`briefing: calendar JSON parse failed: ${err}`);\n return [];\n }\n}\n\ninterface IcsParsedLine {\n property: string;\n params: Record<string, string>;\n value: string;\n}\n\n/**\n * Parse a single ICS content line into its property, parameters, and value.\n * Returns null if the line is not a well-formed property line.\n *\n * Example:\n * `DTSTART;TZID=America/New_York:20260411T233000`\n * → { property: \"DTSTART\", params: { TZID: \"America/New_York\" }, value: \"20260411T233000\" }\n */\nfunction parseIcsLine(line: string): IcsParsedLine | null {\n // Find the first `:` outside of any parameter value. Per RFC 5545 parameter\n // values may be quoted, but the minimal-parser use case here only needs to\n // handle unquoted TZID values.\n const colonIdx = line.indexOf(\":\");\n if (colonIdx <= 0) return null;\n const head = line.slice(0, colonIdx);\n const value = line.slice(colonIdx + 1).trim();\n // Head is of the form `PROPERTY[;PARAM=val[;PARAM=val]]`.\n const headParts = head.split(\";\");\n const property = headParts[0]!.toUpperCase();\n if (!/^[A-Z0-9-]+$/.test(property)) return null;\n const params: Record<string, string> = {};\n for (let i = 1; i < headParts.length; i++) {\n const segment = headParts[i]!;\n const eqIdx = segment.indexOf(\"=\");\n if (eqIdx <= 0) continue;\n const name = segment.slice(0, eqIdx).toUpperCase();\n let val = segment.slice(eqIdx + 1);\n // Strip surrounding quotes if present (RFC 5545 §3.1).\n if (val.startsWith('\"') && val.endsWith('\"') && val.length >= 2) {\n val = val.slice(1, -1);\n }\n params[name] = val;\n }\n return { property, params, value };\n}\n\ninterface IcsDateField {\n raw: string;\n params: Record<string, string>;\n}\n\n/** @internal — exported for testing only. */\nexport function parseIcsEvents(raw: string): CalendarEvent[] {\n const events: CalendarEvent[] = [];\n // RFC 5545 §3.1 line unfolding: a CRLF (now \\n) followed by a single\n // whitespace character (space or tab) is a fold — remove both characters\n // to join the continuation onto the preceding logical line. This MUST\n // happen after normalising CRLF → \\n and BEFORE splitting on \\n.\n const normalized = raw.replace(/\\r\\n/g, \"\\n\").replace(/\\n[ \\t]/g, \"\");\n const blocks = normalized.split(/BEGIN:VEVENT/i).slice(1);\n for (const block of blocks) {\n const endIdx = block.search(/END:VEVENT/i);\n const body = endIdx === -1 ? block : block.slice(0, endIdx);\n const simpleFields: Record<string, string> = {};\n const dateFields: Record<string, IcsDateField> = {};\n for (const line of body.split(\"\\n\")) {\n const parsed = parseIcsLine(line);\n if (!parsed) continue;\n const { property, params, value } = parsed;\n if (property === \"DTSTART\" || property === \"DTEND\") {\n if (dateFields[property] === undefined) {\n dateFields[property] = { raw: value, params };\n }\n } else if (simpleFields[property] === undefined) {\n simpleFields[property] = value;\n }\n }\n const title = simpleFields.SUMMARY;\n const dtstart = dateFields.DTSTART;\n if (!title || !dtstart) continue;\n const dtend = dateFields.DTEND;\n events.push({\n id: simpleFields.UID ?? cryptoRandomId(),\n title,\n start: normalizeIcsDate(dtstart.raw, dtstart.params),\n end: dtend ? normalizeIcsDate(dtend.raw, dtend.params) : undefined,\n location: simpleFields.LOCATION,\n notes: simpleFields.DESCRIPTION,\n });\n }\n return events;\n}\n\n/**\n * Normalise an ICS date/datetime value (optionally with a `TZID` parameter)\n * into an ISO 8601 string that downstream code can compare unambiguously.\n *\n * Behaviour:\n * - `20260411T150000Z` → `2026-04-11T15:00:00Z`\n * - `20260411` → `2026-04-11T00:00:00Z` (date-only events are day-boundaries)\n * - `20260411T150000` (floating, no Z, no TZID) → `2026-04-11T15:00:00` (floating)\n * - `20260411T233000` with `TZID=America/New_York` → `2026-04-12T03:30:00Z`\n * (applies the zone offset at that wallclock time; DST-aware via Intl)\n * - Unknown TZID falls back to UTC with a logged warning (conservative:\n * the event still appears, but on the UTC date).\n */\nfunction normalizeIcsDate(value: string, params: Record<string, string> = {}): string {\n // Date-time with explicit Z suffix (UTC).\n if (/^\\d{8}T\\d{6}Z$/.test(value)) {\n const y = value.slice(0, 4);\n const m = value.slice(4, 6);\n const d = value.slice(6, 8);\n const hh = value.slice(9, 11);\n const mm = value.slice(11, 13);\n const ss = value.slice(13, 15);\n return `${y}-${m}-${d}T${hh}:${mm}:${ss}Z`;\n }\n // Date-time without Z: may be floating or zoned via TZID.\n if (/^\\d{8}T\\d{6}$/.test(value)) {\n const y = value.slice(0, 4);\n const m = value.slice(4, 6);\n const d = value.slice(6, 8);\n const hh = value.slice(9, 11);\n const mm = value.slice(11, 13);\n const ss = value.slice(13, 15);\n const local = `${y}-${m}-${d}T${hh}:${mm}:${ss}`;\n const tzid = params.TZID;\n if (tzid) {\n const utcIso = icsWallclockToUtc(local, tzid);\n if (utcIso) return utcIso;\n log.warn(\n `briefing: unsupported TZID \"${tzid}\" — treating as UTC for ${local}`,\n );\n return `${local}Z`;\n }\n // No TZID → floating. Downstream compares the date slice directly.\n return local;\n }\n // Date-only (all-day event). Date-only values carry no TZID per RFC 5545.\n if (/^\\d{8}$/.test(value)) {\n return `${value.slice(0, 4)}-${value.slice(4, 6)}-${value.slice(6, 8)}T00:00:00Z`;\n }\n return value;\n}\n\n/**\n * Convert a wallclock local datetime in a named IANA timezone to a UTC ISO\n * string. Returns null if the timezone is unsupported by the runtime.\n *\n * Implementation note: this is the standard \"invert the formatter\" technique.\n * We treat the local wallclock as though it were UTC, ask the runtime what\n * time that instant shows in the target zone, and the delta is the zone's\n * offset at that wallclock moment (DST-aware).\n */\nfunction icsWallclockToUtc(local: string, tzid: string): string | null {\n const match = local.match(/^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})$/);\n if (!match) return null;\n const [, y, mo, d, hh, mm, ss] = match;\n // Treat the wallclock as UTC for the first probe.\n const naiveUtcMs = Date.UTC(\n Number(y),\n Number(mo) - 1,\n Number(d),\n Number(hh),\n Number(mm),\n Number(ss),\n );\n if (!Number.isFinite(naiveUtcMs)) return null;\n\n let formatter: Intl.DateTimeFormat;\n try {\n formatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: tzid,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n } catch {\n return null;\n }\n\n const zonedMs = zonedFormatToMs(formatter, new Date(naiveUtcMs));\n if (zonedMs === null) return null;\n // Offset = naiveUtc − zonedAtNaiveUtc (positive for zones east of UTC).\n const offsetMs = naiveUtcMs - zonedMs;\n // Apply the offset once to land on the real UTC instant.\n const realUtcMs = naiveUtcMs + offsetMs;\n // Second pass: offsets can differ when the wallclock crosses a DST boundary.\n const zonedMs2 = zonedFormatToMs(formatter, new Date(realUtcMs));\n if (zonedMs2 !== null) {\n const offsetMs2 = realUtcMs - zonedMs2;\n if (offsetMs2 !== offsetMs) {\n return new Date(naiveUtcMs + offsetMs2).toISOString();\n }\n }\n return new Date(realUtcMs).toISOString();\n}\n\n/**\n * Format a Date in the given timezone and return the absolute ms timestamp\n * of that wallclock time interpreted as if it were UTC. Used only by\n * `icsWallclockToUtc` to compute zone offsets.\n */\nfunction zonedFormatToMs(formatter: Intl.DateTimeFormat, date: Date): number | null {\n const parts = formatter.formatToParts(date);\n const get = (type: string): string | undefined =>\n parts.find((p) => p.type === type)?.value;\n const y = get(\"year\");\n const mo = get(\"month\");\n const d = get(\"day\");\n const hh = get(\"hour\");\n const mm = get(\"minute\");\n const ss = get(\"second\");\n if (!y || !mo || !d || !hh || !mm || !ss) return null;\n // RFC 5545 / Intl edge-case: some runtimes return `hour: \"24\"` for midnight\n // while keeping the same calendar day (instead of returning hour=0 with the\n // next day). Passing 24 straight to Date.UTC would roll the date forward by\n // one day, producing a 24-hour-skewed offset in icsWallclockToUtc and\n // shifting TZID midnight events to the wrong briefing day. Normalise to 0\n // and leave the date component unchanged.\n const normalizedHour = Number(hh) === 24 ? 0 : Number(hh);\n const ms = Date.UTC(Number(y), Number(mo) - 1, Number(d), normalizedHour, Number(mm), Number(ss));\n return Number.isFinite(ms) ? ms : null;\n}\n\n/**\n * Returns true when `isoStr` has an explicit UTC or numeric offset suffix\n * (Z, ±HH:MM, or ±HHMM). Floating datetimes produced by `normalizeIcsDate`\n * have no such suffix.\n */\nfunction isoHasTimezone(isoStr: string): boolean {\n return /(Z|[+-]\\d{2}:?\\d{2})$/.test(isoStr);\n}\n\n/**\n * Parse an ISO datetime string (UTC-aware or floating) to milliseconds since\n * epoch, or `null` if the string is not a valid datetime.\n *\n * - UTC / offset-aware strings are passed directly to `new Date()`.\n * - Floating strings (no timezone suffix) are interpreted as UTC so that\n * interval arithmetic uses the same epoch base as UTC-aware strings.\n * The caller is responsible for using the correct date-boundary constants.\n */\nfunction isoToMs(isoStr: string): number | null {\n if (!isoStr) return null;\n let src = isoStr;\n if (!isoHasTimezone(src)) {\n // Treat floating time as UTC for interval math (append Z).\n src = src + \"Z\";\n }\n const ms = new Date(src).getTime();\n return Number.isFinite(ms) ? ms : null;\n}\n\n/** @internal — exported for testing only. */\nexport function eventFallsOnDate(event: CalendarEvent, dateIso: string): boolean {\n const target = dateIso.slice(0, 10);\n const start = event.start;\n\n // Floating ICS datetime (no Z, no offset): `normalizeIcsDate` produces\n // \"YYYY-MM-DDTHH:MM:SS\" with no timezone. Passing this to `new Date()`\n // causes ECMAScript to parse it as local time, which then round-trips\n // through UTC via `toISOString()` and can shift the calendar date.\n // For floating times we compare date portions directly (no epoch arithmetic).\n const startIsFloating = !isoHasTimezone(start);\n\n if (startIsFloating) {\n // Validate the start timestamp with the same rigour applied to end:\n // 1. Shape check — must match the ISO-8601 date or datetime pattern.\n // 2. Real-date check — round-trip through UTC to reject impossible dates\n // like \"2026-02-30\" that JavaScript silently auto-corrects.\n // 3. Time-component check — reject out-of-range hours/minutes/seconds\n // (e.g. \"2026-04-11T25:99:00\") that JavaScript rolls over to a\n // different day, which would cause the event to be matched against\n // unrelated calendar dates.\n // If start fails any check we skip the event entirely — there is no usable\n // start date to fall back on.\n const startShapeOk =\n typeof start === \"string\" &&\n /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?)?$/.test(start);\n if (!startShapeOk) {\n log.debug(`briefing: skipping calendar event with invalid start value: ${JSON.stringify(start)}`);\n return false;\n }\n const startDateStr = start.slice(0, 10);\n const startDateProbe = new Date(startDateStr + \"T00:00:00Z\");\n if (\n Number.isNaN(startDateProbe.getTime()) ||\n startDateProbe.toISOString().slice(0, 10) !== startDateStr\n ) {\n log.warn(\n `briefing: skipping calendar event \"${event.title}\" with impossible start date ${JSON.stringify(startDateStr)}`,\n );\n return false;\n }\n const startRawTime = start.indexOf(\"T\") !== -1 ? start.slice(start.indexOf(\"T\") + 1) : \"\";\n if (startRawTime !== \"\") {\n const startTimeParts = startRawTime.split(\":\").map(Number);\n const shh = startTimeParts[0] ?? 0;\n const smm = startTimeParts[1] ?? 0;\n const sss = Math.floor(startTimeParts[2] ?? 0);\n if (shh > 23 || smm > 59 || sss > 59) {\n log.warn(\n `briefing: skipping calendar event \"${event.title}\" with out-of-range start time ${JSON.stringify(startRawTime)}`,\n );\n return false;\n }\n }\n\n const startDate = startDateStr;\n const end = event.end;\n\n // Point event (no end) — simple date prefix comparison.\n if (!end) return startDate === target;\n\n // Validate that end is a recognisable ISO-8601 date/datetime string before\n // slicing it for lexicographic comparison. A malformed end (e.g. a JSON\n // feed emitting \"end\": \"invalid\") would otherwise produce a non-date prefix\n // from `end.slice(0, 10)` and cause the event to appear on unrelated days.\n // Fallback: treat the event as a single-day event starting on startDate.\n const endIsValid =\n typeof end === \"string\" &&\n /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?)?$/.test(end);\n if (!endIsValid) {\n log.warn(\n `briefing: event \"${event.title}\" has malformed end timestamp ${JSON.stringify(end)}; treating as single-day event at ${startDate}`,\n );\n // Render the event but only on its start date.\n return startDate === target;\n }\n\n // UhLh: Reject impossible calendar dates that pass the regex (e.g. \"2026-99-99\").\n // The regex only validates the *shape* of the string — it accepts month 99 and\n // day 99. We must additionally verify the date is real by constructing a UTC\n // Date and checking that the ISO round-trip matches the input prefix. If the\n // date is impossible, Date will auto-correct it (e.g. \"2026-01-99\" becomes some\n // later date), so the round-trip will differ. Fall back to single-day semantics.\n const endDate = end.slice(0, 10);\n const endDateProbe = new Date(endDate + \"T00:00:00Z\");\n if (\n Number.isNaN(endDateProbe.getTime()) ||\n endDateProbe.toISOString().slice(0, 10) !== endDate\n ) {\n log.warn(\n `briefing: event \"${event.title}\" has impossible end date ${JSON.stringify(endDate)}; treating as single-day event at ${startDate}`,\n );\n return startDate === target;\n }\n\n // Validate the time components of the end timestamp when present.\n // The regex above only checks the shape (e.g. two digits for hour) but does\n // not enforce numeric ranges. A value like \"2026-04-11T25:99:99\" passes the\n // regex and the date-round-trip check above yet carries an impossible time.\n // JavaScript's Date constructor silently rolls such values over to a later\n // date, which would make the event bleed into unrelated days. Extract the\n // individual time fields and reject anything outside the valid range.\n const rawTime = end.indexOf(\"T\") !== -1 ? end.slice(end.indexOf(\"T\") + 1) : \"\";\n if (rawTime !== \"\") {\n const timeParts = rawTime.split(\":\").map(Number);\n const hh = timeParts[0] ?? 0;\n const mm = timeParts[1] ?? 0;\n // Seconds may carry a fractional component; floor to get the integer part.\n const ss = Math.floor(timeParts[2] ?? 0);\n const timeIsValid = hh <= 23 && mm <= 59 && ss <= 59;\n if (!timeIsValid) {\n log.warn(\n `briefing: event \"${event.title}\" has out-of-range end time ${JSON.stringify(rawTime)}; treating as single-day event at ${startDate}`,\n );\n return startDate === target;\n }\n }\n\n // Span event: include if [start, end) overlaps the target calendar day.\n //\n // We can't use pure YYYY-MM-DD lexicographic comparison because a\n // same-day event (`start=2026-04-11T14:30`, `end=2026-04-11T15:00`)\n // has `startDate === endDate === \"2026-04-11\"`, and a `target < endDate`\n // check would wrongly exclude it. A cross-day event ending at\n // `2026-04-12T00:00:00` (exact midnight) also needs the end day to be\n // treated as exclusive per half-open `[start, end)` semantics.\n //\n // Decide whether the end day is still active on the end date by looking\n // at the time portion: if the end time is strictly after midnight, the\n // event is still running at the start of the end day and should include\n // it; if the end time is exactly midnight, the event ends precisely at\n // the boundary and the end day is excluded. Within-day spans always\n // have a non-zero end time and so correctly include their own date.\n //\n // UhLg: A date-only end value (no \"T\" separator) produces an empty\n // endTime string. The regex above does not match empty string, so\n // endAtExactMidnight would be false and the event would incorrectly\n // appear on the end date. Date-only end values carry [start, end)\n // semantics (the end date is exclusive), so we treat them as midnight.\n const endTime = end.slice(11); // \"HH:MM\", \"HH:MM:SS\", \"HH:MM:SS.mmm\", or \"\" (date-only)\n // Treat any end time that is exactly midnight — or absent (date-only) — as\n // day-exclusive per [start, end) semantics.\n // Cases covered:\n // \"\" — date-only end (UhLg fix: exclusive like midnight)\n // \"00:00\" — HH:MM form (valid floating-time ISO value, no seconds)\n // \"00:00:00\" — HH:MM:SS form\n // \"00:00:00.000...\" — with fractional seconds (any number of trailing zeros)\n // A bare `>` string comparison incorrectly treats \"00:00:00.000\" as > \"00:00:00\"\n // because the fractional suffix makes the string lexicographically longer.\n const endIsDateOnly = endTime === \"\";\n const endAtExactMidnight = endIsDateOnly || /^00(:00){1,2}(\\.0+)?$/.test(endTime);\n const endActiveOnEndDay = !endAtExactMidnight;\n if (endActiveOnEndDay) {\n return startDate <= target && target <= endDate;\n }\n return startDate <= target && target < endDate;\n }\n\n // UTC or offset-aware ISO string: parse and normalise to UTC milliseconds,\n // then check whether the event's [start, end) interval overlaps the target\n // UTC day [dayStart, dayEnd).\n const startMs = isoToMs(start);\n if (startMs === null) {\n log.debug(`briefing: skipping calendar event with invalid start value: ${JSON.stringify(start)}`);\n return false;\n }\n\n // Boundaries of the target UTC day (half-open: [dayStart, dayEnd)).\n const dayStart = Date.UTC(\n Number(target.slice(0, 4)),\n Number(target.slice(5, 7)) - 1,\n Number(target.slice(8, 10)),\n );\n const dayEnd = dayStart + 86_400_000; // +24 h\n\n const end = event.end;\n if (!end) {\n // Point event: included iff start falls within [dayStart, dayEnd).\n return startMs >= dayStart && startMs < dayEnd;\n }\n\n const endMs = isoToMs(end);\n if (endMs === null) {\n // Unparseable end — fall back to point-event semantics.\n return startMs >= dayStart && startMs < dayEnd;\n }\n\n // Interval event: overlaps day iff start < dayEnd AND end > dayStart.\n // Using strict > for end so that an event ending exactly at midnight\n // (dayEnd of previous day) is NOT counted on the next day.\n return startMs < dayEnd && endMs > dayStart;\n}\n\nfunction cryptoRandomId(): string {\n // Keep dependency-free: Math.random is fine for synthetic fixture IDs.\n return `evt-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// buildBriefing\n// ──────────────────────────────────────────────────────────────────────────\n\n/** Dependency-injection hook for LLM follow-up generation (used in tests). */\nexport type BriefingFollowupGenerator = (\n prompt: {\n sections: BriefingSections;\n windowLabel: string;\n maxFollowups: number;\n },\n) => Promise<BriefingFollowup[]>;\n\n/** Options accepted by `buildBriefing`. */\nexport interface BuildBriefingOptions {\n /** Workspace-scoped storage. Tests pass a temp dir. */\n storage: StorageManager;\n /** Parsed window. If omitted, a default 1-day window is used. */\n window?: ParsedBriefingWindow;\n /** Optional focus filter. */\n focus?: BriefingFocus | null;\n /** Optional namespace hint for logging. */\n namespace?: string;\n /** Calendar source. Section omitted entirely when undefined. */\n calendarSource?: CalendarSource;\n /** Maximum LLM follow-ups (0 to disable the section). */\n maxFollowups?: number;\n /** Whether the module is allowed to invoke the Responses API. */\n allowLlm?: boolean;\n /** OpenAI API key. If absent the follow-up section is gracefully omitted. */\n openaiApiKey?: string;\n /** OpenAI-compatible base URL (for Azure or proxied endpoints). */\n openaiBaseUrl?: string;\n /** Model id for the Responses call. */\n model?: string;\n /** Injected follow-up generator. Overrides real LLM call (tests). */\n followupGenerator?: BriefingFollowupGenerator;\n /** Injected \"now\" — makes tests deterministic. */\n now?: Date;\n}\n\nconst MAX_ACTIVE_THREADS = 8;\nconst MAX_RECENT_ENTITIES = 8;\nconst MAX_OPEN_COMMITMENTS = 8;\n\n/**\n * Build the daily context briefing.\n *\n * Never throws on LLM failures — the suggested follow-ups section is simply\n * omitted and `followupsUnavailableReason` is set.\n */\nexport async function buildBriefing(options: BuildBriefingOptions): Promise<BriefingResult> {\n const now = options.now ?? new Date();\n const window = options.window ?? defaultWindow(now);\n const maxFollowups = clampFollowups(options.maxFollowups);\n const focus = options.focus ?? null;\n\n const [allMemories, allEntities] = await Promise.all([\n safeReadMemories(options.storage),\n safeReadEntities(options.storage),\n ]);\n\n const memoriesInWindow = filterMemoriesByWindow(allMemories, window);\n const focusedMemories = focus\n ? memoriesInWindow.filter((m) => focusMatchesMemory(m, focus))\n : memoriesInWindow;\n\n const activeThreads = buildActiveThreads(focusedMemories);\n const recentEntities = buildRecentEntities(allEntities, window, focus);\n // TODO(#370): openCommitments only covers memories inside the lookback window.\n // Still-open commitments (pending tag, commitment category) that pre-date the\n // window are silently omitted. A separate query over allMemories filtered to\n // open-status entries would surface these. Deferred to avoid scope creep here.\n const openCommitments = buildOpenCommitments(focusedMemories);\n\n const calendarLoadResult = options.calendarSource\n ? await loadTodayCalendar(options.calendarSource, now)\n : undefined;\n\n const calendarSourceErrors: BriefingCalendarSourceError[] =\n calendarLoadResult?.error ? [calendarLoadResult.error] : [];\n\n const sectionsBase: BriefingSections = {\n activeThreads,\n recentEntities,\n openCommitments,\n suggestedFollowups: [],\n todayCalendar: calendarLoadResult?.events,\n };\n\n let followups: BriefingFollowup[] = [];\n let followupsUnavailableReason: string | undefined;\n\n if (maxFollowups === 0 || options.allowLlm === false) {\n followupsUnavailableReason = \"LLM follow-ups disabled by configuration\";\n } else if (!options.openaiApiKey && !options.followupGenerator) {\n followupsUnavailableReason = \"OPENAI_API_KEY not configured\";\n } else {\n try {\n const generator = options.followupGenerator ?? buildOpenAiFollowupGenerator({\n apiKey: options.openaiApiKey!,\n model: options.model ?? BRIEFING_FOLLOWUP_DEFAULT_MODEL,\n baseURL: options.openaiBaseUrl,\n });\n const generated = await generator({\n sections: sectionsBase,\n windowLabel: window.label,\n maxFollowups,\n });\n followups = generated.slice(0, maxFollowups);\n } catch (err) {\n const errMsg = stringifyError(err);\n const modelName = options.model ?? BRIEFING_FOLLOWUP_DEFAULT_MODEL;\n // Detect \"model not found / invalid\" errors from the Responses API and\n // produce a user-friendly message that surfaces the problematic identifier.\n if (\n /model/i.test(errMsg) &&\n (/not found/i.test(errMsg) || /does not exist/i.test(errMsg) || /invalid/i.test(errMsg))\n ) {\n followupsUnavailableReason =\n `configured follow-up model '${modelName}' is not available in the Responses API`;\n } else {\n followupsUnavailableReason = `LLM follow-ups failed: ${errMsg}`;\n }\n log.warn(`briefing: ${followupsUnavailableReason}`);\n }\n }\n\n const sections: BriefingSections = {\n ...sectionsBase,\n suggestedFollowups: followups,\n };\n\n const windowIso = { from: window.from.toISOString(), to: window.to.toISOString() };\n const markdown = renderBriefingMarkdown({\n sections,\n windowLabel: window.label,\n focus,\n followupsUnavailableReason,\n generatedAt: now,\n namespace: options.namespace,\n });\n\n const json: Record<string, unknown> = {\n generatedAt: now.toISOString(),\n window: windowIso,\n focus,\n namespace: options.namespace ?? null,\n sections,\n followupsUnavailableReason: followupsUnavailableReason ?? null,\n calendarSourceErrors: calendarSourceErrors.length > 0 ? calendarSourceErrors : null,\n };\n\n const result: BriefingResult = {\n markdown,\n json,\n sections,\n followupsUnavailableReason,\n window: windowIso,\n };\n\n if (calendarSourceErrors.length > 0) {\n result.calendarSourceErrors = calendarSourceErrors;\n }\n\n return result;\n}\n\nfunction clampFollowups(value: number | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n return Math.max(0, Math.min(10, Math.floor(value)));\n}\n\nfunction defaultWindow(now: Date): ParsedBriefingWindow {\n const parsed = parseBriefingWindow(\"yesterday\", now);\n if (parsed) return parsed;\n return { from: new Date(now.getTime() - DAY_MS), to: now, label: \"yesterday\" };\n}\n\nasync function safeReadMemories(storage: StorageManager): Promise<MemoryFile[]> {\n try {\n return await storage.readAllMemories();\n } catch (err) {\n log.warn(`briefing: readAllMemories failed: ${err}`);\n return [];\n }\n}\n\nasync function safeReadEntities(storage: StorageManager): Promise<EntityFile[]> {\n try {\n return await storage.readAllEntityFiles();\n } catch (err) {\n log.warn(`briefing: readAllEntityFiles failed: ${err}`);\n return [];\n }\n}\n\nfunction memoryTimestamp(memory: MemoryFile): number {\n const raw = memory.frontmatter.updated || memory.frontmatter.created;\n if (!raw) return 0;\n const t = Date.parse(raw);\n return Number.isFinite(t) ? t : 0;\n}\n\n/** @internal — exported for testing only. */\nexport function filterMemoriesByWindow(memories: MemoryFile[], window: ParsedBriefingWindow): MemoryFile[] {\n const fromMs = window.from.getTime();\n const toMs = window.to.getTime();\n return memories.filter((m) => {\n // Exclude explicitly retired statuses so commitments overridden within the\n // window don't appear as open. In addition to `superseded` / `archived`\n // (temporal retirement), also exclude `rejected` and `quarantined`, which\n // come from governance/disposition workflows: those memories have been\n // explicitly marked unsafe or invalid and must NOT flow into active\n // threads, open commitments, or follow-up generation, even if they\n // fall within the briefing window. Surfacing them would reintroduce\n // quarantined content into downstream automation as actionable context.\n //\n // `pending_review` memories are awaiting human review — not invalidated —\n // and must be included so reviewers see them in the briefing.\n const status = m.frontmatter.status;\n if (\n status === \"superseded\" ||\n status === \"archived\" ||\n status === \"rejected\" ||\n status === \"quarantined\"\n ) {\n return false;\n }\n const ts = memoryTimestamp(m);\n return ts >= fromMs && ts < toMs;\n });\n}\n\n/** @internal — exported for testing only. */\nexport function buildActiveThreads(memories: MemoryFile[]): BriefingActiveThread[] {\n const buckets = new Map<string, BriefingActiveThread>();\n for (const memory of memories) {\n const threadKey = extractThreadKey(memory);\n const updatedAt = memory.frontmatter.updated || memory.frontmatter.created || \"\";\n const existing = buckets.get(threadKey);\n if (!existing || updatedAt > existing.updatedAt) {\n buckets.set(threadKey, {\n id: threadKey,\n title: summarizeContentTitle(memory),\n updatedAt,\n // Always derive reason from the newest memory so the description\n // reflects the most-recent activity type, not the first memory seen.\n reason: describeReason(memory),\n });\n }\n }\n return Array.from(buckets.values())\n .sort((a, b) => {\n if (a.updatedAt > b.updatedAt) return -1;\n if (a.updatedAt < b.updatedAt) return 1;\n // Tiebreaker: lexicographic order by id ensures a deterministic, stable\n // result when multiple threads share the same updatedAt timestamp (e.g.\n // after a batch extraction run).\n return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;\n })\n .slice(0, MAX_ACTIVE_THREADS);\n}\n\nfunction extractThreadKey(memory: MemoryFile): string {\n const entityRef = memory.frontmatter.entityRef?.trim();\n if (entityRef) return `entity:${entityRef}`;\n const tags = memory.frontmatter.tags ?? [];\n const topicTag = tags.find((t) => t.startsWith(\"topic:\"));\n if (topicTag) return topicTag;\n if (tags.length > 0) return `tag:${tags[0]}`;\n return `memory:${memory.frontmatter.id}`;\n}\n\nfunction summarizeContentTitle(memory: MemoryFile): string {\n const firstLine = (memory.content || \"\").split(\"\\n\").find((line) => line.trim().length > 0) ?? \"\";\n const trimmed = firstLine.trim();\n if (trimmed.length === 0) return memory.frontmatter.id;\n return trimmed.length > 120 ? `${trimmed.slice(0, 117)}...` : trimmed;\n}\n\nfunction describeReason(memory: MemoryFile): string {\n const cat = memory.frontmatter.category;\n if (cat === \"commitment\") return \"open commitment\";\n if (cat === \"decision\") return \"recent decision\";\n if (cat === \"correction\") return \"recent correction\";\n return \"recent activity\";\n}\n\n/** @internal — exported for testing only. */\nexport function buildRecentEntities(\n entities: EntityFile[],\n window: ParsedBriefingWindow,\n focus: BriefingFocus | null,\n): BriefingRecentEntity[] {\n const fromMs = window.from.getTime();\n const scored: BriefingRecentEntity[] = [];\n const now = window.to;\n for (const entity of entities) {\n if (focus && !focusMatchesEntity(entity, focus)) continue;\n const toMs = window.to.getTime();\n const updatedMs = entity.updated ? Date.parse(entity.updated) : 0;\n if (!Number.isFinite(updatedMs) || updatedMs < fromMs || updatedMs >= toMs) continue;\n const score = StorageManager.scoreEntity(entity, now);\n scored.push({\n name: entity.name,\n type: entity.type,\n updatedAt: entity.updated,\n score: Number(score.toFixed(4)),\n summary: entity.synthesis || entity.summary,\n });\n }\n return scored\n .sort((a, b) => {\n const scoreDiff = b.score - a.score;\n if (scoreDiff !== 0) return scoreDiff;\n if (a.updatedAt > b.updatedAt) return -1;\n if (a.updatedAt < b.updatedAt) return 1;\n return 0;\n })\n .slice(0, MAX_RECENT_ENTITIES);\n}\n\nfunction buildOpenCommitments(memories: MemoryFile[]): BriefingOpenCommitment[] {\n const commitments: BriefingOpenCommitment[] = [];\n\n for (const memory of memories) {\n const tags = memory.frontmatter.tags ?? [];\n const isPending = tags.some((t) => t.toLowerCase() === \"pending\");\n const isCommitment = memory.frontmatter.category === \"commitment\";\n const isUnresolvedQuestion = /(?:\\?$|\\bfollow[- ]up\\b|\\btodo\\b)/i.test(memory.content);\n\n if (isPending || isCommitment || isUnresolvedQuestion) {\n const kind: BriefingOpenCommitment[\"kind\"] = isCommitment\n ? \"commitment\"\n : isUnresolvedQuestion\n ? \"question\"\n : \"pending_memory\";\n commitments.push({\n id: memory.frontmatter.id,\n kind,\n text: summarizeContentTitle(memory),\n source: memory.frontmatter.source,\n createdAt: memory.frontmatter.created,\n });\n }\n }\n\n return commitments\n .sort((a, b) => {\n // Missing timestamps sort last (highest comparator value).\n if (!a.createdAt && !b.createdAt) return 0;\n if (!a.createdAt) return 1;\n if (!b.createdAt) return -1;\n if (a.createdAt > b.createdAt) return -1;\n if (a.createdAt < b.createdAt) return 1;\n return 0;\n })\n .slice(0, MAX_OPEN_COMMITMENTS);\n}\n\ninterface CalendarLoadResult {\n events: CalendarEvent[] | undefined;\n error: BriefingCalendarSourceError | undefined;\n}\n\nasync function loadTodayCalendar(\n source: CalendarSource,\n now: Date,\n): Promise<CalendarLoadResult> {\n const sourceLabel = (source as { filePath?: string }).filePath ?? \"calendar\";\n try {\n const dateIso = now.toISOString().slice(0, 10);\n const events = await source.eventsForDate(dateIso);\n // Return the events array (possibly empty for a legitimately empty calendar).\n // An empty array is distinct from `undefined`: empty means \"source responded\n // with no events today\"; undefined means \"source failed\".\n return { events, error: undefined };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn(`briefing: calendar source error (${sourceLabel}): ${message}`);\n // Return undefined events (not []) to signal an error so callers can\n // distinguish \"no events today\" from \"the calendar source threw\".\n return {\n events: undefined,\n error: { source: sourceLabel, error: message },\n };\n }\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Follow-ups (Responses API)\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction buildOpenAiFollowupGenerator(cfg: {\n apiKey: string;\n model: string;\n baseURL?: string;\n}): BriefingFollowupGenerator {\n return async ({ sections, windowLabel, maxFollowups }) => {\n // Lazy import keeps the module dependency-free when LLM path is unused.\n const { OpenAI } = (await import(\"openai\")) as {\n OpenAI: new (opts: { apiKey: string; baseURL?: string }) => unknown;\n };\n const clientOpts: { apiKey: string; baseURL?: string } = { apiKey: cfg.apiKey };\n if (cfg.baseURL) clientOpts.baseURL = cfg.baseURL;\n const client = new OpenAI(clientOpts) as {\n responses: {\n create: (args: {\n model: string;\n instructions: string;\n input: string;\n max_output_tokens?: number;\n }) => Promise<{ output_text?: string }>;\n };\n };\n\n const prompt = buildFollowupPrompt(sections, windowLabel, maxFollowups);\n const response = await client.responses.create({\n model: cfg.model,\n instructions: FOLLOWUP_INSTRUCTIONS,\n input: prompt,\n max_output_tokens: 512,\n });\n\n const text = typeof response.output_text === \"string\" ? response.output_text : \"\";\n return parseFollowupResponse(text, maxFollowups);\n };\n}\n\nconst FOLLOWUP_INSTRUCTIONS = `You suggest short follow-up prompts for a daily context briefing.\nReturn strict JSON of the form { \"followups\": [{ \"text\": \"...\", \"rationale\": \"...\" }] }.\nRules:\n- Never invent facts absent from the input.\n- Keep each \"text\" under 140 characters.\n- Prefer concrete, action-oriented phrasing.\n- Omit duplicates. Avoid filler.`;\n\nfunction buildFollowupPrompt(\n sections: BriefingSections,\n windowLabel: string,\n maxFollowups: number,\n): string {\n const lines: string[] = [];\n lines.push(`Window: ${windowLabel}`);\n lines.push(`Desired follow-ups: ${maxFollowups}`);\n lines.push(\"\");\n lines.push(\"Active threads:\");\n for (const t of sections.activeThreads) lines.push(`- ${t.title} (${t.reason})`);\n lines.push(\"\");\n lines.push(\"Recent entities:\");\n for (const e of sections.recentEntities) lines.push(`- ${e.name} [${e.type}]`);\n lines.push(\"\");\n lines.push(\"Open commitments:\");\n for (const c of sections.openCommitments) lines.push(`- [${c.kind}] ${c.text}`);\n return lines.join(\"\\n\");\n}\n\nfunction parseFollowupResponse(raw: string, max: number): BriefingFollowup[] {\n // JSON.parse throws on invalid JSON — let the caller catch it so the outer\n // try/catch in buildBriefing can set followupsUnavailableReason rather than\n // silently returning an empty array that masks the parse failure.\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== \"object\") {\n throw new Error(`LLM returned non-object JSON: ${typeof parsed}`);\n }\n const arr = (parsed as { followups?: unknown }).followups;\n if (!Array.isArray(arr)) {\n throw new Error(`LLM response missing \"followups\" array`);\n }\n const out: BriefingFollowup[] = [];\n for (const entry of arr) {\n if (!entry || typeof entry !== \"object\") continue;\n const text = (entry as Record<string, unknown>).text;\n if (typeof text !== \"string\" || text.trim().length === 0) continue;\n const rationale = (entry as Record<string, unknown>).rationale;\n out.push({\n text: text.trim(),\n rationale: typeof rationale === \"string\" ? rationale.trim() : undefined,\n });\n if (out.length >= max) break;\n }\n return out;\n}\n\nfunction stringifyError(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Markdown rendering\n// ──────────────────────────────────────────────────────────────────────────\n\ninterface RenderContext {\n sections: BriefingSections;\n windowLabel: string;\n focus: BriefingFocus | null;\n followupsUnavailableReason?: string;\n generatedAt: Date;\n namespace?: string;\n}\n\nexport function renderBriefingMarkdown(ctx: RenderContext): string {\n const lines: string[] = [];\n lines.push(`# Daily Context Briefing`);\n lines.push(\"\");\n lines.push(`_Generated ${ctx.generatedAt.toISOString()} (window: ${ctx.windowLabel})_`);\n if (ctx.focus) {\n lines.push(`_Focus: ${ctx.focus.type}:${ctx.focus.value}_`);\n }\n if (ctx.namespace) {\n lines.push(`_Namespace: ${ctx.namespace}_`);\n }\n lines.push(\"\");\n\n lines.push(`## Active threads`);\n if (ctx.sections.activeThreads.length === 0) {\n lines.push(`_No active threads in window._`);\n } else {\n for (const t of ctx.sections.activeThreads) {\n lines.push(`- **${t.title}** — ${t.reason} (updated ${t.updatedAt})`);\n }\n }\n lines.push(\"\");\n\n lines.push(`## Recent entities`);\n if (ctx.sections.recentEntities.length === 0) {\n lines.push(`_No entities updated in window._`);\n } else {\n for (const e of ctx.sections.recentEntities) {\n const summary = e.summary ? ` — ${e.summary}` : \"\";\n lines.push(`- **${e.name}** (${e.type}, score ${e.score})${summary}`);\n }\n }\n lines.push(\"\");\n\n lines.push(`## Open commitments`);\n if (ctx.sections.openCommitments.length === 0) {\n lines.push(`_No open commitments detected._`);\n } else {\n for (const c of ctx.sections.openCommitments) {\n lines.push(`- [${c.kind}] ${c.text}`);\n }\n }\n lines.push(\"\");\n\n lines.push(`## Suggested follow-ups`);\n if (ctx.followupsUnavailableReason) {\n lines.push(`_Unavailable: ${ctx.followupsUnavailableReason}_`);\n } else if (ctx.sections.suggestedFollowups.length === 0) {\n lines.push(`_No follow-ups suggested._`);\n } else {\n for (const f of ctx.sections.suggestedFollowups) {\n const rationale = f.rationale ? ` _(${f.rationale})_` : \"\";\n lines.push(`- ${f.text}${rationale}`);\n }\n }\n lines.push(\"\");\n\n if (ctx.sections.todayCalendar !== undefined) {\n lines.push(`## Today's calendar`);\n if (ctx.sections.todayCalendar.length === 0) {\n lines.push(`_No events on the calendar today._`);\n } else {\n for (const ev of ctx.sections.todayCalendar) {\n const end = ev.end ? ` → ${ev.end}` : \"\";\n const loc = ev.location ? ` @ ${ev.location}` : \"\";\n lines.push(`- **${ev.title}** (${ev.start}${end})${loc}`);\n }\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trimEnd() + \"\\n\";\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Save helpers\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Resolve the directory where `--save` writes dated briefings.\n * Respects the following precedence:\n * 1. explicit `configOverride` argument\n * 2. `$REMNIC_HOME/briefings/`\n * 3. `$HOME/.remnic/briefings/`\n */\nexport function resolveBriefingSaveDir(\n configOverride: string | null | undefined,\n env?: NodeJS.ProcessEnv,\n): string {\n if (typeof configOverride === \"string\" && configOverride.trim().length > 0) {\n return path.resolve(configOverride.trim());\n }\n const remnicHome = (env === undefined ? readEnvVar(\"REMNIC_HOME\") : env.REMNIC_HOME)?.trim();\n if (remnicHome && remnicHome.length > 0) {\n return path.join(remnicHome, \"briefings\");\n }\n const home = env === undefined\n ? resolveHomeDir()\n : env.HOME ?? env.USERPROFILE ?? os.homedir();\n return path.join(home, \".remnic\", \"briefings\");\n}\n\n/** Format the dated filename for a given briefing. */\nexport function briefingFilename(date: Date, format: \"markdown\" | \"json\" = \"markdown\"): string {\n const day = date.toISOString().slice(0, 10);\n return format === \"json\" ? `${day}.json` : `${day}.md`;\n}\n"],"mappings":"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","names":["from","end"]}