@remnic/core 9.3.712 → 9.3.714

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 (328) hide show
  1. package/dist/access-boundary.d.ts +6 -6
  2. package/dist/access-boundary.js +17 -16
  3. package/dist/access-cli.js +40 -39
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +5 -5
  6. package/dist/access-http.js +24 -23
  7. package/dist/access-mcp.d.ts +18 -5
  8. package/dist/access-mcp.js +21 -20
  9. package/dist/access-operations-batch.js +18 -17
  10. package/dist/access-operations.d.ts +6 -5
  11. package/dist/access-operations.js +20 -19
  12. package/dist/access-schema.d.ts +10 -0
  13. package/dist/access-schema.js +1 -1
  14. package/dist/{access-service-Dx2rSJjH.d.ts → access-service-lddjZoRh.d.ts} +20 -5
  15. package/dist/access-service.d.ts +5 -5
  16. package/dist/access-service.js +16 -15
  17. package/dist/access-surface-catalog.d.ts +5 -5
  18. package/dist/access-surface-catalog.js +6 -1
  19. package/dist/access-surface-catalog.js.map +1 -1
  20. package/dist/action-confidence.d.ts +1 -1
  21. package/dist/active-memory-bridge.d.ts +3 -1
  22. package/dist/active-memory-bridge.js +2 -1
  23. package/dist/active-recall.d.ts +1 -1
  24. package/dist/active-recall.js +4 -3
  25. package/dist/active-recall.js.map +1 -1
  26. package/dist/adapters/index.js +4 -4
  27. package/dist/adapters/registry.js +2 -2
  28. package/dist/behavior-learner.d.ts +1 -1
  29. package/dist/behavior-signals.d.ts +1 -1
  30. package/dist/bootstrap.d.ts +4 -4
  31. package/dist/briefing.d.ts +1 -1
  32. package/dist/briefing.js +8 -7
  33. package/dist/buffer-surprise-report.d.ts +1 -1
  34. package/dist/buffer.d.ts +1 -1
  35. package/dist/calibration.d.ts +1 -1
  36. package/dist/capabilities.d.ts +1 -1
  37. package/dist/{catalog-CadPvH29.d.ts → catalog-CbR0CsUw.d.ts} +1 -1
  38. package/dist/causal-behavior.d.ts +1 -1
  39. package/dist/causal-consolidation.d.ts +1 -1
  40. package/dist/causal-consolidation.js +9 -8
  41. package/dist/causal-consolidation.js.map +1 -1
  42. package/dist/{chunk-OMSTU233.js → chunk-2KAYTPPT.js} +4 -4
  43. package/dist/{chunk-VYZNWH4J.js → chunk-2SXMCQEQ.js} +3 -3
  44. package/dist/{chunk-NXL5CVE7.js → chunk-2Y6LMOQQ.js} +2 -2
  45. package/dist/{chunk-AMXOCZHE.js → chunk-3VUPWDSE.js} +15 -3
  46. package/dist/{chunk-AMXOCZHE.js.map → chunk-3VUPWDSE.js.map} +1 -1
  47. package/dist/{chunk-FVQJYWH7.js → chunk-5GKPFL3S.js} +1 -1
  48. package/dist/{chunk-FVQJYWH7.js.map → chunk-5GKPFL3S.js.map} +1 -1
  49. package/dist/{chunk-LQ4J7ELC.js → chunk-67HG7KFE.js} +2 -2
  50. package/dist/{chunk-ZBG4K36I.js → chunk-6FUJ2VYY.js} +3 -3
  51. package/dist/{chunk-GMRNKPWO.js → chunk-6QUPUTT7.js} +2 -2
  52. package/dist/{chunk-Z56IHRVV.js → chunk-6UU43ZGD.js} +2 -2
  53. package/dist/{chunk-APJQ6UEA.js → chunk-AGNBY3VG.js} +4 -4
  54. package/dist/{chunk-OWOKOFXK.js → chunk-AJOIM6UR.js} +2 -2
  55. package/dist/{chunk-JBPKEARU.js → chunk-AU7Q3LSC.js} +4 -4
  56. package/dist/{chunk-YVWZW37D.js → chunk-BNOAB5HH.js} +62 -12
  57. package/dist/{chunk-YVWZW37D.js.map → chunk-BNOAB5HH.js.map} +1 -1
  58. package/dist/{chunk-A2R5NV6O.js → chunk-CTAHKIG6.js} +205 -29
  59. package/dist/chunk-CTAHKIG6.js.map +1 -0
  60. package/dist/{chunk-K22IJO4R.js → chunk-CTOQEZSN.js} +2 -2
  61. package/dist/{chunk-SINGJCUR.js → chunk-CX77GNMB.js} +14 -3
  62. package/dist/chunk-CX77GNMB.js.map +1 -0
  63. package/dist/{chunk-HSDJCT3V.js → chunk-DXGS5YOQ.js} +3 -3
  64. package/dist/{chunk-HV57RHMD.js → chunk-EH5ED3C6.js} +2 -2
  65. package/dist/{chunk-NUWZFSKC.js → chunk-FVZ2ISIX.js} +9 -1
  66. package/dist/chunk-FVZ2ISIX.js.map +1 -0
  67. package/dist/{chunk-GKPIY7EQ.js → chunk-FXZKXW7C.js} +117 -46
  68. package/dist/chunk-FXZKXW7C.js.map +1 -0
  69. package/dist/{chunk-7NDYFAJS.js → chunk-GM3BMWKR.js} +2 -2
  70. package/dist/{chunk-ZVDRL6SK.js → chunk-HHLWSWWF.js} +2 -2
  71. package/dist/chunk-HHLWSWWF.js.map +1 -0
  72. package/dist/{chunk-5QUS24F7.js → chunk-I56LKMF7.js} +2 -2
  73. package/dist/{chunk-Z3B2YW56.js → chunk-IHMT6XTY.js} +9 -5
  74. package/dist/chunk-IHMT6XTY.js.map +1 -0
  75. package/dist/chunk-JAKIDQB2.js +173 -0
  76. package/dist/chunk-JAKIDQB2.js.map +1 -0
  77. package/dist/{chunk-35YJ6KCV.js → chunk-JEIROMLX.js} +2 -2
  78. package/dist/{chunk-SKQCFAYU.js → chunk-JVEMUX6L.js} +2 -2
  79. package/dist/{chunk-CXMXAC5R.js → chunk-K44MIN6D.js} +3 -3
  80. package/dist/{chunk-5KQCOIPW.js → chunk-MECU6WSH.js} +188 -31
  81. package/dist/chunk-MECU6WSH.js.map +1 -0
  82. package/dist/{chunk-BQCFXAMN.js → chunk-MPHDVHIB.js} +2 -2
  83. package/dist/{chunk-BOGENF7P.js → chunk-MSVSP5VO.js} +1 -1
  84. package/dist/chunk-MSVSP5VO.js.map +1 -0
  85. package/dist/{chunk-QXNFQKWU.js → chunk-MTHNJCOJ.js} +2 -2
  86. package/dist/{chunk-3TCRU4JA.js → chunk-O62P2LFL.js} +2 -2
  87. package/dist/{chunk-JSDZMOT7.js → chunk-OC56UWV5.js} +11 -11
  88. package/dist/{chunk-7IBEWQLG.js → chunk-QOIONSOI.js} +2 -2
  89. package/dist/{chunk-4P5UAL3C.js → chunk-RBHANGVX.js} +6 -6
  90. package/dist/{chunk-SK2CR6MW.js → chunk-RVLB4E6N.js} +2 -2
  91. package/dist/{chunk-I3BT2IDW.js → chunk-SYDHFFAW.js} +1110 -28
  92. package/dist/chunk-SYDHFFAW.js.map +1 -0
  93. package/dist/{chunk-VILEUJXC.js → chunk-UC4YOAC2.js} +74 -2
  94. package/dist/{chunk-VILEUJXC.js.map → chunk-UC4YOAC2.js.map} +1 -1
  95. package/dist/{chunk-CNVIWMQI.js → chunk-UY4JMEAK.js} +2 -2
  96. package/dist/{chunk-S6FQLQGH.js → chunk-V7GDTQ6I.js} +2 -2
  97. package/dist/{chunk-JNOYYWCA.js → chunk-VO4UICII.js} +3 -3
  98. package/dist/{chunk-54TI5GLV.js → chunk-WI4QX7GH.js} +3 -3
  99. package/dist/{chunk-3XHD3XGK.js → chunk-XCTDHF7U.js} +30 -2
  100. package/dist/chunk-XCTDHF7U.js.map +1 -0
  101. package/dist/{chunk-XKU4YE6Z.js → chunk-XZTUMWKQ.js} +2 -2
  102. package/dist/{cli-DTWRoJEI.d.ts → cli-iAiVkbYJ.d.ts} +3 -3
  103. package/dist/cli.d.ts +6 -6
  104. package/dist/cli.js +43 -42
  105. package/dist/compounding/engine.d.ts +1 -1
  106. package/dist/compounding/engine.js +8 -7
  107. package/dist/compounding/preference-consolidator.d.ts +1 -1
  108. package/dist/compression-optimizer.d.ts +1 -1
  109. package/dist/config.d.ts +1 -1
  110. package/dist/config.js +4 -3
  111. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  112. package/dist/connectors/codex-materialize-runner.js +8 -7
  113. package/dist/connectors/codex-materialize.d.ts +1 -1
  114. package/dist/connectors/index.d.ts +1 -1
  115. package/dist/connectors/index.js +9 -8
  116. package/dist/consolidation-provenance-check.d.ts +1 -1
  117. package/dist/consolidation-undo.d.ts +1 -1
  118. package/dist/contradiction/index.d.ts +1 -1
  119. package/dist/conversation-index/backend.d.ts +1 -1
  120. package/dist/conversation-index/chunker.d.ts +1 -1
  121. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  122. package/dist/conversation-index/indexer.d.ts +1 -1
  123. package/dist/conversation-index/search.d.ts +1 -1
  124. package/dist/day-summary.d.ts +1 -1
  125. package/dist/delinearize.d.ts +1 -1
  126. package/dist/direct-answer-wiring.d.ts +1 -1
  127. package/dist/direct-answer.d.ts +1 -1
  128. package/dist/embedding-fallback.d.ts +1 -1
  129. package/dist/enrichment/index.d.ts +1 -1
  130. package/dist/entity-retrieval.d.ts +1 -1
  131. package/dist/entity-retrieval.js +8 -7
  132. package/dist/entity-schema.d.ts +1 -1
  133. package/dist/explicit-capture.d.ts +4 -4
  134. package/dist/explicit-capture.js +3 -2
  135. package/dist/extraction-faithfulness.d.ts +1 -1
  136. package/dist/extraction-judge-telemetry.d.ts +1 -1
  137. package/dist/extraction-judge-training.d.ts +1 -1
  138. package/dist/extraction-judge.d.ts +1 -1
  139. package/dist/extraction.d.ts +1 -1
  140. package/dist/extraction.js +4 -3
  141. package/dist/fallback-llm.d.ts +1 -1
  142. package/dist/identity-continuity.d.ts +1 -1
  143. package/dist/importance.d.ts +1 -1
  144. package/dist/index.d.ts +9 -9
  145. package/dist/index.js +62 -61
  146. package/dist/index.js.map +1 -1
  147. package/dist/intent.d.ts +1 -1
  148. package/dist/lcm/engine.d.ts +1 -1
  149. package/dist/lcm/index.d.ts +1 -1
  150. package/dist/lcm/index.js +3 -3
  151. package/dist/lcm/tools.d.ts +1 -1
  152. package/dist/lifecycle.d.ts +1 -1
  153. package/dist/live-connectors-runner.d.ts +1 -1
  154. package/dist/local-llm.d.ts +1 -1
  155. package/dist/maintenance/memory-governance.d.ts +1 -1
  156. package/dist/maintenance/memory-governance.js +8 -7
  157. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +8 -7
  158. package/dist/maintenance/rebuild-memory-projection.js +9 -8
  159. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  160. package/dist/memory-action-policy.d.ts +1 -1
  161. package/dist/memory-cache.d.ts +1 -1
  162. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  163. package/dist/memory-projection-store.d.ts +1 -1
  164. package/dist/memory-provenance.d.ts +1 -1
  165. package/dist/memory-worth-outcomes.d.ts +1 -1
  166. package/dist/models-json.d.ts +1 -1
  167. package/dist/namespaces/migrate.d.ts +2 -2
  168. package/dist/namespaces/migrate.js +12 -11
  169. package/dist/namespaces/principal.d.ts +1 -1
  170. package/dist/namespaces/search.d.ts +1 -1
  171. package/dist/namespaces/search.js +3 -3
  172. package/dist/namespaces/storage.d.ts +2 -2
  173. package/dist/namespaces/storage.js +8 -7
  174. package/dist/native-knowledge.d.ts +1 -1
  175. package/dist/operator-toolkit.d.ts +1 -1
  176. package/dist/operator-toolkit.js +17 -16
  177. package/dist/orchestration/maintenance.d.ts +2 -2
  178. package/dist/orchestration/maintenance.js +10 -9
  179. package/dist/{orchestrator-B1iVjEyc.d.ts → orchestrator-iVZWi8aW.d.ts} +21 -4
  180. package/dist/orchestrator.d.ts +4 -4
  181. package/dist/orchestrator.js +32 -31
  182. package/dist/patterns-cli.d.ts +1 -1
  183. package/dist/policy-runtime.d.ts +1 -1
  184. package/dist/provenance.d.ts +1 -1
  185. package/dist/provenance.js +3 -2
  186. package/dist/qmd-recall-cache.d.ts +1 -1
  187. package/dist/qmd.d.ts +1 -1
  188. package/dist/recall-disclosure-escalation.d.ts +1 -1
  189. package/dist/recall-explain-renderer.d.ts +1 -1
  190. package/dist/recall-explain-renderer.js +3 -3
  191. package/dist/recall-handles.d.ts +228 -0
  192. package/dist/recall-handles.js +42 -0
  193. package/dist/recall-handles.js.map +1 -0
  194. package/dist/recall-planner-llm.d.ts +1 -1
  195. package/dist/recall-state.d.ts +40 -2
  196. package/dist/recall-state.js +3 -1
  197. package/dist/recall-tag-filter.d.ts +1 -1
  198. package/dist/recall-xray-cli.d.ts +1 -1
  199. package/dist/recall-xray-cli.js +4 -4
  200. package/dist/recall-xray-renderer.d.ts +1 -1
  201. package/dist/recall-xray-renderer.js +3 -3
  202. package/dist/recall-xray.d.ts +1 -1
  203. package/dist/recall-xray.js +2 -2
  204. package/dist/resolve-auth-token.d.ts +1 -1
  205. package/dist/resume-bundles.js +5 -4
  206. package/dist/retrieval-agents.d.ts +1 -1
  207. package/dist/retrieval-tiers.d.ts +1 -1
  208. package/dist/routing/engine.d.ts +1 -1
  209. package/dist/routing/store.d.ts +1 -1
  210. package/dist/sanitize.d.ts +2 -0
  211. package/dist/sanitize.js +6 -2
  212. package/dist/search/embed-helper.d.ts +1 -1
  213. package/dist/search/factory.d.ts +1 -1
  214. package/dist/search/factory.js +2 -2
  215. package/dist/search/index.d.ts +1 -1
  216. package/dist/search/index.js +4 -4
  217. package/dist/search/lancedb-backend.d.ts +1 -1
  218. package/dist/search/meilisearch-backend.d.ts +1 -1
  219. package/dist/search/noop-backend.d.ts +1 -1
  220. package/dist/search/orama-backend.d.ts +1 -1
  221. package/dist/search/port.d.ts +1 -1
  222. package/dist/search/remote-backend.d.ts +1 -1
  223. package/dist/{semantic-consolidation-CY8uVRNJ.d.ts → semantic-consolidation-DSjMDZ1u.d.ts} +1 -1
  224. package/dist/semantic-consolidation.d.ts +2 -2
  225. package/dist/semantic-consolidation.js +9 -8
  226. package/dist/semantic-rule-promotion.js +8 -7
  227. package/dist/semantic-rule-verifier.d.ts +1 -1
  228. package/dist/semantic-rule-verifier.js +8 -7
  229. package/dist/session-observer-bands.d.ts +1 -1
  230. package/dist/session-observer-state.d.ts +1 -1
  231. package/dist/shared-context/manager.d.ts +3 -3
  232. package/dist/signal.d.ts +1 -1
  233. package/dist/storage.d.ts +1 -1
  234. package/dist/storage.js +7 -6
  235. package/dist/summarizer.d.ts +1 -1
  236. package/dist/summary-snapshot.d.ts +1 -1
  237. package/dist/temporal-supersession.d.ts +1 -1
  238. package/dist/temporal-validity.d.ts +1 -1
  239. package/dist/threading.d.ts +1 -1
  240. package/dist/tier-migration.d.ts +1 -1
  241. package/dist/tier-routing.d.ts +1 -1
  242. package/dist/topics.d.ts +1 -1
  243. package/dist/transcript.d.ts +1 -1
  244. package/dist/transfer/import-sqlite.js +2 -2
  245. package/dist/{types-Dr0Cw3L9.d.ts → types-D9dwzU_x.d.ts} +25 -1
  246. package/dist/types.d.ts +1 -1
  247. package/dist/types.js +1 -1
  248. package/dist/utility-runtime.d.ts +1 -1
  249. package/dist/verified-recall.js +8 -7
  250. package/package.json +2 -2
  251. package/src/access-boundary.ts +4 -1
  252. package/src/access-http.ts +78 -20
  253. package/src/access-mcp.test.ts +29 -0
  254. package/src/access-mcp.ts +99 -17
  255. package/src/access-operations-batch.ts +14 -0
  256. package/src/access-operations.ts +5 -0
  257. package/src/access-schema.ts +8 -0
  258. package/src/access-service-observe-idempotency.test.ts +308 -0
  259. package/src/access-service.ts +106 -5
  260. package/src/access-surface-catalog.test.ts +4 -2
  261. package/src/access-surface-catalog.ts +5 -0
  262. package/src/active-memory-bridge.test.ts +72 -0
  263. package/src/active-memory-bridge.ts +21 -2
  264. package/src/chat/chat-cli.test.ts +142 -0
  265. package/src/chat/chat-cli.ts +206 -0
  266. package/src/chat/chat-config.ts +57 -0
  267. package/src/chat/chat-engine.test.ts +272 -0
  268. package/src/chat/chat-engine.ts +518 -0
  269. package/src/chat/chat-executor.ts +133 -0
  270. package/src/chat/chat-factory.ts +161 -0
  271. package/src/chat/chat-http.test.ts +197 -0
  272. package/src/chat/chat-http.ts +222 -0
  273. package/src/chat/chat-llm.ts +229 -0
  274. package/src/chat/chat-mcp.test.ts +135 -0
  275. package/src/chat/chat-security.test.ts +491 -0
  276. package/src/chat/chat-session.ts +296 -0
  277. package/src/chat/chat-system-prompt.ts +76 -0
  278. package/src/chat/chat-tools.ts +255 -0
  279. package/src/chat/chat-types.ts +167 -0
  280. package/src/cli.ts +20 -0
  281. package/src/config.ts +9 -0
  282. package/src/orchestrator.ts +106 -5
  283. package/src/recall-handles-wiring.test.ts +477 -0
  284. package/src/recall-handles.test.ts +283 -0
  285. package/src/recall-handles.ts +414 -0
  286. package/src/recall-state.ts +99 -0
  287. package/src/sanitize.ts +6 -0
  288. package/src/types.ts +29 -0
  289. package/dist/chunk-3XHD3XGK.js.map +0 -1
  290. package/dist/chunk-5KQCOIPW.js.map +0 -1
  291. package/dist/chunk-A2R5NV6O.js.map +0 -1
  292. package/dist/chunk-BOGENF7P.js.map +0 -1
  293. package/dist/chunk-GKPIY7EQ.js.map +0 -1
  294. package/dist/chunk-I3BT2IDW.js.map +0 -1
  295. package/dist/chunk-NUWZFSKC.js.map +0 -1
  296. package/dist/chunk-SINGJCUR.js.map +0 -1
  297. package/dist/chunk-Z3B2YW56.js.map +0 -1
  298. package/dist/chunk-ZVDRL6SK.js.map +0 -1
  299. /package/dist/{chunk-OMSTU233.js.map → chunk-2KAYTPPT.js.map} +0 -0
  300. /package/dist/{chunk-VYZNWH4J.js.map → chunk-2SXMCQEQ.js.map} +0 -0
  301. /package/dist/{chunk-NXL5CVE7.js.map → chunk-2Y6LMOQQ.js.map} +0 -0
  302. /package/dist/{chunk-LQ4J7ELC.js.map → chunk-67HG7KFE.js.map} +0 -0
  303. /package/dist/{chunk-ZBG4K36I.js.map → chunk-6FUJ2VYY.js.map} +0 -0
  304. /package/dist/{chunk-GMRNKPWO.js.map → chunk-6QUPUTT7.js.map} +0 -0
  305. /package/dist/{chunk-Z56IHRVV.js.map → chunk-6UU43ZGD.js.map} +0 -0
  306. /package/dist/{chunk-APJQ6UEA.js.map → chunk-AGNBY3VG.js.map} +0 -0
  307. /package/dist/{chunk-OWOKOFXK.js.map → chunk-AJOIM6UR.js.map} +0 -0
  308. /package/dist/{chunk-JBPKEARU.js.map → chunk-AU7Q3LSC.js.map} +0 -0
  309. /package/dist/{chunk-K22IJO4R.js.map → chunk-CTOQEZSN.js.map} +0 -0
  310. /package/dist/{chunk-HSDJCT3V.js.map → chunk-DXGS5YOQ.js.map} +0 -0
  311. /package/dist/{chunk-HV57RHMD.js.map → chunk-EH5ED3C6.js.map} +0 -0
  312. /package/dist/{chunk-7NDYFAJS.js.map → chunk-GM3BMWKR.js.map} +0 -0
  313. /package/dist/{chunk-5QUS24F7.js.map → chunk-I56LKMF7.js.map} +0 -0
  314. /package/dist/{chunk-35YJ6KCV.js.map → chunk-JEIROMLX.js.map} +0 -0
  315. /package/dist/{chunk-SKQCFAYU.js.map → chunk-JVEMUX6L.js.map} +0 -0
  316. /package/dist/{chunk-CXMXAC5R.js.map → chunk-K44MIN6D.js.map} +0 -0
  317. /package/dist/{chunk-BQCFXAMN.js.map → chunk-MPHDVHIB.js.map} +0 -0
  318. /package/dist/{chunk-QXNFQKWU.js.map → chunk-MTHNJCOJ.js.map} +0 -0
  319. /package/dist/{chunk-3TCRU4JA.js.map → chunk-O62P2LFL.js.map} +0 -0
  320. /package/dist/{chunk-JSDZMOT7.js.map → chunk-OC56UWV5.js.map} +0 -0
  321. /package/dist/{chunk-7IBEWQLG.js.map → chunk-QOIONSOI.js.map} +0 -0
  322. /package/dist/{chunk-4P5UAL3C.js.map → chunk-RBHANGVX.js.map} +0 -0
  323. /package/dist/{chunk-SK2CR6MW.js.map → chunk-RVLB4E6N.js.map} +0 -0
  324. /package/dist/{chunk-CNVIWMQI.js.map → chunk-UY4JMEAK.js.map} +0 -0
  325. /package/dist/{chunk-S6FQLQGH.js.map → chunk-V7GDTQ6I.js.map} +0 -0
  326. /package/dist/{chunk-JNOYYWCA.js.map → chunk-VO4UICII.js.map} +0 -0
  327. /package/dist/{chunk-54TI5GLV.js.map → chunk-WI4QX7GH.js.map} +0 -0
  328. /package/dist/{chunk-XKU4YE6Z.js.map → chunk-XZTUMWKQ.js.map} +0 -0
