@remnic/core 9.62.0 → 9.62.2

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 (512) hide show
  1. package/dist/access-admin-ops-surface.d.ts +11 -11
  2. package/dist/access-admin-ops-surface.js +28 -28
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-authorization-probe.d.ts +11 -11
  5. package/dist/access-authorization-probe.js +29 -29
  6. package/dist/access-boundary.d.ts +11 -11
  7. package/dist/access-boundary.js +28 -28
  8. package/dist/access-cli.js +93 -91
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-coding-context-resolution.d.ts +1 -1
  11. package/dist/access-extraction-force-flush.d.ts +11 -11
  12. package/dist/access-extraction-force-flush.js +28 -28
  13. package/dist/access-health-types.d.ts +1 -1
  14. package/dist/access-http-lcm-compaction.d.ts +11 -11
  15. package/dist/access-http-lifecycle-flush.d.ts +11 -11
  16. package/dist/access-http-offline-stream.d.ts +11 -11
  17. package/dist/access-http-query.js +28 -28
  18. package/dist/access-http.d.ts +12 -12
  19. package/dist/access-http.js +38 -38
  20. package/dist/access-identity-continuity-surface.d.ts +9 -9
  21. package/dist/access-identity-continuity-surface.js +28 -28
  22. package/dist/access-lcm-surface.d.ts +11 -11
  23. package/dist/access-lcm-surface.js +28 -28
  24. package/dist/access-mcp.d.ts +11 -11
  25. package/dist/access-mcp.js +33 -33
  26. package/dist/access-memory-search-fanout.d.ts +2 -2
  27. package/dist/{access-namespace-preflight-EMvicnrb.d.ts → access-namespace-preflight-yO4LMGFH.d.ts} +1 -1
  28. package/dist/access-namespace-preflight.d.ts +3 -3
  29. package/dist/access-namespace-preflight.js +28 -28
  30. package/dist/access-observe-write-surface.d.ts +11 -11
  31. package/dist/access-observe-write-surface.js +28 -28
  32. package/dist/access-offline-manifest.d.ts +9 -9
  33. package/dist/access-offline-manifest.js +2 -2
  34. package/dist/access-operations-batch.js +29 -29
  35. package/dist/access-operations.d.ts +11 -11
  36. package/dist/access-operations.js +32 -32
  37. package/dist/access-recall-concurrency.d.ts +11 -11
  38. package/dist/access-recall-concurrency.js +28 -28
  39. package/dist/access-recall-response.d.ts +11 -11
  40. package/dist/access-recall-response.js +28 -28
  41. package/dist/access-recall-surface.d.ts +11 -11
  42. package/dist/access-recall-surface.js +28 -28
  43. package/dist/{access-service-BeDYQQ62.d.ts → access-service-M4LgO141.d.ts} +7 -7
  44. package/dist/access-service-helpers.d.ts +11 -11
  45. package/dist/access-service.d.ts +11 -11
  46. package/dist/access-service.js +28 -28
  47. package/dist/access-surface-catalog.d.ts +11 -11
  48. package/dist/access-surface-catalog.js +30 -30
  49. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  50. package/dist/action-confidence.d.ts +1 -1
  51. package/dist/active-memory-bridge.d.ts +1 -1
  52. package/dist/active-memory-bridge.js +2 -2
  53. package/dist/active-recall.d.ts +1 -1
  54. package/dist/active-recall.js +3 -3
  55. package/dist/ambient-provenance.d.ts +1 -1
  56. package/dist/artifact-search.d.ts +1 -1
  57. package/dist/{auto-sync-FMWQQB3J.js → auto-sync-Z52VWMNC.js} +3 -3
  58. package/dist/behavior-learner.d.ts +1 -1
  59. package/dist/behavior-learner.js +2 -2
  60. package/dist/behavior-signals.d.ts +1 -1
  61. package/dist/bootstrap.d.ts +9 -9
  62. package/dist/briefing-window.d.ts +2 -2
  63. package/dist/briefing.d.ts +2 -2
  64. package/dist/briefing.js +13 -12
  65. package/dist/buffer-surprise-report.d.ts +1 -1
  66. package/dist/buffer-turn-helpers.d.ts +1 -1
  67. package/dist/buffer.d.ts +2 -2
  68. package/dist/bulk-import/index.d.ts +3 -3
  69. package/dist/calibration.d.ts +1 -1
  70. package/dist/capabilities.d.ts +1 -1
  71. package/dist/{catalog-B2SxZ6LU.d.ts → catalog-CyYTf_ok.d.ts} +1 -1
  72. package/dist/causal-behavior.d.ts +1 -1
  73. package/dist/causal-behavior.js +3 -3
  74. package/dist/causal-chain.js +3 -3
  75. package/dist/causal-consolidation.d.ts +1 -1
  76. package/dist/causal-consolidation.js +16 -16
  77. package/dist/causal-retrieval.js +3 -3
  78. package/dist/causal-trajectory-graph.d.ts +1 -1
  79. package/dist/causal-trajectory.js +2 -2
  80. package/dist/{chunk-B2QHVLJO.js → chunk-256FBCVX.js} +22 -10
  81. package/dist/chunk-256FBCVX.js.map +1 -0
  82. package/dist/{chunk-QP2IZTUR.js → chunk-2TYIAKU5.js} +2 -2
  83. package/dist/{chunk-HQBVQICL.js → chunk-347ZR6D4.js} +2 -2
  84. package/dist/{chunk-76YNCJ5H.js → chunk-3F3CVVDS.js} +2 -2
  85. package/dist/{chunk-TE4MKFT2.js → chunk-3MA7JVXN.js} +4 -4
  86. package/dist/{chunk-KHQ57QLJ.js → chunk-46WM6JX2.js} +7 -3
  87. package/dist/chunk-46WM6JX2.js.map +1 -0
  88. package/dist/chunk-47DU4SGJ.js +92 -0
  89. package/dist/chunk-47DU4SGJ.js.map +1 -0
  90. package/dist/{chunk-AWRJBAIH.js → chunk-4FFROSFG.js} +37 -14
  91. package/dist/{chunk-AWRJBAIH.js.map → chunk-4FFROSFG.js.map} +1 -1
  92. package/dist/{chunk-N4OYPGZS.js → chunk-4HO3542O.js} +2 -2
  93. package/dist/{chunk-HEEEMJ26.js → chunk-4IZ2IT7D.js} +3 -3
  94. package/dist/{chunk-4XAVQLBR.js → chunk-4Y2RHVCV.js} +2 -2
  95. package/dist/{chunk-33JBK2XP.js → chunk-5F6HMNMZ.js} +2 -2
  96. package/dist/{chunk-5WQMORU5.js → chunk-5PFGMO33.js} +2 -2
  97. package/dist/{chunk-6HEM6HTQ.js → chunk-6GGTATZF.js} +2 -2
  98. package/dist/{chunk-W3Y6FYRK.js → chunk-7BJYTX6Q.js} +2 -2
  99. package/dist/{chunk-2GRLJMKJ.js → chunk-7DRSWPUV.js} +3 -3
  100. package/dist/{chunk-TVVEYCNW.js → chunk-7K5Q6COX.js} +4 -4
  101. package/dist/{chunk-HXXGZ4KV.js → chunk-ALNZEWGN.js} +2 -2
  102. package/dist/{chunk-5WVUO6QT.js → chunk-AR253JBM.js} +1 -1
  103. package/dist/chunk-AR253JBM.js.map +1 -0
  104. package/dist/{chunk-S3B3UIQ3.js → chunk-AYIHDC5S.js} +2 -2
  105. package/dist/{chunk-2RIDW23Y.js → chunk-BBHFAVMP.js} +8 -8
  106. package/dist/{chunk-MJ4UGUR6.js → chunk-BHO6RHE5.js} +3 -3
  107. package/dist/{chunk-URN7XWGC.js → chunk-BP6WMYLP.js} +3 -3
  108. package/dist/{chunk-YUIBXMZY.js → chunk-CALURYWR.js} +284 -249
  109. package/dist/chunk-CALURYWR.js.map +1 -0
  110. package/dist/{chunk-D5HDJWNN.js → chunk-CH627RRV.js} +4 -4
  111. package/dist/{chunk-C3R732UY.js → chunk-CLJ5QS6J.js} +257 -60
  112. package/dist/chunk-CLJ5QS6J.js.map +1 -0
  113. package/dist/{chunk-YLHM5BQQ.js → chunk-DCUMFQYM.js} +171 -8
  114. package/dist/chunk-DCUMFQYM.js.map +1 -0
  115. package/dist/{chunk-ZBJMUXZH.js → chunk-DJ7HMNSL.js} +15 -8
  116. package/dist/chunk-DJ7HMNSL.js.map +1 -0
  117. package/dist/{chunk-XDK6ZFLL.js → chunk-DROAPP6N.js} +3 -3
  118. package/dist/{chunk-MU3TPZOV.js → chunk-DTLF2SLZ.js} +2 -2
  119. package/dist/{chunk-I67HKRBF.js → chunk-EFWHCTYJ.js} +2 -2
  120. package/dist/{chunk-XD4VGLDL.js → chunk-FF6E6HOT.js} +56 -52
  121. package/dist/chunk-FF6E6HOT.js.map +1 -0
  122. package/dist/{chunk-NP7FLVZW.js → chunk-G2FCSILA.js} +2 -2
  123. package/dist/{chunk-3GPBFDXH.js → chunk-H23GIXJC.js} +2 -2
  124. package/dist/{chunk-WT6UL3UA.js → chunk-H7PRHUBD.js} +2 -2
  125. package/dist/{chunk-4JGSG7QN.js → chunk-HSBQJRV2.js} +2 -2
  126. package/dist/{chunk-L33N3BCA.js → chunk-HVKMJAEF.js} +2 -2
  127. package/dist/{chunk-CSOYVTRX.js → chunk-IIPJKCZB.js} +3 -3
  128. package/dist/{chunk-E57E5SCS.js → chunk-IRLH4NM2.js} +3 -3
  129. package/dist/{chunk-H32ANIFP.js → chunk-IZRNVNPV.js} +2 -2
  130. package/dist/{chunk-XBR5BAKW.js → chunk-JCJGYNIS.js} +3 -3
  131. package/dist/{chunk-EIQFIJDM.js → chunk-JDI7G6EA.js} +2 -2
  132. package/dist/{chunk-QWPAQLYV.js → chunk-JFLKSD5V.js} +2 -2
  133. package/dist/{chunk-KQS72GCR.js → chunk-LJOIZPJH.js} +2 -2
  134. package/dist/{chunk-N4EPIKSY.js → chunk-LLGDVG52.js} +3 -3
  135. package/dist/{chunk-7N7DB4L5.js → chunk-LTJTP5YQ.js} +10 -9
  136. package/dist/chunk-LTJTP5YQ.js.map +1 -0
  137. package/dist/{chunk-VOELBUS4.js → chunk-NXH34IPL.js} +2 -2
  138. package/dist/{chunk-XL3TATMJ.js → chunk-OQIRBGUU.js} +21 -12
  139. package/dist/chunk-OQIRBGUU.js.map +1 -0
  140. package/dist/chunk-PJKTFXE2.js +119 -0
  141. package/dist/chunk-PJKTFXE2.js.map +1 -0
  142. package/dist/{chunk-JGW2EUCQ.js → chunk-PMRUMGK6.js} +2 -2
  143. package/dist/{chunk-KAB7TZN3.js → chunk-PSNN25DW.js} +2 -2
  144. package/dist/{chunk-LRGSLV7M.js → chunk-PYHOAXTI.js} +4 -4
  145. package/dist/{chunk-PA5OPZX2.js → chunk-QCI73Z7C.js} +2 -2
  146. package/dist/{chunk-EHMMRZOZ.js → chunk-QICOU4RY.js} +2 -2
  147. package/dist/{chunk-FW73HN33.js → chunk-RFH7U5LT.js} +2 -2
  148. package/dist/{chunk-4SGDYYWV.js → chunk-RPKJHYVE.js} +2 -2
  149. package/dist/{chunk-DSA47WBN.js → chunk-RYST72N5.js} +13 -2
  150. package/dist/chunk-RYST72N5.js.map +1 -0
  151. package/dist/{chunk-L4DLLKPN.js → chunk-SZ4HFZKB.js} +2 -2
  152. package/dist/chunk-T3GIETKV.js +152 -0
  153. package/dist/chunk-T3GIETKV.js.map +1 -0
  154. package/dist/{chunk-MYZ4NA43.js → chunk-TGSMU3F2.js} +3 -3
  155. package/dist/{chunk-CM4SZZBN.js → chunk-TIRJV2LW.js} +2 -2
  156. package/dist/{chunk-EGW4O32Z.js → chunk-UDTME32W.js} +7 -4
  157. package/dist/chunk-UDTME32W.js.map +1 -0
  158. package/dist/{chunk-CIA6ZUBA.js → chunk-WMOJIOIG.js} +2 -2
  159. package/dist/{chunk-W4Q54HM3.js → chunk-WR2YKUIW.js} +2 -2
  160. package/dist/{chunk-VWDTV6SH.js → chunk-X6E7TT3A.js} +2 -2
  161. package/dist/{chunk-D4OCJSLV.js → chunk-YDPAE2RD.js} +2 -2
  162. package/dist/{chunk-G3YBWFUC.js → chunk-YIIC5IDU.js} +35 -18
  163. package/dist/chunk-YIIC5IDU.js.map +1 -0
  164. package/dist/{chunk-QRKYABS6.js → chunk-YSR3DXGC.js} +2 -2
  165. package/dist/{chunk-LBJBNWS2.js → chunk-YTHQHH5U.js} +2 -2
  166. package/dist/{chunk-GN7HO2LA.js → chunk-ZPGHA7EO.js} +12 -12
  167. package/dist/{chunk-VUDALPI5.js → chunk-ZQKXRKMR.js} +19 -5
  168. package/dist/chunk-ZQKXRKMR.js.map +1 -0
  169. package/dist/{chunk-FQSDU634.js → chunk-ZS4JADYY.js} +3 -3
  170. package/dist/{cli-DB_uakTc.d.ts → cli-Bw9z-KqX.d.ts} +5 -5
  171. package/dist/cli.d.ts +13 -13
  172. package/dist/cli.js +62 -62
  173. package/dist/coding/pre-action-gate.d.ts +1 -1
  174. package/dist/coding/pre-action-gate.js +3 -3
  175. package/dist/compounding/engine.d.ts +2 -2
  176. package/dist/compounding/engine.js +13 -12
  177. package/dist/compounding/preference-consolidator.d.ts +1 -1
  178. package/dist/compression-optimizer.d.ts +1 -1
  179. package/dist/config.d.ts +1 -1
  180. package/dist/config.js +3 -3
  181. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  182. package/dist/connectors/codex-materialize-runner.js +13 -12
  183. package/dist/connectors/codex-materialize.d.ts +1 -1
  184. package/dist/connectors/index.d.ts +1 -1
  185. package/dist/connectors/index.js +13 -12
  186. package/dist/consolidation-provenance-check.d.ts +2 -2
  187. package/dist/consolidation-undo.d.ts +2 -2
  188. package/dist/contradiction/index.d.ts +2 -2
  189. package/dist/converge-config.d.ts +1 -1
  190. package/dist/convergence-refresh.d.ts +2 -2
  191. package/dist/convergence-refresh.js +15 -14
  192. package/dist/conversation-index/backend.d.ts +1 -1
  193. package/dist/conversation-index/chunker.d.ts +1 -1
  194. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  195. package/dist/conversation-index/indexer.d.ts +1 -1
  196. package/dist/conversation-index/search.d.ts +1 -1
  197. package/dist/corpus-watermark.d.ts +1 -1
  198. package/dist/corpus-watermark.js +15 -14
  199. package/dist/day-summary.d.ts +1 -1
  200. package/dist/delinearize.d.ts +1 -1
  201. package/dist/dependency-propagation-config.d.ts +1 -1
  202. package/dist/{dependency-propagation-delivery-DcOVpK3y.d.ts → dependency-propagation-delivery-BxhvAppj.d.ts} +1 -1
  203. package/dist/direct-answer-wiring.d.ts +1 -1
  204. package/dist/direct-answer-wiring.js +3 -3
  205. package/dist/direct-answer.d.ts +1 -1
  206. package/dist/direct-answer.js +2 -2
  207. package/dist/embedding-fallback.d.ts +1 -1
  208. package/dist/enrichment/index.d.ts +1 -1
  209. package/dist/entity-origin-fields.d.ts +1 -1
  210. package/dist/entity-retrieval.d.ts +2 -2
  211. package/dist/entity-retrieval.js +13 -12
  212. package/dist/entity-schema.d.ts +1 -1
  213. package/dist/episodic-context.d.ts +92 -0
  214. package/dist/episodic-context.js +16 -0
  215. package/dist/episodic-context.js.map +1 -0
  216. package/dist/explicit-capture.d.ts +9 -9
  217. package/dist/external-wiki-access.d.ts +11 -11
  218. package/dist/external-wiki-access.js +29 -29
  219. package/dist/external-wiki-collection-registration.d.ts +1 -1
  220. package/dist/external-wiki-collection.d.ts +1 -1
  221. package/dist/external-wiki-mcp-tools.d.ts +11 -11
  222. package/dist/extraction-error-classification.d.ts +1 -1
  223. package/dist/extraction-faithfulness.d.ts +1 -1
  224. package/dist/extraction-judge-telemetry.d.ts +1 -1
  225. package/dist/extraction-judge-training.d.ts +1 -1
  226. package/dist/extraction-judge.d.ts +1 -1
  227. package/dist/extraction-liveness.d.ts +1 -1
  228. package/dist/extraction-normalization.d.ts +1 -1
  229. package/dist/extraction-normalization.js +2 -2
  230. package/dist/extraction-prompt.d.ts +1 -1
  231. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  232. package/dist/extraction-source-grounding.d.ts +1 -1
  233. package/dist/extraction-source-grounding.js +3 -3
  234. package/dist/extraction.d.ts +1 -1
  235. package/dist/extraction.js +18 -18
  236. package/dist/fallback-llm.d.ts +1 -1
  237. package/dist/{forget-5TWK7CZT.js → forget-SZ2BXDGF.js} +2 -2
  238. package/dist/graph-dashboard-diff.d.ts +1 -1
  239. package/dist/graph-dashboard-key.d.ts +1 -1
  240. package/dist/graph-dashboard-parser.d.ts +1 -1
  241. package/dist/graph-edge-reinforcement.d.ts +1 -1
  242. package/dist/graph-path-reconstruction.d.ts +1 -1
  243. package/dist/graph-path-scoring.d.ts +1 -1
  244. package/dist/graph-snapshot.d.ts +1 -1
  245. package/dist/graph.d.ts +1 -1
  246. package/dist/harmonic-construction.js +2 -2
  247. package/dist/harmonic-retrieval.js +2 -2
  248. package/dist/importance.d.ts +1 -1
  249. package/dist/importers/index.d.ts +1 -1
  250. package/dist/in-flight-reads.d.ts +1 -1
  251. package/dist/index.d.ts +22 -21
  252. package/dist/index.js +118 -103
  253. package/dist/intent.d.ts +1 -1
  254. package/dist/lcm/engine.d.ts +8 -2
  255. package/dist/lcm/engine.js +4 -4
  256. package/dist/lcm/index.d.ts +1 -1
  257. package/dist/lcm/index.js +9 -9
  258. package/dist/lcm/tools.d.ts +1 -1
  259. package/dist/lifecycle.d.ts +1 -1
  260. package/dist/live-connectors-runner.d.ts +1 -1
  261. package/dist/local-llm.d.ts +1 -1
  262. package/dist/local-model-endpoint.d.ts +1 -1
  263. package/dist/maintenance/memory-governance.d.ts +1 -1
  264. package/dist/maintenance/memory-governance.js +13 -12
  265. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  266. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -12
  267. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  268. package/dist/maintenance/rebuild-memory-projection.js +14 -13
  269. package/dist/{maintenance-5c1olVtB.d.ts → maintenance-uJb74j64.d.ts} +3 -3
  270. package/dist/mcp-memory-inspector-app.d.ts +11 -11
  271. package/dist/memory-action-policy.d.ts +1 -1
  272. package/dist/memory-cache.d.ts +1 -1
  273. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  274. package/dist/memory-projection-store.d.ts +1 -1
  275. package/dist/memory-provenance.d.ts +1 -1
  276. package/dist/memory-snapshot.d.ts +1 -1
  277. package/dist/memory-worth-outcomes.d.ts +2 -2
  278. package/dist/models-json.d.ts +1 -1
  279. package/dist/namespaces/migrate.d.ts +3 -3
  280. package/dist/namespaces/migrate.js +14 -13
  281. package/dist/namespaces/principal.d.ts +1 -1
  282. package/dist/namespaces/search.d.ts +1 -1
  283. package/dist/namespaces/search.js +6 -5
  284. package/dist/namespaces/storage.d.ts +3 -3
  285. package/dist/namespaces/storage.js +13 -12
  286. package/dist/native-knowledge.d.ts +1 -1
  287. package/dist/offline-sync-impression-drain.d.ts +1 -1
  288. package/dist/operator-doctor-corpus.d.ts +1 -1
  289. package/dist/operator-doctor-corpus.js +16 -15
  290. package/dist/operator-doctor-replica.d.ts +1 -1
  291. package/dist/operator-toolkit.d.ts +3 -3
  292. package/dist/operator-toolkit.js +21 -20
  293. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  294. package/dist/orchestration/maintenance.d.ts +4 -4
  295. package/dist/orchestration/maintenance.js +18 -17
  296. package/dist/{orchestrator-HPuY6I4i.d.ts → orchestrator-CFi-5JSR.d.ts} +23 -8
  297. package/dist/orchestrator.d.ts +9 -9
  298. package/dist/orchestrator.js +93 -91
  299. package/dist/patterns-cli.d.ts +1 -1
  300. package/dist/{pipeline-CvVe1Q2_.d.ts → pipeline-BdF3ferY.d.ts} +1 -1
  301. package/dist/policy-runtime.d.ts +1 -1
  302. package/dist/policy-runtime.js +3 -3
  303. package/dist/proactive-contention.d.ts +1 -1
  304. package/dist/provenance.d.ts +1 -1
  305. package/dist/provenance.js +2 -2
  306. package/dist/{public-http-D0JKFkyf.d.ts → public-http-DK-QwaBu.d.ts} +1 -1
  307. package/dist/{qmd-Bd0Tp76_.d.ts → qmd-D_62bYNl.d.ts} +1 -1
  308. package/dist/qmd-preflight.d.ts +2 -2
  309. package/dist/qmd-recall-cache.d.ts +1 -1
  310. package/dist/qmd.d.ts +2 -2
  311. package/dist/recall-concurrency-config.d.ts +1 -1
  312. package/dist/recall-disclosure-escalation.d.ts +1 -1
  313. package/dist/recall-explain-renderer.d.ts +1 -1
  314. package/dist/recall-explain-renderer.js +3 -3
  315. package/dist/recall-memory-map.d.ts +1 -1
  316. package/dist/recall-planner-llm.d.ts +1 -1
  317. package/dist/recall-query-policy.js +2 -2
  318. package/dist/recall-state.d.ts +1 -1
  319. package/dist/recall-tag-filter.d.ts +1 -1
  320. package/dist/recall-timings.d.ts +1 -1
  321. package/dist/recall-tokenization.d.ts +3 -1
  322. package/dist/recall-tokenization.js +5 -1
  323. package/dist/recall-xray-cli.d.ts +1 -1
  324. package/dist/recall-xray-cli.js +4 -4
  325. package/dist/recall-xray-renderer.d.ts +1 -1
  326. package/dist/recall-xray-renderer.js +3 -3
  327. package/dist/recall-xray.d.ts +1 -1
  328. package/dist/recall-xray.js +2 -2
  329. package/dist/reconcile/cursor.d.ts +1 -1
  330. package/dist/reconcile/manifest.d.ts +10 -1
  331. package/dist/reconcile/manifest.js +1 -1
  332. package/dist/reconcile/plan.d.ts +1 -1
  333. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  334. package/dist/replay/normalizers/claude.d.ts +1 -1
  335. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  336. package/dist/replay/normalizers/shared.d.ts +1 -1
  337. package/dist/replay/runner.d.ts +1 -1
  338. package/dist/replay/types.d.ts +1 -1
  339. package/dist/replica-divergence.d.ts +1 -1
  340. package/dist/replica-peers-config.d.ts +1 -1
  341. package/dist/resolve-auth-token.d.ts +1 -1
  342. package/dist/resume-bundles.js +6 -6
  343. package/dist/retrieval-agents.d.ts +2 -2
  344. package/dist/retrieval-tiers.d.ts +1 -1
  345. package/dist/routing/engine.d.ts +1 -1
  346. package/dist/routing/store.d.ts +1 -1
  347. package/dist/salvage-envelope.d.ts +1 -1
  348. package/dist/{scope-profiles-ClLtm9gK.d.ts → scope-profiles-CeMv7pP0.d.ts} +1 -1
  349. package/dist/search/embed-helper.d.ts +1 -1
  350. package/dist/search/factory.d.ts +1 -1
  351. package/dist/search/factory.js +5 -4
  352. package/dist/search/index.d.ts +1 -1
  353. package/dist/search/index.js +9 -8
  354. package/dist/search/lancedb-backend.d.ts +14 -1
  355. package/dist/search/lancedb-backend.js +1 -1
  356. package/dist/search/meilisearch-backend.d.ts +1 -1
  357. package/dist/search/noop-backend.d.ts +1 -1
  358. package/dist/search/orama-backend.d.ts +22 -1
  359. package/dist/search/orama-backend.js +2 -1
  360. package/dist/search/port.d.ts +1 -1
  361. package/dist/search/remote-backend.d.ts +1 -1
  362. package/dist/{semantic-consolidation-B1EkeEDj.d.ts → semantic-consolidation-B-85brYj.d.ts} +1 -1
  363. package/dist/semantic-consolidation.d.ts +2 -2
  364. package/dist/semantic-consolidation.js +14 -14
  365. package/dist/semantic-rule-promotion.js +13 -12
  366. package/dist/semantic-rule-verifier.d.ts +1 -1
  367. package/dist/semantic-rule-verifier.js +13 -13
  368. package/dist/{service-Cf3ANQj9.d.ts → service-CoO0HA2E.d.ts} +2 -2
  369. package/dist/session-observer-bands.d.ts +1 -1
  370. package/dist/session-observer-state.d.ts +1 -1
  371. package/dist/shared-context/manager.d.ts +1 -1
  372. package/dist/signal.d.ts +1 -1
  373. package/dist/source-agent-qualifier.d.ts +1 -1
  374. package/dist/source-agent-qualifier.js +15 -14
  375. package/dist/{storage-DS2O_6Qt.d.ts → storage-BVAVitkO.d.ts} +1 -1
  376. package/dist/storage.d.ts +2 -2
  377. package/dist/storage.js +12 -11
  378. package/dist/summarizer.d.ts +1 -1
  379. package/dist/summary-snapshot.d.ts +1 -1
  380. package/dist/support-passport/index.d.ts +14 -14
  381. package/dist/support-passport/index.js +31 -31
  382. package/dist/temporal-supersession.d.ts +2 -2
  383. package/dist/temporal-timeline-recall.d.ts +1 -1
  384. package/dist/temporal-validity.d.ts +1 -1
  385. package/dist/threading.d.ts +1 -1
  386. package/dist/tier-migration.d.ts +2 -2
  387. package/dist/tier-routing.d.ts +1 -1
  388. package/dist/topics.d.ts +1 -1
  389. package/dist/transcript.d.ts +1 -1
  390. package/dist/transfer/import-sqlite.js +2 -2
  391. package/dist/trust-score-stage.d.ts +1 -1
  392. package/dist/trust-score.d.ts +1 -1
  393. package/dist/trust-zones.js +2 -2
  394. package/dist/{types-BOANGhCJ.d.ts → types-DWHOxlZP.d.ts} +3 -0
  395. package/dist/types.d.ts +1 -1
  396. package/dist/types.js +1 -1
  397. package/dist/user-message-cleaning.d.ts +23 -0
  398. package/dist/user-message-cleaning.js +10 -0
  399. package/dist/user-message-cleaning.js.map +1 -0
  400. package/dist/utility-runtime.d.ts +1 -1
  401. package/dist/verified-recall.js +13 -13
  402. package/dist/whitespace.d.ts +26 -1
  403. package/dist/whitespace.js +11 -3
  404. package/dist/work-product-ledger.js +2 -2
  405. package/dist/write-envelope.d.ts +1 -1
  406. package/package.json +12 -2
  407. package/src/access-service-offline-file-content.test.ts +1 -0
  408. package/src/cli.ts +14 -13
  409. package/src/config.ts +11 -0
  410. package/src/entity-retrieval.ts +4 -7
  411. package/src/episodic-context-recall.integration.test.ts +169 -0
  412. package/src/episodic-context.test.ts +266 -0
  413. package/src/episodic-context.ts +274 -0
  414. package/src/harmonic-construction.test.ts +187 -2
  415. package/src/harmonic-retrieval.ts +54 -32
  416. package/src/index.ts +3 -4
  417. package/src/lcm/engine.ts +18 -1
  418. package/src/lifecycle/tombstones.test.ts +134 -0
  419. package/src/lifecycle/tombstones.ts +29 -2
  420. package/src/orchestration/episodic-context-section.ts +255 -0
  421. package/src/orchestration/recall-internal-deps.ts +2 -0
  422. package/src/orchestration/recall-internal.ts +40 -25
  423. package/src/orchestration/recall-result-formatter.ts +37 -0
  424. package/src/orchestration/recall-section-coordinator.ts +20 -14
  425. package/src/recall-tokenization.ts +14 -8
  426. package/src/reconcile/manifest.test.ts +133 -4
  427. package/src/reconcile/manifest.ts +43 -7
  428. package/src/search/factory.ts +1 -0
  429. package/src/search/lancedb-backend.ts +24 -16
  430. package/src/search/orama-backend.test.ts +208 -1
  431. package/src/search/orama-backend.ts +133 -18
  432. package/src/search/orama-cjk-tokenizer.test.ts +108 -0
  433. package/src/search/orama-cjk-tokenizer.ts +143 -0
  434. package/src/storage/tombstone-migration-sources.test.ts +116 -0
  435. package/src/storage/tombstone-migration-sources.ts +90 -0
  436. package/src/storage.ts +13 -34
  437. package/src/types.ts +3 -3
  438. package/src/user-message-cleaning.ts +139 -0
  439. package/src/whitespace.test.ts +178 -0
  440. package/src/whitespace.ts +119 -0
  441. package/dist/chunk-5WVUO6QT.js.map +0 -1
  442. package/dist/chunk-6MKAMLQL.js +0 -16
  443. package/dist/chunk-6MKAMLQL.js.map +0 -1
  444. package/dist/chunk-7N7DB4L5.js.map +0 -1
  445. package/dist/chunk-B2QHVLJO.js.map +0 -1
  446. package/dist/chunk-C3R732UY.js.map +0 -1
  447. package/dist/chunk-DSA47WBN.js.map +0 -1
  448. package/dist/chunk-EGW4O32Z.js.map +0 -1
  449. package/dist/chunk-G3YBWFUC.js.map +0 -1
  450. package/dist/chunk-KHQ57QLJ.js.map +0 -1
  451. package/dist/chunk-VUDALPI5.js.map +0 -1
  452. package/dist/chunk-XD4VGLDL.js.map +0 -1
  453. package/dist/chunk-XL3TATMJ.js.map +0 -1
  454. package/dist/chunk-YLHM5BQQ.js.map +0 -1
  455. package/dist/chunk-YUIBXMZY.js.map +0 -1
  456. package/dist/chunk-ZBJMUXZH.js.map +0 -1
  457. /package/dist/{auto-sync-FMWQQB3J.js.map → auto-sync-Z52VWMNC.js.map} +0 -0
  458. /package/dist/{chunk-QP2IZTUR.js.map → chunk-2TYIAKU5.js.map} +0 -0
  459. /package/dist/{chunk-HQBVQICL.js.map → chunk-347ZR6D4.js.map} +0 -0
  460. /package/dist/{chunk-76YNCJ5H.js.map → chunk-3F3CVVDS.js.map} +0 -0
  461. /package/dist/{chunk-TE4MKFT2.js.map → chunk-3MA7JVXN.js.map} +0 -0
  462. /package/dist/{chunk-N4OYPGZS.js.map → chunk-4HO3542O.js.map} +0 -0
  463. /package/dist/{chunk-HEEEMJ26.js.map → chunk-4IZ2IT7D.js.map} +0 -0
  464. /package/dist/{chunk-4XAVQLBR.js.map → chunk-4Y2RHVCV.js.map} +0 -0
  465. /package/dist/{chunk-33JBK2XP.js.map → chunk-5F6HMNMZ.js.map} +0 -0
  466. /package/dist/{chunk-5WQMORU5.js.map → chunk-5PFGMO33.js.map} +0 -0
  467. /package/dist/{chunk-6HEM6HTQ.js.map → chunk-6GGTATZF.js.map} +0 -0
  468. /package/dist/{chunk-W3Y6FYRK.js.map → chunk-7BJYTX6Q.js.map} +0 -0
  469. /package/dist/{chunk-2GRLJMKJ.js.map → chunk-7DRSWPUV.js.map} +0 -0
  470. /package/dist/{chunk-TVVEYCNW.js.map → chunk-7K5Q6COX.js.map} +0 -0
  471. /package/dist/{chunk-HXXGZ4KV.js.map → chunk-ALNZEWGN.js.map} +0 -0
  472. /package/dist/{chunk-S3B3UIQ3.js.map → chunk-AYIHDC5S.js.map} +0 -0
  473. /package/dist/{chunk-2RIDW23Y.js.map → chunk-BBHFAVMP.js.map} +0 -0
  474. /package/dist/{chunk-MJ4UGUR6.js.map → chunk-BHO6RHE5.js.map} +0 -0
  475. /package/dist/{chunk-URN7XWGC.js.map → chunk-BP6WMYLP.js.map} +0 -0
  476. /package/dist/{chunk-D5HDJWNN.js.map → chunk-CH627RRV.js.map} +0 -0
  477. /package/dist/{chunk-XDK6ZFLL.js.map → chunk-DROAPP6N.js.map} +0 -0
  478. /package/dist/{chunk-MU3TPZOV.js.map → chunk-DTLF2SLZ.js.map} +0 -0
  479. /package/dist/{chunk-I67HKRBF.js.map → chunk-EFWHCTYJ.js.map} +0 -0
  480. /package/dist/{chunk-NP7FLVZW.js.map → chunk-G2FCSILA.js.map} +0 -0
  481. /package/dist/{chunk-3GPBFDXH.js.map → chunk-H23GIXJC.js.map} +0 -0
  482. /package/dist/{chunk-WT6UL3UA.js.map → chunk-H7PRHUBD.js.map} +0 -0
  483. /package/dist/{chunk-4JGSG7QN.js.map → chunk-HSBQJRV2.js.map} +0 -0
  484. /package/dist/{chunk-L33N3BCA.js.map → chunk-HVKMJAEF.js.map} +0 -0
  485. /package/dist/{chunk-CSOYVTRX.js.map → chunk-IIPJKCZB.js.map} +0 -0
  486. /package/dist/{chunk-E57E5SCS.js.map → chunk-IRLH4NM2.js.map} +0 -0
  487. /package/dist/{chunk-H32ANIFP.js.map → chunk-IZRNVNPV.js.map} +0 -0
  488. /package/dist/{chunk-XBR5BAKW.js.map → chunk-JCJGYNIS.js.map} +0 -0
  489. /package/dist/{chunk-EIQFIJDM.js.map → chunk-JDI7G6EA.js.map} +0 -0
  490. /package/dist/{chunk-QWPAQLYV.js.map → chunk-JFLKSD5V.js.map} +0 -0
  491. /package/dist/{chunk-KQS72GCR.js.map → chunk-LJOIZPJH.js.map} +0 -0
  492. /package/dist/{chunk-N4EPIKSY.js.map → chunk-LLGDVG52.js.map} +0 -0
  493. /package/dist/{chunk-VOELBUS4.js.map → chunk-NXH34IPL.js.map} +0 -0
  494. /package/dist/{chunk-JGW2EUCQ.js.map → chunk-PMRUMGK6.js.map} +0 -0
  495. /package/dist/{chunk-KAB7TZN3.js.map → chunk-PSNN25DW.js.map} +0 -0
  496. /package/dist/{chunk-LRGSLV7M.js.map → chunk-PYHOAXTI.js.map} +0 -0
  497. /package/dist/{chunk-PA5OPZX2.js.map → chunk-QCI73Z7C.js.map} +0 -0
  498. /package/dist/{chunk-EHMMRZOZ.js.map → chunk-QICOU4RY.js.map} +0 -0
  499. /package/dist/{chunk-FW73HN33.js.map → chunk-RFH7U5LT.js.map} +0 -0
  500. /package/dist/{chunk-4SGDYYWV.js.map → chunk-RPKJHYVE.js.map} +0 -0
  501. /package/dist/{chunk-L4DLLKPN.js.map → chunk-SZ4HFZKB.js.map} +0 -0
  502. /package/dist/{chunk-MYZ4NA43.js.map → chunk-TGSMU3F2.js.map} +0 -0
  503. /package/dist/{chunk-CM4SZZBN.js.map → chunk-TIRJV2LW.js.map} +0 -0
  504. /package/dist/{chunk-CIA6ZUBA.js.map → chunk-WMOJIOIG.js.map} +0 -0
  505. /package/dist/{chunk-W4Q54HM3.js.map → chunk-WR2YKUIW.js.map} +0 -0
  506. /package/dist/{chunk-VWDTV6SH.js.map → chunk-X6E7TT3A.js.map} +0 -0
  507. /package/dist/{chunk-D4OCJSLV.js.map → chunk-YDPAE2RD.js.map} +0 -0
  508. /package/dist/{chunk-QRKYABS6.js.map → chunk-YSR3DXGC.js.map} +0 -0
  509. /package/dist/{chunk-LBJBNWS2.js.map → chunk-YTHQHH5U.js.map} +0 -0
  510. /package/dist/{chunk-GN7HO2LA.js.map → chunk-ZPGHA7EO.js.map} +0 -0
  511. /package/dist/{chunk-FQSDU634.js.map → chunk-ZS4JADYY.js.map} +0 -0
  512. /package/dist/{forget-5TWK7CZT.js.map → forget-SZ2BXDGF.js.map} +0 -0
