@remnic/core 9.27.0 → 9.28.0

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 (439) hide show
  1. package/dist/access-admin-ops-surface.d.ts +13 -10
  2. package/dist/access-admin-ops-surface.js +43 -38
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-authorization-probe.d.ts +13 -10
  5. package/dist/access-authorization-probe.js +44 -39
  6. package/dist/access-boundary.d.ts +13 -10
  7. package/dist/access-boundary.js +43 -38
  8. package/dist/access-cli.js +100 -94
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-health-types.d.ts +10 -1
  11. package/dist/access-http-lcm-compaction.d.ts +13 -10
  12. package/dist/access-http.d.ts +13 -10
  13. package/dist/access-http.js +53 -48
  14. package/dist/access-identity-continuity-surface.d.ts +9 -8
  15. package/dist/access-identity-continuity-surface.js +43 -38
  16. package/dist/access-lcm-surface.d.ts +13 -10
  17. package/dist/access-lcm-surface.js +43 -38
  18. package/dist/access-mcp.d.ts +13 -10
  19. package/dist/access-mcp.js +48 -43
  20. package/dist/access-memory-search-fanout.d.ts +2 -2
  21. package/dist/{access-namespace-preflight-wRSZEO5V.d.ts → access-namespace-preflight-BiQ_-iUJ.d.ts} +1 -1
  22. package/dist/access-namespace-preflight.d.ts +3 -3
  23. package/dist/access-namespace-preflight.js +43 -38
  24. package/dist/access-observe-write-surface.d.ts +13 -10
  25. package/dist/access-observe-write-surface.js +43 -38
  26. package/dist/access-operations-batch.js +45 -40
  27. package/dist/access-operations.d.ts +16 -13
  28. package/dist/access-operations.js +47 -42
  29. package/dist/access-recall-concurrency.d.ts +13 -10
  30. package/dist/access-recall-concurrency.js +43 -38
  31. package/dist/access-recall-response.d.ts +13 -10
  32. package/dist/access-recall-response.js +43 -38
  33. package/dist/access-recall-surface.d.ts +13 -10
  34. package/dist/access-recall-surface.js +43 -38
  35. package/dist/access-schema.d.ts +80 -80
  36. package/dist/access-schema.js +4 -4
  37. package/dist/{access-service-B4-Fu9x2.d.ts → access-service-CXkIgcGh.d.ts} +12 -8
  38. package/dist/access-service.d.ts +13 -10
  39. package/dist/access-service.js +43 -38
  40. package/dist/access-surface-catalog.d.ts +13 -10
  41. package/dist/access-wearables-meetings-surface.d.ts +4 -3
  42. package/dist/action-confidence.d.ts +1 -1
  43. package/dist/active-memory-bridge.d.ts +1 -1
  44. package/dist/active-recall.d.ts +1 -1
  45. package/dist/active-recall.js +4 -2
  46. package/dist/active-recall.js.map +1 -1
  47. package/dist/adapters/index.js +7 -7
  48. package/dist/adapters/registry.js +3 -3
  49. package/dist/behavior-learner.d.ts +1 -1
  50. package/dist/behavior-signals.d.ts +1 -1
  51. package/dist/bootstrap.d.ts +9 -8
  52. package/dist/briefing.d.ts +3 -2
  53. package/dist/briefing.js +12 -10
  54. package/dist/buffer-surprise-report.d.ts +1 -1
  55. package/dist/buffer.d.ts +3 -2
  56. package/dist/bulk-import/index.d.ts +3 -3
  57. package/dist/calibration.d.ts +1 -1
  58. package/dist/capabilities.d.ts +1 -1
  59. package/dist/{capsule-crypto-YO5QJ6L3.js → capsule-crypto-7FJQINUR.js} +2 -2
  60. package/dist/{catalog-BLLxZ5L5.d.ts → catalog-Bouj8Gfg.d.ts} +1 -1
  61. package/dist/causal-behavior.d.ts +1 -1
  62. package/dist/causal-consolidation.d.ts +1 -1
  63. package/dist/causal-consolidation.js +13 -11
  64. package/dist/causal-consolidation.js.map +1 -1
  65. package/dist/causal-trajectory-graph.d.ts +1 -1
  66. package/dist/{chunk-7RZJWZ46.js → chunk-227UFSEQ.js} +5 -5
  67. package/dist/{chunk-UT3OQPFA.js → chunk-2BEJ4XCF.js} +2 -2
  68. package/dist/{chunk-EOLC6EXV.js → chunk-2FYNLDKJ.js} +24 -3
  69. package/dist/chunk-2FYNLDKJ.js.map +1 -0
  70. package/dist/{chunk-BXLOS5AJ.js → chunk-2NLLXCJG.js} +2 -2
  71. package/dist/{chunk-6NNNURLK.js → chunk-2PHX3I5C.js} +8 -8
  72. package/dist/{chunk-HORJVJ6K.js → chunk-2TQ2UFKH.js} +65 -60
  73. package/dist/chunk-2TQ2UFKH.js.map +1 -0
  74. package/dist/{chunk-RPA2RX5P.js → chunk-3BSJBIZ3.js} +2 -2
  75. package/dist/{chunk-JCVQV6QX.js → chunk-3UOSVTFR.js} +11 -11
  76. package/dist/{chunk-AJ7QCSIS.js → chunk-7CPOZH6Y.js} +2 -2
  77. package/dist/{chunk-MEBQFQ26.js → chunk-AHFZXUZM.js} +7 -5
  78. package/dist/chunk-AHFZXUZM.js.map +1 -0
  79. package/dist/{chunk-U3TH5Q2Q.js → chunk-ALTP3MFS.js} +2 -2
  80. package/dist/{chunk-77CNV7DY.js → chunk-BLAKS3CP.js} +4 -4
  81. package/dist/{chunk-XQ4EH6DI.js → chunk-BR4UFMLO.js} +2 -2
  82. package/dist/chunk-CVILPI77.js +432 -0
  83. package/dist/chunk-CVILPI77.js.map +1 -0
  84. package/dist/{chunk-WEAO45M4.js → chunk-DKQM5Q6Q.js} +2 -2
  85. package/dist/{chunk-CSXHRAJJ.js → chunk-EG64LXKL.js} +3 -3
  86. package/dist/{chunk-PTN6UAUA.js → chunk-ES36HTSC.js} +4 -4
  87. package/dist/{chunk-5BRT4Z2I.js → chunk-EZWWCN7I.js} +2 -2
  88. package/dist/{chunk-XKGPIWGI.js → chunk-FBZTWUK5.js} +5 -5
  89. package/dist/{chunk-GJJBPI6I.js → chunk-FOCEI3TN.js} +6 -3
  90. package/dist/chunk-FOCEI3TN.js.map +1 -0
  91. package/dist/{chunk-FRVTCCGD.js → chunk-GJPCP5CA.js} +2 -2
  92. package/dist/{chunk-CI26JDZA.js → chunk-GQSMYXKL.js} +6 -4
  93. package/dist/{chunk-CI26JDZA.js.map → chunk-GQSMYXKL.js.map} +1 -1
  94. package/dist/{chunk-TGQ2NTWH.js → chunk-IJ6WHMFB.js} +16 -2
  95. package/dist/{chunk-TGQ2NTWH.js.map → chunk-IJ6WHMFB.js.map} +1 -1
  96. package/dist/{chunk-VDX2J7OX.js → chunk-IPLYGWQF.js} +6 -6
  97. package/dist/{chunk-YSGBD3QN.js → chunk-IYT632D5.js} +3 -3
  98. package/dist/{chunk-2QSZNTDO.js → chunk-JBPKEARU.js} +7 -7
  99. package/dist/{chunk-RSYJV25N.js → chunk-JIF3VRKQ.js} +8 -8
  100. package/dist/{chunk-V25OWXAC.js → chunk-JQ7T5VDC.js} +1 -1
  101. package/dist/chunk-JQ7T5VDC.js.map +1 -0
  102. package/dist/{chunk-EUSLKI4X.js → chunk-KKBTBUVT.js} +2 -2
  103. package/dist/{chunk-RNY3BO35.js → chunk-LIHC3T43.js} +2 -2
  104. package/dist/{chunk-RGJBM7Z3.js → chunk-MJPV4LBH.js} +79 -79
  105. package/dist/{chunk-RGJBM7Z3.js.map → chunk-MJPV4LBH.js.map} +1 -1
  106. package/dist/{chunk-UGH6VPPO.js → chunk-MWTMTW2T.js} +2 -2
  107. package/dist/{chunk-MG6MNSP4.js → chunk-MXJ3VP6S.js} +6 -6
  108. package/dist/{chunk-XKO7BM2C.js → chunk-NBNDVNJ2.js} +186 -25
  109. package/dist/chunk-NBNDVNJ2.js.map +1 -0
  110. package/dist/{chunk-M5EPMNS4.js → chunk-P2CLYN6H.js} +2 -2
  111. package/dist/{chunk-BNGPHGVZ.js → chunk-PXQM2HOG.js} +13 -6
  112. package/dist/{chunk-BNGPHGVZ.js.map → chunk-PXQM2HOG.js.map} +1 -1
  113. package/dist/{chunk-CIQXI47W.js → chunk-Q5VJUNXA.js} +1192 -268
  114. package/dist/chunk-Q5VJUNXA.js.map +1 -0
  115. package/dist/{chunk-KGTD2KZJ.js → chunk-Q6YJW6KE.js} +2 -2
  116. package/dist/{chunk-X3SQYAPP.js → chunk-R372P2EH.js} +2 -2
  117. package/dist/{chunk-4MJZTF42.js → chunk-RKXZ7P4V.js} +3 -3
  118. package/dist/chunk-RMMVQQA6.js +70 -0
  119. package/dist/chunk-RMMVQQA6.js.map +1 -0
  120. package/dist/{chunk-2RAC4JIG.js → chunk-S24E4MBQ.js} +14 -14
  121. package/dist/chunk-S24E4MBQ.js.map +1 -0
  122. package/dist/{chunk-RYHWZ52A.js → chunk-S2BBISHU.js} +4 -4
  123. package/dist/{chunk-LLISELSY.js → chunk-TBMRQZDY.js} +2 -2
  124. package/dist/{chunk-FMLKOL2Z.js → chunk-TC3VNKGX.js} +4 -4
  125. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  126. package/dist/{chunk-NUWMZIYZ.js → chunk-UR5SIN7H.js} +53 -35
  127. package/dist/chunk-UR5SIN7H.js.map +1 -0
  128. package/dist/{chunk-JDOJZTFF.js → chunk-VFNI3RPT.js} +2 -2
  129. package/dist/chunk-VNA7W7QF.js +134 -0
  130. package/dist/chunk-VNA7W7QF.js.map +1 -0
  131. package/dist/{chunk-EYJSW2RV.js → chunk-VYYNBJXH.js} +5 -5
  132. package/dist/chunk-WNIUPHWV.js +152 -0
  133. package/dist/chunk-WNIUPHWV.js.map +1 -0
  134. package/dist/chunk-WRJVB3C2.js +118 -0
  135. package/dist/chunk-WRJVB3C2.js.map +1 -0
  136. package/dist/{chunk-BHLN7L7M.js → chunk-WVVK2RFM.js} +6 -6
  137. package/dist/{chunk-DQEMWVMT.js → chunk-X7Y7WX73.js} +1 -1
  138. package/dist/{chunk-HEXSNYJD.js → chunk-YOBNCD3Z.js} +6 -6
  139. package/dist/chunk-YXZG5TVN.js +40 -0
  140. package/dist/chunk-YXZG5TVN.js.map +1 -0
  141. package/dist/{chunk-4DJQYKMN.js → chunk-ZIKENA2C.js} +2 -2
  142. package/dist/chunk-ZIKENA2C.js.map +1 -0
  143. package/dist/{chunk-SK3EYPKC.js → chunk-ZN4UZWMT.js} +2 -2
  144. package/dist/{cli-Bz7X7dGx.d.ts → cli-DJbkaZBU.d.ts} +5 -5
  145. package/dist/cli.d.ts +14 -12
  146. package/dist/cli.js +79 -74
  147. package/dist/compounding/engine.d.ts +3 -2
  148. package/dist/compounding/engine.js +12 -10
  149. package/dist/compounding/preference-consolidator.d.ts +1 -1
  150. package/dist/compression-optimizer.d.ts +1 -1
  151. package/dist/config.d.ts +1 -1
  152. package/dist/config.js +4 -2
  153. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  154. package/dist/connectors/codex-materialize-runner.js +12 -10
  155. package/dist/connectors/codex-materialize.d.ts +1 -1
  156. package/dist/connectors/index.d.ts +1 -1
  157. package/dist/connectors/index.js +12 -10
  158. package/dist/consolidation-provenance-check.d.ts +3 -2
  159. package/dist/consolidation-undo.d.ts +3 -2
  160. package/dist/contradiction/index.d.ts +3 -2
  161. package/dist/conversation-index/backend.d.ts +1 -1
  162. package/dist/conversation-index/backend.js +2 -2
  163. package/dist/conversation-index/chunker.d.ts +1 -1
  164. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  165. package/dist/conversation-index/indexer.d.ts +1 -1
  166. package/dist/conversation-index/search.d.ts +1 -1
  167. package/dist/corpus-watermark.d.ts +15 -2
  168. package/dist/corpus-watermark.js +25 -21
  169. package/dist/day-summary.d.ts +1 -1
  170. package/dist/delinearize.d.ts +1 -1
  171. package/dist/direct-answer-wiring.d.ts +1 -1
  172. package/dist/direct-answer.d.ts +1 -1
  173. package/dist/embedding-fallback.d.ts +1 -1
  174. package/dist/enrichment/index.d.ts +1 -1
  175. package/dist/entity-id-normalization.d.ts +4 -0
  176. package/dist/entity-id-normalization.js +10 -0
  177. package/dist/entity-id-normalization.js.map +1 -0
  178. package/dist/entity-retrieval-boundaries.d.ts +3 -0
  179. package/dist/entity-retrieval-boundaries.js +8 -0
  180. package/dist/entity-retrieval-boundaries.js.map +1 -0
  181. package/dist/entity-retrieval.d.ts +3 -2
  182. package/dist/entity-retrieval.js +13 -10
  183. package/dist/entity-schema.d.ts +1 -1
  184. package/dist/entity-schema.js +1 -1
  185. package/dist/explicit-capture.d.ts +9 -8
  186. package/dist/extraction-error-classification.d.ts +1 -1
  187. package/dist/extraction-faithfulness.d.ts +1 -1
  188. package/dist/extraction-judge-telemetry.d.ts +1 -1
  189. package/dist/extraction-judge-training.d.ts +1 -1
  190. package/dist/extraction-judge.d.ts +1 -1
  191. package/dist/extraction-liveness.d.ts +1 -1
  192. package/dist/extraction.d.ts +1 -1
  193. package/dist/fallback-llm.d.ts +1 -1
  194. package/dist/{first-start-migration-LEXL3XYL.js → first-start-migration-BKNGOFED.js} +4 -4
  195. package/dist/graph-dashboard-diff.d.ts +1 -1
  196. package/dist/graph-dashboard-key.d.ts +1 -1
  197. package/dist/graph-dashboard-parser.d.ts +1 -1
  198. package/dist/graph-edge-reinforcement.d.ts +1 -1
  199. package/dist/graph-snapshot.d.ts +1 -1
  200. package/dist/graph.d.ts +1 -1
  201. package/dist/importance.d.ts +1 -1
  202. package/dist/importers/index.d.ts +1 -1
  203. package/dist/in-flight-reads.d.ts +1 -1
  204. package/dist/index.d.ts +409 -407
  205. package/dist/index.js +147 -141
  206. package/dist/intent.d.ts +1 -1
  207. package/dist/lcm/engine.d.ts +1 -1
  208. package/dist/lcm/engine.js +3 -3
  209. package/dist/lcm/index.d.ts +1 -1
  210. package/dist/lcm/index.js +9 -9
  211. package/dist/lcm/tools.d.ts +1 -1
  212. package/dist/lifecycle.d.ts +1 -1
  213. package/dist/live-connectors-runner.d.ts +1 -1
  214. package/dist/local-llm.d.ts +1 -1
  215. package/dist/local-model-endpoint.d.ts +1 -1
  216. package/dist/maintenance/memory-governance.d.ts +1 -1
  217. package/dist/maintenance/memory-governance.js +12 -10
  218. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +3 -2
  219. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +12 -10
  220. package/dist/maintenance/rebuild-memory-projection.d.ts +3 -2
  221. package/dist/maintenance/rebuild-memory-projection.js +13 -11
  222. package/dist/{maintenance-DgnD2z8S.d.ts → maintenance-DveW6azo.d.ts} +3 -3
  223. package/dist/mcp-memory-inspector-app.d.ts +13 -10
  224. package/dist/memory-action-policy.d.ts +1 -1
  225. package/dist/memory-cache.d.ts +1 -1
  226. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  227. package/dist/memory-projection-mutations.d.ts +4 -0
  228. package/dist/memory-projection-mutations.js +15 -0
  229. package/dist/memory-projection-mutations.js.map +1 -0
  230. package/dist/memory-projection-store.d.ts +1 -1
  231. package/dist/memory-provenance.d.ts +1 -1
  232. package/dist/memory-worth-outcomes.d.ts +3 -2
  233. package/dist/models-json.d.ts +1 -1
  234. package/dist/namespaces/migrate.d.ts +4 -3
  235. package/dist/namespaces/migrate.js +22 -20
  236. package/dist/namespaces/principal.d.ts +1 -1
  237. package/dist/namespaces/search.d.ts +1 -1
  238. package/dist/namespaces/search.js +9 -9
  239. package/dist/namespaces/storage.d.ts +4 -3
  240. package/dist/namespaces/storage.js +12 -10
  241. package/dist/native-knowledge.d.ts +1 -1
  242. package/dist/offline-sync-impression-drain.d.ts +1 -1
  243. package/dist/offline-sync-impression-drain.js +3 -3
  244. package/dist/operator-doctor-corpus.d.ts +22 -3
  245. package/dist/operator-doctor-corpus.js +32 -22
  246. package/dist/operator-doctor-replica.d.ts +52 -0
  247. package/dist/operator-doctor-replica.js +15 -0
  248. package/dist/operator-doctor-replica.js.map +1 -0
  249. package/dist/operator-toolkit.d.ts +7 -3
  250. package/dist/operator-toolkit.js +33 -27
  251. package/dist/orchestration/compression-guideline-coordinator.d.ts +3 -2
  252. package/dist/orchestration/maintenance.d.ts +5 -4
  253. package/dist/orchestration/maintenance.js +17 -15
  254. package/dist/{orchestrator-rIHmHpv1.d.ts → orchestrator-Cvlgpe6I.d.ts} +7 -7
  255. package/dist/orchestrator.d.ts +9 -8
  256. package/dist/orchestrator.js +99 -93
  257. package/dist/patterns-cli.d.ts +1 -1
  258. package/dist/{pipeline-Bq5zU6Bp.d.ts → pipeline-BveYVaz7.d.ts} +1 -1
  259. package/dist/policy-runtime.d.ts +1 -1
  260. package/dist/proactive-contention.d.ts +1 -1
  261. package/dist/provenance.d.ts +1 -1
  262. package/dist/{qmd-3ILJkC70.d.ts → qmd-CLWDsbYR.d.ts} +1 -1
  263. package/dist/qmd-preflight.d.ts +2 -2
  264. package/dist/qmd-recall-cache.d.ts +1 -1
  265. package/dist/qmd.d.ts +2 -2
  266. package/dist/recall-concurrency-config.d.ts +1 -1
  267. package/dist/recall-disclosure-escalation.d.ts +1 -1
  268. package/dist/recall-explain-renderer.d.ts +1 -1
  269. package/dist/recall-explain-renderer.js +3 -3
  270. package/dist/recall-memory-map.d.ts +1 -1
  271. package/dist/recall-planner-llm.d.ts +1 -1
  272. package/dist/recall-state.d.ts +1 -1
  273. package/dist/recall-state.js +2 -2
  274. package/dist/recall-tag-filter.d.ts +1 -1
  275. package/dist/recall-timings.d.ts +1 -1
  276. package/dist/recall-xray-cli.d.ts +1 -1
  277. package/dist/recall-xray-cli.js +4 -4
  278. package/dist/recall-xray-renderer.d.ts +1 -1
  279. package/dist/recall-xray-renderer.js +3 -3
  280. package/dist/recall-xray.d.ts +1 -1
  281. package/dist/recall-xray.js +2 -2
  282. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  283. package/dist/replay/normalizers/claude.d.ts +1 -1
  284. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  285. package/dist/replay/normalizers/shared.d.ts +1 -1
  286. package/dist/replay/runner.d.ts +1 -1
  287. package/dist/replay/types.d.ts +1 -1
  288. package/dist/replica-divergence.d.ts +279 -0
  289. package/dist/replica-divergence.js +28 -0
  290. package/dist/replica-divergence.js.map +1 -0
  291. package/dist/replica-peers-config.d.ts +5 -0
  292. package/dist/replica-peers-config.js +13 -0
  293. package/dist/replica-peers-config.js.map +1 -0
  294. package/dist/resolve-auth-token.d.ts +21 -2
  295. package/dist/resolve-auth-token.js +5 -1
  296. package/dist/resume-bundles.js +5 -3
  297. package/dist/retrieval-agents.d.ts +2 -2
  298. package/dist/retrieval-tiers.d.ts +1 -1
  299. package/dist/routing/engine.d.ts +1 -1
  300. package/dist/routing/store.d.ts +1 -1
  301. package/dist/salvage-envelope.d.ts +1 -1
  302. package/dist/schemas.d.ts +76 -76
  303. package/dist/{scope-profiles-D0-ff4xT.d.ts → scope-profiles-BVf3DZ7z.d.ts} +1 -1
  304. package/dist/search/embed-helper.d.ts +1 -1
  305. package/dist/search/factory.d.ts +1 -1
  306. package/dist/search/factory.js +8 -8
  307. package/dist/search/index.d.ts +1 -1
  308. package/dist/search/index.js +13 -13
  309. package/dist/search/lancedb-backend.d.ts +1 -1
  310. package/dist/search/lancedb-backend.js +2 -2
  311. package/dist/search/meilisearch-backend.d.ts +1 -1
  312. package/dist/search/meilisearch-backend.js +2 -2
  313. package/dist/search/noop-backend.d.ts +1 -1
  314. package/dist/search/orama-backend.d.ts +1 -1
  315. package/dist/search/orama-backend.js +2 -2
  316. package/dist/search/port.d.ts +1 -1
  317. package/dist/search/remote-backend.d.ts +1 -1
  318. package/dist/{semantic-consolidation-4Tfh7c1g.d.ts → semantic-consolidation-DXLV47y2.d.ts} +1 -1
  319. package/dist/semantic-consolidation.d.ts +2 -2
  320. package/dist/semantic-consolidation.js +13 -11
  321. package/dist/semantic-rule-promotion.js +12 -10
  322. package/dist/semantic-rule-verifier.d.ts +1 -1
  323. package/dist/semantic-rule-verifier.js +12 -10
  324. package/dist/{service-cTvil7D_.d.ts → service-DbgPTeMJ.d.ts} +2 -2
  325. package/dist/session-observer-bands.d.ts +1 -1
  326. package/dist/session-observer-state.d.ts +1 -1
  327. package/dist/shared-context/manager.d.ts +9 -9
  328. package/dist/signal.d.ts +1 -1
  329. package/dist/{storage-C9ibpTme.d.ts → storage-DOzTm8wG.d.ts} +13 -19
  330. package/dist/storage.d.ts +3 -2
  331. package/dist/storage.js +13 -10
  332. package/dist/summarizer.d.ts +1 -1
  333. package/dist/summary-snapshot.d.ts +1 -1
  334. package/dist/temporal-supersession.d.ts +3 -2
  335. package/dist/temporal-timeline-recall.d.ts +1 -1
  336. package/dist/temporal-validity.d.ts +1 -1
  337. package/dist/threading.d.ts +1 -1
  338. package/dist/tier-migration.d.ts +3 -2
  339. package/dist/tier-routing.d.ts +1 -1
  340. package/dist/topics.d.ts +1 -1
  341. package/dist/transcript.d.ts +1 -1
  342. package/dist/transfer/autodetect.js +1 -1
  343. package/dist/transfer/backup.js +2 -2
  344. package/dist/transfer/capsule-export.js +3 -3
  345. package/dist/transfer/capsule-import.js +2 -2
  346. package/dist/transfer/types.d.ts +66 -66
  347. package/dist/trust-score-stage.d.ts +1 -1
  348. package/dist/trust-score.d.ts +1 -1
  349. package/dist/{types-DHBxIF0s.d.ts → types-BA7W-_xy.d.ts} +53 -4
  350. package/dist/types.d.ts +1 -1
  351. package/dist/types.js +1 -1
  352. package/dist/utility-runtime.d.ts +1 -1
  353. package/dist/verified-recall.js +12 -10
  354. package/dist/write-envelope.d.ts +1 -1
  355. package/package.json +2 -2
  356. package/src/access-health-types.ts +8 -0
  357. package/src/access-http.test.ts +4 -0
  358. package/src/access-service-health.test.ts +23 -0
  359. package/src/access-service.ts +27 -4
  360. package/src/cli.ts +9 -7
  361. package/src/config.ts +2 -1
  362. package/src/corpus-watermark.test.ts +21 -0
  363. package/src/corpus-watermark.ts +25 -3
  364. package/src/entity-id-normalization.ts +55 -0
  365. package/src/entity-retrieval-boundaries.ts +134 -0
  366. package/src/entity-retrieval.ts +253 -27
  367. package/src/entity-schema.ts +2 -1
  368. package/src/memory-projection-mutations.ts +132 -0
  369. package/src/namespaces/storage.ts +5 -3
  370. package/src/operator-doctor-corpus.ts +41 -0
  371. package/src/operator-doctor-replica.test.ts +261 -0
  372. package/src/operator-doctor-replica.ts +129 -0
  373. package/src/operator-toolkit.ts +5 -4
  374. package/src/orchestration/orchestrator-init.ts +2 -2
  375. package/src/replica-divergence.test.ts +1475 -0
  376. package/src/replica-divergence.ts +910 -0
  377. package/src/replica-peers-config.ts +250 -0
  378. package/src/resolve-auth-token.ts +38 -0
  379. package/src/storage/entity-canonical-id-migration-adapter.ts +72 -0
  380. package/src/storage/entity-canonical-id-migration-runner.ts +68 -0
  381. package/src/storage/entity-canonical-id-migration.ts +904 -0
  382. package/src/storage/entity-store.ts +44 -0
  383. package/src/storage/memory-frontmatter-metadata.ts +17 -0
  384. package/src/storage/memory-migration-serialization.ts +37 -0
  385. package/src/storage/memory-read-store.ts +3 -2
  386. package/src/storage/profile-header.ts +8 -7
  387. package/src/storage-profile-timestamp.test.ts +68 -0
  388. package/src/storage.ts +68 -69
  389. package/src/types.ts +3 -3
  390. package/dist/chunk-2RAC4JIG.js.map +0 -1
  391. package/dist/chunk-4DJQYKMN.js.map +0 -1
  392. package/dist/chunk-CIQXI47W.js.map +0 -1
  393. package/dist/chunk-EOLC6EXV.js.map +0 -1
  394. package/dist/chunk-GJJBPI6I.js.map +0 -1
  395. package/dist/chunk-HORJVJ6K.js.map +0 -1
  396. package/dist/chunk-MEBQFQ26.js.map +0 -1
  397. package/dist/chunk-NUWMZIYZ.js.map +0 -1
  398. package/dist/chunk-V25OWXAC.js.map +0 -1
  399. package/dist/chunk-XKO7BM2C.js.map +0 -1
  400. /package/dist/{capsule-crypto-YO5QJ6L3.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
  401. /package/dist/{chunk-7RZJWZ46.js.map → chunk-227UFSEQ.js.map} +0 -0
  402. /package/dist/{chunk-UT3OQPFA.js.map → chunk-2BEJ4XCF.js.map} +0 -0
  403. /package/dist/{chunk-BXLOS5AJ.js.map → chunk-2NLLXCJG.js.map} +0 -0
  404. /package/dist/{chunk-6NNNURLK.js.map → chunk-2PHX3I5C.js.map} +0 -0
  405. /package/dist/{chunk-RPA2RX5P.js.map → chunk-3BSJBIZ3.js.map} +0 -0
  406. /package/dist/{chunk-JCVQV6QX.js.map → chunk-3UOSVTFR.js.map} +0 -0
  407. /package/dist/{chunk-AJ7QCSIS.js.map → chunk-7CPOZH6Y.js.map} +0 -0
  408. /package/dist/{chunk-U3TH5Q2Q.js.map → chunk-ALTP3MFS.js.map} +0 -0
  409. /package/dist/{chunk-77CNV7DY.js.map → chunk-BLAKS3CP.js.map} +0 -0
  410. /package/dist/{chunk-XQ4EH6DI.js.map → chunk-BR4UFMLO.js.map} +0 -0
  411. /package/dist/{chunk-WEAO45M4.js.map → chunk-DKQM5Q6Q.js.map} +0 -0
  412. /package/dist/{chunk-CSXHRAJJ.js.map → chunk-EG64LXKL.js.map} +0 -0
  413. /package/dist/{chunk-PTN6UAUA.js.map → chunk-ES36HTSC.js.map} +0 -0
  414. /package/dist/{chunk-5BRT4Z2I.js.map → chunk-EZWWCN7I.js.map} +0 -0
  415. /package/dist/{chunk-XKGPIWGI.js.map → chunk-FBZTWUK5.js.map} +0 -0
  416. /package/dist/{chunk-FRVTCCGD.js.map → chunk-GJPCP5CA.js.map} +0 -0
  417. /package/dist/{chunk-VDX2J7OX.js.map → chunk-IPLYGWQF.js.map} +0 -0
  418. /package/dist/{chunk-YSGBD3QN.js.map → chunk-IYT632D5.js.map} +0 -0
  419. /package/dist/{chunk-2QSZNTDO.js.map → chunk-JBPKEARU.js.map} +0 -0
  420. /package/dist/{chunk-RSYJV25N.js.map → chunk-JIF3VRKQ.js.map} +0 -0
  421. /package/dist/{chunk-EUSLKI4X.js.map → chunk-KKBTBUVT.js.map} +0 -0
  422. /package/dist/{chunk-RNY3BO35.js.map → chunk-LIHC3T43.js.map} +0 -0
  423. /package/dist/{chunk-UGH6VPPO.js.map → chunk-MWTMTW2T.js.map} +0 -0
  424. /package/dist/{chunk-MG6MNSP4.js.map → chunk-MXJ3VP6S.js.map} +0 -0
  425. /package/dist/{chunk-M5EPMNS4.js.map → chunk-P2CLYN6H.js.map} +0 -0
  426. /package/dist/{chunk-KGTD2KZJ.js.map → chunk-Q6YJW6KE.js.map} +0 -0
  427. /package/dist/{chunk-X3SQYAPP.js.map → chunk-R372P2EH.js.map} +0 -0
  428. /package/dist/{chunk-4MJZTF42.js.map → chunk-RKXZ7P4V.js.map} +0 -0
  429. /package/dist/{chunk-RYHWZ52A.js.map → chunk-S2BBISHU.js.map} +0 -0
  430. /package/dist/{chunk-LLISELSY.js.map → chunk-TBMRQZDY.js.map} +0 -0
  431. /package/dist/{chunk-FMLKOL2Z.js.map → chunk-TC3VNKGX.js.map} +0 -0
  432. /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
  433. /package/dist/{chunk-JDOJZTFF.js.map → chunk-VFNI3RPT.js.map} +0 -0
  434. /package/dist/{chunk-EYJSW2RV.js.map → chunk-VYYNBJXH.js.map} +0 -0
  435. /package/dist/{chunk-BHLN7L7M.js.map → chunk-WVVK2RFM.js.map} +0 -0
  436. /package/dist/{chunk-DQEMWVMT.js.map → chunk-X7Y7WX73.js.map} +0 -0
  437. /package/dist/{chunk-HEXSNYJD.js.map → chunk-YOBNCD3Z.js.map} +0 -0
  438. /package/dist/{chunk-SK3EYPKC.js.map → chunk-ZN4UZWMT.js.map} +0 -0
  439. /package/dist/{first-start-migration-LEXL3XYL.js.map → first-start-migration-BKNGOFED.js.map} +0 -0
@@ -7,6 +7,7 @@ import { collectNativeKnowledgeChunks, type NativeKnowledgeChunk } from "./nativ
7
7
  import { compareEntityTimestamps, normalizeEntityName, type StorageManager } from "./storage.js";
8
8
  import { normalizeEntityText, resolveRequestedEntitySectionKeys } from "./entity-schema.js";
9
9
  import type { EntityStructuredSection, MemoryFile, PluginConfig, TranscriptEntry } from "./types.js";
10
+ import { containsPhrase } from "./entity-retrieval-boundaries.js";
10
11
 
11
12
  const ENTITY_INDEX_VERSION = 3;
12
13
  const RECENT_TRANSCRIPT_LOOKBACK_HOURS = 24;
@@ -51,6 +52,7 @@ type EntityMentionIndexEntry = {
51
52
  type EntityMentionIndex = {
52
53
  version: number;
53
54
  updatedAt: string;
55
+ entityStatusVersion?: number;
54
56
  entities: EntityMentionIndexEntry[];
55
57
  };
56
58
 
@@ -89,12 +91,6 @@ function uniqueStrings(values: string[]): string[] {
89
91
  return [...new Set(values.map((value) => value.trim()).filter((value) => value.length > 0))];
90
92
  }
91
93
 
92
- function containsPhrase(haystack: string, needle: string): boolean {
93
- if (!needle) return false;
94
- const escaped = needle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
95
- return new RegExp(`(^|\\b)${escaped}(\\b|$)`, "i").test(haystack);
96
- }
97
-
98
94
  function compactLine(value: string, maxLength: number = 220): string {
99
95
  const normalized = value.replace(/\s+/g, " ").trim();
100
96
  if (normalized.length <= maxLength) return normalized;
@@ -383,6 +379,57 @@ async function readEntityIndexState(storage: StorageManager): Promise<EntityMent
383
379
  }
384
380
  }
385
381
 
382
+
383
+ async function readCurrentPersistedEntityIndex(
384
+ storage: StorageManager,
385
+ config: PluginConfig,
386
+ recallNamespaces?: string[],
387
+ namespaceStorage?: (namespace: string) => Promise<StorageManager>,
388
+ ): Promise<EntityMentionIndex | null> {
389
+ if (
390
+ resolveNamespaceCapabilities(config).namespaces &&
391
+ namespaceStorage &&
392
+ recallNamespaces &&
393
+ recallNamespaces.length > 0
394
+ ) {
395
+ return null;
396
+ }
397
+ const index = await readEntityIndexState(storage);
398
+ if (!index || index.entityStatusVersion !== storage.getMemoryStatusVersion()) {
399
+ return null;
400
+ }
401
+ return index;
402
+ }
403
+ const namespaceEntityIndexCache = new Map<string, EntityMentionIndex>();
404
+ const MAX_NAMESPACE_ENTITY_INDEX_CACHE_ENTRIES = 32;
405
+
406
+ function namespaceEntityIndexCacheKey(
407
+ storages: StorageManager[],
408
+ recallNamespaces: string[],
409
+ ): string {
410
+ const namespaceKey = uniqueStrings(recallNamespaces).sort().join("\u001f");
411
+ const storageKey = storages
412
+ .map((scopedStorage) => {
413
+ const aliases = Object.entries(scopedStorage.entityAliases)
414
+ .sort(([left], [right]) => left.localeCompare(right));
415
+ return (
416
+ `${path.resolve(scopedStorage.dir)}@${scopedStorage.getMemoryStatusVersion()}` +
417
+ `:${scopedStorage.getMemoryCorpusVersion()}:${scopedStorage.hotCacheKeyId()}:${JSON.stringify(aliases)}`
418
+ );
419
+ })
420
+ .sort()
421
+ .join("\u001f");
422
+ return `${namespaceKey}\u001e${storageKey}`;
423
+ }
424
+
425
+ function rememberNamespaceEntityIndex(key: string, index: EntityMentionIndex): void {
426
+ if (namespaceEntityIndexCache.size >= MAX_NAMESPACE_ENTITY_INDEX_CACHE_ENTRIES) {
427
+ const oldestKey = namespaceEntityIndexCache.keys().next().value;
428
+ if (typeof oldestKey === "string") namespaceEntityIndexCache.delete(oldestKey);
429
+ }
430
+ namespaceEntityIndexCache.set(key, index);
431
+ }
432
+
386
433
  async function writeEntityIndexState(storage: StorageManager, index: EntityMentionIndex): Promise<void> {
387
434
  const statePath = entityIndexStatePath(storage);
388
435
  await mkdir(path.dirname(statePath), { recursive: true });
@@ -438,13 +485,32 @@ function mergeNativeChunk(entry: EntityMentionIndexEntry, chunk: NativeKnowledge
438
485
  entry.aliases = uniqueStrings([...entry.aliases, ...(chunk.aliases ?? [])]);
439
486
  }
440
487
 
488
+ function hasFreshNativeExplicitMention(
489
+ index: EntityMentionIndex,
490
+ nativeChunks: NativeKnowledgeChunk[],
491
+ query: string,
492
+ ): boolean {
493
+ if (nativeChunks.length === 0) return false;
494
+ const nativeCanonicalIds = new Set(nativeChunks.map(nativePseudoCanonicalId));
495
+ const freshNativeIndex: EntityMentionIndex = {
496
+ ...index,
497
+ entities: [
498
+ ...index.entities.filter((entry) => !nativeCanonicalIds.has(entry.canonicalId)),
499
+ ...nativeChunks.map(createPseudoNativeEntry),
500
+ ],
501
+ };
502
+ return resolveLanguageIndependentExplicitCandidates(freshNativeIndex, query).length > 0;
503
+ }
504
+
441
505
  async function buildEntityMentionIndex(
442
506
  storage: StorageManager,
443
507
  config: PluginConfig,
444
508
  recallNamespaces?: string[],
445
509
  namespaceStorage?: (namespace: string) => Promise<StorageManager>,
510
+ nativeChunksOverride?: NativeKnowledgeChunk[],
511
+ resolvedStorages?: StorageManager[],
446
512
  ): Promise<EntityMentionIndex> {
447
- const storages = await resolveEntityIndexStorages(
513
+ const storages = resolvedStorages ?? await resolveEntityIndexStorages(
448
514
  storage,
449
515
  config,
450
516
  recallNamespaces,
@@ -452,23 +518,27 @@ async function buildEntityMentionIndex(
452
518
  );
453
519
  const shouldPersistIndex =
454
520
  storages.length === 1 && path.resolve(storages[0]!.dir) === path.resolve(storage.dir);
521
+ const entityStatusVersionBefore = shouldPersistIndex ? storage.getMemoryStatusVersion() : undefined;
455
522
  const [previousIndex, entityFileSets, memorySets, nativeChunks] = await Promise.all([
456
523
  shouldPersistIndex ? readEntityIndexState(storage) : Promise.resolve(null),
457
524
  Promise.all(storages.map((scopedStorage) => scopedStorage.readAllEntityFiles())),
458
525
  Promise.all(storages.map((scopedStorage) => scopedStorage.readAllMemories())),
459
- readNativeChunks(config, recallNamespaces),
526
+ nativeChunksOverride ? Promise.resolve(nativeChunksOverride) : readNativeChunks(config, recallNamespaces),
460
527
  ]);
461
- // Pair each entity with the alias table of the store it came from (#1534):
462
- // canonical ids must reflect the owning store's aliases, never another
528
+ // Pair each entity with the storage that owns it (#1534): canonical ids must
529
+ // reflect that store's aliases and historical migration mappings, never another
463
530
  // namespace's.
464
531
  const entityRecords = entityFileSets.flatMap((set, index) =>
465
- set.map((entity) => ({ entity, aliases: storages[index]!.entityAliases })),
532
+ set.map((entity) => ({ entity, storage: storages[index]! })),
466
533
  );
467
534
  const memories = memorySets.flat();
468
535
 
469
536
  const entities = new Map<string, EntityMentionIndexEntry>();
470
- for (const { entity, aliases } of entityRecords) {
471
- const canonicalId = normalizeEntityName(entity.name, entity.type, aliases);
537
+ for (const { entity, storage: entityStorage } of entityRecords) {
538
+ const canonicalId =
539
+ typeof entityStorage.normalizeEntityName === "function"
540
+ ? entityStorage.normalizeEntityName(entity.name, entity.type)
541
+ : normalizeEntityName(entity.name, entity.type, entityStorage.entityAliases);
472
542
  const rawStructuredSections = entity.structuredSections ?? [];
473
543
  const rawBeliefLedgerFactKeys = beliefLedgerFactKeys(rawStructuredSections);
474
544
  const sanitizedFacts = entity.facts
@@ -539,15 +609,18 @@ async function buildEntityMentionIndex(
539
609
  const sortedEntities = [...entities.values()].sort((left, right) => left.name.localeCompare(right.name));
540
610
  const previousEntities = previousIndex ? JSON.stringify(previousIndex.entities) : "";
541
611
  const nextEntities = JSON.stringify(sortedEntities);
612
+ const entityStatusVersionAfter = shouldPersistIndex ? storage.getMemoryStatusVersion() : undefined;
613
+ const canPersistIndex = shouldPersistIndex && entityStatusVersionBefore === entityStatusVersionAfter;
542
614
  const index: EntityMentionIndex = {
543
615
  version: ENTITY_INDEX_VERSION,
544
616
  updatedAt:
545
617
  previousIndex && previousEntities === nextEntities
546
618
  ? previousIndex.updatedAt
547
619
  : new Date().toISOString(),
620
+ entityStatusVersion: canPersistIndex ? entityStatusVersionAfter : undefined,
548
621
  entities: sortedEntities,
549
622
  };
550
- if (shouldPersistIndex) {
623
+ if (canPersistIndex) {
551
624
  await writeEntityIndexState(storage, index);
552
625
  }
553
626
  return index;
@@ -575,6 +648,114 @@ function resolveExplicitCandidates(
575
648
  return candidates.sort((left, right) => right.score - left.score);
576
649
  }
577
650
 
651
+ const EXPLICIT_ENTITY_MENTION_SCORE = 9;
652
+
653
+ const IMPLICIT_ENTITY_STOP_WORDS = new Set([
654
+ "a",
655
+ "an",
656
+ "and",
657
+ "are",
658
+ "as",
659
+ "at",
660
+ "be",
661
+ "by",
662
+ "can",
663
+ "do",
664
+ "for",
665
+ "from",
666
+ "has",
667
+ "how",
668
+ "i",
669
+ "if",
670
+ "in",
671
+ "is",
672
+ "it",
673
+ "me",
674
+ "my",
675
+ "of",
676
+ "on",
677
+ "or",
678
+ "the",
679
+ "to",
680
+ "was",
681
+ "what",
682
+ "when",
683
+ "where",
684
+ "who",
685
+ "why",
686
+ "with",
687
+ "you",
688
+ "your",
689
+ ]);
690
+
691
+ function isDistinctiveImplicitAlias(normalizedAlias: string): boolean {
692
+ const tokens = normalizedAlias.split(/\s+/).filter(Boolean);
693
+ if (tokens.length > 1 && tokens.every((token) => IMPLICIT_ENTITY_STOP_WORDS.has(token))) return false;
694
+ if (tokens.length !== 1) return true;
695
+ const token = tokens[0]!;
696
+ return Array.from(token).length > 1 && !IMPLICIT_ENTITY_STOP_WORDS.has(token);
697
+ }
698
+
699
+ function isShortLatinAlias(alias: string): boolean {
700
+ return /^[A-Za-z]{2,3}$/.test(alias.trim());
701
+ }
702
+
703
+ function hasStrongShortLatinAliasMention(query: string, alias: string): boolean {
704
+ const normalizedAlias = alias.trim();
705
+ const titleCaseAlias = `${normalizedAlias[0]!.toUpperCase()}${normalizedAlias.slice(1).toLowerCase()}`;
706
+ const forms = new Set([normalizedAlias, normalizedAlias.toUpperCase(), titleCaseAlias]);
707
+ return [...forms].some((form) => {
708
+ if (form === form.toLowerCase()) return false;
709
+ const escaped = form.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
710
+ return new RegExp(`(?:^|[^A-Za-z0-9])${escaped}(?:$|[^A-Za-z0-9])`).test(query);
711
+ });
712
+ }
713
+
714
+ function resolveLanguageIndependentExplicitCandidates(
715
+ index: EntityMentionIndex,
716
+ query: string,
717
+ ): EntityCandidate[] {
718
+ const canonicalIdsByAlias = new Map<string, Set<string>>();
719
+ for (const entry of index.entities) {
720
+ for (const alias of uniqueStrings([entry.name, ...entry.aliases])) {
721
+ const normalizedAlias = normalizeEntityText(alias);
722
+ if (!normalizedAlias) continue;
723
+ const canonicalIds = canonicalIdsByAlias.get(normalizedAlias) ?? new Set<string>();
724
+ canonicalIds.add(entry.canonicalId);
725
+ canonicalIdsByAlias.set(normalizedAlias, canonicalIds);
726
+ }
727
+ }
728
+
729
+ const candidates: EntityCandidate[] = [];
730
+ for (const entry of index.entities) {
731
+ let bestAlias = "";
732
+ let bestScore = 0;
733
+ for (const alias of uniqueStrings([entry.name, ...entry.aliases])) {
734
+ const normalizedAlias = normalizeEntityText(alias);
735
+ const score = scoreAliasMatch(query, alias);
736
+ if (
737
+ !normalizedAlias ||
738
+ !isDistinctiveImplicitAlias(normalizedAlias) ||
739
+ (isShortLatinAlias(alias) && !hasStrongShortLatinAliasMention(query, alias)) ||
740
+ canonicalIdsByAlias.get(normalizedAlias)?.size !== 1 ||
741
+ score < EXPLICIT_ENTITY_MENTION_SCORE ||
742
+ score <= bestScore
743
+ ) {
744
+ continue;
745
+ }
746
+ bestAlias = alias;
747
+ bestScore = score;
748
+ }
749
+ if (bestAlias) {
750
+ candidates.push({ entry, alias: bestAlias, score: bestScore, source: "query" });
751
+ }
752
+ }
753
+
754
+ return candidates.sort(
755
+ (left, right) => right.score - left.score || left.entry.name.localeCompare(right.entry.name),
756
+ );
757
+ }
758
+
578
759
  function resolveRecentTurnCandidates(
579
760
  index: EntityMentionIndex,
580
761
  transcriptEntries: TranscriptEntry[],
@@ -825,26 +1006,71 @@ function formatEntityHintSection(
825
1006
  }
826
1007
 
827
1008
  export async function buildEntityRecallSection(options: BuildEntityRecallSectionOptions): Promise<string | null> {
828
- const mode = detectEntityQueryMode(options.query);
829
- if (!mode) return null;
830
-
831
- const index = await buildEntityMentionIndex(
832
- options.storage,
833
- options.config,
834
- options.recallNamespaces,
835
- options.namespaceStorage,
836
- );
837
- if (index.entities.length === 0) return null;
838
-
1009
+ const prefixedMode = detectEntityQueryMode(options.query);
1010
+ const persistedIndex = prefixedMode
1011
+ ? null
1012
+ : await readCurrentPersistedEntityIndex(
1013
+ options.storage,
1014
+ options.config,
1015
+ options.recallNamespaces,
1016
+ options.namespaceStorage,
1017
+ );
1018
+ let nativeChunks: NativeKnowledgeChunk[] | undefined;
1019
+ if (
1020
+ !prefixedMode &&
1021
+ persistedIndex &&
1022
+ resolveLanguageIndependentExplicitCandidates(persistedIndex, options.query).length === 0
1023
+ ) {
1024
+ nativeChunks = await readNativeChunks(options.config, options.recallNamespaces);
1025
+ if (!hasFreshNativeExplicitMention(persistedIndex, nativeChunks, options.query)) {
1026
+ return null;
1027
+ }
1028
+ }
1029
+ const namespaceScoped =
1030
+ resolveNamespaceCapabilities(options.config).namespaces &&
1031
+ options.namespaceStorage !== undefined &&
1032
+ (options.recallNamespaces?.length ?? 0) > 0;
1033
+ const resolvedStorages = namespaceScoped
1034
+ ? await resolveEntityIndexStorages(
1035
+ options.storage,
1036
+ options.config,
1037
+ options.recallNamespaces,
1038
+ options.namespaceStorage,
1039
+ )
1040
+ : undefined;
1041
+ const namespaceCacheKey =
1042
+ resolvedStorages && options.recallNamespaces
1043
+ ? namespaceEntityIndexCacheKey(resolvedStorages, options.recallNamespaces)
1044
+ : undefined;
1045
+ let index: EntityMentionIndex | undefined = namespaceCacheKey
1046
+ ? namespaceEntityIndexCache.get(namespaceCacheKey)
1047
+ : undefined;
1048
+ if (!index) {
1049
+ index = await buildEntityMentionIndex(
1050
+ options.storage,
1051
+ options.config,
1052
+ options.recallNamespaces,
1053
+ options.namespaceStorage,
1054
+ nativeChunks,
1055
+ resolvedStorages,
1056
+ );
1057
+ if (namespaceCacheKey) rememberNamespaceEntityIndex(namespaceCacheKey, index);
1058
+ }
839
1059
  const explicitCandidates = resolveExplicitCandidates(index, options.query);
840
- const candidates = explicitCandidates.length > 0
1060
+ const queryCandidates = prefixedMode
841
1061
  ? explicitCandidates
1062
+ : resolveLanguageIndependentExplicitCandidates(index, options.query);
1063
+ const mode = prefixedMode ?? (queryCandidates.length > 0 ? "direct" : null);
1064
+ if (!mode) return null;
1065
+
1066
+ const candidates = queryCandidates.length > 0
1067
+ ? queryCandidates
842
1068
  : resolveRecentTurnCandidates(index, options.transcriptEntries, options.recentTurns);
843
1069
 
844
1070
  if (candidates.length === 0) return null;
845
1071
 
846
1072
  const queryTokens = tokenize(options.query);
847
- const candidateLimit = explicitCandidates.length === 0 && mode === "follow_up"
1073
+ const candidateLimit = queryCandidates.length === 0 && mode === "follow_up"
848
1074
  ? 1
849
1075
  : options.maxHints;
850
1076
  const rankedCandidates = candidates.slice(0, candidateLimit);
@@ -44,8 +44,9 @@ const DEFAULT_ENTITY_SCHEMAS: Record<string, EntitySchemaDefinition> = {
44
44
 
45
45
  export function normalizeEntityText(value: string): string {
46
46
  return value
47
+ .normalize("NFC")
47
48
  .toLowerCase()
48
- .replace(/[^a-z0-9]+/g, " ")
49
+ .replace(/[^\p{L}\p{M}\p{N}]+/gu, " ")
49
50
  .trim();
50
51
  }
51
52
 
@@ -0,0 +1,132 @@
1
+ import { lstat, realpath } from "node:fs/promises";
2
+ import { isErrnoCode } from "./utils/errno.js";
3
+ import { assertPathInsideRoot } from "./utils/path-containment.js";
4
+ import { getMemoryProjectionPath, initializeMemoryProjectionDb } from "./memory-projection-store.js";
5
+ import { type BetterSqlite3Database, openBetterSqlite3 } from "./runtime/better-sqlite.js";
6
+
7
+ const PROJECTION_WRITE_BUSY_TIMEOUT_MS = 100;
8
+ const PROJECTION_WRITE_RETRY_COUNT = 4;
9
+ const PROJECTION_WRITE_RETRY_DELAY_MS = 100;
10
+
11
+ function isSqliteBusyError(error: unknown): boolean {
12
+ const messages: string[] = [];
13
+ const seen = new Set<unknown>();
14
+ let current: unknown = error;
15
+ while (current !== null && typeof current === "object" && !seen.has(current)) {
16
+ seen.add(current);
17
+ if (current instanceof Error) messages.push(current.message);
18
+ if (!("cause" in current)) break;
19
+ current = current.cause;
20
+ }
21
+ const lower = messages.join("\n").toLowerCase();
22
+ return lower.includes("database is locked") || lower.includes("sqlite_busy");
23
+ }
24
+
25
+ async function validateProjectionPath(
26
+ memoryDir: string,
27
+ projectionPath: string,
28
+ ): Promise<boolean> {
29
+ let projectionStat;
30
+ try {
31
+ projectionStat = await lstat(projectionPath);
32
+ } catch (error) {
33
+ if (isErrnoCode(error, "ENOENT")) return false;
34
+ throw error;
35
+ }
36
+ if (projectionStat.isSymbolicLink() || !projectionStat.isFile()) {
37
+ throw new Error(`Refusing memory projection rewrite through unsafe database path: ${projectionPath}.`);
38
+ }
39
+ const [memoryRoot, projectionReal] = await Promise.all([
40
+ realpath(memoryDir),
41
+ realpath(projectionPath),
42
+ ]);
43
+ assertPathInsideRoot(memoryRoot, projectionReal, projectionPath);
44
+ return true;
45
+ }
46
+
47
+ async function rewriteProjectedEntityReferenceRows(
48
+ memoryDir: string,
49
+ entries: ReadonlyArray<readonly [string, string]>,
50
+ memoryId?: string,
51
+ ): Promise<void> {
52
+ if (memoryId !== undefined && memoryId.length === 0) {
53
+ throw new Error("Projection memoryId must not be empty.");
54
+ }
55
+ const scopedMemory = memoryId !== undefined;
56
+ const validEntries = entries.filter(
57
+ ([previousEntityRef, nextEntityRef]) =>
58
+ previousEntityRef.length > 0 && nextEntityRef.length > 0 && previousEntityRef !== nextEntityRef,
59
+ );
60
+ if (validEntries.length === 0) return;
61
+
62
+ const projectionPath = getMemoryProjectionPath(memoryDir);
63
+ if (!(await validateProjectionPath(memoryDir, projectionPath))) return;
64
+
65
+ let lastError: unknown;
66
+ for (let attempt = 0; attempt < PROJECTION_WRITE_RETRY_COUNT; attempt += 1) {
67
+ if (!(await validateProjectionPath(memoryDir, projectionPath))) return;
68
+ let db: BetterSqlite3Database | null = null;
69
+ try {
70
+ db = openBetterSqlite3(projectionPath, { fileMustExist: true });
71
+ db.pragma(`busy_timeout = ${PROJECTION_WRITE_BUSY_TIMEOUT_MS}`);
72
+ initializeMemoryProjectionDb(db);
73
+ const updateCurrent = db.prepare(
74
+ scopedMemory
75
+ ? "UPDATE memory_current SET entity_ref = ? WHERE memory_id = ? AND entity_ref = ?"
76
+ : "UPDATE memory_current SET entity_ref = ? WHERE entity_ref = ?",
77
+ );
78
+ const updateMentions = db.prepare(
79
+ scopedMemory
80
+ ? `
81
+ UPDATE memory_entity_mentions
82
+ SET entity_ref = ?
83
+ WHERE memory_id = ? AND entity_ref = ? AND mention_source = 'frontmatter.entityRef'
84
+ `
85
+ : `
86
+ UPDATE memory_entity_mentions
87
+ SET entity_ref = ?
88
+ WHERE entity_ref = ? AND mention_source = 'frontmatter.entityRef'
89
+ `,
90
+ );
91
+ const rewrite = db.transaction(() => {
92
+ for (const [previousEntityRef, nextEntityRef] of validEntries) {
93
+ const params = scopedMemory
94
+ ? [nextEntityRef, memoryId, previousEntityRef]
95
+ : [nextEntityRef, previousEntityRef];
96
+ updateCurrent.run(...params);
97
+ updateMentions.run(...params);
98
+ }
99
+ });
100
+ rewrite();
101
+ return;
102
+ } catch (error) {
103
+ lastError = error;
104
+ if (!isSqliteBusyError(error) || attempt === PROJECTION_WRITE_RETRY_COUNT - 1) {
105
+ throw error;
106
+ }
107
+ const { promise, resolve } = Promise.withResolvers<void>();
108
+ setTimeout(resolve, PROJECTION_WRITE_RETRY_DELAY_MS);
109
+ await promise;
110
+ } finally {
111
+ db?.close();
112
+ }
113
+ }
114
+
115
+ throw lastError instanceof Error ? lastError : new Error("Projection rewrite failed.");
116
+ }
117
+
118
+ export async function rewriteProjectedMemoryEntityReference(
119
+ memoryDir: string,
120
+ memoryId: string,
121
+ previousEntityRef: string,
122
+ nextEntityRef: string,
123
+ ): Promise<void> {
124
+ await rewriteProjectedEntityReferenceRows(memoryDir, [[previousEntityRef, nextEntityRef]], memoryId);
125
+ }
126
+
127
+ export async function rewriteProjectedEntityReferences(
128
+ memoryDir: string,
129
+ replacements: Readonly<Record<string, string>>,
130
+ ): Promise<void> {
131
+ await rewriteProjectedEntityReferenceRows(memoryDir, Object.entries(replacements));
132
+ }
@@ -284,6 +284,7 @@ export class NamespaceStorageRouter {
284
284
  root = await this.defaultNamespaceRoot();
285
285
  const cached = this.cache.get(ns);
286
286
  if (cached && cached.dir === root) {
287
+ await this.applySecureStoreConfig(cached);
287
288
  this.notifyResolved(ns, root);
288
289
  return cached;
289
290
  }
@@ -291,6 +292,7 @@ export class NamespaceStorageRouter {
291
292
  const cached = this.cache.get(ns);
292
293
  root = await this.namespaceRoot(ns);
293
294
  if (cached && cached.dir === root) {
295
+ await this.applySecureStoreConfig(cached);
294
296
  this.notifyResolved(ns, root);
295
297
  return cached;
296
298
  }
@@ -335,7 +337,7 @@ export class NamespaceStorageRouter {
335
337
  // recovery paths (e.g. the CLI lifecycle-ledger rebuild) refuse an encrypted
336
338
  // ledger they could actually rewrite, and namespace writes could silently
337
339
  // fall back to plaintext. Mirror the orchestrator's setup exactly.
338
- this.applySecureStoreConfig(sm);
340
+ await this.applySecureStoreConfig(sm);
339
341
  this.cache.set(ns, sm);
340
342
  // #2019: let the orchestrator wire write-triggered prioritized embedding on
341
343
  // every router-created namespace storage, not just the primary default store.
@@ -478,12 +480,12 @@ export class NamespaceStorageRouter {
478
480
  * root keyring id — exactly the id the orchestrator and `secure-store unlock`
479
481
  * register under. No-op when secure-store is disabled.
480
482
  */
481
- private applySecureStoreConfig(sm: StorageManager): void {
483
+ private async applySecureStoreConfig(sm: StorageManager): Promise<void> {
482
484
  if (!resolveRecallAuxiliaryCapabilities(this.config).secureStore) return;
483
485
  sm.setSecureStoreRequired(true);
484
486
  const existingKey = keyring.getKey(secureStoreDir(this.config.memoryDir));
485
487
  if (existingKey) {
486
- sm.setSecureStoreKey(existingKey, this.config.secureStoreEncryptOnWrite);
488
+ await sm.setSecureStoreKeyAndWait(existingKey, this.config.secureStoreEncryptOnWrite);
487
489
  }
488
490
  }
489
491
 
@@ -23,7 +23,9 @@ import {
23
23
  computeCorpusWatermarks,
24
24
  resolveCorpusNamespaceRoots,
25
25
  } from "./corpus-watermark.js";
26
+ import { summarizeReplicaDivergence } from "./operator-doctor-replica.js";
26
27
  import type { OperatorDoctorCheck } from "./operator-toolkit.js";
28
+ import type { ResolveSecretRefFn } from "./resolve-auth-token.js";
27
29
  import type { PluginConfig } from "./types.js";
28
30
 
29
31
  const DIGEST_PREFIX_LENGTH = 12;
@@ -93,3 +95,42 @@ export async function summarizeCorpusWatermark(
93
95
  details: { corpus: watermarks },
94
96
  };
95
97
  }
98
+
99
+ /**
100
+ * Extract the watermark array this check stores under `details.corpus` (issue
101
+ * #2149). The replica-divergence doctor check reuses the local watermark set
102
+ * computed here rather than rescanning the corpus, and consumes it through this
103
+ * helper so the `details.corpus` shape stays owned by the module that produces it.
104
+ */
105
+ export function corpusWatermarksFromCheck(check: OperatorDoctorCheck): CorpusWatermark[] {
106
+ const details = check.details;
107
+ if (!details || typeof details !== "object" || !("corpus" in details) || !Array.isArray(details.corpus)) {
108
+ return [];
109
+ }
110
+ // This check always stores a CorpusWatermark[] under `corpus` (guarded above).
111
+ return details.corpus as CorpusWatermark[];
112
+ }
113
+
114
+ /**
115
+ * Build the corpus-watermark and replica-divergence doctor checks together.
116
+ *
117
+ * They are paired deliberately: the replica comparison consumes the corpus
118
+ * check's watermarks (one scan, not two) AND its completeness — an incomplete
119
+ * local census must not let the replica check certify convergence. The pairing
120
+ * lives HERE, next to the corpus check + `corpusWatermarksFromCheck` it consumes
121
+ * and the `PluginConfig` it needs, so the sibling replica module stays a light
122
+ * tsup DTS entry free of the heavy `PluginConfig` type graph (round 6, coderabbit).
123
+ */
124
+ export async function summarizeCorpusAndReplica(
125
+ config: PluginConfig,
126
+ storageFactory: (dir: string) => CorpusStorage,
127
+ resolveSecretRef?: ResolveSecretRefFn | null,
128
+ ): Promise<OperatorDoctorCheck[]> {
129
+ const watermarkCheck = await summarizeCorpusWatermark(config, storageFactory);
130
+ const replicaCheck = await summarizeReplicaDivergence(
131
+ config.replicaPeers,
132
+ corpusWatermarksFromCheck(watermarkCheck),
133
+ { resolveSecretRef, localCensusComplete: watermarkCheck.status === "ok" },
134
+ );
135
+ return [watermarkCheck, replicaCheck];
136
+ }