@@ -0,0 +1,296 @@
1
+ /**
2
+ * Chat session state — transcript + pending-plan pointer persisted under
3
+ * `<memoryDir>/state/chat/<chatSessionId>.jsonl` (issue #1583).
4
+ *
5
+ * Atomic appends (rule 54). Chat transcripts are excluded from memory
6
+ * extraction — the work-task exclusion tag is stamped on creation so talking
7
+ * *about* memories does not create memories of the conversation itself.
8
+ */
9
+
10
+ import { mkdir, readFile, appendFile, readdir, stat, unlink } from "node:fs/promises";
11
+ import { join } from "node:path";
12
+ import { randomUUID } from "node:crypto";
13
+
14
+ import type { ChatSessionState, ChatTranscriptEntry } from "./chat-types.js";
15
+
16
+ const CHAT_DIR_NAME = "state/chat";
17
+
18
+ /**
19
+ * Resolve the chat-session directory for a given memory dir.
20
+ */
21
+ export function chatSessionDir(memoryDir: string): string {
22
+ return join(memoryDir, CHAT_DIR_NAME);
23
+ }
24
+
25
+ /**
26
+ * Resolve the transcript file path for a chat session id.
27
+ */
28
+ /**
29
+ * Validate a chat session id is safe for filesystem use (no path traversal).
30
+ * Accepts UUIDs and alphanumeric+dash identifiers only (P1 — path safety).
31
+ */
32
+ export function isSafeChatSessionId(chatSessionId: string): boolean {
33
+ return /^[A-Za-z0-9]{8,128}$/.test(chatSessionId.replace(/-/g, ""));
34
+ }
35
+
36
+ export function chatSessionFile(memoryDir: string, chatSessionId: string): string {
37
+ if (!isSafeChatSessionId(chatSessionId)) {
38
+ throw new Error("Invalid chat session id");
39
+ }
40
+ return join(chatSessionDir(memoryDir), `${chatSessionId}.jsonl`);
41
+ }
42
+
43
+ /**
44
+ * Create a new chat session. The session binds the caller's principal and
45
+ * sessionKey at creation (rule 42); every tool call flows through
46
+ * access-service with that identity.
47
+ */
48
+ export async function createChatSession(
49
+ memoryDir: string,
50
+ opts: { principal?: string; sessionKey?: string; namespace?: string },
51
+ ): Promise<ChatSessionState> {
52
+ const id = randomUUID();
53
+ const now = new Date().toISOString();
54
+ const state: ChatSessionState = {
55
+ id,
56
+ principal: opts.principal,
57
+ sessionKey: opts.sessionKey,
58
+ namespace: opts.namespace,
59
+ transcript: [],
60
+ confirmedPlanIds: new Set(),
61
+ createdAt: now,
62
+ };
63
+ // Ensure the directory exists.
64
+ await mkdir(chatSessionDir(memoryDir), { recursive: true });
65
+ // Write a metadata header line so the file is never empty and carries
66
+ // the principal/scope binding (used for per-session isolation checks).
67
+ await appendFile(
68
+ chatSessionFile(memoryDir, id),
69
+ JSON.stringify({
70
+ seq: 0,
71
+ ts: now,
72
+ role: "system" as const,
73
+ content: `Chat session created. Principal: ${opts.principal ?? "default"}. Namespace: ${opts.namespace ?? "default"}. work_task: Excluded from memory extraction`,
74
+ // Structured binding fields so loadChatSession doesn't need to regex-parse
75
+ // prose (robust against dotted principals like alice@example.com).
76
+ ...(opts.principal ? { principal: opts.principal } : {}),
77
+ ...(opts.namespace ? { namespace: opts.namespace } : {}),
78
+ ...(opts.sessionKey ? { sessionKey: opts.sessionKey } : {}),
79
+ }) + "\n",
80
+ "utf8",
81
+ );
82
+ return state;
83
+ }
84
+
85
+ /**
86
+ * Load a chat session from disk, including its full transcript.
87
+ * Returns `null` if the session file does not exist.
88
+ *
89
+ * Per-session isolation: the caller MUST verify that the loaded session's
90
+ * principal matches the requesting principal before operating on it.
91
+ */
92
+ export async function loadChatSession(
93
+ memoryDir: string,
94
+ chatSessionId: string,
95
+ ): Promise<ChatSessionState | null> {
96
+ let raw: string;
97
+ try {
98
+ raw = await readFile(chatSessionFile(memoryDir, chatSessionId), "utf8");
99
+ } catch {
100
+ return null;
101
+ }
102
+ const lines = raw.split("\n").filter((l) => l.trim().length > 0);
103
+ const transcript: ChatTranscriptEntry[] = [];
104
+ let principal: string | undefined;
105
+ let sessionKey: string | undefined;
106
+ let namespace: string | undefined;
107
+ let createdAt = "";
108
+ let pendingPlanId: string | undefined;
109
+ let pendingPromotionId: string | undefined;
110
+ for (const line of lines) {
111
+ try {
112
+ const entry = JSON.parse(line) as ChatTranscriptEntry & Record<string, unknown>;
113
+ transcript.push(entry);
114
+ // Extract binding from the system header line.
115
+ if (entry.role === "system" && entry.seq === 0) {
116
+ // Prefer structured fields (robust against dotted principals).
117
+ const metaPrincipal = typeof entry.principal === "string" ? entry.principal : undefined;
118
+ const metaNamespace = typeof entry.namespace === "string" ? entry.namespace : undefined;
119
+ const metaSessionKey = typeof entry.sessionKey === "string" ? entry.sessionKey : undefined;
120
+ if (metaPrincipal) principal = metaPrincipal;
121
+ else {
122
+ // Greedy regex fallback for older session files (captures until ". Namespace").
123
+ const pMatch = entry.content.match(/Principal: (.+?)\.\s/);
124
+ if (pMatch) principal = pMatch[1]?.trim() === "default" ? undefined : pMatch[1]?.trim();
125
+ }
126
+ if (metaNamespace) namespace = metaNamespace;
127
+ else {
128
+ const nsMatch = entry.content.match(/Namespace: (.+?)\.\s/);
129
+ if (nsMatch) namespace = nsMatch[1]?.trim() === "default" ? undefined : nsMatch[1]?.trim();
130
+ }
131
+ if (metaSessionKey) sessionKey = metaSessionKey;
132
+ createdAt = entry.ts;
133
+ }
134
+ // Scan for pending-plan / pending-promotion markers (append-only state).
135
+ if (entry.role === "system") {
136
+ const pm = entry.content.match(/^pending_plan:(.+)$/);
137
+ if (pm) pendingPlanId = pm[1];
138
+ const pp = entry.content.match(/^pending_promotion:(.+)$/);
139
+ if (pp) pendingPromotionId = pp[1];
140
+ const resolved = entry.content.match(/^(plan_applied|plan_cancelled|promotion_applied|promotion_cancelled):/);
141
+ if (resolved) {
142
+ // Only clear the matching pending — a plan resolution must not drop
143
+ // an active promotion (and vice versa) (cursor Medium OlACs).
144
+ if (entry.content.startsWith("plan_")) {
145
+ pendingPlanId = undefined;
146
+ }
147
+ if (entry.content.startsWith("promotion_")) {
148
+ pendingPromotionId = undefined;
149
+ }
150
+ }
151
+ }
152
+ } catch {
153
+ // Skip malformed lines (rule 54 — atomic appends; partial lines are
154
+ // tolerated, never crash the engine).
155
+ }
156
+ }
157
+ return {
158
+ id: chatSessionId,
159
+ principal,
160
+ sessionKey,
161
+ namespace,
162
+ transcript,
163
+ confirmedPlanIds: new Set(),
164
+ ...(pendingPlanId ? { pendingPlanId } : {}),
165
+ ...(pendingPromotionId ? { pendingPromotionId } : {}),
166
+ createdAt,
167
+ };
168
+ }
169
+
170
+ /**
171
+ * Append a transcript entry to the session file (atomic append, rule 54).
172
+ */
173
+ export async function appendTranscriptEntry(
174
+ memoryDir: string,
175
+ chatSessionId: string,
176
+ entry: Omit<ChatTranscriptEntry, "seq" | "ts">,
177
+ ): Promise<ChatTranscriptEntry> {
178
+ const full: ChatTranscriptEntry = {
179
+ ...entry,
180
+ seq: Date.now(),
181
+ ts: new Date().toISOString(),
182
+ };
183
+ await appendFile(
184
+ chatSessionFile(memoryDir, chatSessionId),
185
+ JSON.stringify(full) + "\n",
186
+ "utf8",
187
+ );
188
+ return full;
189
+ }
190
+
191
+ /**
192
+ * Append a pending-plan marker so a later turn can confirm the plan
193
+ * (append-only state — loadChatSession scans for the latest unresolved one).
194
+ */
195
+ export async function markPendingPlan(
196
+ memoryDir: string,
197
+ chatSessionId: string,
198
+ planId: string,
199
+ ): Promise<void> {
200
+ await appendTranscriptEntry(memoryDir, chatSessionId, {
201
+ role: "system",
202
+ content: `pending_plan:${planId}`,
203
+ });
204
+ }
205
+
206
+ /**
207
+ * Append a pending-promotion marker so a later turn can confirm the promotion.
208
+ */
209
+ export async function markPendingPromotion(
210
+ memoryDir: string,
211
+ chatSessionId: string,
212
+ memoryId: string,
213
+ ): Promise<void> {
214
+ await appendTranscriptEntry(memoryDir, chatSessionId, {
215
+ role: "system",
216
+ content: `pending_promotion:${memoryId}`,
217
+ });
218
+ }
219
+
220
+ /**
221
+ * Record that a pending plan was applied or cancelled.
222
+ */
223
+ export async function markPlanResolved(
224
+ memoryDir: string,
225
+ chatSessionId: string,
226
+ planId: string,
227
+ ): Promise<void> {
228
+ await appendTranscriptEntry(memoryDir, chatSessionId, {
229
+ role: "system",
230
+ content: `plan_applied:${planId}`,
231
+ });
232
+ }
233
+
234
+ /**
235
+ * Record that a pending promotion was applied or cancelled.
236
+ */
237
+ export async function markPromotionResolved(
238
+ memoryDir: string,
239
+ chatSessionId: string,
240
+ memoryId: string,
241
+ ): Promise<void> {
242
+ await appendTranscriptEntry(memoryDir, chatSessionId, {
243
+ role: "system",
244
+ content: `promotion_applied:${memoryId}`,
245
+ });
246
+ }
247
+
248
+ /**
249
+ * Clean up expired chat sessions based on TTL.
250
+ */
251
+ export async function cleanupExpiredChatSessions(
252
+ memoryDir: string,
253
+ ttlHours: number,
254
+ ): Promise<number> {
255
+ const dir = chatSessionDir(memoryDir);
256
+ let files: string[];
257
+ try {
258
+ files = await readdir(dir);
259
+ } catch {
260
+ return 0;
261
+ }
262
+ const now = Date.now();
263
+ let removed = 0;
264
+ for (const file of files) {
265
+ if (!file.endsWith(".jsonl")) continue;
266
+ try {
267
+ const filePath = join(dir, file);
268
+ const st = await stat(filePath);
269
+ const ageHours = (now - st.mtimeMs) / (1000 * 60 * 60);
270
+ // TTL of 0 = expire everything immediately. For positive TTLs the
271
+ // boundary is inclusive; sub-millisecond APFS mtime skew is negligible
272
+ // against an hour-scale threshold (rule 54 — deterministic cleanup).
273
+ if (ttlHours <= 0 || ageHours >= ttlHours) {
274
+ await unlink(filePath);
275
+ removed++;
276
+ }
277
+ } catch {
278
+ // Best-effort cleanup; skip files we can't stat/unlink.
279
+ }
280
+ }
281
+ return removed;
282
+ }
283
+
284
+ /**
285
+ * Verify that a session belongs to the given principal (rule 42/47 —
286
+ * per-session isolation, no cross-visibility).
287
+ */
288
+ export function sessionBelongsToPrincipal(
289
+ session: ChatSessionState,
290
+ principal?: string,
291
+ ): boolean {
292
+ // A session with no recorded principal is accessible to anyone (legacy/
293
+ // single-user case). A session with a principal requires an exact match.
294
+ if (!session.principal) return true;
295
+ return session.principal === principal;
296
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Sealed system prompt for the chat engine (issue #1583).
3
+ *
4
+ * The prompt encodes the core rules that every turn enforces:
5
+ * - Always cite memory ids/handles and source quotes when asserting what's
6
+ * remembered.
7
+ * - NEVER apply a mutation without explicit user confirmation in the
8
+ * conversation.
9
+ * - Render plans as the diff the Correction Contract returns.
10
+ * - Prefer "I found nothing" over speculation.
11
+ *
12
+ * The engine supplements the prompt with a tool-citation guard at runtime
13
+ * (the model must ground assertions in tool results from the current turn).
14
+ */
15
+
16
+ /**
17
+ * Build the system prompt for the chat engine. Parameterised by whether the
18
+ * correction (mutation) tools are available — when #1580 is not yet merged,
19
+ * correction_plan/apply are omitted and the prompt reflects that.
20
+ */
21
+ export function buildChatSystemPrompt(opts: {
22
+ correctionAvailable: boolean;
23
+ }): string {
24
+ const lines: string[] = [
25
+ "You are Remnic Chat — a conversational memory inspector and corrector.",
26
+ "You help the user understand, explore, and fix what Remnic remembers.",
27
+ "",
28
+ "## Core rules",
29
+ "",
30
+ "1. GROUND EVERY ASSERTION. When you state what Remnic remembers, you MUST",
31
+ " cite the memory id or handle, include the source quote, and the date.",
32
+ " If no tool result in this turn supports the claim, say",
33
+ " \"I found nothing\" instead of guessing.",
34
+ "",
35
+ "2. NO MUTATION WITHOUT CONFIRMATION. You may propose a correction plan",
36
+ " (correction_plan), but you must NEVER apply it (correction_apply) until",
37
+ " the user explicitly confirms in the conversation.",
38
+ "",
39
+ "3. RENDER PLANS AS DIFFS. When you surface a correction plan, render it",
40
+ " as the diff preview the plan returns — before/after, affected memory",
41
+ " ids, and the supersession reason.",
42
+ "",
43
+ "4. BE HONEST ABOUT LIMITS. If a tool returns no results, say so. If you",
44
+ " are unsure, say so. Never fabricate memory content.",
45
+ "",
46
+ "5. RESPECT SCOPE. You operate within the caller's namespace and principal.",
47
+ " Do not attempt to access memories outside the caller's scope.",
48
+ ];
49
+
50
+ if (opts.correctionAvailable) {
51
+ lines.push(
52
+ "",
53
+ "## Mutation protocol",
54
+ "",
55
+ "When the user asks to change or forget memories:",
56
+ "1. Call correction_plan to generate a diff preview.",
57
+ "2. Present the diff to the user and ask them to reply 'apply' to confirm.",
58
+ "3. Only after explicit confirmation, call correction_apply.",
59
+ "",
60
+ "For bulk/destructive requests ('forget everything about X'), always go",
61
+ "through correction_plan first — there is no direct-delete tool.",
62
+ );
63
+ } else {
64
+ lines.push(
65
+ "",
66
+ "## Mutation status",
67
+ "",
68
+ "Correction (mutation) tools are not yet available in this build.",
69
+ "You can inspect and search memories but cannot apply corrections.",
70
+ "When the user asks to change memories, explain that correction tools",
71
+ "require the Correction Contract (#1580) which is pending.",
72
+ );
73
+ }
74
+
75
+ return lines.join("\n");
76
+ }
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Chat tools — the ONLY tools available to the chat engine (issue #1583).
3
+ *
4
+ * Each tool is a thin adapter over an existing access-service method (rule 22
5
+ * — zero new business logic here). Mutating tools (correction_apply,
6
+ * memory_promote) are marked and go through the confirmation protocol in the
7
+ * engine before reaching the executor.
8
+ */
9
+
10
+ import type { ChatToolSchema } from "./chat-types.js";
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // Tool identifiers
14
+ // ---------------------------------------------------------------------------
15
+
16
+ export type ChatToolName =
17
+ | "memory_search"
18
+ | "memory_get"
19
+ | "memory_timeline"
20
+ | "recall_explain"
21
+ | "entity_get"
22
+ | "stats"
23
+ | "correction_plan"
24
+ | "correction_apply"
25
+ | "memory_promote"
26
+ | "review_list"
27
+ | "scope_inspect";
28
+
29
+ /** Tools that mutate memory — require confirmation before execution. */
30
+ export const MUTATING_TOOLS: ReadonlySet<ChatToolName> = new Set([
31
+ "correction_apply",
32
+ "memory_promote",
33
+ ]);
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // Tool schema definitions (sent to the LLM as the function-calling schema)
37
+ // ---------------------------------------------------------------------------
38
+
39
+ const MEMORY_SEARCH_SCHEMA: ChatToolSchema = {
40
+ type: "function",
41
+ function: {
42
+ name: "memory_search",
43
+ description:
44
+ "Semantic search across stored memories. Returns matching memory paths, scores, and snippets. Use this to find what Remnic remembers about a topic.",
45
+ parameters: {
46
+ type: "object",
47
+ properties: {
48
+ query: { type: "string", description: "The search query." },
49
+ maxResults: { type: "number", description: "Maximum results (default 8)." },
50
+ },
51
+ required: ["query"],
52
+ additionalProperties: false,
53
+ },
54
+ },
55
+ };
56
+
57
+ const MEMORY_GET_SCHEMA: ChatToolSchema = {
58
+ type: "function",
59
+ function: {
60
+ name: "memory_get",
61
+ description:
62
+ "Fetch a single memory by its id. Returns the full memory content, category, tags, and source attribution.",
63
+ parameters: {
64
+ type: "object",
65
+ properties: {
66
+ memoryId: { type: "string", description: "The memory id to fetch." },
67
+ },
68
+ required: ["memoryId"],
69
+ additionalProperties: false,
70
+ },
71
+ },
72
+ };
73
+
74
+ const MEMORY_TIMELINE_SCHEMA: ChatToolSchema = {
75
+ type: "function",
76
+ function: {
77
+ name: "memory_timeline",
78
+ description:
79
+ "Read the lifecycle timeline of a single memory — creation, updates, consolidations, and tier transitions.",
80
+ parameters: {
81
+ type: "object",
82
+ properties: {
83
+ memoryId: { type: "string", description: "The memory id." },
84
+ limit: { type: "number", description: "Maximum rows (default 200)." },
85
+ },
86
+ required: ["memoryId"],
87
+ additionalProperties: false,
88
+ },
89
+ },
90
+ };
91
+
92
+ const RECALL_EXPLAIN_SCHEMA: ChatToolSchema = {
93
+ type: "function",
94
+ function: {
95
+ name: "recall_explain",
96
+ description:
97
+ "Explain why Remnic would recall certain memories for a given query. Returns tier scoring and matching details. Use this to answer 'why did you remember this?'",
98
+ parameters: {
99
+ type: "object",
100
+ properties: {
101
+ query: { type: "string", description: "Optional query to explain recall for. When omitted, explains the most recent recall." },
102
+ },
103
+ required: [],
104
+ additionalProperties: false,
105
+ },
106
+ },
107
+ };
108
+
109
+ const ENTITY_GET_SCHEMA: ChatToolSchema = {
110
+ type: "function",
111
+ function: {
112
+ name: "entity_get",
113
+ description:
114
+ "Fetch the compiled entity record for a named entity (person, project, tool, etc.). Returns traits, timeline, and associated memories.",
115
+ parameters: {
116
+ type: "object",
117
+ properties: {
118
+ name: { type: "string", description: "Entity name." },
119
+ },
120
+ required: ["name"],
121
+ additionalProperties: false,
122
+ },
123
+ },
124
+ };
125
+
126
+ const STATS_SCHEMA: ChatToolSchema = {
127
+ type: "function",
128
+ function: {
129
+ name: "stats",
130
+ description:
131
+ "Return aggregate memory statistics — memory count, entity count, profile summary, and open questions. Use this for high-level 'what do you know?' questions.",
132
+ parameters: {
133
+ type: "object",
134
+ properties: {},
135
+ additionalProperties: false,
136
+ },
137
+ },
138
+ };
139
+
140
+ const CORRECTION_PLAN_SCHEMA: ChatToolSchema = {
141
+ type: "function",
142
+ function: {
143
+ name: "correction_plan",
144
+ description:
145
+ "Generate a correction plan (diff preview) for a requested memory change. This does NOT apply the change — it previews what would happen. The user must confirm before correction_apply runs.",
146
+ parameters: {
147
+ type: "object",
148
+ properties: {
149
+ request: {
150
+ type: "string",
151
+ description:
152
+ "Natural-language description of the correction, e.g. 'we finished the MySQL migration in March' or 'forget the outdated database credentials'.",
153
+ },
154
+ },
155
+ required: ["request"],
156
+ additionalProperties: false,
157
+ },
158
+ },
159
+ };
160
+
161
+ const CORRECTION_APPLY_SCHEMA: ChatToolSchema = {
162
+ type: "function",
163
+ function: {
164
+ name: "correction_apply",
165
+ description:
166
+ "Apply a previously generated correction plan. The engine intercepts this call and requires explicit user confirmation before it executes.",
167
+ parameters: {
168
+ type: "object",
169
+ properties: {
170
+ planId: { type: "string", description: "The plan id from correction_plan." },
171
+ },
172
+ required: ["planId"],
173
+ additionalProperties: false,
174
+ },
175
+ },
176
+ };
177
+
178
+ const MEMORY_PROMOTE_SCHEMA: ChatToolSchema = {
179
+ type: "function",
180
+ function: {
181
+ name: "memory_promote",
182
+ description:
183
+ "Promote a memory's tier (e.g. from cold to hot). The engine requires user confirmation before executing.",
184
+ parameters: {
185
+ type: "object",
186
+ properties: {
187
+ memoryId: { type: "string", description: "The memory id to promote." },
188
+ },
189
+ required: ["memoryId"],
190
+ additionalProperties: false,
191
+ },
192
+ },
193
+ };
194
+
195
+ const REVIEW_LIST_SCHEMA: ChatToolSchema = {
196
+ type: "function",
197
+ function: {
198
+ name: "review_list",
199
+ description:
200
+ "List items in the contradiction/quality review queue. Returns pairs of potentially conflicting memories awaiting resolution.",
201
+ parameters: {
202
+ type: "object",
203
+ properties: {
204
+ runId: { type: "string", description: "Optional governance run id." },
205
+ },
206
+ additionalProperties: false,
207
+ },
208
+ },
209
+ };
210
+
211
+ const SCOPE_INSPECT_SCHEMA: ChatToolSchema = {
212
+ type: "function",
213
+ function: {
214
+ name: "scope_inspect",
215
+ description:
216
+ "Inspect the current scope/namespace resolution — which namespace the chat session operates in and how it was resolved.",
217
+ parameters: {
218
+ type: "object",
219
+ properties: {},
220
+ additionalProperties: false,
221
+ },
222
+ },
223
+ };
224
+
225
+ /**
226
+ * All read-only tool schemas, always available when chat is enabled.
227
+ */
228
+ const READONLY_SCHEMAS: ChatToolSchema[] = [
229
+ MEMORY_SEARCH_SCHEMA,
230
+ MEMORY_GET_SCHEMA,
231
+ MEMORY_TIMELINE_SCHEMA,
232
+ RECALL_EXPLAIN_SCHEMA,
233
+ ENTITY_GET_SCHEMA,
234
+ STATS_SCHEMA,
235
+ REVIEW_LIST_SCHEMA,
236
+ ];
237
+
238
+ /**
239
+ * Build the tool schema list for the LLM. The correction tools are only
240
+ * included when the Correction Contract (#1580) is available; scope_inspect
241
+ * is only included when the scope resolver (#1494) is available.
242
+ */
243
+ export function buildChatToolSchemas(opts: {
244
+ correctionAvailable: boolean;
245
+ scopeInspectAvailable: boolean;
246
+ }): ChatToolSchema[] {
247
+ const tools = [...READONLY_SCHEMAS];
248
+ if (opts.correctionAvailable) {
249
+ tools.push(CORRECTION_PLAN_SCHEMA, CORRECTION_APPLY_SCHEMA, MEMORY_PROMOTE_SCHEMA);
250
+ }
251
+ if (opts.scopeInspectAvailable) {
252
+ tools.push(SCOPE_INSPECT_SCHEMA);
253
+ }
254
+ return tools;
255
+ }