@@ -19,6 +19,7 @@
19
19
 
20
20
  import type { LastRecallBudgetSummary } from "../recall-state.js";
21
21
  import { estimateTokenCount } from "../token-estimate.js";
22
+ import { graphemeUnits, truncateGraphemeSafe } from "../whitespace.js";
22
23
  import type { PluginConfig, RecallSectionConfig } from "../types.js";
23
24
 
24
25
  export interface RecallSectionAppendOptions {
@@ -145,7 +146,7 @@ export class RecallSectionCoordinator {
145
146
  finalContent =
146
147
  sectionId === "profile"
147
148
  ? this.truncateProfileToBoundary(finalContent, maxChars)
148
- : `${finalContent.slice(0, maxChars)}\n\n...(trimmed)\n`;
149
+ : `${truncateGraphemeSafe(finalContent, maxChars)}\n\n...(trimmed)\n`;
149
150
  }
150
151
  if (finalContent.length === 0) return false;
151
152
  const existing = sectionBuckets.get(sectionId) ?? [];
@@ -174,11 +175,16 @@ export class RecallSectionCoordinator {
174
175
  const contentLimit = maxChars - suffix.length;
175
176
  if (contentLimit <= 0) {
176
177
  const boundary = content.lastIndexOf("\n", maxChars);
177
- return content.slice(0, boundary > 0 ? boundary : maxChars).trimEnd();
178
+ const clipped = boundary > 0
179
+ ? content.slice(0, boundary)
180
+ : truncateGraphemeSafe(content, maxChars);
181
+ return clipped.trimEnd();
178
182
  }
179
183
  const boundary = content.lastIndexOf("\n", contentLimit);
180
- const end = boundary > 0 ? boundary : contentLimit;
181
- return `${content.slice(0, end).trimEnd()}${suffix}`;
184
+ const clipped = boundary > 0
185
+ ? content.slice(0, boundary)
186
+ : truncateGraphemeSafe(content, contentLimit);
187
+ return `${clipped.trimEnd()}${suffix}`;
182
188
  }
183
189
  truncateRecallSectionToBudget(
184
190
  content: string,
@@ -191,20 +197,20 @@ export class RecallSectionCoordinator {
191
197
  content.length <= maxChars
192
198
  ? content
193
199
  : maxChars <= suffix.length
194
- ? content.slice(0, maxChars)
195
- : `${content.slice(0, maxChars - suffix.length)}${suffix}`;
200
+ ? truncateGraphemeSafe(content, maxChars)
201
+ : `${truncateGraphemeSafe(content, maxChars - suffix.length)}${suffix}`;
196
202
  if (maxTokens === undefined || estimateTokenCount(charBounded) <= maxTokens) {
197
203
  return charBounded;
198
204
  }
199
205
  const markerFits =
200
206
  maxChars > suffix.length && estimateTokenCount(suffix) <= maxTokens;
201
- const tokenSource = content.length > maxChars ? content.slice(0, maxChars) : content;
202
- const codePoints = [...tokenSource];
207
+ const tokenSource = content.length > maxChars ? truncateGraphemeSafe(content, maxChars) : content;
208
+ const units = graphemeUnits(tokenSource);
203
209
  let low = 0;
204
- let high = codePoints.length;
210
+ let high = units.length;
205
211
  while (low < high) {
206
212
  const mid = Math.ceil((low + high) / 2);
207
- const prefix = codePoints.slice(0, mid).join("");
213
+ const prefix = units.slice(0, mid).join("");
208
214
  const candidate = markerFits ? `${prefix}${suffix}` : prefix;
209
215
  if (candidate.length <= maxChars && estimateTokenCount(candidate) <= maxTokens) {
210
216
  low = mid;
@@ -214,19 +220,19 @@ export class RecallSectionCoordinator {
214
220
  }
215
221
  if (markerFits && low === 0) {
216
222
  low = 0;
217
- high = codePoints.length;
223
+ high = units.length;
218
224
  while (low < high) {
219
225
  const mid = Math.ceil((low + high) / 2);
220
- const prefix = codePoints.slice(0, mid).join("");
226
+ const prefix = units.slice(0, mid).join("");
221
227
  if (prefix.length <= maxChars && estimateTokenCount(prefix) <= maxTokens) {
222
228
  low = mid;
223
229
  } else {
224
230
  high = mid - 1;
225
231
  }
226
232
  }
227
- return codePoints.slice(0, low).join("");
233
+ return units.slice(0, low).join("");
228
234
  }
229
- const prefix = codePoints.slice(0, low).join("");
235
+ const prefix = units.slice(0, low).join("");
230
236
  return markerFits ? `${prefix}${suffix}` : prefix;
231
237
  }
232
238
 
@@ -4,7 +4,7 @@ export interface NormalizeRecallTokenOptions {
4
4
 
5
5
  const DEFAULT_RECALL_STOP_WORDS = ["the", "and", "for", "with", "from", "into", "that", "this", "why", "did"];
6
6
 
7
- function isUnsegmentableRecallChar(char: string): boolean {
7
+ export function isUnsegmentableRecallChar(char: string): boolean {
8
8
  if (char === "ー" || char === "ー") return true;
9
9
  return /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}]/u.test(char);
10
10
  }
@@ -24,21 +24,27 @@ function shouldKeepRecallToken(token: string, minTokenLength: number, stopWords:
24
24
  return token.length >= 2 && hasNonAsciiCodepoint && /\p{L}/u.test(token);
25
25
  }
26
26
 
27
- function addUnsegmentableRecallSegment(tokens: Set<string>, segment: string, stopWords: Set<string>): void {
27
+ export function expandUnsegmentableRecallNGrams(segment: string): string[] {
28
28
  const chars = [...segment].filter((ch) => /[\p{L}\p{N}\p{M}]/u.test(ch) || isUnsegmentableRecallChar(ch));
29
+ const tokens: string[] = [];
29
30
  for (const ch of chars) {
30
- if (!stopWords.has(ch)) tokens.add(ch);
31
+ tokens.push(ch);
31
32
  }
32
33
  for (const size of [2, 3, 4]) {
33
34
  if (chars.length < size) continue;
34
35
  for (let index = 0; index <= chars.length - size; index += 1) {
35
- const token = chars.slice(index, index + size).join("");
36
- if (!stopWords.has(token)) tokens.add(token);
36
+ tokens.push(chars.slice(index, index + size).join(""));
37
37
  }
38
38
  }
39
- const whole = chars.join("");
40
- if (whole.length > 3 && !stopWords.has(whole)) {
41
- tokens.add(whole);
39
+ if (chars.length > 3) {
40
+ tokens.push(chars.join(""));
41
+ }
42
+ return tokens;
43
+ }
44
+
45
+ function addUnsegmentableRecallSegment(tokens: Set<string>, segment: string, stopWords: Set<string>): void {
46
+ for (const token of expandUnsegmentableRecallNGrams(segment)) {
47
+ if (!stopWords.has(token)) tokens.add(token);
42
48
  }
43
49
  }
44
50
 
@@ -50,6 +50,7 @@ test("reconcile manifest keeps file identity separate from canonical semantic id
50
50
  category: "fact",
51
51
  contentHash: semanticHash,
52
52
  normalizerVersion: 4,
53
+ identityResolutionVersion: 2,
53
54
  status: "active",
54
55
  });
55
56
  });
@@ -100,11 +101,52 @@ test("reconcile manifest reparses cached pre-version identities after Unicode mi
100
101
  });
101
102
 
102
103
  assert.equal(reads, 1);
104
+ // The café body is lossy under the legacy normalizer, so the persisted
105
+ // legacy hash stays primary and the recovered current identity rides along
106
+ // as an alias (issue #2367).
103
107
  assert.equal(
104
108
  manifest.files[0]?.memory?.contentHash,
105
- ContentHashIndex.computeHash(content),
109
+ legacyHash,
106
110
  );
107
- assert.equal("contentHashAliases" in (manifest.files[0]?.memory ?? {}), false);
111
+ assert.deepEqual(manifest.files[0]?.memory?.contentHashAliases, [
112
+ ContentHashIndex.computeHash(content),
113
+ ]);
114
+ });
115
+
116
+ test("reconcile manifest reparses cached identities lacking the identity-resolution version", async () => {
117
+ const content = "The user prefers café.";
118
+ const legacyHash = computeLegacyContentHash(content);
119
+ const serialized = memoryFile({ id: "legacy-identity-version", content, contentHash: legacyHash });
120
+ const file = { path: "facts/legacy-identity-version.md", sha256: fileHash(serialized) };
121
+ let reads = 0;
122
+
123
+ const manifest = await buildReconcileManifest({
124
+ files: [file],
125
+ parseMemory: parseFrontmatter,
126
+ readFile: async () => {
127
+ reads += 1;
128
+ return serialized;
129
+ },
130
+ // Same normalizerVersion, but written before identity-resolution
131
+ // versioning existed: the entry carries no aliases and must NOT be
132
+ // reused (issue #2367 review round 2).
133
+ cachedFiles: [{
134
+ ...file,
135
+ memory: {
136
+ id: "legacy-identity-version",
137
+ category: "fact",
138
+ contentHash: legacyHash,
139
+ normalizerVersion: 4,
140
+ status: "active",
141
+ },
142
+ }],
143
+ });
144
+
145
+ assert.equal(reads, 1);
146
+ assert.equal(manifest.files[0]?.memory?.identityResolutionVersion, 2);
147
+ assert.deepEqual(manifest.files[0]?.memory?.contentHashAliases, [
148
+ ContentHashIndex.computeHash(content),
149
+ ]);
108
150
  });
