@remnic/core 9.4.2 → 9.6.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 (379) hide show
  1. package/dist/access-admin-ops-surface.d.ts +6 -6
  2. package/dist/access-admin-ops-surface.js +28 -28
  3. package/dist/access-boundary.d.ts +27 -8
  4. package/dist/access-boundary.js +33 -29
  5. package/dist/access-cli.js +83 -81
  6. package/dist/access-cli.js.map +1 -1
  7. package/dist/access-http.d.ts +52 -6
  8. package/dist/access-http.js +40 -38
  9. package/dist/access-identity-continuity-surface.d.ts +5 -5
  10. package/dist/access-identity-continuity-surface.js +28 -28
  11. package/dist/access-lcm-surface.d.ts +6 -6
  12. package/dist/access-lcm-surface.js +28 -28
  13. package/dist/access-mcp.d.ts +16 -6
  14. package/dist/access-mcp.js +37 -35
  15. package/dist/access-observe-write-surface.d.ts +6 -6
  16. package/dist/access-observe-write-surface.js +28 -28
  17. package/dist/access-operations-batch.js +33 -32
  18. package/dist/access-operations.d.ts +9 -9
  19. package/dist/access-operations.js +35 -34
  20. package/dist/access-recall-surface.d.ts +6 -6
  21. package/dist/access-recall-surface.js +28 -28
  22. package/dist/access-schema.d.ts +4 -4
  23. package/dist/access-schema.js +4 -4
  24. package/dist/{access-service-m-2VO_Ig.d.ts → access-service-CXJaql3A.d.ts} +4 -4
  25. package/dist/access-service.d.ts +6 -6
  26. package/dist/access-service.js +28 -28
  27. package/dist/access-surface-catalog.d.ts +6 -6
  28. package/dist/access-surface-catalog.js +1 -0
  29. package/dist/access-surface-catalog.js.map +1 -1
  30. package/dist/access-token-capabilities.d.ts +174 -0
  31. package/dist/access-token-capabilities.js +33 -0
  32. package/dist/action-confidence.d.ts +1 -1
  33. package/dist/active-memory-bridge.d.ts +1 -1
  34. package/dist/active-recall.d.ts +1 -1
  35. package/dist/active-recall.js +2 -2
  36. package/dist/adapters/index.js +4 -4
  37. package/dist/adapters/registry.js +2 -2
  38. package/dist/{auto-sync-HMHQHUAG.js → auto-sync-4A5YBWYO.js} +4 -4
  39. package/dist/behavior-learner.d.ts +1 -1
  40. package/dist/behavior-signals.d.ts +1 -1
  41. package/dist/bootstrap.d.ts +5 -5
  42. package/dist/briefing.d.ts +2 -2
  43. package/dist/briefing.js +9 -9
  44. package/dist/buffer-surprise-report.d.ts +1 -1
  45. package/dist/buffer.d.ts +2 -2
  46. package/dist/calibration.d.ts +1 -1
  47. package/dist/capabilities.d.ts +1 -1
  48. package/dist/{capsule-crypto-CZJSLEFG.js → capsule-crypto-RAARDY3M.js} +2 -2
  49. package/dist/capsule-crypto-RAARDY3M.js.map +1 -0
  50. package/dist/{catalog-BxWokdC2.d.ts → catalog-C9cu67Ig.d.ts} +1 -1
  51. package/dist/causal-behavior.d.ts +1 -1
  52. package/dist/causal-behavior.js +5 -5
  53. package/dist/causal-chain.js +3 -3
  54. package/dist/causal-consolidation.d.ts +1 -1
  55. package/dist/causal-consolidation.js +13 -13
  56. package/dist/causal-retrieval.js +3 -3
  57. package/dist/causal-trajectory-graph.d.ts +1 -1
  58. package/dist/causal-trajectory.js +1 -1
  59. package/dist/{chunk-6ZIETXZ2.js → chunk-23JFRB73.js} +2 -2
  60. package/dist/{chunk-IC6QX5TC.js → chunk-3XIY7MDQ.js} +6 -6
  61. package/dist/{chunk-FZGGZAAU.js → chunk-4GNEDXDI.js} +146 -2
  62. package/dist/chunk-4GNEDXDI.js.map +1 -0
  63. package/dist/{chunk-LOR6ZM5R.js → chunk-4LV23CHK.js} +2 -2
  64. package/dist/{chunk-E2SPGGUI.js → chunk-4OKLXWDZ.js} +13 -6
  65. package/dist/chunk-4OKLXWDZ.js.map +1 -0
  66. package/dist/{chunk-AER6MT24.js → chunk-6SXVCD7W.js} +2 -2
  67. package/dist/{chunk-OHDJ34CC.js → chunk-72WG5QKN.js} +2 -2
  68. package/dist/{chunk-CZAZX7JP.js → chunk-7MW3CVLD.js} +4 -4
  69. package/dist/{chunk-CXLNZXG5.js → chunk-7XGSIUP5.js} +1 -1
  70. package/dist/{chunk-CZAA5N5S.js → chunk-AYZJID4S.js} +2 -2
  71. package/dist/{chunk-M7XQSUBB.js → chunk-B3ABVQ36.js} +116 -9
  72. package/dist/chunk-B3ABVQ36.js.map +1 -0
  73. package/dist/{chunk-6BISDEN6.js → chunk-BEM4D2QG.js} +14 -14
  74. package/dist/{chunk-ZPOROUTX.js → chunk-CYWA2CXR.js} +5 -5
  75. package/dist/{chunk-M5QKGHCR.js → chunk-CYWCKFCL.js} +5 -5
  76. package/dist/chunk-D7FOKIY5.js +173 -0
  77. package/dist/chunk-D7FOKIY5.js.map +1 -0
  78. package/dist/{chunk-4BFRBP45.js → chunk-DEG5ULFJ.js} +2 -2
  79. package/dist/{chunk-JLR3JSTL.js → chunk-DS7MM2ES.js} +3 -3
  80. package/dist/{chunk-2BFLDH5F.js → chunk-EEIROWEG.js} +2 -2
  81. package/dist/{chunk-5QZDMSSN.js → chunk-FKCRGLRD.js} +237 -82
  82. package/dist/{chunk-5QZDMSSN.js.map → chunk-FKCRGLRD.js.map} +1 -1
  83. package/dist/{chunk-X4A62ET7.js → chunk-H2DXDQCQ.js} +17 -17
  84. package/dist/{chunk-27FLVMDC.js → chunk-HLN7RROI.js} +7 -7
  85. package/dist/chunk-IC2TCZJ2.js +54 -0
  86. package/dist/chunk-IC2TCZJ2.js.map +1 -0
  87. package/dist/{chunk-2U2A5HF4.js → chunk-J3XHPFEU.js} +6 -6
  88. package/dist/{chunk-AKUCU7CI.js → chunk-JI5AVXYO.js} +5 -5
  89. package/dist/{chunk-KCJ5H6XQ.js → chunk-JSNVWNGX.js} +2 -2
  90. package/dist/{chunk-7Z2DZNWN.js → chunk-KL4UAXUY.js} +43 -2
  91. package/dist/{chunk-7Z2DZNWN.js.map → chunk-KL4UAXUY.js.map} +1 -1
  92. package/dist/{chunk-FLVL4L3L.js → chunk-KTULX4YO.js} +4 -4
  93. package/dist/{chunk-ILFJ7AVS.js → chunk-LADFWYHY.js} +35 -21
  94. package/dist/chunk-LADFWYHY.js.map +1 -0
  95. package/dist/{chunk-437S3G37.js → chunk-LNQUAJNC.js} +1 -1
  96. package/dist/{chunk-EPGWWCZF.js → chunk-LR5DZ56F.js} +6 -6
  97. package/dist/{chunk-YDSWRD33.js → chunk-N3JDIRBW.js} +4 -4
  98. package/dist/{chunk-OUMTBFSQ.js → chunk-NKCPUHCI.js} +5 -5
  99. package/dist/{chunk-7QWMTOIF.js → chunk-P454KXD6.js} +112 -34
  100. package/dist/chunk-P454KXD6.js.map +1 -0
  101. package/dist/{chunk-DR6PEJU3.js → chunk-PCLIWBGD.js} +44 -59
  102. package/dist/chunk-PCLIWBGD.js.map +1 -0
  103. package/dist/{chunk-BGTAL46Y.js → chunk-PNLFN2PZ.js} +2 -2
  104. package/dist/{chunk-P6SYWE4G.js → chunk-PVUJ6WVV.js} +10 -10
  105. package/dist/{chunk-YPEMNNNY.js → chunk-RGK27ELN.js} +6 -6
  106. package/dist/{chunk-2QSZNTDO.js → chunk-RKNJBZ55.js} +4 -4
  107. package/dist/{chunk-66FLU5BT.js → chunk-SIRPLF54.js} +6 -6
  108. package/dist/{chunk-M7GGMGMZ.js → chunk-SVOHGUMI.js} +1202 -126
  109. package/dist/chunk-SVOHGUMI.js.map +1 -0
  110. package/dist/{chunk-HRCACVHL.js → chunk-TLUDFPZL.js} +2 -2
  111. package/dist/{chunk-2FOD2YY3.js → chunk-UFUKHGZD.js} +236 -103
  112. package/dist/chunk-UFUKHGZD.js.map +1 -0
  113. package/dist/{chunk-2MR3MFQB.js → chunk-UPSAT4PY.js} +2 -2
  114. package/dist/{chunk-4P4626RY.js → chunk-UTRJFDP2.js} +4 -4
  115. package/dist/{chunk-CGS7UKWM.js → chunk-VCW74PNH.js} +2 -2
  116. package/dist/{chunk-5GPPACXK.js → chunk-VSMRDBFT.js} +2 -1
  117. package/dist/{chunk-NG7YBCJO.js → chunk-XCL57M6Q.js} +4 -4
  118. package/dist/{chunk-CLX5VDNY.js → chunk-Y4RKAQZ7.js} +4 -4
  119. package/dist/{chunk-DGYCWCQ7.js → chunk-Y7UNNAZD.js} +2 -2
  120. package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
  121. package/dist/{chunk-XN3TUUX2.js → chunk-YQB32INI.js} +2 -2
  122. package/dist/{cli-EiBBOt3r.d.ts → cli-CqdPA6z9.d.ts} +3 -3
  123. package/dist/cli.d.ts +7 -7
  124. package/dist/cli.js +61 -59
  125. package/dist/compounding/engine.d.ts +2 -2
  126. package/dist/compounding/engine.js +9 -9
  127. package/dist/compounding/preference-consolidator.d.ts +1 -1
  128. package/dist/compression-optimizer.d.ts +1 -1
  129. package/dist/config.d.ts +1 -1
  130. package/dist/config.js +2 -2
  131. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  132. package/dist/connectors/codex-materialize-runner.js +9 -9
  133. package/dist/connectors/codex-materialize.d.ts +1 -1
  134. package/dist/connectors/index.d.ts +1 -1
  135. package/dist/connectors/index.js +13 -11
  136. package/dist/consolidation-provenance-check.d.ts +2 -2
  137. package/dist/consolidation-undo.d.ts +2 -2
  138. package/dist/contradiction/index.d.ts +2 -2
  139. package/dist/contradiction/index.js +4 -4
  140. package/dist/conversation-index/backend.d.ts +1 -1
  141. package/dist/conversation-index/backend.js +2 -2
  142. package/dist/conversation-index/chunker.d.ts +1 -1
  143. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  144. package/dist/conversation-index/indexer.d.ts +1 -1
  145. package/dist/conversation-index/search.d.ts +1 -1
  146. package/dist/dashboard-runtime.js +2 -2
  147. package/dist/day-summary.d.ts +1 -1
  148. package/dist/delinearize.d.ts +1 -1
  149. package/dist/direct-answer-wiring.d.ts +1 -1
  150. package/dist/direct-answer.d.ts +1 -1
  151. package/dist/embedding-fallback.d.ts +1 -1
  152. package/dist/enrichment/index.d.ts +1 -1
  153. package/dist/entity-retrieval.d.ts +2 -2
  154. package/dist/entity-retrieval.js +9 -9
  155. package/dist/entity-schema.d.ts +1 -1
  156. package/dist/explicit-capture.d.ts +5 -5
  157. package/dist/extraction-faithfulness.d.ts +1 -1
  158. package/dist/extraction-judge-telemetry.d.ts +1 -1
  159. package/dist/extraction-judge-training.d.ts +1 -1
  160. package/dist/extraction-judge.d.ts +1 -1
  161. package/dist/extraction.d.ts +1 -1
  162. package/dist/fallback-llm.d.ts +1 -1
  163. package/dist/{first-start-migration-DY6YCRC2.js → first-start-migration-VBJQL6OI.js} +5 -5
  164. package/dist/graph-dashboard-diff.d.ts +1 -1
  165. package/dist/graph-dashboard-key.d.ts +1 -1
  166. package/dist/graph-dashboard-parser.d.ts +1 -1
  167. package/dist/graph-edge-reinforcement.d.ts +1 -1
  168. package/dist/graph-snapshot.d.ts +1 -1
  169. package/dist/graph.d.ts +1 -1
  170. package/dist/identity-continuity.d.ts +1 -1
  171. package/dist/importance.d.ts +1 -1
  172. package/dist/index.d.ts +271 -17
  173. package/dist/index.js +163 -99
  174. package/dist/intent.d.ts +1 -1
  175. package/dist/lcm/engine.d.ts +1 -1
  176. package/dist/lcm/engine.js +2 -2
  177. package/dist/lcm/index.d.ts +1 -1
  178. package/dist/lcm/index.js +2 -2
  179. package/dist/lcm/tools.d.ts +1 -1
  180. package/dist/lifecycle.d.ts +1 -1
  181. package/dist/live-connectors-runner.d.ts +1 -1
  182. package/dist/local-llm.d.ts +1 -1
  183. package/dist/local-model-endpoint.d.ts +1 -1
  184. package/dist/maintenance/memory-governance.d.ts +1 -1
  185. package/dist/maintenance/memory-governance.js +10 -10
  186. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +9 -9
  187. package/dist/maintenance/rebuild-memory-projection.js +11 -11
  188. package/dist/mcp-memory-inspector-app.d.ts +6 -6
  189. package/dist/mcp-read-only-tools.d.ts +16 -0
  190. package/dist/mcp-read-only-tools.js +8 -0
  191. package/dist/mcp-read-only-tools.js.map +1 -0
  192. package/dist/memory-action-policy.d.ts +1 -1
  193. package/dist/memory-cache.d.ts +1 -1
  194. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  195. package/dist/memory-projection-store.d.ts +1 -1
  196. package/dist/memory-provenance.d.ts +1 -1
  197. package/dist/memory-worth-outcomes.d.ts +2 -2
  198. package/dist/models-json.d.ts +1 -1
  199. package/dist/namespaces/migrate.d.ts +3 -3
  200. package/dist/namespaces/migrate.js +19 -19
  201. package/dist/namespaces/principal.d.ts +1 -1
  202. package/dist/namespaces/search.d.ts +1 -1
  203. package/dist/namespaces/search.js +10 -10
  204. package/dist/namespaces/storage.d.ts +3 -3
  205. package/dist/namespaces/storage.js +9 -9
  206. package/dist/native-knowledge.d.ts +1 -1
  207. package/dist/operator-toolkit.d.ts +2 -2
  208. package/dist/operator-toolkit.js +25 -25
  209. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  210. package/dist/orchestration/maintenance.d.ts +2 -2
  211. package/dist/orchestration/maintenance.js +11 -11
  212. package/dist/{orchestrator-B2Y28Z9t.d.ts → orchestrator-CWFrT8AF.d.ts} +91 -60
  213. package/dist/orchestrator.d.ts +5 -5
  214. package/dist/orchestrator.js +85 -83
  215. package/dist/patterns-cli.d.ts +1 -1
  216. package/dist/policy-runtime.d.ts +1 -1
  217. package/dist/provenance.d.ts +1 -1
  218. package/dist/{qmd-Db9mOkzB.d.ts → qmd--fnPMK60.d.ts} +1 -1
  219. package/dist/qmd-preflight.d.ts +2 -2
  220. package/dist/qmd-recall-cache.d.ts +1 -1
  221. package/dist/qmd.d.ts +2 -2
  222. package/dist/recall-disclosure-escalation.d.ts +1 -1
  223. package/dist/recall-explain-renderer.d.ts +1 -1
  224. package/dist/recall-planner-llm.d.ts +1 -1
  225. package/dist/recall-state.d.ts +1 -1
  226. package/dist/recall-tag-filter.d.ts +1 -1
  227. package/dist/recall-timings.d.ts +1 -1
  228. package/dist/recall-xray-cli.d.ts +1 -1
  229. package/dist/recall-xray-renderer.d.ts +1 -1
  230. package/dist/recall-xray.d.ts +1 -1
  231. package/dist/resolve-auth-token.d.ts +1 -1
  232. package/dist/resume-bundles.js +4 -4
  233. package/dist/retrieval-agents.d.ts +2 -2
  234. package/dist/retrieval-tiers.d.ts +1 -1
  235. package/dist/routing/engine.d.ts +1 -1
  236. package/dist/routing/store.d.ts +1 -1
  237. package/dist/schemas.d.ts +22 -22
  238. package/dist/search/document-scanner.js +2 -2
  239. package/dist/search/embed-helper.d.ts +1 -1
  240. package/dist/search/factory.d.ts +1 -1
  241. package/dist/search/factory.js +9 -9
  242. package/dist/search/index.d.ts +1 -1
  243. package/dist/search/index.js +13 -13
  244. package/dist/search/lancedb-backend.d.ts +1 -1
  245. package/dist/search/lancedb-backend.js +3 -3
  246. package/dist/search/meilisearch-backend.d.ts +1 -1
  247. package/dist/search/meilisearch-backend.js +3 -3
  248. package/dist/search/noop-backend.d.ts +1 -1
  249. package/dist/search/orama-backend.d.ts +1 -1
  250. package/dist/search/orama-backend.js +3 -3
  251. package/dist/search/port.d.ts +1 -1
  252. package/dist/search/remote-backend.d.ts +1 -1
  253. package/dist/{semantic-consolidation-BDVIbLRw.d.ts → semantic-consolidation-O5lMZ4LG.d.ts} +1 -1
  254. package/dist/semantic-consolidation.d.ts +2 -2
  255. package/dist/semantic-consolidation.js +11 -11
  256. package/dist/semantic-rule-promotion.js +9 -9
  257. package/dist/semantic-rule-verifier.d.ts +1 -1
  258. package/dist/semantic-rule-verifier.js +10 -10
  259. package/dist/session-observer-bands.d.ts +1 -1
  260. package/dist/session-observer-state.d.ts +1 -1
  261. package/dist/shared-context/manager.d.ts +1 -1
  262. package/dist/signal.d.ts +1 -1
  263. package/dist/storage-C1maCNbc.d.ts +1591 -0
  264. package/dist/storage.d.ts +5 -1239
  265. package/dist/storage.js +8 -8
  266. package/dist/summarizer.d.ts +1 -1
  267. package/dist/summary-snapshot.d.ts +1 -1
  268. package/dist/temporal-supersession.d.ts +2 -2
  269. package/dist/temporal-validity.d.ts +1 -1
  270. package/dist/threading.d.ts +1 -1
  271. package/dist/tier-migration.d.ts +2 -2
  272. package/dist/tier-routing.d.ts +1 -1
  273. package/dist/{tier-stats-TG6GUZ6N.js → tier-stats-5XF4UBRQ.js} +4 -4
  274. package/dist/tokens.d.ts +17 -2
  275. package/dist/tokens.js +3 -1
  276. package/dist/topics.d.ts +1 -1
  277. package/dist/transcript.d.ts +1 -1
  278. package/dist/transfer/backup.js +2 -2
  279. package/dist/transfer/capsule-export.js +3 -3
  280. package/dist/transfer/capsule-import.js +3 -3
  281. package/dist/transfer/types.d.ts +12 -12
  282. package/dist/trust-score-stage.d.ts +1 -1
  283. package/dist/trust-score.d.ts +1 -1
  284. package/dist/{types-ljkd82rn.d.ts → types-CGgcNWCG.d.ts} +31 -1
  285. package/dist/types.d.ts +1 -1
  286. package/dist/utility-runtime.d.ts +1 -1
  287. package/dist/verified-recall.js +10 -10
  288. package/package.json +2 -2
  289. package/src/access-boundary.test.ts +62 -0
  290. package/src/access-boundary.ts +165 -126
  291. package/src/access-http.test.ts +781 -0
  292. package/src/access-http.ts +334 -108
  293. package/src/access-mcp.test.ts +264 -0
  294. package/src/access-mcp.ts +45 -70
  295. package/src/access-operations-batch.ts +35 -12
  296. package/src/access-surface-catalog.test.ts +22 -14
  297. package/src/access-surface-catalog.ts +6 -3
  298. package/src/access-token-capabilities.test.ts +844 -0
  299. package/src/access-token-capabilities.ts +391 -0
  300. package/src/chat/chat-mcp.test.ts +232 -0
  301. package/src/chat/chat-session.ts +34 -0
  302. package/src/cli-wearables-fuse.test.ts +197 -0
  303. package/src/cli.ts +25 -0
  304. package/src/index.ts +14 -0
  305. package/src/mcp-read-only-tools.ts +61 -0
  306. package/src/storage.ts +16 -0
  307. package/src/tokens.ts +32 -3
  308. package/src/wearables/cli.test.ts +102 -0
  309. package/src/wearables/cli.ts +65 -0
  310. package/src/wearables/config.test.ts +32 -0
  311. package/src/wearables/config.ts +52 -0
  312. package/src/wearables/day-store.test.ts +246 -0
  313. package/src/wearables/day-store.ts +272 -3
  314. package/src/wearables/fusion/cluster.ts +230 -0
  315. package/src/wearables/fusion/fuse.ts +218 -0
  316. package/src/wearables/fusion/fusion.test.ts +2575 -0
  317. package/src/wearables/fusion/index.ts +50 -0
  318. package/src/wearables/fusion/reconcile.ts +831 -0
  319. package/src/wearables/fusion/reconstruct.ts +251 -0
  320. package/src/wearables/fusion/store.ts +480 -0
  321. package/src/wearables/fusion/types.ts +228 -0
  322. package/src/wearables/index.ts +41 -0
  323. package/src/wearables/service.test.ts +1030 -2
  324. package/src/wearables/service.ts +258 -16
  325. package/src/wearables/speakers.test.ts +128 -0
  326. package/src/wearables/speakers.ts +58 -4
  327. package/src/wearables/storage-io.test.ts +146 -0
  328. package/src/wearables/types.ts +31 -0
  329. package/dist/chunk-2FOD2YY3.js.map +0 -1
  330. package/dist/chunk-7QWMTOIF.js.map +0 -1
  331. package/dist/chunk-DR6PEJU3.js.map +0 -1
  332. package/dist/chunk-E2SPGGUI.js.map +0 -1
  333. package/dist/chunk-FZGGZAAU.js.map +0 -1
  334. package/dist/chunk-ILFJ7AVS.js.map +0 -1
  335. package/dist/chunk-M7GGMGMZ.js.map +0 -1
  336. package/dist/chunk-M7XQSUBB.js.map +0 -1
  337. /package/dist/{capsule-crypto-CZJSLEFG.js.map → access-token-capabilities.js.map} +0 -0
  338. /package/dist/{auto-sync-HMHQHUAG.js.map → auto-sync-4A5YBWYO.js.map} +0 -0
  339. /package/dist/{chunk-6ZIETXZ2.js.map → chunk-23JFRB73.js.map} +0 -0
  340. /package/dist/{chunk-IC6QX5TC.js.map → chunk-3XIY7MDQ.js.map} +0 -0
  341. /package/dist/{chunk-LOR6ZM5R.js.map → chunk-4LV23CHK.js.map} +0 -0
  342. /package/dist/{chunk-AER6MT24.js.map → chunk-6SXVCD7W.js.map} +0 -0
  343. /package/dist/{chunk-OHDJ34CC.js.map → chunk-72WG5QKN.js.map} +0 -0
  344. /package/dist/{chunk-CZAZX7JP.js.map → chunk-7MW3CVLD.js.map} +0 -0
  345. /package/dist/{chunk-CXLNZXG5.js.map → chunk-7XGSIUP5.js.map} +0 -0
  346. /package/dist/{chunk-CZAA5N5S.js.map → chunk-AYZJID4S.js.map} +0 -0
  347. /package/dist/{chunk-6BISDEN6.js.map → chunk-BEM4D2QG.js.map} +0 -0
  348. /package/dist/{chunk-ZPOROUTX.js.map → chunk-CYWA2CXR.js.map} +0 -0
  349. /package/dist/{chunk-M5QKGHCR.js.map → chunk-CYWCKFCL.js.map} +0 -0
  350. /package/dist/{chunk-4BFRBP45.js.map → chunk-DEG5ULFJ.js.map} +0 -0
  351. /package/dist/{chunk-JLR3JSTL.js.map → chunk-DS7MM2ES.js.map} +0 -0
  352. /package/dist/{chunk-2BFLDH5F.js.map → chunk-EEIROWEG.js.map} +0 -0
  353. /package/dist/{chunk-X4A62ET7.js.map → chunk-H2DXDQCQ.js.map} +0 -0
  354. /package/dist/{chunk-27FLVMDC.js.map → chunk-HLN7RROI.js.map} +0 -0
  355. /package/dist/{chunk-2U2A5HF4.js.map → chunk-J3XHPFEU.js.map} +0 -0
  356. /package/dist/{chunk-AKUCU7CI.js.map → chunk-JI5AVXYO.js.map} +0 -0
  357. /package/dist/{chunk-KCJ5H6XQ.js.map → chunk-JSNVWNGX.js.map} +0 -0
  358. /package/dist/{chunk-FLVL4L3L.js.map → chunk-KTULX4YO.js.map} +0 -0
  359. /package/dist/{chunk-437S3G37.js.map → chunk-LNQUAJNC.js.map} +0 -0
  360. /package/dist/{chunk-EPGWWCZF.js.map → chunk-LR5DZ56F.js.map} +0 -0
  361. /package/dist/{chunk-YDSWRD33.js.map → chunk-N3JDIRBW.js.map} +0 -0
  362. /package/dist/{chunk-OUMTBFSQ.js.map → chunk-NKCPUHCI.js.map} +0 -0
  363. /package/dist/{chunk-BGTAL46Y.js.map → chunk-PNLFN2PZ.js.map} +0 -0
  364. /package/dist/{chunk-P6SYWE4G.js.map → chunk-PVUJ6WVV.js.map} +0 -0
  365. /package/dist/{chunk-YPEMNNNY.js.map → chunk-RGK27ELN.js.map} +0 -0
  366. /package/dist/{chunk-2QSZNTDO.js.map → chunk-RKNJBZ55.js.map} +0 -0
  367. /package/dist/{chunk-66FLU5BT.js.map → chunk-SIRPLF54.js.map} +0 -0
  368. /package/dist/{chunk-HRCACVHL.js.map → chunk-TLUDFPZL.js.map} +0 -0
  369. /package/dist/{chunk-2MR3MFQB.js.map → chunk-UPSAT4PY.js.map} +0 -0
  370. /package/dist/{chunk-4P4626RY.js.map → chunk-UTRJFDP2.js.map} +0 -0
  371. /package/dist/{chunk-CGS7UKWM.js.map → chunk-VCW74PNH.js.map} +0 -0
  372. /package/dist/{chunk-5GPPACXK.js.map → chunk-VSMRDBFT.js.map} +0 -0
  373. /package/dist/{chunk-NG7YBCJO.js.map → chunk-XCL57M6Q.js.map} +0 -0
  374. /package/dist/{chunk-CLX5VDNY.js.map → chunk-Y4RKAQZ7.js.map} +0 -0
  375. /package/dist/{chunk-DGYCWCQ7.js.map → chunk-Y7UNNAZD.js.map} +0 -0
  376. /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
  377. /package/dist/{chunk-XN3TUUX2.js.map → chunk-YQB32INI.js.map} +0 -0
  378. /package/dist/{first-start-migration-DY6YCRC2.js.map → first-start-migration-VBJQL6OI.js.map} +0 -0
  379. /package/dist/{tier-stats-TG6GUZ6N.js.map → tier-stats-5XF4UBRQ.js.map} +0 -0
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Wearable cross-source fusion — deterministic conversation clustering.
3
+ *
4
+ * Conversations from multiple sources recording the same real-world event
5
+ * overlap or sit within a proximity gap. This module groups them into
6
+ * clusters that are fully deterministic: the only inputs are start/end
7
+ * times, source ids, and conversation ids (no randomness, no LLM).
8
+ *
9
+ * Cross-source time proximity BRIDGES the same real-world conversation
10
+ * recorded by DIFFERENT sources. A single source's own distinct
11
+ * conversations are never merged by time proximity alone — that would
12
+ * collapse the source's conversation boundaries. Two same-source
13
+ * conversations may end up in one cluster only when a different-source
14
+ * conversation within the gap corroborates that they are part of the same
15
+ * real-world event (a cross-source chain/bridge).
16
+ */
17
+
18
+ import type { FusionConversationInput } from "./types.js";
19
+
20
+ /** Default max gap (ms) between two conversations to merge into one cluster. */
21
+ export const DEFAULT_PROXIMITY_GAP_MS = 5 * 60_000;
22
+
23
+ interface Interval {
24
+ start: number;
25
+ end: number;
26
+ }
27
+
28
+ /** The latest extent of a set of segments as an epoch-ms value + its ISO.
29
+ * Each segment contributes its OWN extent — its `endIso` when known,
30
+ * otherwise its `startIso` — and the result is the maximum. Reconstructed
31
+ * `--:--` transcripts rebuild segments with only a start, so this reaches
32
+ * the last segment start; segment ISOs are already cross-midnight-rolled by
33
+ * the reconstruct layer, so the derived end is consistent with the segment
34
+ * timeline. Returns undefined when no segment carries a parseable extent.
35
+ *
36
+ * This is the SINGLE shared primitive behind every end/interval derivation
37
+ * in the fusion pipeline (cluster interval, fused conversation end): when a
38
+ * conversation-level end is missing, the window falls back to the latest
39
+ * segment extent instead of collapsing to a zero-length point at the start.
40
+ */
41
+ export interface SegmentExtent {
42
+ /** Epoch ms of the latest extent. */
43
+ ms: number;
44
+ /** ISO string that produced `ms` (a segment endIso, else its startIso). */
45
+ iso: string;
46
+ }
47
+
48
+ export function maxSegmentExtent(
49
+ segments: readonly { endIso?: string; startIso?: string }[],
50
+ ): SegmentExtent | undefined {
51
+ let best: SegmentExtent | undefined;
52
+ for (const seg of segments) {
53
+ const iso = seg.endIso ?? seg.startIso;
54
+ if (iso === undefined) continue;
55
+ const ms = Date.parse(iso);
56
+ if (!Number.isFinite(ms)) continue;
57
+ if (best === undefined || ms > best.ms) {
58
+ best = { ms, iso };
59
+ }
60
+ }
61
+ return best;
62
+ }
63
+
64
+ /**
65
+ * Resolve a conversation's effective [start, end] window in epoch ms.
66
+ *
67
+ * When the conversation carries no explicit end (`endIso` undefined — the
68
+ * reconstructed form of a stored transcript whose heading end renders as
69
+ * `--:--`), the window is derived from the segments so it spans the actual
70
+ * utterances instead of collapsing to a zero-length point at the start:
71
+ *
72
+ * 1. conversation `endIso`, when known;
73
+ * 2. the latest segment END (`segment.endIso`);
74
+ * 3. the latest segment START (`segment.startIso`) — reconstructed
75
+ * transcripts rebuild segments with only a start, so the window must
76
+ * reach the last segment start;
77
+ * 4. the conversation start itself (no segments at all).
78
+ *
79
+ * Each segment contributes its own extent (end when known, otherwise its
80
+ * start); the window end is the maximum extent. Segment ISOs are already
81
+ * rolled for cross-midnight by the reconstruct layer, so the derived end is
82
+ * consistent with the segment timeline. The end is clamped to `>= start` so
83
+ * the window is always valid regardless of input anomalies.
84
+ */
85
+ function effectiveInterval(conversation: FusionConversationInput): Interval {
86
+ const start = Date.parse(conversation.startIso);
87
+ const endRaw =
88
+ conversation.endIso !== undefined ? Date.parse(conversation.endIso) : NaN;
89
+ // No conversation-level end ("--:--"): derive the window from the latest
90
+ // SEGMENT extent via the shared primitive, so every end/interval derivation
91
+ // in the pipeline uses ONE coherent implementation. Falling back only to
92
+ // `start` would produce a zero/negative-length window that drops or
93
+ // mis-clusters the conversation (issue #1810).
94
+ const end = Number.isFinite(endRaw)
95
+ ? (endRaw as number)
96
+ : (maxSegmentExtent(conversation.segments)?.ms ?? start);
97
+ // Clamp universally so the window is always non-negative. An explicit
98
+ // conversation end that precedes the start (malformed/cross-day input)
99
+ // would otherwise yield a negative-length window that shrinks the merge
100
+ // horizon and can split a within-gap cluster.
101
+ return { start, end: Math.max(end, start) };
102
+ }
103
+
104
+ function compareConversation(
105
+ a: FusionConversationInput,
106
+ b: FusionConversationInput,
107
+ ): number {
108
+ if (a.source !== b.source) return a.source < b.source ? -1 : 1;
109
+ if (a.conversationId !== b.conversationId) {
110
+ return a.conversationId < b.conversationId ? -1 : 1;
111
+ }
112
+ return 0;
113
+ }
114
+
115
+ /**
116
+ * Cluster conversations across sources for one day. Returns clusters in
117
+ * chronological order; each cluster is sorted by (start, source, id).
118
+ * Conversations whose start time is unparseable are emitted as
119
+ * single-element clusters at the tail (sorted by source then id) so no
120
+ * data is lost.
121
+ *
122
+ * ## Cross-source bridging rule (issue #1849)
123
+ *
124
+ * Time proximity is meant to bridge the SAME real-world conversation
125
+ * recorded by DIFFERENT sources — not to merge one source's own distinct
126
+ * conversations. Two conversations from the SAME source are therefore
127
+ * never directly joined by time proximity alone; they may end up in the
128
+ * same cluster only through a cross-source chain where a different-source
129
+ * conversation within the gap corroborates the bridge. This preserves the
130
+ * source's own conversation boundaries when no other source corroborates
131
+ * a merge.
132
+ *
133
+ * Concretely, a union-find pass links every pair of conversations that
134
+ * (a) come from DIFFERENT sources and (b) sit within the proximity gap
135
+ * (the later start ≤ the earlier end + gap). The transitive closure then
136
+ * groups same-source conversations that are bridged by at least one
137
+ * intervening different-source conversation. A single source with two
138
+ * near-back-to-back conversations and no other source recording the same
139
+ * window stays in two separate clusters.
140
+ */
141
+ export function clusterConversations(
142
+ inputs: readonly FusionConversationInput[],
143
+ proximityGapMs: number = DEFAULT_PROXIMITY_GAP_MS,
144
+ ): FusionConversationInput[][] {
145
+ const finite: Array<{ conv: FusionConversationInput; interval: Interval }> = [];
146
+ const noStart: FusionConversationInput[] = [];
147
+ for (const conv of inputs) {
148
+ const interval = effectiveInterval(conv);
149
+ if (Number.isFinite(interval.start)) {
150
+ finite.push({ conv, interval });
151
+ } else {
152
+ noStart.push(conv);
153
+ }
154
+ }
155
+
156
+ // Deterministic processing + output ordering: (start, source, id).
157
+ finite.sort((a, b) => {
158
+ if (a.interval.start !== b.interval.start) {
159
+ return a.interval.start - b.interval.start;
160
+ }
161
+ return compareConversation(a.conv, b.conv);
162
+ });
163
+
164
+ const n = finite.length;
165
+
166
+ // Union-find so that same-source pairs are never directly joined by time
167
+ // proximity alone; they may share a cluster only through a cross-source
168
+ // bridge (transitive closure over different-source proximity edges).
169
+ const parent = new Array<number>(n);
170
+ for (let i = 0; i < n; i++) parent[i] = i;
171
+
172
+ const find = (x: number): number => {
173
+ let root = x;
174
+ while (parent[root] !== root) root = parent[root];
175
+ // Path compression.
176
+ let cur = x;
177
+ while (parent[cur] !== root) {
178
+ const next = parent[cur]!;
179
+ parent[cur] = root;
180
+ cur = next;
181
+ }
182
+ return root;
183
+ };
184
+
185
+ const union = (a: number, b: number): void => {
186
+ const ra = find(a);
187
+ const rb = find(b);
188
+ if (ra !== rb) parent[ra] = rb;
189
+ };
190
+
191
+ // Link every cross-source pair within the proximity gap. `finite` is
192
+ // sorted by start, so once j's start exceeds i's end + gap, every later
193
+ // j is also out of reach — break early.
194
+ for (let i = 0; i < n; i++) {
195
+ const endGap = finite[i]!.interval.end + proximityGapMs;
196
+ for (let j = i + 1; j < n; j++) {
197
+ if (finite[j]!.interval.start > endGap) break;
198
+ // Only DIFFERENT sources may be directly joined by proximity.
199
+ if (finite[i]!.conv.source === finite[j]!.conv.source) continue;
200
+ union(i, j);
201
+ }
202
+ }
203
+
204
+ // Group conversations by union-find root. Because `finite` is sorted and
205
+ // we iterate in index order, each group's conversations stay in (start,
206
+ // source, id) order, and groups are discovered in chronological order
207
+ // (the first root seen belongs to the earliest-starting conversation).
208
+ const clusters: FusionConversationInput[][] = [];
209
+ const rootToCluster = new Map<number, number>();
210
+ for (let i = 0; i < n; i++) {
211
+ const root = find(i);
212
+ let idx = rootToCluster.get(root);
213
+ if (idx === undefined) {
214
+ idx = clusters.length;
215
+ rootToCluster.set(root, idx);
216
+ clusters.push([]);
217
+ }
218
+ clusters[idx]!.push(finite[i]!.conv);
219
+ }
220
+
221
+ // Conversations with no parseable start can't be ordered in time, so
222
+ // each becomes its own cluster, appended after the time-ordered ones.
223
+ // Sort for determinism (source, id).
224
+ noStart.sort(compareConversation);
225
+ for (const conv of noStart) {
226
+ clusters.push([conv]);
227
+ }
228
+
229
+ return clusters;
230
+ }
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Wearable cross-source fusion — day-level orchestrator.
3
+ *
4
+ * Takes every enabled source's normalized conversations for one day,
5
+ * clusters them across sources, reconciles each cluster, and attaches a
6
+ * stable content-hash id so re-running over unchanged inputs produces a
7
+ * byte-identical artifact (idempotent — no duplicate files).
8
+ *
9
+ * Deterministic end to end: no timestamps from "now", no LLM, no
10
+ * randomness. The only time-derived value is the `fusedAt` frontmatter
11
+ * field added at storage time (excluded from the content hash).
12
+ */
13
+
14
+ import { createHash } from "node:crypto";
15
+ import { clusterConversations } from "./cluster.js";
16
+ import {
17
+ DEFAULT_SOURCE_TRUST,
18
+ DEFAULT_WINDOW_TOLERANCE_MS,
19
+ fuseCluster,
20
+ type FuseClusterResult,
21
+ } from "./reconcile.js";
22
+ import { DEFAULT_PROXIMITY_GAP_MS } from "./cluster.js";
23
+ import type {
24
+ FusionConversationInput,
25
+ FusionDayResult,
26
+ FusionOptions,
27
+ FusedConversationProvenance,
28
+ FusedWearableConversation,
29
+ } from "./types.js";
30
+
31
+ const FUSION_ID_PREFIX = "fusion";
32
+ /**
33
+ * Fusion algorithm/schema version. Folded into the day content hash (the
34
+ * idempotency key) so a change to the clustering, reconciliation, or
35
+ * reconstruction algorithm invalidates cached artifacts even when the raw
36
+ * inputs and fusion config are byte-identical — pre-existing `_fusion/`
37
+ * files are regenerated rather than served stale. Bump this whenever the
38
+ * fusion algorithm meaningfully changes (this PR changed it repeatedly).
39
+ * The per-conversation id (`canonicalInputsKey`) is intentionally NOT
40
+ * folded with the version, so a conversation keeps a stable identity.
41
+ */
42
+ export const FUSION_ALGO_VERSION = "2026-07-12-1";
43
+
44
+ /**
45
+ * Canonical, stable serialization of a set of fusion inputs — the base
46
+ * for the per-conversation id. Input-only so a conversation keeps a
47
+ * stable identity across re-runs regardless of input order. The day
48
+ * content hash additionally folds the effective fusion config (see
49
+ * `canonicalDayKey`) so a config change invalidates the cached artifact.
50
+ */
51
+ function canonicalInputsKey(
52
+ date: string,
53
+ inputs: readonly FusionConversationInput[],
54
+ ): string {
55
+ const sorted = [...inputs].sort((a, b) => {
56
+ if (a.source !== b.source) return a.source < b.source ? -1 : 1;
57
+ if (a.conversationId !== b.conversationId) {
58
+ return a.conversationId < b.conversationId ? -1 : 1;
59
+ }
60
+ return 0;
61
+ });
62
+ // Serialize the structured tuples UNAMBIGUOUSLY before hashing. The old
63
+ // `|`/newline-delimited form could collide: a speaker label or segment
64
+ // text containing `|` (or a newline plus a forged `seg|…`/`conv|…`
65
+ // prefix) could make two DISTINCT inputs serialize to identical bytes,
66
+ // hashing alike — so fuseDay wrongly took the idempotent-skip path and
67
+ // kept serving a stale artifact. JSON string quoting makes every field
68
+ // boundary unforgeable, and the positional array order is the
69
+ // deterministic key order (no object keys to sort).
70
+ const record = [
71
+ date,
72
+ sorted.map((conv) => [
73
+ conv.source,
74
+ conv.conversationId,
75
+ conv.startIso,
76
+ conv.endIso ?? "",
77
+ conv.title ?? "",
78
+ conv.summary ?? "",
79
+ conv.segments.map((segment) => [
80
+ segment.speaker,
81
+ segment.isSelf ? "self" : "other",
82
+ segment.startIso ?? "",
83
+ segment.endIso ?? "",
84
+ segment.text,
85
+ ]),
86
+ ]),
87
+ ];
88
+ return createHash("sha256").update(JSON.stringify(record), "utf-8").digest("hex");
89
+ }
90
+
91
+ /**
92
+ * Effective-config fingerprint folded into the day content hash so a
93
+ * change to any clustering/reconciliation knob (proximity gap, window
94
+ * tolerance, or per-source trust) invalidates the cached artifact.
95
+ * Defaults are resolved so an explicit default hashes identically to an
96
+ * omission, keeping the skip-unchanged path deterministic. Only sources
97
+ * that actually contribute to the day are included, so a trust change
98
+ * for an absent source cannot spuriously trigger a rebuild.
99
+ */
100
+ function configFingerprint(
101
+ options: FusionOptions,
102
+ sources: readonly string[],
103
+ ): string {
104
+ const proximityGapMs = options.proximityGapMs ?? DEFAULT_PROXIMITY_GAP_MS;
105
+ const windowToleranceMs =
106
+ options.windowToleranceMs ?? DEFAULT_WINDOW_TOLERANCE_MS;
107
+ const trustMap = options.sourceTrust ?? {};
108
+ // JSON form so a source id (or future field) containing `|` cannot forge
109
+ // a trust-entry boundary and collide two distinct effective configs into
110
+ // one day hash.
111
+ const trustEntries = [...new Set(sources)]
112
+ .sort()
113
+ .map((source) => [source, trustMap[source] ?? DEFAULT_SOURCE_TRUST]);
114
+ return JSON.stringify([proximityGapMs, windowToleranceMs, trustEntries]);
115
+ }
116
+
117
+ /**
118
+ * Day idempotency key: the input-only hash combined with the effective
119
+ * fusion-config fingerprint AND the fusion algorithm version. Same inputs +
120
+ * same config + same version => same hash (no duplicate rewrite); a config
121
+ * change OR an algorithm-version bump => new hash => rebuild. The version
122
+ * is what forces regeneration when the ALGORITHM itself changes but the
123
+ * inputs and config are byte-identical (issue #1849).
124
+ */
125
+ export function canonicalDayKey(
126
+ date: string,
127
+ inputs: readonly FusionConversationInput[],
128
+ options: FusionOptions,
129
+ algoVersion: string = FUSION_ALGO_VERSION,
130
+ ): string {
131
+ const inputsKey = canonicalInputsKey(date, inputs);
132
+ const fingerprint = configFingerprint(
133
+ options,
134
+ inputs.map((conv) => conv.source),
135
+ );
136
+ return createHash("sha256")
137
+ .update(inputsKey)
138
+ .update("\n")
139
+ .update(fingerprint)
140
+ .update("\n")
141
+ .update(algoVersion)
142
+ .digest("hex");
143
+ }
144
+
145
+ function buildProvenance(
146
+ cluster: readonly FusionConversationInput[],
147
+ proximityGapMs: number,
148
+ windowToleranceMs: number,
149
+ ): FusedConversationProvenance {
150
+ return {
151
+ contributions: cluster.map((conv) => ({
152
+ source: conv.source,
153
+ conversationId: conv.conversationId,
154
+ startIso: conv.startIso,
155
+ ...(conv.endIso !== undefined ? { endIso: conv.endIso } : {}),
156
+ segmentCount: conv.segments.length,
157
+ })),
158
+ proximityGapMs,
159
+ windowToleranceMs,
160
+ method: "time-proximity",
161
+ };
162
+ }
163
+
164
+ /**
165
+ * Fuse every source's conversations for one day into a stable result.
166
+ * Empty input yields an empty (but well-formed) result so callers can
167
+ * treat "nothing to fuse" uniformly.
168
+ */
169
+ export function fuseDay(
170
+ date: string,
171
+ inputs: readonly FusionConversationInput[],
172
+ options: FusionOptions = {},
173
+ ): FusionDayResult {
174
+ const proximityGapMs = options.proximityGapMs ?? DEFAULT_PROXIMITY_GAP_MS;
175
+ const windowToleranceMs =
176
+ options.windowToleranceMs ?? DEFAULT_WINDOW_TOLERANCE_MS;
177
+
178
+ const clusters = clusterConversations(inputs, proximityGapMs);
179
+ const conversations: FusedWearableConversation[] = clusters.map((cluster) => {
180
+ const fused: FuseClusterResult = fuseCluster(cluster, {
181
+ ...options,
182
+ windowToleranceMs,
183
+ });
184
+ const id = `${FUSION_ID_PREFIX}-${canonicalInputsKey(date, cluster).slice(0, 24)}`;
185
+ const result: FusedWearableConversation = {
186
+ id,
187
+ date,
188
+ startIso: fused.startIso,
189
+ sources: fused.sources,
190
+ speakers: fused.speakers,
191
+ segments: fused.segments,
192
+ disagreements: fused.disagreements,
193
+ provenance: buildProvenance(cluster, proximityGapMs, windowToleranceMs),
194
+ };
195
+ if (fused.endIso !== undefined) result.endIso = fused.endIso;
196
+ if (fused.title !== undefined) result.title = fused.title;
197
+ if (fused.summary !== undefined) result.summary = fused.summary;
198
+ return result;
199
+ });
200
+
201
+ const sourcesSeen = new Set<string>();
202
+ const sources: string[] = [];
203
+ for (const conv of conversations) {
204
+ for (const source of conv.sources) {
205
+ if (!sourcesSeen.has(source)) {
206
+ sourcesSeen.add(source);
207
+ sources.push(source);
208
+ }
209
+ }
210
+ }
211
+
212
+ return {
213
+ date,
214
+ conversations,
215
+ sources,
216
+ contentHash: canonicalDayKey(date, inputs, options),
217
+ };
218
+ }