@remnic/core 9.66.0 → 9.66.1

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 (482) hide show
  1. package/dist/access-admin-ops-surface.d.ts +11 -11
  2. package/dist/access-admin-ops-surface.js +22 -22
  3. package/dist/access-authorization-probe.d.ts +11 -11
  4. package/dist/access-authorization-probe.js +23 -23
  5. package/dist/access-boundary.d.ts +11 -11
  6. package/dist/access-boundary.js +22 -22
  7. package/dist/access-cli.js +86 -84
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-coding-context-resolution.d.ts +1 -1
  10. package/dist/access-extraction-force-flush.d.ts +11 -11
  11. package/dist/access-extraction-force-flush.js +22 -22
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +11 -11
  14. package/dist/access-http-lifecycle-flush.d.ts +11 -11
  15. package/dist/access-http-offline-stream.d.ts +11 -11
  16. package/dist/access-http-query.d.ts +2 -2
  17. package/dist/access-http-query.js +24 -24
  18. package/dist/access-http.d.ts +12 -12
  19. package/dist/access-http.js +39 -39
  20. package/dist/access-identity-continuity-surface.d.ts +9 -9
  21. package/dist/access-identity-continuity-surface.js +22 -22
  22. package/dist/access-lcm-surface.d.ts +11 -11
  23. package/dist/access-lcm-surface.js +22 -22
  24. package/dist/access-mcp.d.ts +11 -11
  25. package/dist/access-mcp.js +29 -29
  26. package/dist/access-memory-search-fanout.d.ts +2 -2
  27. package/dist/{access-namespace-preflight-CLWUoMyW.d.ts → access-namespace-preflight-50VIkPhB.d.ts} +1 -1
  28. package/dist/access-namespace-preflight.d.ts +3 -3
  29. package/dist/access-namespace-preflight.js +22 -22
  30. package/dist/access-observe-write-surface.d.ts +11 -11
  31. package/dist/access-observe-write-surface.js +22 -22
  32. package/dist/access-offline-manifest.d.ts +9 -9
  33. package/dist/access-operations-batch.js +24 -24
  34. package/dist/access-operations.d.ts +16 -16
  35. package/dist/access-operations.js +28 -28
  36. package/dist/access-recall-concurrency.d.ts +11 -11
  37. package/dist/access-recall-concurrency.js +22 -22
  38. package/dist/access-recall-response.d.ts +11 -11
  39. package/dist/access-recall-response.js +22 -22
  40. package/dist/access-recall-surface.d.ts +11 -11
  41. package/dist/access-recall-surface.js +22 -22
  42. package/dist/access-schema.d.ts +89 -89
  43. package/dist/access-schema.js +3 -3
  44. package/dist/{access-service-CEUE1Isj.d.ts → access-service-C2tV2-uL.d.ts} +65 -65
  45. package/dist/access-service-helpers.d.ts +11 -11
  46. package/dist/access-service.d.ts +11 -11
  47. package/dist/access-service.js +22 -22
  48. package/dist/access-surface-catalog.d.ts +11 -11
  49. package/dist/access-surface-catalog.js +24 -24
  50. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  51. package/dist/action-confidence.d.ts +1 -1
  52. package/dist/active-memory-bridge.d.ts +1 -1
  53. package/dist/active-recall.d.ts +1 -1
  54. package/dist/active-recall.js +2 -2
  55. package/dist/adapters/index.js +7 -7
  56. package/dist/adapters/registry.js +3 -3
  57. package/dist/ambient-provenance.d.ts +1 -1
  58. package/dist/artifact-search.d.ts +1 -1
  59. package/dist/behavior-learner.d.ts +1 -1
  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 +9 -9
  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-D1HgugTA.d.ts → catalog-C2jA-gLm.d.ts} +1 -1
  72. package/dist/causal-behavior.d.ts +1 -1
  73. package/dist/causal-consolidation.d.ts +1 -1
  74. package/dist/causal-consolidation.js +10 -10
  75. package/dist/causal-trajectory-graph.d.ts +1 -1
  76. package/dist/{chunk-J3OND5QT.js → chunk-2FA7U5XY.js} +2 -2
  77. package/dist/{chunk-GEJKYA7D.js → chunk-2ITZ74A6.js} +9 -9
  78. package/dist/{chunk-2LBAFHOQ.js → chunk-2X6BGKQL.js} +8 -8
  79. package/dist/{chunk-KODXCHXJ.js → chunk-46XR5FNZ.js} +39 -3
  80. package/dist/chunk-46XR5FNZ.js.map +1 -0
  81. package/dist/{chunk-4STAANV7.js → chunk-4XLTUR6R.js} +3 -3
  82. package/dist/{chunk-FTTJRVB7.js → chunk-65JOGLIS.js} +2 -2
  83. package/dist/{chunk-FESUGFIL.js → chunk-7UOXCCCI.js} +2 -2
  84. package/dist/{chunk-PEBH5DCK.js → chunk-AF5H7TKI.js} +100 -18
  85. package/dist/chunk-AF5H7TKI.js.map +1 -0
  86. package/dist/{chunk-6CEGSTBD.js → chunk-B4AOWRYF.js} +4 -4
  87. package/dist/{chunk-FYWLSFFS.js → chunk-C5IUOBCN.js} +2 -2
  88. package/dist/{chunk-FKKGCGYL.js → chunk-CHGG74CY.js} +2 -2
  89. package/dist/{chunk-H7VDIF2V.js → chunk-CX4OLNIH.js} +2 -2
  90. package/dist/{chunk-Z3YEGSR4.js → chunk-D3UXGE5D.js} +10 -10
  91. package/dist/{chunk-7XOG75AU.js → chunk-D6Q5EPOV.js} +2 -2
  92. package/dist/{chunk-MJRGVXPQ.js → chunk-EH65UV2Z.js} +2 -2
  93. package/dist/{chunk-VQ4AMTGZ.js → chunk-EWKVYCFP.js} +1 -1
  94. package/dist/{chunk-23CVL7HS.js → chunk-FFUMTH27.js} +2 -2
  95. package/dist/{chunk-GX6FTSYH.js → chunk-GAJK3DQ5.js} +2 -2
  96. package/dist/{chunk-O57GM3FR.js → chunk-GBEOUCBB.js} +2 -2
  97. package/dist/{chunk-DMEHOEC7.js → chunk-H2IRSXZN.js} +3 -3
  98. package/dist/{chunk-CFVTRUR3.js → chunk-H6RSANGQ.js} +2 -2
  99. package/dist/chunk-HVAEXYPL.js +98 -0
  100. package/dist/chunk-HVAEXYPL.js.map +1 -0
  101. package/dist/{chunk-OAJMQKQR.js → chunk-IGZCAHFL.js} +2 -2
  102. package/dist/{chunk-CN4VKV3S.js → chunk-INUBU6I5.js} +2 -2
  103. package/dist/{chunk-CTCGHNWN.js → chunk-J2R275FN.js} +4 -4
  104. package/dist/{chunk-2QSZNTDO.js → chunk-JBPKEARU.js} +7 -7
  105. package/dist/{chunk-VQNRICAQ.js → chunk-JKTV3JNX.js} +3 -3
  106. package/dist/{chunk-33MFRY25.js → chunk-KI64TTBL.js} +2 -2
  107. package/dist/{chunk-VCKWULAK.js → chunk-KJXCD7VR.js} +5 -5
  108. package/dist/{chunk-7LCGFUMB.js → chunk-KQAFEZQX.js} +4 -4
  109. package/dist/{chunk-GSKINLAK.js → chunk-LJABGXC4.js} +3 -3
  110. package/dist/{chunk-NPIBN2VL.js → chunk-LK4TOYPU.js} +2 -2
  111. package/dist/{chunk-EZSCW4EM.js → chunk-LYUUA6QB.js} +2 -2
  112. package/dist/{chunk-I5VB44ZK.js → chunk-M5ERTI4I.js} +2 -2
  113. package/dist/{chunk-IHGMRDEE.js → chunk-MUEGIKKY.js} +227 -144
  114. package/dist/chunk-MUEGIKKY.js.map +1 -0
  115. package/dist/{chunk-QCRJMU5V.js → chunk-NFP4KPTA.js} +2 -2
  116. package/dist/{chunk-YXFCALVT.js → chunk-NSTNGMSS.js} +8 -8
  117. package/dist/{chunk-L4X4PJYK.js → chunk-NUF7VSEX.js} +2 -2
  118. package/dist/{chunk-IVIAHQBR.js → chunk-OJUEUQDJ.js} +2 -2
  119. package/dist/{chunk-ZW4VXELZ.js → chunk-OMX6TKXH.js} +2 -2
  120. package/dist/{chunk-EFQCDJZ2.js → chunk-QBNE55VA.js} +2 -2
  121. package/dist/{chunk-6QDXA26G.js → chunk-RPIS5FQ7.js} +47 -47
  122. package/dist/{chunk-HJXA6ZM7.js → chunk-S4CDUXQY.js} +2 -2
  123. package/dist/{chunk-72OIT7KS.js → chunk-S4Z2OBTX.js} +3 -3
  124. package/dist/{chunk-4FHRZD5T.js → chunk-SZMYGDSM.js} +2 -2
  125. package/dist/{chunk-MAH64N55.js → chunk-TBCDF556.js} +4 -4
  126. package/dist/{chunk-56IV4J5W.js → chunk-TCF4MU7L.js} +443 -58
  127. package/dist/chunk-TCF4MU7L.js.map +1 -0
  128. package/dist/{chunk-K66OY4EI.js → chunk-TCQRIIIN.js} +2 -2
  129. package/dist/{chunk-KXIXO76C.js → chunk-U65VJSCJ.js} +14 -14
  130. package/dist/{chunk-HNPE66LB.js → chunk-U6NGKS32.js} +7 -7
  131. package/dist/{chunk-WKJFIMVN.js → chunk-UW4RYPWC.js} +2 -2
  132. package/dist/{chunk-MN5NOOI7.js → chunk-VG4SSPAW.js} +2 -2
  133. package/dist/chunk-WFCWP4XU.js +17 -0
  134. package/dist/chunk-WFCWP4XU.js.map +1 -0
  135. package/dist/{chunk-UNUMFURP.js → chunk-X5PIDJ3L.js} +3 -3
  136. package/dist/{chunk-RZ3IZIJG.js → chunk-XOHYGIWF.js} +2 -2
  137. package/dist/{chunk-MINHJ55X.js → chunk-XXW32OL7.js} +1 -1
  138. package/dist/{chunk-MINHJ55X.js.map → chunk-XXW32OL7.js.map} +1 -1
  139. package/dist/{chunk-6RUHELWR.js → chunk-YWPLOJ7T.js} +2 -2
  140. package/dist/{chunk-ZJPM7GZ3.js → chunk-ZPS724LT.js} +2 -2
  141. package/dist/{chunk-7UTDHQZ5.js → chunk-ZZZWEDF4.js} +2 -2
  142. package/dist/{cli-BEkm2MEf.d.ts → cli-CsfFMe6n.d.ts} +5 -5
  143. package/dist/cli.d.ts +13 -13
  144. package/dist/cli.js +63 -63
  145. package/dist/coding/export-okf-codegraph.d.ts +1 -1
  146. package/dist/coding/export-okf-codegraph.js +9 -9
  147. package/dist/coding/pre-action-gate.d.ts +1 -1
  148. package/dist/compounding/engine.d.ts +2 -2
  149. package/dist/compounding/engine.js +9 -9
  150. package/dist/compounding/preference-consolidator.d.ts +1 -1
  151. package/dist/compression-optimizer.d.ts +1 -1
  152. package/dist/config.d.ts +1 -1
  153. package/dist/config.js +2 -2
  154. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  155. package/dist/connectors/codex-materialize-runner.js +9 -9
  156. package/dist/connectors/codex-materialize.d.ts +1 -1
  157. package/dist/connectors/index.d.ts +1 -1
  158. package/dist/connectors/index.js +9 -9
  159. package/dist/consolidation-provenance-check.d.ts +2 -2
  160. package/dist/consolidation-undo.d.ts +2 -2
  161. package/dist/contradiction/index.d.ts +3 -3
  162. package/dist/converge-config.d.ts +1 -1
  163. package/dist/convergence-refresh.d.ts +2 -2
  164. package/dist/convergence-refresh.js +11 -11
  165. package/dist/conversation-index/backend.d.ts +1 -1
  166. package/dist/conversation-index/chunker.d.ts +1 -1
  167. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  168. package/dist/conversation-index/indexer.d.ts +1 -1
  169. package/dist/conversation-index/search.d.ts +1 -1
  170. package/dist/corpus-watermark.d.ts +1 -1
  171. package/dist/corpus-watermark.js +11 -11
  172. package/dist/cross-lingual-recall.d.ts +1 -1
  173. package/dist/day-summary.d.ts +1 -1
  174. package/dist/delinearize.d.ts +1 -1
  175. package/dist/dependency-propagation-config.d.ts +1 -1
  176. package/dist/{dependency-propagation-delivery-BCpeo14F.d.ts → dependency-propagation-delivery-D4WMbOwA.d.ts} +1 -1
  177. package/dist/direct-answer-wiring.d.ts +1 -1
  178. package/dist/direct-answer.d.ts +1 -1
  179. package/dist/embedding-fallback.d.ts +1 -1
  180. package/dist/enrichment/index.d.ts +1 -1
  181. package/dist/entity-origin-fields.d.ts +1 -1
  182. package/dist/entity-retrieval.d.ts +2 -2
  183. package/dist/entity-retrieval.js +9 -9
  184. package/dist/entity-schema.d.ts +1 -1
  185. package/dist/episodic-context.d.ts +1 -1
  186. package/dist/eval-trajectory-contracts.d.ts +1 -1
  187. package/dist/eval-trajectory-store.d.ts +1 -1
  188. package/dist/eval-trajectory.d.ts +1 -1
  189. package/dist/explicit-capture.d.ts +9 -9
  190. package/dist/external-wiki-access.d.ts +11 -11
  191. package/dist/external-wiki-access.js +23 -23
  192. package/dist/external-wiki-collection-registration.d.ts +1 -1
  193. package/dist/external-wiki-collection.d.ts +1 -1
  194. package/dist/external-wiki-mcp-tools.d.ts +11 -11
  195. package/dist/extraction-error-classification.d.ts +1 -1
  196. package/dist/extraction-faithfulness.d.ts +1 -1
  197. package/dist/extraction-judge-telemetry.d.ts +1 -1
  198. package/dist/extraction-judge-training.d.ts +1 -1
  199. package/dist/extraction-judge.d.ts +1 -1
  200. package/dist/extraction-liveness.d.ts +1 -1
  201. package/dist/extraction-normalization.d.ts +1 -1
  202. package/dist/extraction-prompt.d.ts +1 -1
  203. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  204. package/dist/extraction-source-grounding.d.ts +1 -1
  205. package/dist/extraction.d.ts +1 -1
  206. package/dist/extraction.js +9 -9
  207. package/dist/fallback-llm.d.ts +1 -1
  208. package/dist/graph-dashboard-diff.d.ts +1 -1
  209. package/dist/graph-dashboard-key.d.ts +1 -1
  210. package/dist/graph-dashboard-parser.d.ts +1 -1
  211. package/dist/graph-edge-reinforcement.d.ts +1 -1
  212. package/dist/graph-path-reconstruction.d.ts +1 -1
  213. package/dist/graph-path-scoring.d.ts +1 -1
  214. package/dist/graph-snapshot.d.ts +1 -1
  215. package/dist/graph.d.ts +1 -1
  216. package/dist/harmonic-retrieval.js +1 -1
  217. package/dist/importance.d.ts +1 -1
  218. package/dist/importers/index.d.ts +1 -1
  219. package/dist/in-flight-reads.d.ts +1 -1
  220. package/dist/{index-D_pyMUaP.d.ts → index-DuJnzwHv.d.ts} +2 -2
  221. package/dist/index.d.ts +807 -698
  222. package/dist/index.js +130 -102
  223. package/dist/intent.d.ts +1 -1
  224. package/dist/lcm/engine.d.ts +1 -1
  225. package/dist/lcm/engine.js +4 -4
  226. package/dist/lcm/index.d.ts +1 -1
  227. package/dist/lcm/index.js +10 -10
  228. package/dist/lcm/tools.d.ts +1 -1
  229. package/dist/lifecycle.d.ts +1 -1
  230. package/dist/live-connectors-runner.d.ts +1 -1
  231. package/dist/local-llm.d.ts +1 -1
  232. package/dist/local-model-endpoint.d.ts +1 -1
  233. package/dist/location/index.d.ts +3 -3
  234. package/dist/location/index.js +11 -11
  235. package/dist/maintenance/memory-governance.d.ts +1 -1
  236. package/dist/maintenance/memory-governance.js +9 -9
  237. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  238. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +9 -9
  239. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  240. package/dist/maintenance/rebuild-memory-projection.js +10 -10
  241. package/dist/{maintenance-DDUX9d6D.d.ts → maintenance-BBeaeYRR.d.ts} +3 -3
  242. package/dist/mcp-memory-inspector-app.d.ts +11 -11
  243. package/dist/memory-action-policy.d.ts +1 -1
  244. package/dist/memory-cache.d.ts +1 -1
  245. package/dist/memory-controller.d.ts +1 -1
  246. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  247. package/dist/memory-projection-store.d.ts +1 -1
  248. package/dist/memory-provenance.d.ts +1 -1
  249. package/dist/memory-snapshot.d.ts +1 -1
  250. package/dist/memory-subject-cli.d.ts +11 -11
  251. package/dist/memory-subject.d.ts +11 -11
  252. package/dist/memory-worth-outcomes.d.ts +2 -2
  253. package/dist/models-json.d.ts +1 -1
  254. package/dist/namespaces/migrate.d.ts +3 -3
  255. package/dist/namespaces/migrate.js +10 -10
  256. package/dist/namespaces/principal.d.ts +1 -1
  257. package/dist/namespaces/search.d.ts +1 -1
  258. package/dist/namespaces/search.js +5 -5
  259. package/dist/namespaces/storage.d.ts +3 -3
  260. package/dist/namespaces/storage.js +9 -9
  261. package/dist/native-knowledge.d.ts +1 -1
  262. package/dist/offline-sync-impression-drain.d.ts +1 -1
  263. package/dist/operator-doctor-corpus.d.ts +1 -1
  264. package/dist/operator-doctor-corpus.js +12 -12
  265. package/dist/operator-doctor-replica.d.ts +1 -1
  266. package/dist/operator-toolkit.d.ts +3 -3
  267. package/dist/operator-toolkit.js +19 -19
  268. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  269. package/dist/orchestration/maintenance.d.ts +4 -4
  270. package/dist/orchestration/maintenance.js +18 -18
  271. package/dist/{orchestrator-3F4jihCo.d.ts → orchestrator-CaqnwNwM.d.ts} +8 -8
  272. package/dist/orchestrator.d.ts +9 -9
  273. package/dist/orchestrator.js +86 -84
  274. package/dist/patterns-cli.d.ts +1 -1
  275. package/dist/{pipeline-CB1dj6Uh.d.ts → pipeline-CrxVjlJr.d.ts} +1 -1
  276. package/dist/policy-runtime.d.ts +1 -1
  277. package/dist/proactive-contention.d.ts +1 -1
  278. package/dist/provenance.d.ts +1 -1
  279. package/dist/{public-http-34-JIAGQ.d.ts → public-http-Cwvl4QZr.d.ts} +1 -1
  280. package/dist/{qmd-edLLZXc5.d.ts → qmd-BZgbJm0g.d.ts} +1 -1
  281. package/dist/qmd-preflight.d.ts +2 -2
  282. package/dist/qmd-recall-cache.d.ts +1 -1
  283. package/dist/qmd.d.ts +2 -2
  284. package/dist/recall-concurrency-config.d.ts +1 -1
  285. package/dist/recall-deep.d.ts +37 -0
  286. package/dist/recall-deep.js +81 -0
  287. package/dist/recall-deep.js.map +1 -0
  288. package/dist/recall-disclosure-escalation.d.ts +1 -1
  289. package/dist/recall-explain-renderer.d.ts +1 -1
  290. package/dist/recall-explain-renderer.js +3 -3
  291. package/dist/recall-memory-map.d.ts +1 -1
  292. package/dist/recall-navigate.d.ts +70 -0
  293. package/dist/recall-navigate.js +51 -0
  294. package/dist/recall-navigate.js.map +1 -0
  295. package/dist/recall-planner-llm.d.ts +1 -1
  296. package/dist/recall-state-view-wire.d.ts +14 -0
  297. package/dist/recall-state-view-wire.js +11 -0
  298. package/dist/recall-state-view-wire.js.map +1 -0
  299. package/dist/recall-state-view.d.ts +25 -0
  300. package/dist/recall-state-view.js +22 -0
  301. package/dist/recall-state-view.js.map +1 -0
  302. package/dist/recall-state.d.ts +1 -1
  303. package/dist/recall-tag-filter.d.ts +1 -1
  304. package/dist/recall-timings.d.ts +1 -1
  305. package/dist/recall-xray-cli.d.ts +1 -1
  306. package/dist/recall-xray-cli.js +4 -4
  307. package/dist/recall-xray-renderer.d.ts +1 -1
  308. package/dist/recall-xray-renderer.js +3 -3
  309. package/dist/recall-xray.d.ts +1 -1
  310. package/dist/recall-xray.js +2 -2
  311. package/dist/reconcile/cursor.d.ts +1 -1
  312. package/dist/reconcile/manifest.d.ts +1 -1
  313. package/dist/reconcile/plan.d.ts +1 -1
  314. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  315. package/dist/replay/normalizers/claude.d.ts +1 -1
  316. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  317. package/dist/replay/normalizers/shared.d.ts +1 -1
  318. package/dist/replay/runner.d.ts +1 -1
  319. package/dist/replay/types.d.ts +1 -1
  320. package/dist/replica-divergence.d.ts +1 -1
  321. package/dist/replica-peers-config.d.ts +1 -1
  322. package/dist/resolve-auth-token.d.ts +1 -1
  323. package/dist/resume-bundles.js +3 -3
  324. package/dist/retrieval-agents.d.ts +2 -2
  325. package/dist/retrieval-tiers.d.ts +1 -1
  326. package/dist/routing/engine.d.ts +1 -1
  327. package/dist/routing/store.d.ts +1 -1
  328. package/dist/salvage-envelope.d.ts +1 -1
  329. package/dist/schemas.d.ts +152 -152
  330. package/dist/{scope-profiles-BF2lu81V.d.ts → scope-profiles-DFaojvoP.d.ts} +1 -1
  331. package/dist/search/embed-helper.d.ts +1 -1
  332. package/dist/search/factory.d.ts +1 -1
  333. package/dist/search/factory.js +4 -4
  334. package/dist/search/index.d.ts +1 -1
  335. package/dist/search/index.js +10 -10
  336. package/dist/search/lancedb-backend.d.ts +1 -1
  337. package/dist/search/meilisearch-backend.d.ts +1 -1
  338. package/dist/search/noop-backend.d.ts +1 -1
  339. package/dist/search/orama-backend.d.ts +1 -1
  340. package/dist/search/port.d.ts +1 -1
  341. package/dist/search/remote-backend.d.ts +1 -1
  342. package/dist/{semantic-consolidation-5OuWXBRt.d.ts → semantic-consolidation-BiX68wZA.d.ts} +1 -1
  343. package/dist/semantic-consolidation.d.ts +2 -2
  344. package/dist/semantic-consolidation.js +10 -10
  345. package/dist/semantic-rule-promotion.js +9 -9
  346. package/dist/semantic-rule-verifier.d.ts +1 -1
  347. package/dist/semantic-rule-verifier.js +9 -9
  348. package/dist/{service-CrqEhLXD.d.ts → service-D5h2zZ0M.d.ts} +2 -2
  349. package/dist/session-observer-bands.d.ts +1 -1
  350. package/dist/session-observer-state.d.ts +1 -1
  351. package/dist/shared-context/manager.d.ts +7 -7
  352. package/dist/signal.d.ts +1 -1
  353. package/dist/source-agent-qualifier.d.ts +1 -1
  354. package/dist/source-agent-qualifier.js +9 -9
  355. package/dist/{storage-BQn-xnxm.d.ts → storage-CtsaojWD.d.ts} +1 -1
  356. package/dist/storage.d.ts +2 -2
  357. package/dist/storage.js +8 -8
  358. package/dist/subject-config.d.ts +1 -1
  359. package/dist/summarizer.d.ts +1 -1
  360. package/dist/summary-snapshot.d.ts +1 -1
  361. package/dist/support-passport/index.d.ts +14 -14
  362. package/dist/support-passport/index.js +25 -25
  363. package/dist/temporal-supersession.d.ts +2 -2
  364. package/dist/temporal-timeline-recall.d.ts +1 -1
  365. package/dist/temporal-validity.d.ts +1 -1
  366. package/dist/threading.d.ts +1 -1
  367. package/dist/tier-migration.d.ts +2 -2
  368. package/dist/tier-routing.d.ts +1 -1
  369. package/dist/topics.d.ts +1 -1
  370. package/dist/transcript.d.ts +1 -1
  371. package/dist/transfer/capsule-export.js +2 -2
  372. package/dist/transfer/capsule-import.js +2 -2
  373. package/dist/transfer/export-okf.d.ts +1 -1
  374. package/dist/transfer/export-okf.js +10 -10
  375. package/dist/transfer/types.d.ts +78 -78
  376. package/dist/trust-score-stage.d.ts +1 -1
  377. package/dist/trust-score.d.ts +1 -1
  378. package/dist/{types-BRpcNjHZ.d.ts → types-CIpfYz1I.d.ts} +16 -11
  379. package/dist/types.d.ts +1 -1
  380. package/dist/types.js +1 -1
  381. package/dist/utility-runtime.d.ts +1 -1
  382. package/dist/verified-recall.js +9 -9
  383. package/dist/who-knows-cli.d.ts +11 -11
  384. package/dist/who-knows-cli.js +10 -10
  385. package/dist/who-knows.d.ts +11 -11
  386. package/dist/who-knows.js +9 -9
  387. package/dist/write-envelope.d.ts +1 -1
  388. package/package.json +2 -2
  389. package/src/activity/config.test.ts +1 -1
  390. package/src/activity/config.ts +48 -3
  391. package/src/activity/index.ts +2 -0
  392. package/src/activity/journal.test.ts +97 -0
  393. package/src/activity/journal.ts +113 -0
  394. package/src/activity/privacy.test.ts +53 -0
  395. package/src/activity/privacy.ts +80 -0
  396. package/src/activity/timeline/index.ts +2 -0
  397. package/src/activity/timeline/journal-recap.test.ts +113 -0
  398. package/src/activity/timeline/journal-recap.ts +130 -0
  399. package/src/activity/timeline/query.test.ts +198 -0
  400. package/src/activity/timeline/query.ts +313 -0
  401. package/src/activity/timeline/weekly.test.ts +215 -0
  402. package/src/activity/timeline/weekly.ts +234 -0
  403. package/src/activity/types.ts +14 -0
  404. package/src/activity/vault-publish.test.ts +166 -0
  405. package/src/activity/vault-publish.ts +101 -0
  406. package/src/config.test.ts +1 -1
  407. package/src/config.ts +2 -22
  408. package/src/dedup/merge-on-write.test.ts +91 -0
  409. package/src/dedup/merge-on-write.ts +75 -0
  410. package/src/dedup/novelty-gate.test.ts +143 -0
  411. package/src/dedup/novelty-gate.ts +163 -0
  412. package/src/location/recall-exclusion.test.ts +1 -0
  413. package/src/orchestration/extraction-persist.ts +22 -23
  414. package/src/orchestration/generic-recall-paths.ts +11 -0
  415. package/src/orchestration/recall-entry.ts +8 -3
  416. package/src/recall-deep.test.ts +72 -0
  417. package/src/recall-deep.ts +113 -0
  418. package/src/recall-navigate.test.ts +84 -0
  419. package/src/recall-navigate.ts +100 -0
  420. package/src/recall-state-view-wire.test.ts +35 -0
  421. package/src/recall-state-view-wire.ts +28 -0
  422. package/src/recall-state-view.test.ts +131 -0
  423. package/src/recall-state-view.ts +138 -0
  424. package/src/shared-context/governance.test.ts +53 -0
  425. package/src/shared-context/governance.ts +86 -0
  426. package/src/types.ts +3 -10
  427. package/dist/chunk-56IV4J5W.js.map +0 -1
  428. package/dist/chunk-IHGMRDEE.js.map +0 -1
  429. package/dist/chunk-KODXCHXJ.js.map +0 -1
  430. package/dist/chunk-PEBH5DCK.js.map +0 -1
  431. /package/dist/{chunk-J3OND5QT.js.map → chunk-2FA7U5XY.js.map} +0 -0
  432. /package/dist/{chunk-GEJKYA7D.js.map → chunk-2ITZ74A6.js.map} +0 -0
  433. /package/dist/{chunk-2LBAFHOQ.js.map → chunk-2X6BGKQL.js.map} +0 -0
  434. /package/dist/{chunk-4STAANV7.js.map → chunk-4XLTUR6R.js.map} +0 -0
  435. /package/dist/{chunk-FTTJRVB7.js.map → chunk-65JOGLIS.js.map} +0 -0
  436. /package/dist/{chunk-FESUGFIL.js.map → chunk-7UOXCCCI.js.map} +0 -0
  437. /package/dist/{chunk-6CEGSTBD.js.map → chunk-B4AOWRYF.js.map} +0 -0
  438. /package/dist/{chunk-FYWLSFFS.js.map → chunk-C5IUOBCN.js.map} +0 -0
  439. /package/dist/{chunk-FKKGCGYL.js.map → chunk-CHGG74CY.js.map} +0 -0
  440. /package/dist/{chunk-H7VDIF2V.js.map → chunk-CX4OLNIH.js.map} +0 -0
  441. /package/dist/{chunk-Z3YEGSR4.js.map → chunk-D3UXGE5D.js.map} +0 -0
  442. /package/dist/{chunk-7XOG75AU.js.map → chunk-D6Q5EPOV.js.map} +0 -0
  443. /package/dist/{chunk-MJRGVXPQ.js.map → chunk-EH65UV2Z.js.map} +0 -0
  444. /package/dist/{chunk-VQ4AMTGZ.js.map → chunk-EWKVYCFP.js.map} +0 -0
  445. /package/dist/{chunk-23CVL7HS.js.map → chunk-FFUMTH27.js.map} +0 -0
  446. /package/dist/{chunk-GX6FTSYH.js.map → chunk-GAJK3DQ5.js.map} +0 -0
  447. /package/dist/{chunk-O57GM3FR.js.map → chunk-GBEOUCBB.js.map} +0 -0
  448. /package/dist/{chunk-DMEHOEC7.js.map → chunk-H2IRSXZN.js.map} +0 -0
  449. /package/dist/{chunk-CFVTRUR3.js.map → chunk-H6RSANGQ.js.map} +0 -0
  450. /package/dist/{chunk-OAJMQKQR.js.map → chunk-IGZCAHFL.js.map} +0 -0
  451. /package/dist/{chunk-CN4VKV3S.js.map → chunk-INUBU6I5.js.map} +0 -0
  452. /package/dist/{chunk-CTCGHNWN.js.map → chunk-J2R275FN.js.map} +0 -0
  453. /package/dist/{chunk-2QSZNTDO.js.map → chunk-JBPKEARU.js.map} +0 -0
  454. /package/dist/{chunk-VQNRICAQ.js.map → chunk-JKTV3JNX.js.map} +0 -0
  455. /package/dist/{chunk-33MFRY25.js.map → chunk-KI64TTBL.js.map} +0 -0
  456. /package/dist/{chunk-VCKWULAK.js.map → chunk-KJXCD7VR.js.map} +0 -0
  457. /package/dist/{chunk-7LCGFUMB.js.map → chunk-KQAFEZQX.js.map} +0 -0
  458. /package/dist/{chunk-GSKINLAK.js.map → chunk-LJABGXC4.js.map} +0 -0
  459. /package/dist/{chunk-NPIBN2VL.js.map → chunk-LK4TOYPU.js.map} +0 -0
  460. /package/dist/{chunk-EZSCW4EM.js.map → chunk-LYUUA6QB.js.map} +0 -0
  461. /package/dist/{chunk-I5VB44ZK.js.map → chunk-M5ERTI4I.js.map} +0 -0
  462. /package/dist/{chunk-QCRJMU5V.js.map → chunk-NFP4KPTA.js.map} +0 -0
  463. /package/dist/{chunk-YXFCALVT.js.map → chunk-NSTNGMSS.js.map} +0 -0
  464. /package/dist/{chunk-L4X4PJYK.js.map → chunk-NUF7VSEX.js.map} +0 -0
  465. /package/dist/{chunk-IVIAHQBR.js.map → chunk-OJUEUQDJ.js.map} +0 -0
  466. /package/dist/{chunk-ZW4VXELZ.js.map → chunk-OMX6TKXH.js.map} +0 -0
  467. /package/dist/{chunk-EFQCDJZ2.js.map → chunk-QBNE55VA.js.map} +0 -0
  468. /package/dist/{chunk-6QDXA26G.js.map → chunk-RPIS5FQ7.js.map} +0 -0
  469. /package/dist/{chunk-HJXA6ZM7.js.map → chunk-S4CDUXQY.js.map} +0 -0
  470. /package/dist/{chunk-72OIT7KS.js.map → chunk-S4Z2OBTX.js.map} +0 -0
  471. /package/dist/{chunk-4FHRZD5T.js.map → chunk-SZMYGDSM.js.map} +0 -0
  472. /package/dist/{chunk-MAH64N55.js.map → chunk-TBCDF556.js.map} +0 -0
  473. /package/dist/{chunk-K66OY4EI.js.map → chunk-TCQRIIIN.js.map} +0 -0
  474. /package/dist/{chunk-KXIXO76C.js.map → chunk-U65VJSCJ.js.map} +0 -0
  475. /package/dist/{chunk-HNPE66LB.js.map → chunk-U6NGKS32.js.map} +0 -0
  476. /package/dist/{chunk-WKJFIMVN.js.map → chunk-UW4RYPWC.js.map} +0 -0
  477. /package/dist/{chunk-MN5NOOI7.js.map → chunk-VG4SSPAW.js.map} +0 -0
  478. /package/dist/{chunk-UNUMFURP.js.map → chunk-X5PIDJ3L.js.map} +0 -0
  479. /package/dist/{chunk-RZ3IZIJG.js.map → chunk-XOHYGIWF.js.map} +0 -0
  480. /package/dist/{chunk-6RUHELWR.js.map → chunk-YWPLOJ7T.js.map} +0 -0
  481. /package/dist/{chunk-ZJPM7GZ3.js.map → chunk-ZPS724LT.js.map} +0 -0
  482. /package/dist/{chunk-7UTDHQZ5.js.map → chunk-ZZZWEDF4.js.map} +0 -0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Isolated merge-on-write judge (issue #2330 first slice).
3
+ *
4
+ * Default off. Persist wiring comes later. Failures create.
5
+ */
6
+
7
+ export const DEFAULT_MERGE_MIN = 0.8;
8
+ export const DEFAULT_SKIP_THRESHOLD = 0.92;
9
+
10
+ export const REFUSED_MERGE_CATEGORIES = [
11
+ "procedure",
12
+ "reasoning_trace",
13
+ "moment",
14
+ "correction",
15
+ ] as const;
16
+
17
+ export type MergeOnWriteDecision = "merge" | "create";
18
+ export type MergeJudgeVerdict = MergeOnWriteDecision | "uncertain";
19
+
20
+ export interface MergeOnWritePair {
21
+ category: string;
22
+ score: number;
23
+ incomingContent?: string;
24
+ existingContent?: string;
25
+ existingId?: string;
26
+ }
27
+
28
+ export type MergeJudge = (
29
+ pair: MergeOnWritePair,
30
+ ) => Promise<MergeJudgeVerdict> | MergeJudgeVerdict;
31
+
32
+ export function shouldConsiderMerge(opts: {
33
+ score: number;
34
+ skipThreshold?: number;
35
+ mergeMin?: number;
36
+ }): boolean {
37
+ const mergeMin = opts.mergeMin ?? DEFAULT_MERGE_MIN;
38
+ const skipThreshold = opts.skipThreshold ?? DEFAULT_SKIP_THRESHOLD;
39
+ if (!(mergeMin > 0)) return false;
40
+ if (!Number.isFinite(opts.score) || !Number.isFinite(skipThreshold)) return false;
41
+ return mergeMin <= opts.score && opts.score < skipThreshold;
42
+ }
43
+
44
+ export async function judgeMergeDecision(
45
+ pair: MergeOnWritePair,
46
+ judge: MergeJudge,
47
+ ): Promise<MergeOnWriteDecision> {
48
+ try {
49
+ const verdict = await judge(pair);
50
+ return verdict === "merge" ? "merge" : "create";
51
+ } catch {
52
+ return "create";
53
+ }
54
+ }
55
+
56
+ export async function applyMergeOnWrite(opts: {
57
+ pair: MergeOnWritePair;
58
+ judge: MergeJudge;
59
+ enabled?: boolean;
60
+ mergeMin?: number;
61
+ skipThreshold?: number;
62
+ }): Promise<MergeOnWriteDecision> {
63
+ if (opts.enabled !== true) return "create";
64
+ if ((REFUSED_MERGE_CATEGORIES as readonly string[]).includes(opts.pair.category)) return "create";
65
+ if (
66
+ !shouldConsiderMerge({
67
+ score: opts.pair.score,
68
+ mergeMin: opts.mergeMin,
69
+ skipThreshold: opts.skipThreshold,
70
+ })
71
+ ) {
72
+ return "create";
73
+ }
74
+ return judgeMergeDecision(opts.pair, opts.judge);
75
+ }
@@ -0,0 +1,143 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import { parseConfig } from "../config.js";
5
+ import {
6
+ applyNoveltyGate,
7
+ DEFAULT_NOVELTY_ADD_THRESHOLD,
8
+ DEFAULT_NOVELTY_NOOP_THRESHOLD,
9
+ embeddingsFromCosineHits,
10
+ scoreNovelty,
11
+ type NoveltyNeighbor,
12
+ } from "./novelty-gate.js";
13
+
14
+ function neighborAtCosine(id: string, cosine: number): NoveltyNeighbor {
15
+ const s = Math.min(1, Math.max(-1, cosine));
16
+ return { id, embedding: [s, Math.sqrt(Math.max(0, 1 - s * s))] };
17
+ }
18
+
19
+ const CANDIDATE = [1, 0];
20
+
21
+ test("novelty gate: parseConfig defaults keep the gate off with a wide uncertain band", () => {
22
+ const config = parseConfig({});
23
+ assert.equal(config.noveltyGateEnabled, false);
24
+ assert.equal(config.noveltyAddThreshold, DEFAULT_NOVELTY_ADD_THRESHOLD);
25
+ assert.equal(config.noveltyNoopThreshold, DEFAULT_NOVELTY_NOOP_THRESHOLD);
26
+ assert.ok(config.noveltyAddThreshold - config.noveltyNoopThreshold > 0.3);
27
+ });
28
+
29
+ test("novelty gate: conservative preset stays off", () => {
30
+ const config = parseConfig({ memoryOsPreset: "conservative" });
31
+ assert.equal(config.noveltyGateEnabled, false);
32
+ });
33
+
34
+ test("novelty gate: gate off does not call lookup", async () => {
35
+ let called = 0;
36
+ const decision = await applyNoveltyGate({
37
+ enabled: false,
38
+ addThreshold: DEFAULT_NOVELTY_ADD_THRESHOLD,
39
+ noopThreshold: DEFAULT_NOVELTY_NOOP_THRESHOLD,
40
+ lookup: async () => {
41
+ called += 1;
42
+ throw new Error("lookup must not run when the gate is off");
43
+ },
44
+ });
45
+ assert.equal(called, 0);
46
+ assert.equal(decision.decision, "uncertain");
47
+ });
48
+
49
+ test("novelty gate: paraphrase routes noop", () => {
50
+ const decision = scoreNovelty(CANDIDATE, [neighborAtCosine("paraphrase", 0.98)]);
51
+ assert.equal(decision.decision, "noop");
52
+ assert.equal(decision.neighborId, "paraphrase");
53
+ assert.ok(decision.score <= DEFAULT_NOVELTY_NOOP_THRESHOLD);
54
+ });
55
+
56
+ test("novelty gate: unrelated routes add", () => {
57
+ const decision = scoreNovelty(CANDIDATE, [neighborAtCosine("other", 0.05)]);
58
+ assert.equal(decision.decision, "add");
59
+ assert.equal(decision.neighborId, "other");
60
+ assert.ok(decision.score >= DEFAULT_NOVELTY_ADD_THRESHOLD);
61
+ });
62
+
63
+ test("novelty gate: exactly at addThreshold is add", () => {
64
+ const neighbor = neighborAtCosine("edge-add", 1 - DEFAULT_NOVELTY_ADD_THRESHOLD);
65
+ const measured = scoreNovelty(CANDIDATE, [neighbor], { addThreshold: 1, noopThreshold: -1 });
66
+ const decision = scoreNovelty(CANDIDATE, [neighbor], {
67
+ addThreshold: measured.score,
68
+ noopThreshold: DEFAULT_NOVELTY_NOOP_THRESHOLD,
69
+ });
70
+ assert.equal(decision.decision, "add");
71
+ });
72
+
73
+ test("novelty gate: exactly at noopThreshold is noop", () => {
74
+ const neighbor = neighborAtCosine("edge-noop", 1 - DEFAULT_NOVELTY_NOOP_THRESHOLD);
75
+ const measured = scoreNovelty(CANDIDATE, [neighbor], { addThreshold: 1, noopThreshold: -1 });
76
+ const decision = scoreNovelty(CANDIDATE, [neighbor], {
77
+ addThreshold: DEFAULT_NOVELTY_ADD_THRESHOLD,
78
+ noopThreshold: measured.score,
79
+ });
80
+ assert.equal(decision.decision, "noop");
81
+ });
82
+
83
+ test("novelty gate: mid-band routes uncertain", () => {
84
+ const mid = (DEFAULT_NOVELTY_ADD_THRESHOLD + DEFAULT_NOVELTY_NOOP_THRESHOLD) / 2;
85
+ const decision = scoreNovelty(CANDIDATE, [neighborAtCosine("mid", 1 - mid)]);
86
+ assert.equal(decision.decision, "uncertain");
87
+ });
88
+
89
+ test("novelty gate: empty neighborhood is add", () => {
90
+ const decision = scoreNovelty(CANDIDATE, []);
91
+ assert.equal(decision.decision, "add");
92
+ assert.equal(decision.score, 1);
93
+ assert.equal(decision.neighborId, undefined);
94
+ });
95
+
96
+ test("novelty gate: thrown lookup is uncertain", async () => {
97
+ const decision = await applyNoveltyGate({
98
+ enabled: true,
99
+ addThreshold: DEFAULT_NOVELTY_ADD_THRESHOLD,
100
+ noopThreshold: DEFAULT_NOVELTY_NOOP_THRESHOLD,
101
+ lookup: async () => {
102
+ throw new Error("backend down");
103
+ },
104
+ });
105
+ assert.equal(decision.decision, "uncertain");
106
+ });
107
+
108
+ test("novelty gate: cross-connector neighbor cannot noop (PR #2564 review)", () => {
109
+ // Identical content already stored by connector A (cosine ~1) must not
110
+ // suppress connector B's candidate: neighborhood scoped to same-connector
111
+ // neighbors only (mirrors the PR #1852 semantic skip gate).
112
+ const identicalFromA = { id: "a-dup", score: 1, sourceConnector: "connector-a" };
113
+ const { neighborhood } = embeddingsFromCosineHits([identicalFromA], {
114
+ candidateConnector: "connector-b",
115
+ });
116
+ assert.deepEqual(neighborhood, []);
117
+ const decision = scoreNovelty(CANDIDATE, neighborhood);
118
+ assert.equal(decision.decision, "add");
119
+ });
120
+
121
+ test("novelty gate: unattributed neighbor is scoped out when candidate has a connector", () => {
122
+ const unattributed = { id: "anon-dup", score: 1 };
123
+ const { neighborhood } = embeddingsFromCosineHits([unattributed], {
124
+ candidateConnector: "connector-b",
125
+ });
126
+ assert.deepEqual(neighborhood, []);
127
+ });
128
+
129
+ test("novelty gate: same-connector paraphrase still noops", () => {
130
+ const sameConnector = { id: "b-dup", score: 0.98, sourceConnector: "connector-b" };
131
+ const { neighborhood } = embeddingsFromCosineHits([sameConnector], {
132
+ candidateConnector: "connector-b",
133
+ });
134
+ assert.equal(neighborhood.length, 1);
135
+ assert.equal(scoreNovelty(CANDIDATE, neighborhood).decision, "noop");
136
+ });
137
+
138
+ test("novelty gate: candidate without connector keeps unscoped neighborhood", () => {
139
+ const foreign = { id: "a-dup", score: 0.98, sourceConnector: "connector-a" };
140
+ const { neighborhood } = embeddingsFromCosineHits([foreign]);
141
+ assert.equal(neighborhood.length, 1);
142
+ assert.equal(scoreNovelty(CANDIDATE, neighborhood).decision, "noop");
143
+ });
@@ -0,0 +1,163 @@
1
+ import { coerceBooleanLike, coerceNumber } from "../connectors/coerce.js";
2
+
3
+ /**
4
+ * Embedding-density novelty gate (issue #1953, SAGE).
5
+ *
6
+ * score = 1 - mean(cosine of k nearest). Higher score = more novel.
7
+ * score >= noveltyAddThreshold → add (skip semantic/LLM dedup)
8
+ * score <= noveltyNoopThreshold → noop (drop; do not touch contentHashIndex)
9
+ * else → uncertain (fall through to semantic dedup)
10
+ *
11
+ * Defaults keep a wide UNCERTAIN band. noveltyGateEnabled defaults false.
12
+ * Backend failure is not handled here — callers treat a thrown lookup as uncertain.
13
+ */
14
+ export const DEFAULT_NOVELTY_ADD_THRESHOLD = 0.55;
15
+ export const DEFAULT_NOVELTY_NOOP_THRESHOLD = 0.15;
16
+ export const DEFAULT_NOVELTY_K = 5;
17
+
18
+ export interface NoveltyNeighbor {
19
+ id: string;
20
+ embedding: number[];
21
+ }
22
+
23
+ export interface NoveltyDecision {
24
+ score: number;
25
+ decision: "add" | "noop" | "uncertain";
26
+ neighborId?: string;
27
+ }
28
+
29
+ export interface NoveltyThresholds {
30
+ addThreshold?: number;
31
+ noopThreshold?: number;
32
+ k?: number;
33
+ }
34
+
35
+ export interface WritePathDedupConfig {
36
+ semanticDedupEnabled: boolean;
37
+ semanticDedupThreshold: number;
38
+ semanticDedupCandidates: number;
39
+ noveltyGateEnabled: boolean;
40
+ noveltyAddThreshold: number;
41
+ noveltyNoopThreshold: number;
42
+ }
43
+
44
+ function clamp01(value: number | undefined, fallback: number): number {
45
+ return value !== undefined && Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : fallback;
46
+ }
47
+
48
+ function cosine(a: number[], b: number[]): number {
49
+ if (a.length === 0 || a.length !== b.length) return 0;
50
+ let dot = 0;
51
+ let magA = 0;
52
+ let magB = 0;
53
+ for (let i = 0; i < a.length; i++) {
54
+ dot += a[i] * b[i];
55
+ magA += a[i] * a[i];
56
+ magB += b[i] * b[i];
57
+ }
58
+ const denom = Math.sqrt(magA) * Math.sqrt(magB);
59
+ if (denom === 0) return 0;
60
+ const raw = dot / denom;
61
+ if (!Number.isFinite(raw)) return 0;
62
+ if (raw < 0) return 0;
63
+ if (raw > 1) return 1;
64
+ return raw;
65
+ }
66
+
67
+ export function parseWritePathDedupConfig(cfg: Record<string, unknown>): WritePathDedupConfig {
68
+ const rawCandidates = coerceNumber(cfg.semanticDedupCandidates, "semanticDedupCandidates");
69
+ let semanticDedupCandidates = 5;
70
+ if (rawCandidates !== undefined && rawCandidates >= 0) {
71
+ const n = Math.floor(rawCandidates);
72
+ semanticDedupCandidates = rawCandidates > 0 && n === 0 ? 1 : n;
73
+ }
74
+ return {
75
+ semanticDedupEnabled: coerceBooleanLike(cfg.semanticDedupEnabled, "semanticDedupEnabled") !== false,
76
+ semanticDedupThreshold: clamp01(
77
+ coerceNumber(cfg.semanticDedupThreshold, "semanticDedupThreshold"),
78
+ 0.92,
79
+ ),
80
+ semanticDedupCandidates,
81
+ noveltyGateEnabled: coerceBooleanLike(cfg.noveltyGateEnabled, "noveltyGateEnabled") === true,
82
+ noveltyAddThreshold: clamp01(
83
+ coerceNumber(cfg.noveltyAddThreshold, "noveltyAddThreshold"),
84
+ DEFAULT_NOVELTY_ADD_THRESHOLD,
85
+ ),
86
+ noveltyNoopThreshold: clamp01(
87
+ coerceNumber(cfg.noveltyNoopThreshold, "noveltyNoopThreshold"),
88
+ DEFAULT_NOVELTY_NOOP_THRESHOLD,
89
+ ),
90
+ };
91
+ }
92
+
93
+ export function embeddingsFromCosineHits(
94
+ hits: ReadonlyArray<{ id: string; score: number; sourceConnector?: string }>,
95
+ opts: { candidateConnector?: string } = {},
96
+ ): { embedding: number[]; neighborhood: NoveltyNeighbor[] } {
97
+ // Connector-aware scoping (PR #2564 review finding on 54d865cb9): a
98
+ // neighbor from a different (or unattributed) connector must not drive a
99
+ // noop — same contract as the semantic skip gate (PR #1852). Candidates
100
+ // without a connector keep the unscoped neighborhood.
101
+ const candidateConnector = opts.candidateConnector?.trim() || undefined;
102
+ const scoped = candidateConnector
103
+ ? hits.filter((hit) => (hit.sourceConnector?.trim() || undefined) === candidateConnector)
104
+ : hits;
105
+ return {
106
+ embedding: [1, 0],
107
+ neighborhood: scoped.map((hit) => {
108
+ const s = Number.isFinite(hit.score) ? Math.min(1, Math.max(-1, hit.score)) : 0;
109
+ return { id: hit.id, embedding: [s, Math.sqrt(Math.max(0, 1 - s * s))] };
110
+ }),
111
+ };
112
+ }
113
+
114
+ export function scoreNovelty(
115
+ embedding: number[],
116
+ neighborhood: NoveltyNeighbor[],
117
+ thresholds: NoveltyThresholds = {},
118
+ ): NoveltyDecision {
119
+ const addThreshold = clamp01(thresholds.addThreshold ?? DEFAULT_NOVELTY_ADD_THRESHOLD, DEFAULT_NOVELTY_ADD_THRESHOLD);
120
+ const noopThreshold = clamp01(thresholds.noopThreshold ?? DEFAULT_NOVELTY_NOOP_THRESHOLD, DEFAULT_NOVELTY_NOOP_THRESHOLD);
121
+ const k = thresholds.k !== undefined && Number.isFinite(thresholds.k) && thresholds.k > 0
122
+ ? Math.floor(thresholds.k)
123
+ : DEFAULT_NOVELTY_K;
124
+
125
+ if (neighborhood.length === 0) {
126
+ return { score: 1, decision: "add" };
127
+ }
128
+
129
+ const ranked = neighborhood
130
+ .map((neighbor) => ({
131
+ id: neighbor.id,
132
+ cosine: cosine(embedding, neighbor.embedding),
133
+ }))
134
+ .sort((a, b) => b.cosine - a.cosine);
135
+ const nearest = ranked.slice(0, Math.max(1, k));
136
+ const density = nearest.reduce((sum, row) => sum + row.cosine, 0) / nearest.length;
137
+ const score = 1 - density;
138
+ const neighborId = ranked[0]?.id;
139
+
140
+ if (score >= addThreshold) return { score, decision: "add", neighborId };
141
+ if (score <= noopThreshold) return { score, decision: "noop", neighborId };
142
+ return { score, decision: "uncertain", neighborId };
143
+ }
144
+
145
+ export async function applyNoveltyGate(opts: {
146
+ enabled: boolean;
147
+ addThreshold: number;
148
+ noopThreshold: number;
149
+ lookup: () => Promise<{ embedding: number[]; neighborhood: NoveltyNeighbor[] }>;
150
+ }): Promise<NoveltyDecision> {
151
+ if (!opts.enabled) {
152
+ return { score: 0, decision: "uncertain" };
153
+ }
154
+ try {
155
+ const { embedding, neighborhood } = await opts.lookup();
156
+ return scoreNovelty(embedding, neighborhood, {
157
+ addThreshold: opts.addThreshold,
158
+ noopThreshold: opts.noopThreshold,
159
+ });
160
+ } catch {
161
+ return { score: 0, decision: "uncertain" };
162
+ }
163
+ }
@@ -17,6 +17,7 @@ test("isLocationDayPath matches only the top-level day-file shape", () => {
17
17
 
18
18
  test("isSearchExcludedPath keeps location day documents out of generic search and recall", () => {
19
19
  assert.equal(isSearchExcludedPath("locations/2026-08-17.md"), true);
20
+ assert.equal(isSearchExcludedPath("journal/2026-08-17.md"), true);
20
21
  assert.equal(
21
22
  isSearchExcludedPath("qmd://collection/locations/2026-08-17.md", {}, "qmd"),
22
23
  true,
@@ -83,6 +83,7 @@ import {
83
83
  } from "../fallback-llm.js";
84
84
  import { EmbeddingFallback } from "../embedding-fallback.js";
85
85
  import { decideSemanticDedup, type SemanticDedupDecision, type SemanticDedupHit } from "../dedup/semantic.js";
86
+ import { applyNoveltyGate, embeddingsFromCosineHits } from "../dedup/novelty-gate.js";
86
87
  import { selectRouteRule, type RouteRule, type RoutingEngineOptions } from "../routing/engine.js";
87
88
  import { ThreadingManager } from "../threading.js";
88
89
  import { NamespaceStorageRouter } from "../namespaces/storage.js";
@@ -1919,26 +1920,24 @@ export class ExtractionPersistCoordinator {
1919
1920
  : undefined;
1920
1921
  const faithfulnessEnforceStatus = faithfulnessGateStatus ?? requireSpansPendingStatus ?? injectionScreenStatus;
1921
1922
 
1922
- // Issue #373 write-time semantic similarity guard. Hook runs after
1923
- // the exact content-hash miss and the importance gate so that:
1924
- // (a) paraphrased near-duplicates never reach writeMemory(), and
1925
- // (b) low-importance facts that will be dropped never trigger an
1926
- // embedding lookup (avoids unnecessary API latency/cost).
1927
- // Fails open when the embedding backend is unavailable.
1928
- //
1929
- // Defense in depth (PR #399 review): decideSemanticDedup already
1930
- // catches lookup errors internally, and the embedding fetch is
1931
- // bounded by a timeout in embedding-fallback.ts. We still wrap the
1932
- // whole call in its own try/catch here so that any unexpected
1933
- // rejection (future refactors, misbehaving custom backends, etc.)
1934
- // can never block the persist loop — a failure in the dedup path
1935
- // must always default to "not a duplicate".
1936
- // Track a pending semantic-skip decision (populated inside the block
1937
- // below). The actual drop happens AFTER contradiction detection so that
1938
- // a high-similarity update/correction is linked as a superseding
1939
- // contradiction rather than silently dropped.
1923
+ const novelty = await applyNoveltyGate({
1924
+ enabled: this.deps.config["noveltyGateEnabled"] === true,
1925
+ addThreshold: this.deps.config.noveltyAddThreshold,
1926
+ noopThreshold: this.deps.config.noveltyNoopThreshold,
1927
+ lookup: async () =>
1928
+ embeddingsFromCosineHits(
1929
+ await this.deps.semanticDedupLookup(
1930
+ fact.content,
1931
+ this.deps.config.semanticDedupCandidates,
1932
+ targetStorage,
1933
+ ),
1934
+ // Same connector scoping as decideSemanticDedup below: a
1935
+ // cross-connector neighbor must not noop this candidate.
1936
+ { candidateConnector: sourceContext?.sourceConnector },
1937
+ ),
1938
+ });
1940
1939
  let pendingSemanticSkip: (SemanticDedupDecision & { action: "skip" }) | null = null;
1941
- if (resolvePipelineProcessingCapabilities(this.deps.config).semanticDedup && injectionScreenStatus !== "pending_review") {
1940
+ if (novelty.decision !== "add" && resolvePipelineProcessingCapabilities(this.deps.config).semanticDedup && injectionScreenStatus !== "pending_review") {
1942
1941
  let semanticDecision: SemanticDedupDecision;
1943
1942
  // UUI2: skip embedding lookup for the rest of this batch once we know
1944
1943
  // the backend is unavailable. The flag is reset per-batch (set to false
@@ -2100,17 +2099,17 @@ export class ExtractionPersistCoordinator {
2100
2099
  // gate's contract is "persists with status: pending_review, never
2101
2100
  // silently dropped" (issue #1576).
2102
2101
  if (
2103
- pendingSemanticSkip &&
2102
+ (pendingSemanticSkip || novelty.decision === "noop") &&
2104
2103
  !contradictionDetected &&
2105
2104
  !isCorrection &&
2106
2105
  faithfulnessEnforceStatus !== "pending_review"
2107
2106
  ) {
2108
2107
  log.debug(
2109
- `dedup: skipping semantic near-duplicate fact "${fact.content
2108
+ `dedup: skipping ${pendingSemanticSkip ? "semantic near-duplicate" : "novelty-noop"} fact "${fact.content
2110
2109
  .slice(0, 60)
2111
- .replace(/\s+/g, " ")}…" score=${pendingSemanticSkip.topScore.toFixed(
2110
+ .replace(/\s+/g, " ")}…" score=${(pendingSemanticSkip?.topScore ?? novelty.score).toFixed(
2112
2111
  3,
2113
- )} neighbor=${pendingSemanticSkip.topId}`,
2112
+ )} neighbor=${pendingSemanticSkip?.topId ?? novelty.neighborId}`,
2114
2113
  );
2115
2114
  dedupedCount++;
2116
2115
  // Do NOT add fact.content to contentHashIndex here. No memory was
@@ -9,6 +9,7 @@ import {
9
9
  isLocationDayPath,
10
10
  isMeetingRecordPath,
11
11
  } from "./orchestrator-helpers.js";
12
+ import { isJournalDayPath } from "../activity/journal.js";
12
13
  import { OKF_RESERVED_BASENAMES } from "../okf/type-mapping.js";
13
14
 
14
15
 
@@ -137,6 +138,7 @@ export function isSearchExcludedPath(
137
138
  isArtifactMemoryPath(candidate) ||
138
139
  isNamespacedActivityDigestPath(candidate, policy.memoryDir) ||
139
140
  isNamespacedLocationDayPath(candidate, policy.memoryDir) ||
141
+ isNamespacedJournalDayPath(candidate, policy.memoryDir) ||
140
142
  isMeetingRecordPath(candidate)
141
143
  ) {
142
144
  return true;
@@ -179,6 +181,15 @@ function isNamespacedLocationDayPath(candidate: string, memoryDir?: string): boo
179
181
  return isLocationDayPath(namespaced[2] ?? "", memoryDir);
180
182
  }
181
183
 
184
+ function isNamespacedJournalDayPath(candidate: string, memoryDir?: string): boolean {
185
+ if (isJournalDayPath(candidate, memoryDir)) return true;
186
+ if (memoryDir === undefined || memoryDir.length === 0) return false;
187
+ const relative = path.relative(memoryDir, path.resolve(memoryDir, candidate));
188
+ const namespaced = /^namespaces[\\/]([^\\/]+)[\\/](.*)$/.exec(relative);
189
+ if (namespaced === null) return false;
190
+ return isJournalDayPath(namespaced[2] ?? "", memoryDir);
191
+ }
192
+
182
193
  /** A path as given, plus its form with a leading COLLECTION segment removed. */
183
194
  function collectionSpellings(
184
195
  filePath: string,
@@ -20,6 +20,7 @@ import { ProfilingCollector } from "../profiling.js";
20
20
  import { trustResultFor, type TrustStageResultItem } from "../trust-score-stage.js";
21
21
  import type { RecallResultFormatter } from "./recall-result-formatter.js";
22
22
  import type { IdentityInjectionMode, PluginConfig, QmdSearchResult } from "../types.js";
23
+ import { applyRecallStateViews } from "../recall-state-view-wire.js";
23
24
 
24
25
  export interface RecallEntryDeps {
25
26
  appendRecallSection(
@@ -274,9 +275,13 @@ export class RecallEntryCoordinator {
274
275
  }): void {
275
276
  const sectionId = "memories";
276
277
  const trustByPath = options.trustByPath ?? null;
277
- const injectable = trustByPath
278
- ? options.results.filter((r) => !trustResultFor(trustByPath, r)?.quarantined)
279
- : options.results;
278
+ const injectable = applyRecallStateViews(
279
+ trustByPath
280
+ ? options.results.filter((r) => !trustResultFor(trustByPath, r)?.quarantined)
281
+ : options.results,
282
+ options.retrievalQuery,
283
+ this.deps.config,
284
+ );
280
285
  if (injectable.length === 0) return;
281
286
 
282
287
  const formatted = this.deps.recallResultFormatter.formatQmdResultEntries(
@@ -0,0 +1,72 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import {
5
+ runDeepRecall,
6
+ runDeepRecallStep,
7
+ type DeepRecallState,
8
+ } from "./recall-deep.js";
9
+
10
+ function seed(extra: Partial<DeepRecallState> = {}): DeepRecallState {
11
+ return {
12
+ query: "who met at the cafe",
13
+ workingSet: ["m-seed"],
14
+ frontier: ["m-b", "m-c"],
15
+ budget: 2,
16
+ ...extra,
17
+ };
18
+ }
19
+
20
+ test("budget 0 stops without calling the policy", () => {
21
+ const result = runDeepRecall(seed({ budget: 0 }), () => {
22
+ throw new Error("policy must not run when budget is 0");
23
+ });
24
+ assert.equal(result.trace.length, 1);
25
+ assert.equal(result.trace[0]?.action, "stop");
26
+ assert.equal(result.state.budget, 0);
27
+ assert.deepEqual(result.state.workingSet, ["m-seed"]);
28
+ assert.deepEqual(result.state.frontier, ["m-b", "m-c"]);
29
+ });
30
+
31
+ test("expand consumes budget and pulls the next frontier item", () => {
32
+ const result = runDeepRecallStep(seed({ budget: 2 }), "expand");
33
+ assert.equal(result.step.action, "expand");
34
+ assert.equal(result.state.budget, 1);
35
+ assert.deepEqual(result.state.workingSet, ["m-seed", "m-b"]);
36
+ assert.deepEqual(result.state.frontier, ["m-c"]);
37
+ });
38
+
39
+ test("stop ends while budget remains", () => {
40
+ let calls = 0;
41
+ const result = runDeepRecall(seed({ budget: 4 }), () => {
42
+ calls += 1;
43
+ return "stop";
44
+ });
45
+ assert.equal(calls, 1);
46
+ assert.equal(result.trace.length, 1);
47
+ assert.equal(result.trace[0]?.action, "stop");
48
+ assert.equal(result.state.budget, 4);
49
+ assert.deepEqual(result.state.workingSet, ["m-seed"]);
50
+ });
51
+
52
+ test("unknown action throws", () => {
53
+ assert.throws(() => runDeepRecallStep(seed(), "rewrite"), /unknown deep recall action/);
54
+ assert.throws(
55
+ () => runDeepRecall(seed(), () => "rewrite"),
56
+ /unknown deep recall action/,
57
+ );
58
+ });
59
+
60
+ test("same state and policy produce the same trace", () => {
61
+ const policy = (state: DeepRecallState) => (state.budget > 1 ? "expand" : "refine");
62
+ const start = seed({ budget: 3, frontier: ["m-z", "m-a"] });
63
+ const first = runDeepRecall(start, policy);
64
+ const second = runDeepRecall(start, policy);
65
+ assert.deepEqual(first, second);
66
+ assert.deepEqual(
67
+ first.trace.map((step) => step.action),
68
+ ["expand", "expand", "refine", "stop"],
69
+ );
70
+ assert.equal(start.budget, 3);
71
+ assert.deepEqual(start.frontier, ["m-z", "m-a"]);
72
+ });