109
151
 
110
152
  test("reconcile manifest replaces a pure-CJK legacy identity with its current hash", async () => {
@@ -146,7 +188,10 @@ test("reconcile manifest recovers a raw hash source beneath citation and attribu
146
188
  readFile: async () => serialized,
147
189
  });
148
190
 
149
- assert.equal(manifest.files[0]?.memory?.contentHash, ContentHashIndex.computeHash(content));
191
+ assert.equal(manifest.files[0]?.memory?.contentHash, computeLegacyContentHash(content));
192
+ assert.deepEqual(manifest.files[0]?.memory?.contentHashAliases, [
193
+ ContentHashIndex.computeHash(content),
194
+ ]);
150
195
  });
151
196
 
152
197
  test("reconcile manifest recovers raw identity beneath a configured citation", async () => {
@@ -169,7 +214,91 @@ test("reconcile manifest recovers raw identity beneath a configured citation", a
169
214
  citationTemplate,
170
215
  });
171
216
 
172
- assert.equal(manifest.files[0]?.memory?.contentHash, ContentHashIndex.computeHash(content));
217
+ assert.equal(manifest.files[0]?.memory?.contentHash, computeLegacyContentHash(content));
218
+ assert.deepEqual(manifest.files[0]?.memory?.contentHashAliases, [
219
+ ContentHashIndex.computeHash(content),
220
+ ]);
221
+ });
222
+
223
+ test("reconcile manifest prefers a persisted explicit hash over a colliding legacy body hash (issue #2367)", async () => {
224
+ // Source `caf` with body `café`: hash("caf") numerically equals the legacy
225
+ // hash of the stored body, but it is the fact's explicit contentHashSource
226
+ // identity written by the current normalizer. The legacy candidate match
227
+ // must not replace it.
228
+ const source = "caf";
229
+ const body = "café";
230
+ const persistedHash = ContentHashIndex.computeHash(source);
231
+ assert.equal(persistedHash, computeLegacyContentHash(body));
232
+ const serialized = memoryFile({ id: "explicit-source", content: body, contentHash: persistedHash });
233
+ const manifest = await buildReconcileManifest({
234
+ files: [{ path: "facts/explicit-source.md", sha256: fileHash(serialized) }],
235
+ parseMemory: parseFrontmatter,
236
+ readFile: async () => serialized,
237
+ });
238
+
239
+ assert.equal(manifest.files[0]?.memory?.contentHash, persistedHash);
240
+ assert.notEqual(manifest.files[0]?.memory?.contentHash, ContentHashIndex.computeHash(body));
241
+ assert.deepEqual(manifest.files[0]?.memory?.contentHashAliases, [
242
+ ContentHashIndex.computeHash(body),
243
+ ]);
244
+ });
245
+
246
+ test("reconcile collapse matches an explicit-source replica through the persisted hash (issue #2367)", async () => {
247
+ const source = "caf";
248
+ const persistedHash = ContentHashIndex.computeHash(source);
249
+ const localSerialized = memoryFile({ id: "explicit-local", content: "café", contentHash: persistedHash });
250
+ const peerSerialized = memoryFile({ id: "explicit-peer", content: source, contentHash: persistedHash });
251
+ const localFile = { path: "facts/explicit-local.md", sha256: fileHash(localSerialized) };
252
+ const peerFile = { path: "facts/explicit-peer.md", sha256: fileHash(peerSerialized) };
253
+ const build = async (file: typeof localFile, raw: string) =>
254
+ await buildReconcileManifest({
255
+ files: [file],
256
+ parseMemory: parseFrontmatter,
257
+ readFile: async () => raw,
258
+ });
259
+ const local = await build(localFile, localSerialized);
260
+ const peer = await build(peerFile, peerSerialized);
261
+ const plan = planReconciliation([{ namespace: "default", local: [localFile], peer: [peerFile] }]);
262
+
263
+ const collapsed = collapseActiveFactDuplicates(
264
+ plan,
265
+ new Map([["default", local]]),
266
+ new Map([["default", peer]]),
267
+ );
268
+
269
+ assert.equal(collapsed.converged, true);
270
+ assert.equal(collapsed.entries.length, 1);
271
+ assert.equal(collapsed.entries[0]?.reason, "semantic_duplicate");
272
+ });
273
+
274
+ test("reconcile manifest does not collapse distinct pure-CJK legacy facts through the empty skeleton (issue #2367)", async () => {
275
+ const first = "利用者は紅茶を好む。";
276
+ const second = "利用者は珈琲を好む。";
277
+ assert.equal(computeLegacyContentHash(first), computeLegacyContentHash(second));
278
+ const build = async (id: string, content: string) => {
279
+ const serialized = memoryFile({ id, content, contentHash: computeLegacyContentHash(content) });
280
+ const file = { path: `facts/${id}.md`, sha256: fileHash(serialized) };
281
+ const manifest = await buildReconcileManifest({
282
+ files: [file],
283
+ parseMemory: parseFrontmatter,
284
+ readFile: async () => serialized,
285
+ });
286
+ return { file, manifest };
287
+ };
288
+ const a = await build("legacy-cjk-first", first);
289
+ const b = await build("legacy-cjk-second", second);
290
+ const plan = planReconciliation([
291
+ { namespace: "default", local: [a.file], peer: [b.file] },
292
+ ]);
293
+
294
+ const collapsed = collapseActiveFactDuplicates(
295
+ plan,
296
+ new Map([["default", a.manifest]]),
297
+ new Map([["default", b.manifest]]),
298
+ );
299
+
300
+ assert.equal(collapsed.converged, false);
301
+ assert.equal(collapsed.entries.length, 2);
173
302
  });
174
303
 
175
304
  test("reconcile manifest does not add a legacy alias to a current Unicode identity", async () => {
@@ -18,12 +18,30 @@ import {
18
18
  export const RECONCILE_MANIFEST_FORMAT = "remnic-reconcile-manifest";
19
19
  export const RECONCILE_MANIFEST_SCHEMA_VERSION = 1;
20
20
  const CONTENT_HASH_NORMALIZER_VERSION = 4;
21
+ /**
22
+ * Version of the identity-resolution LOGIC (alias recovery, candidate
23
+ * ordering), independent of the content normalizer: a cached manifest entry
24
+ * written before an identity-resolution change carries an older value and is
25
+ * reparsed even when its normalizerVersion still matches (issue #2367
26
+ * review round 2). Bump when parsedMemoryIdentity's output shape or
27
+ * semantics change.
28
+ */
29
+ const IDENTITY_RESOLUTION_VERSION = 2;
21
30
 
22
31
  export interface ReconcileMemoryIdentity {
23
32
  id: string;
24
33
  category: string;
25
34
  contentHash: string;
35
+ /**
36
+ * Recovered current-normalizer identities for a record whose persisted hash
37
+ * is ambiguous under the legacy normalizer (issue #2367). The persisted
38
+ * hash stays primary; these participate in duplicate bucketing so a
39
+ * replica carrying the current form of the same fact still collapses.
40
+ */
41
+ contentHashAliases?: readonly string[];
42
+ /** See IDENTITY_RESOLUTION_VERSION; absent on pre-versioning cache entries. */
26
43
  normalizerVersion?: number;
44
+ identityResolutionVersion?: number;
27
45
  status: MemoryStatus;
28
46
  }
29
47
 
@@ -88,17 +106,34 @@ function parsedMemoryIdentity(
88
106
  const legacyMatch = [...candidates].reverse().find(
89
107
  (content) => computeLegacyContentHash(content) === storedHash
90
108
  );
91
- const contentHash = currentMatch
92
- ? ContentHashIndex.computeHash(currentMatch)
93
- : legacyMatch
94
- ? ContentHashIndex.computeHash(legacyMatch)
95
- : storedHash ?? bodyHash;
109
+ let contentHash: string;
110
+ let contentHashAliases: string[] | undefined;
111
+ if (currentMatch) {
112
+ contentHash = ContentHashIndex.computeHash(currentMatch);
113
+ } else if (legacyMatch && normalizeLegacyContent(legacyMatch).length > 0) {
114
+ // A non-empty legacy equality is ambiguous (issue #2367): the persisted
115
+ // hash may be an explicit contentHashSource identity that merely collides
116
+ // with the body's ASCII skeleton under the lossy legacy normalizer, and
117
+ // nothing in the record proves which it is. Keep the persisted hash as
118
+ // the primary identity and expose the recovered current identity as an
119
+ // alias so replicas carrying either form still collapse.
120
+ contentHash = storedHash ?? bodyHash;
121
+ const recovered = ContentHashIndex.computeHash(legacyMatch);
122
+ if (recovered !== contentHash) contentHashAliases = [recovered];
123
+ } else {
124
+ // An EMPTY legacy skeleton identifies nothing (every non-ASCII body maps
125
+ // to it), so preserving it would collapse unrelated records. Recovering
126
+ // the current identity here is repair, not replacement.
127
+ contentHash = legacyMatch ? ContentHashIndex.computeHash(legacyMatch) : storedHash ?? bodyHash;
128
+ }
96
129
 
97
130
  return {
98
131
  id: parsed.frontmatter.id,
99
132
  category: parsed.frontmatter.category,
100
133
  contentHash,
134
+ ...(contentHashAliases ? { contentHashAliases } : {}),
101
135
  normalizerVersion: CONTENT_HASH_NORMALIZER_VERSION,
136
+ identityResolutionVersion: IDENTITY_RESOLUTION_VERSION,
102
137
  status: inferMemoryStatus(parsed.frontmatter, filePath),
103
138
  };
104
139
  }
@@ -136,7 +171,8 @@ export async function buildReconcileManifest(options: BuildReconcileManifestOpti
136
171
  if (
137
172
  cached?.sha256.toLowerCase() === file.sha256.toLowerCase() &&
138
173
  (cached.memory === undefined ||
139
- cached.memory.normalizerVersion === CONTENT_HASH_NORMALIZER_VERSION)
174
+ (cached.memory.normalizerVersion === CONTENT_HASH_NORMALIZER_VERSION &&
175
+ cached.memory.identityResolutionVersion === IDENTITY_RESOLUTION_VERSION))
140
176
  ) {
141
177
  files.push({ ...file, ...(cached.memory ? { memory: cached.memory } : {}) });
142
178
  continue;
@@ -168,7 +204,7 @@ function activeFactByPath(manifest: ReconcileManifest | undefined): Map<string,
168
204
  }
169
205
 
170
206
  function memoryIdentityHashes(memory: ReconcileMemoryIdentity): string[] {
171
- return [memory.contentHash];
207
+ return [memory.contentHash, ...(memory.contentHashAliases ?? [])];
172
208
  }
173
209
 
174
210
  function contentHashRows(
@@ -79,6 +79,7 @@ function resolveNonQmdBackend(config: PluginConfig): SearchBackend | undefined {
79
79
  embedHelper,
80
80
  memoryDir: config.memoryDir,
81
81
  embeddingDimension: config.oramaEmbeddingDimension!,
82
+ cjkSegmentationEnabled: config.oramaCjkSegmentation !== false,
82
83
  });
83
84
  }
84
85
 
@@ -221,12 +221,8 @@ export class LanceDbBackend implements SearchBackend {
221
221
  rows.length > 0 && rows.every((row) => row.vectorProvider === embeddingProviderIdentity),
222
222
  );
223
223
  if (isSearchAborted(execution)) return;
224
- // Create FTS index on content column
225
- try {
226
- await table.createIndex("content", { config: this.lanceIndex.fts() });
227
- } catch {
228
- // FTS index creation may fail on some platforms — degrade gracefully
229
- }
224
+ // FTS index on the content column.
225
+ await this.createFtsIndex(table);
230
226
  if (collection === this.collection) this.table = table;
231
227
  } catch (err) {
232
228
  log.debug(`LanceDbBackend update failed: ${err}`);
@@ -365,11 +361,7 @@ export class LanceDbBackend implements SearchBackend {
365
361
  vectorProvider: "",
366
362
  };
367
363
  const newTable = await db.createTable(collection, [emptyRow]);
368
- try {
369
- await newTable.createIndex("content", { config: this.lanceIndex.fts() });
370
- } catch {
371
- // FTS index creation may fail — degrade gracefully
372
- }
364
+ await this.createFtsIndex(newTable);
373
365
  try {
374
366
  await newTable.delete("docid = '__placeholder__'");
375
367
  } catch {
@@ -424,11 +416,7 @@ export class LanceDbBackend implements SearchBackend {
424
416
  };
425
417
  this.table = await db.createTable(this.collection, [emptyRow]);
426
418
  // Create FTS index on content column
427
- try {
428
- await this.table.createIndex("content", { config: this.lanceIndex.fts() });
429
- } catch {
430
- // FTS index creation may fail — degrade gracefully
431
- }
419
+ await this.createFtsIndex(this.table);
432
420
  // Remove placeholder row
433
421
  try {
434
422
  await this.table.delete("docid = '__placeholder__'");
@@ -438,6 +426,26 @@ export class LanceDbBackend implements SearchBackend {
438
426
  return this.table;
439
427
  }
440
428
 
429
+ /**
430
+ * Create the FTS index on the content column with the default tokenizer.
431
+ *
432
+ * Known limitation (issue #2187): tantivy's default tokenizer does not
433
+ * segment space-free scripts (CJK/Thai), so lexical recall over those
434
+ * scripts is near zero here. LanceDB's `baseTokenizer: "ngram"` option is
435
+ * not script-aware — it would n-gram English content too, degrading
436
+ * precision and bloating the index — so no CJK-capable configuration is
437
+ * available in the current @lancedb/lancedb API. Non-English lexical recall
438
+ * on this backend rides on the vector tier instead. See
439
+ * docs/search-backends.md ("Non-English content").
440
+ */
441
+ private async createFtsIndex(table: any): Promise<void> {
442
+ try {
443
+ await table.createIndex("content", { config: this.lanceIndex.fts() });
444
+ } catch {
445
+ // FTS index creation may fail on some platforms — degrade gracefully
446
+ }
447
+ }
448
+
441
449
  private async searchTable(
442
450
  table: any,
443
451
  query: string,