@remnic/core 9.63.3 → 9.63.5

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 (437) hide show
  1. package/dist/access-admin-ops-surface.d.ts +11 -11
  2. package/dist/access-admin-ops-surface.js +23 -23
  3. package/dist/access-authorization-probe.d.ts +11 -11
  4. package/dist/access-authorization-probe.js +24 -24
  5. package/dist/access-boundary.d.ts +11 -11
  6. package/dist/access-boundary.js +23 -23
  7. package/dist/access-cli.js +55 -54
  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 +23 -23
  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 +13 -1
  17. package/dist/access-http-query.js +27 -24
  18. package/dist/access-http.d.ts +12 -12
  19. package/dist/access-http.js +34 -33
  20. package/dist/access-identity-continuity-surface.d.ts +9 -9
  21. package/dist/access-identity-continuity-surface.js +23 -23
  22. package/dist/access-lcm-surface.d.ts +11 -11
  23. package/dist/access-lcm-surface.js +23 -23
  24. package/dist/access-mcp.d.ts +11 -11
  25. package/dist/access-mcp.js +28 -28
  26. package/dist/access-memory-search-fanout.d.ts +2 -2
  27. package/dist/{access-namespace-preflight-yO4LMGFH.d.ts → access-namespace-preflight-DB0zXFek.d.ts} +1 -1
  28. package/dist/access-namespace-preflight.d.ts +3 -3
  29. package/dist/access-namespace-preflight.js +23 -23
  30. package/dist/access-observe-write-surface.d.ts +11 -11
  31. package/dist/access-observe-write-surface.js +23 -23
  32. package/dist/access-offline-manifest.d.ts +9 -9
  33. package/dist/access-offline-manifest.js +3 -3
  34. package/dist/access-operations-batch.js +24 -24
  35. package/dist/access-operations.d.ts +14 -14
  36. package/dist/access-operations.js +27 -27
  37. package/dist/access-recall-concurrency.d.ts +11 -11
  38. package/dist/access-recall-concurrency.js +23 -23
  39. package/dist/access-recall-response.d.ts +11 -11
  40. package/dist/access-recall-response.js +23 -23
  41. package/dist/access-recall-surface.d.ts +11 -11
  42. package/dist/access-recall-surface.js +23 -23
  43. package/dist/access-schema.d.ts +88 -88
  44. package/dist/{access-service-M4LgO141.d.ts → access-service-cKQrte9Z.d.ts} +71 -77
  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 +23 -23
  48. package/dist/access-surface-catalog.d.ts +11 -11
  49. package/dist/access-surface-catalog.js +25 -25
  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/ambient-provenance.d.ts +1 -1
  55. package/dist/artifact-search.d.ts +1 -1
  56. package/dist/behavior-learner.d.ts +1 -1
  57. package/dist/behavior-signals.d.ts +1 -1
  58. package/dist/bootstrap.d.ts +9 -9
  59. package/dist/briefing-window.d.ts +2 -2
  60. package/dist/briefing.d.ts +2 -2
  61. package/dist/briefing.js +11 -11
  62. package/dist/buffer-surprise-report.d.ts +1 -1
  63. package/dist/buffer-turn-helpers.d.ts +1 -1
  64. package/dist/buffer.d.ts +2 -2
  65. package/dist/buffer.js +4 -4
  66. package/dist/bulk-import/index.d.ts +3 -3
  67. package/dist/calibration.d.ts +1 -1
  68. package/dist/capabilities.d.ts +1 -1
  69. package/dist/{capsule-merge-HCJJMLPS.js → capsule-merge-SGIVB3WA.js} +5 -5
  70. package/dist/{catalog-CyYTf_ok.d.ts → catalog-CCzmf8IH.d.ts} +3 -11
  71. package/dist/causal-behavior.d.ts +1 -1
  72. package/dist/causal-consolidation.d.ts +1 -1
  73. package/dist/causal-consolidation.js +12 -12
  74. package/dist/causal-trajectory-graph.d.ts +1 -1
  75. package/dist/{chunk-XFCQIQQU.js → chunk-2UM6WHME.js} +3 -3
  76. package/dist/{chunk-6F2UMP4H.js → chunk-3Z5TGRFA.js} +8 -8
  77. package/dist/{chunk-JJX5XEIG.js → chunk-77QZW2D6.js} +4 -4
  78. package/dist/{chunk-X4MGNVOO.js → chunk-7AF243WZ.js} +1 -1
  79. package/dist/{chunk-2ASAS3CQ.js → chunk-7KQB4EBS.js} +2 -2
  80. package/dist/{chunk-3LJ2L3T3.js → chunk-7LF2OHIJ.js} +2 -2
  81. package/dist/{chunk-VAMQU4W7.js → chunk-AYVCKGA6.js} +2 -2
  82. package/dist/{chunk-GTRGH4ZT.js → chunk-BB2LH5JM.js} +2 -2
  83. package/dist/{chunk-XMMESCPD.js → chunk-C64XATK7.js} +17 -27
  84. package/dist/chunk-C64XATK7.js.map +1 -0
  85. package/dist/{chunk-6UZR7KEK.js → chunk-CUDSA46O.js} +8 -2
  86. package/dist/chunk-CUDSA46O.js.map +1 -0
  87. package/dist/{chunk-PADG72LJ.js → chunk-DXDAQZ2K.js} +2 -2
  88. package/dist/{chunk-EJQXDKYK.js → chunk-DYZR3Z6D.js} +3 -3
  89. package/dist/{chunk-VN7IIQGS.js → chunk-E4KMY4KR.js} +2 -2
  90. package/dist/{chunk-ZQKXRKMR.js → chunk-EFKZT6AY.js} +2 -2
  91. package/dist/{chunk-DNRTKO2U.js → chunk-EJY3HJMT.js} +2 -2
  92. package/dist/{chunk-RYGJGXL6.js → chunk-ERPBRXVZ.js} +2 -2
  93. package/dist/{chunk-5UFQCU6M.js → chunk-F6JYBVL6.js} +27 -57
  94. package/dist/{chunk-5UFQCU6M.js.map → chunk-F6JYBVL6.js.map} +1 -1
  95. package/dist/{chunk-JWPG65LH.js → chunk-FHKXVTM5.js} +38 -39
  96. package/dist/chunk-FHKXVTM5.js.map +1 -0
  97. package/dist/{chunk-RPKJHYVE.js → chunk-FPEZ74F7.js} +2 -2
  98. package/dist/{chunk-Z334TJRB.js → chunk-GF7RQWXC.js} +2 -2
  99. package/dist/{chunk-6D7PZKCJ.js → chunk-GG4DN63W.js} +2 -2
  100. package/dist/{chunk-IM56VPKO.js → chunk-GTD4Q62X.js} +2 -6
  101. package/dist/{chunk-A73QHOZP.js → chunk-I5FLIB2J.js} +2 -2
  102. package/dist/{chunk-JJ7JW62R.js → chunk-IVXVLDNT.js} +12 -22
  103. package/dist/chunk-IVXVLDNT.js.map +1 -0
  104. package/dist/{chunk-NRFU5MVH.js → chunk-JOEJG4SD.js} +47 -1
  105. package/dist/chunk-JOEJG4SD.js.map +1 -0
  106. package/dist/{chunk-EJLTNPRY.js → chunk-KHCUVYCY.js} +3 -3
  107. package/dist/{chunk-QSIQVC32.js → chunk-KYTRF64R.js} +2 -2
  108. package/dist/{chunk-R74NCKEY.js → chunk-LX4TNSAE.js} +4 -4
  109. package/dist/{chunk-H6ZXNH5I.js → chunk-MUJ4QFUQ.js} +3 -3
  110. package/dist/{chunk-4NMVX5U7.js → chunk-NA56NSKL.js} +2 -2
  111. package/dist/{chunk-MR5HWQHS.js → chunk-NKB43PGI.js} +2 -2
  112. package/dist/{chunk-DLQQU4EG.js → chunk-NS5ETDYD.js} +2 -2
  113. package/dist/{chunk-44KHFMCM.js → chunk-OETHJBAL.js} +76 -53
  114. package/dist/{chunk-44KHFMCM.js.map → chunk-OETHJBAL.js.map} +1 -1
  115. package/dist/{chunk-KWN6NOHQ.js → chunk-PB4WVYGC.js} +2 -2
  116. package/dist/{chunk-Q35XGIEM.js → chunk-PBRCYYO7.js} +2 -2
  117. package/dist/{chunk-QYN5PXDZ.js → chunk-PMVPCZJZ.js} +4 -4
  118. package/dist/{chunk-AJSZ2EK6.js → chunk-QI5RDDEL.js} +3 -3
  119. package/dist/{chunk-I6OQCT3Y.js → chunk-QRWMS6SI.js} +2 -2
  120. package/dist/{chunk-ITYAXU4S.js → chunk-R6UMNP5C.js} +3 -3
  121. package/dist/{chunk-5W62VEFH.js → chunk-RWMSMTQP.js} +2 -2
  122. package/dist/{chunk-FKJVEW6O.js → chunk-SYVGVK4S.js} +2 -2
  123. package/dist/{chunk-TRPX6F2G.js → chunk-TSTI6A3A.js} +10 -13
  124. package/dist/chunk-TSTI6A3A.js.map +1 -0
  125. package/dist/{chunk-XZPSBGHA.js → chunk-UCLMKNHA.js} +2 -2
  126. package/dist/{chunk-ZMSZVISA.js → chunk-UFKPQBXH.js} +3 -3
  127. package/dist/{chunk-B2OOJCUX.js → chunk-UGHCZS6K.js} +2 -2
  128. package/dist/chunk-V3KIRICY.js +727 -0
  129. package/dist/chunk-V3KIRICY.js.map +1 -0
  130. package/dist/{chunk-6ZYQ36IB.js → chunk-VPHSMJ2E.js} +15 -2
  131. package/dist/chunk-VPHSMJ2E.js.map +1 -0
  132. package/dist/{chunk-E2GYBTSP.js → chunk-VYEPACWY.js} +2 -2
  133. package/dist/{chunk-5W5N7XJZ.js → chunk-X7LEDA74.js} +20 -753
  134. package/dist/chunk-X7LEDA74.js.map +1 -0
  135. package/dist/{chunk-KMAP7SNQ.js → chunk-XCB6QDL6.js} +2 -2
  136. package/dist/{chunk-WDUG2CH3.js → chunk-YEQCMA5L.js} +2 -2
  137. package/dist/{chunk-LZCSOUJ7.js → chunk-YFCEBB5P.js} +2 -2
  138. package/dist/{chunk-IKXUG6KC.js → chunk-YXMHUBN2.js} +2 -2
  139. package/dist/{chunk-GFNS3BHV.js → chunk-ZUPKNWRZ.js} +3 -3
  140. package/dist/{chunk-GSTIBXBW.js → chunk-ZVPVTPGI.js} +2 -2
  141. package/dist/{cli-Bw9z-KqX.d.ts → cli-BFBDYV0D.d.ts} +5 -5
  142. package/dist/cli.d.ts +13 -13
  143. package/dist/cli.js +45 -44
  144. package/dist/coding/pre-action-gate.d.ts +1 -1
  145. package/dist/compounding/engine.d.ts +2 -2
  146. package/dist/compounding/engine.js +11 -11
  147. package/dist/compounding/preference-consolidator.d.ts +1 -1
  148. package/dist/compression-optimizer.d.ts +1 -1
  149. package/dist/config.d.ts +1 -1
  150. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  151. package/dist/connectors/codex-materialize-runner.js +11 -11
  152. package/dist/connectors/codex-materialize.d.ts +1 -1
  153. package/dist/connectors/index.d.ts +1 -1
  154. package/dist/connectors/index.js +11 -11
  155. package/dist/consolidation-provenance-check.d.ts +2 -2
  156. package/dist/consolidation-provenance-check.js +5 -5
  157. package/dist/consolidation-undo.d.ts +2 -2
  158. package/dist/consolidation-undo.js +4 -4
  159. package/dist/contradiction/index.d.ts +2 -2
  160. package/dist/converge-config.d.ts +1 -1
  161. package/dist/convergence-refresh.d.ts +2 -2
  162. package/dist/convergence-refresh.js +13 -13
  163. package/dist/conversation-index/backend.d.ts +1 -1
  164. package/dist/conversation-index/chunker.d.ts +1 -1
  165. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  166. package/dist/conversation-index/indexer.d.ts +1 -1
  167. package/dist/conversation-index/search.d.ts +1 -1
  168. package/dist/corpus-watermark.d.ts +1 -1
  169. package/dist/corpus-watermark.js +13 -13
  170. package/dist/day-summary.d.ts +1 -1
  171. package/dist/delinearize.d.ts +1 -1
  172. package/dist/dependency-propagation-config.d.ts +1 -1
  173. package/dist/{dependency-propagation-delivery-BxhvAppj.d.ts → dependency-propagation-delivery-DiY5T63p.d.ts} +1 -1
  174. package/dist/direct-answer-wiring.d.ts +1 -1
  175. package/dist/direct-answer.d.ts +1 -1
  176. package/dist/embedding-fallback.d.ts +1 -1
  177. package/dist/enrichment/index.d.ts +1 -1
  178. package/dist/entity-origin-fields.d.ts +1 -1
  179. package/dist/entity-retrieval.d.ts +2 -2
  180. package/dist/entity-retrieval.js +11 -11
  181. package/dist/entity-schema.d.ts +1 -1
  182. package/dist/episodic-context.d.ts +1 -1
  183. package/dist/explicit-capture.d.ts +9 -9
  184. package/dist/explicit-capture.js +5 -5
  185. package/dist/external-wiki-access.d.ts +11 -11
  186. package/dist/external-wiki-access.js +24 -24
  187. package/dist/external-wiki-collection-registration.d.ts +1 -1
  188. package/dist/external-wiki-collection.d.ts +1 -1
  189. package/dist/external-wiki-mcp-tools.d.ts +11 -11
  190. package/dist/extraction-error-classification.d.ts +1 -1
  191. package/dist/extraction-faithfulness.d.ts +1 -1
  192. package/dist/extraction-judge-telemetry.d.ts +1 -1
  193. package/dist/extraction-judge-training.d.ts +1 -1
  194. package/dist/extraction-judge.d.ts +1 -1
  195. package/dist/extraction-liveness.d.ts +1 -1
  196. package/dist/extraction-normalization.d.ts +1 -1
  197. package/dist/extraction-prompt.d.ts +1 -1
  198. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  199. package/dist/extraction-source-grounding.d.ts +1 -1
  200. package/dist/extraction.d.ts +1 -1
  201. package/dist/extraction.js +14 -14
  202. package/dist/fallback-llm.d.ts +1 -1
  203. package/dist/graph-dashboard-diff.d.ts +1 -1
  204. package/dist/graph-dashboard-key.d.ts +1 -1
  205. package/dist/graph-dashboard-parser.d.ts +1 -1
  206. package/dist/graph-edge-reinforcement.d.ts +1 -1
  207. package/dist/graph-path-reconstruction.d.ts +1 -1
  208. package/dist/graph-path-scoring.d.ts +1 -1
  209. package/dist/graph-snapshot.d.ts +1 -1
  210. package/dist/graph.d.ts +1 -1
  211. package/dist/harmonic-retrieval.js +1 -1
  212. package/dist/importance.d.ts +1 -1
  213. package/dist/importers/index.d.ts +1 -1
  214. package/dist/in-flight-reads.d.ts +1 -1
  215. package/dist/index.d.ts +697 -697
  216. package/dist/index.js +57 -56
  217. package/dist/intent.d.ts +1 -1
  218. package/dist/lcm/engine.d.ts +1 -1
  219. package/dist/lcm/index.d.ts +1 -1
  220. package/dist/lcm/tools.d.ts +1 -1
  221. package/dist/lifecycle.d.ts +1 -1
  222. package/dist/live-connectors-runner.d.ts +1 -1
  223. package/dist/local-llm.d.ts +1 -1
  224. package/dist/local-model-endpoint.d.ts +1 -1
  225. package/dist/maintenance/memory-governance.d.ts +1 -1
  226. package/dist/maintenance/memory-governance.js +11 -11
  227. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  228. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +11 -11
  229. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  230. package/dist/maintenance/rebuild-memory-projection.js +12 -12
  231. package/dist/{maintenance-uJb74j64.d.ts → maintenance-CaqA4z7V.d.ts} +3 -3
  232. package/dist/mcp-memory-inspector-app.d.ts +11 -11
  233. package/dist/memory-action-policy.d.ts +1 -1
  234. package/dist/memory-cache.d.ts +1 -1
  235. package/dist/memory-cache.js +1 -1
  236. package/dist/memory-corpus-version.js +2 -2
  237. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  238. package/dist/memory-projection-store.d.ts +1 -1
  239. package/dist/memory-provenance.d.ts +1 -1
  240. package/dist/memory-snapshot.d.ts +1 -1
  241. package/dist/memory-worth-outcomes.d.ts +2 -2
  242. package/dist/models-json.d.ts +1 -1
  243. package/dist/namespaces/migrate.d.ts +3 -3
  244. package/dist/namespaces/migrate.js +12 -12
  245. package/dist/namespaces/principal.d.ts +1 -1
  246. package/dist/namespaces/search.d.ts +1 -1
  247. package/dist/namespaces/search.js +4 -4
  248. package/dist/namespaces/storage.d.ts +3 -3
  249. package/dist/namespaces/storage.js +11 -11
  250. package/dist/native-knowledge.d.ts +1 -1
  251. package/dist/offline-sync-impression-drain.d.ts +1 -1
  252. package/dist/operator-doctor-corpus.d.ts +1 -1
  253. package/dist/operator-doctor-corpus.js +14 -14
  254. package/dist/operator-doctor-replica.d.ts +1 -1
  255. package/dist/operator-toolkit.d.ts +3 -3
  256. package/dist/operator-toolkit.js +20 -19
  257. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  258. package/dist/orchestration/maintenance.d.ts +4 -4
  259. package/dist/orchestration/maintenance.js +17 -16
  260. package/dist/{orchestrator-CFi-5JSR.d.ts → orchestrator-CSc9GfQv.d.ts} +8 -8
  261. package/dist/orchestrator.d.ts +9 -9
  262. package/dist/orchestrator.js +55 -54
  263. package/dist/page-versioning.js +4 -4
  264. package/dist/patterns-cli.d.ts +1 -1
  265. package/dist/{pipeline-BdF3ferY.d.ts → pipeline-X606GdRJ.d.ts} +1 -1
  266. package/dist/policy-runtime.d.ts +1 -1
  267. package/dist/proactive-contention.d.ts +1 -1
  268. package/dist/provenance.d.ts +1 -1
  269. package/dist/{public-http-DK-QwaBu.d.ts → public-http-8PcrDIYi.d.ts} +1 -1
  270. package/dist/{qmd-CBSxevyb.d.ts → qmd-DCKeR-GX.d.ts} +1 -1
  271. package/dist/qmd-preflight.d.ts +2 -2
  272. package/dist/qmd-recall-cache.d.ts +1 -1
  273. package/dist/qmd.d.ts +2 -2
  274. package/dist/qmd.js +2 -2
  275. package/dist/recall-concurrency-config.d.ts +1 -1
  276. package/dist/recall-disclosure-escalation.d.ts +1 -1
  277. package/dist/recall-explain-renderer.d.ts +1 -1
  278. package/dist/recall-memory-map.d.ts +1 -1
  279. package/dist/recall-planner-llm.d.ts +1 -1
  280. package/dist/recall-state.d.ts +1 -1
  281. package/dist/recall-tag-filter.d.ts +1 -1
  282. package/dist/recall-timings.d.ts +1 -1
  283. package/dist/recall-xray-cli.d.ts +1 -1
  284. package/dist/recall-xray-renderer.d.ts +1 -1
  285. package/dist/recall-xray.d.ts +1 -1
  286. package/dist/reconcile/cursor.d.ts +1 -1
  287. package/dist/reconcile/manifest.d.ts +1 -1
  288. package/dist/reconcile/manifest.js +2 -2
  289. package/dist/reconcile/plan.d.ts +1 -1
  290. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  291. package/dist/replay/normalizers/claude.d.ts +1 -1
  292. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  293. package/dist/replay/normalizers/shared.d.ts +1 -1
  294. package/dist/replay/runner.d.ts +1 -1
  295. package/dist/replay/types.d.ts +1 -1
  296. package/dist/replica-divergence.d.ts +1 -1
  297. package/dist/replica-peers-config.d.ts +1 -1
  298. package/dist/resolve-auth-token.d.ts +1 -1
  299. package/dist/retrieval-agents.d.ts +2 -2
  300. package/dist/retrieval-tiers.d.ts +1 -1
  301. package/dist/routing/engine.d.ts +1 -1
  302. package/dist/routing/store.d.ts +1 -1
  303. package/dist/salvage-envelope.d.ts +1 -1
  304. package/dist/schemas.d.ts +108 -108
  305. package/dist/{scope-profiles-CeMv7pP0.d.ts → scope-profiles-_Y_RHCeE.d.ts} +1 -1
  306. package/dist/search/embed-helper.d.ts +1 -1
  307. package/dist/search/factory.d.ts +1 -1
  308. package/dist/search/factory.js +3 -3
  309. package/dist/search/index.d.ts +1 -1
  310. package/dist/search/index.js +3 -3
  311. package/dist/search/lancedb-backend.d.ts +1 -1
  312. package/dist/search/meilisearch-backend.d.ts +1 -1
  313. package/dist/search/noop-backend.d.ts +1 -1
  314. package/dist/search/orama-backend.d.ts +1 -1
  315. package/dist/search/port.d.ts +1 -1
  316. package/dist/search/remote-backend.d.ts +1 -1
  317. package/dist/{semantic-consolidation-B-85brYj.d.ts → semantic-consolidation-DT2VSrU0.d.ts} +1 -1
  318. package/dist/semantic-consolidation.d.ts +2 -2
  319. package/dist/semantic-consolidation.js +12 -12
  320. package/dist/semantic-rule-promotion.js +11 -11
  321. package/dist/semantic-rule-verifier.d.ts +1 -1
  322. package/dist/semantic-rule-verifier.js +11 -11
  323. package/dist/{service-CoO0HA2E.d.ts → service-BMo-gwDE.d.ts} +3 -3
  324. package/dist/session-observer-bands.d.ts +1 -1
  325. package/dist/session-observer-state.d.ts +1 -1
  326. package/dist/shared-context/manager.d.ts +9 -9
  327. package/dist/signal.d.ts +1 -1
  328. package/dist/source-agent-qualifier.d.ts +1 -1
  329. package/dist/source-agent-qualifier.js +13 -13
  330. package/dist/{storage-BVAVitkO.d.ts → storage-CGzJGUUu.d.ts} +49 -24
  331. package/dist/storage.d.ts +2 -2
  332. package/dist/storage.js +10 -10
  333. package/dist/summarizer.d.ts +1 -1
  334. package/dist/summary-snapshot.d.ts +1 -1
  335. package/dist/support-passport/index.d.ts +14 -14
  336. package/dist/support-passport/index.js +26 -26
  337. package/dist/temporal-supersession.d.ts +2 -2
  338. package/dist/temporal-timeline-recall.d.ts +1 -1
  339. package/dist/temporal-validity.d.ts +1 -1
  340. package/dist/threading.d.ts +1 -1
  341. package/dist/tier-migration.d.ts +2 -2
  342. package/dist/tier-routing.d.ts +1 -1
  343. package/dist/topics.d.ts +1 -1
  344. package/dist/transcript.d.ts +1 -1
  345. package/dist/transfer/capsule-import.js +5 -5
  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-DWHOxlZP.d.ts → types-CBEAYU76.d.ts} +112 -128
  350. package/dist/types.d.ts +1 -1
  351. package/dist/utility-runtime.d.ts +1 -1
  352. package/dist/verified-recall.js +11 -11
  353. package/dist/write-envelope.d.ts +1 -1
  354. package/package.json +2 -2
  355. package/src/access-http-query.ts +12 -0
  356. package/src/access-http.test.ts +32 -0
  357. package/src/access-http.ts +3 -7
  358. package/src/admin/admin-surfaces.test.ts +5 -10
  359. package/src/admin/admin-surfaces.ts +0 -16
  360. package/src/binary-lifecycle/pipeline.test.ts +1 -1
  361. package/src/binary-lifecycle/pipeline.ts +23 -9
  362. package/src/buffer.ts +6 -0
  363. package/src/chat/chat-cli.test.ts +53 -0
  364. package/src/chat/chat-cli.ts +22 -58
  365. package/src/dedup/index.test.ts +65 -1
  366. package/src/dedup/index.ts +24 -2
  367. package/src/maintenance/namespace-planner.ts +0 -2
  368. package/src/meetings/build.test.ts +20 -4
  369. package/src/meetings/build.ts +2 -2
  370. package/src/meetings/day-source.test.ts +3 -1
  371. package/src/meetings/day-source.ts +1 -12
  372. package/src/meetings/fuse.test.ts +64 -15
  373. package/src/meetings/fuse.ts +18 -12
  374. package/src/meetings/types.ts +4 -19
  375. package/src/memory-cache-derived.test.ts +90 -0
  376. package/src/memory-cache.ts +40 -42
  377. package/src/namespaces/catalog.test.ts +53 -8
  378. package/src/namespaces/catalog.ts +5 -37
  379. package/src/orchestration/turn-ingestion-snapshot.test.ts +167 -0
  380. package/src/orchestration/turn-ingestion.ts +2 -1
  381. package/src/storage/content-hash-index.ts +54 -0
  382. package/src/storage-contract/content-hash.test.ts +59 -1
  383. package/src/storage-fact-hash-index-defer.test.ts +9 -9
  384. package/src/storage.ts +39 -40
  385. package/dist/chunk-5W5N7XJZ.js.map +0 -1
  386. package/dist/chunk-6UZR7KEK.js.map +0 -1
  387. package/dist/chunk-6ZYQ36IB.js.map +0 -1
  388. package/dist/chunk-JJ7JW62R.js.map +0 -1
  389. package/dist/chunk-JWPG65LH.js.map +0 -1
  390. package/dist/chunk-NRFU5MVH.js.map +0 -1
  391. package/dist/chunk-TRPX6F2G.js.map +0 -1
  392. package/dist/chunk-XMMESCPD.js.map +0 -1
  393. /package/dist/{capsule-merge-HCJJMLPS.js.map → capsule-merge-SGIVB3WA.js.map} +0 -0
  394. /package/dist/{chunk-XFCQIQQU.js.map → chunk-2UM6WHME.js.map} +0 -0
  395. /package/dist/{chunk-6F2UMP4H.js.map → chunk-3Z5TGRFA.js.map} +0 -0
  396. /package/dist/{chunk-JJX5XEIG.js.map → chunk-77QZW2D6.js.map} +0 -0
  397. /package/dist/{chunk-X4MGNVOO.js.map → chunk-7AF243WZ.js.map} +0 -0
  398. /package/dist/{chunk-2ASAS3CQ.js.map → chunk-7KQB4EBS.js.map} +0 -0
  399. /package/dist/{chunk-3LJ2L3T3.js.map → chunk-7LF2OHIJ.js.map} +0 -0
  400. /package/dist/{chunk-VAMQU4W7.js.map → chunk-AYVCKGA6.js.map} +0 -0
  401. /package/dist/{chunk-GTRGH4ZT.js.map → chunk-BB2LH5JM.js.map} +0 -0
  402. /package/dist/{chunk-PADG72LJ.js.map → chunk-DXDAQZ2K.js.map} +0 -0
  403. /package/dist/{chunk-EJQXDKYK.js.map → chunk-DYZR3Z6D.js.map} +0 -0
  404. /package/dist/{chunk-VN7IIQGS.js.map → chunk-E4KMY4KR.js.map} +0 -0
  405. /package/dist/{chunk-ZQKXRKMR.js.map → chunk-EFKZT6AY.js.map} +0 -0
  406. /package/dist/{chunk-DNRTKO2U.js.map → chunk-EJY3HJMT.js.map} +0 -0
  407. /package/dist/{chunk-RYGJGXL6.js.map → chunk-ERPBRXVZ.js.map} +0 -0
  408. /package/dist/{chunk-RPKJHYVE.js.map → chunk-FPEZ74F7.js.map} +0 -0
  409. /package/dist/{chunk-Z334TJRB.js.map → chunk-GF7RQWXC.js.map} +0 -0
  410. /package/dist/{chunk-6D7PZKCJ.js.map → chunk-GG4DN63W.js.map} +0 -0
  411. /package/dist/{chunk-IM56VPKO.js.map → chunk-GTD4Q62X.js.map} +0 -0
  412. /package/dist/{chunk-A73QHOZP.js.map → chunk-I5FLIB2J.js.map} +0 -0
  413. /package/dist/{chunk-EJLTNPRY.js.map → chunk-KHCUVYCY.js.map} +0 -0
  414. /package/dist/{chunk-QSIQVC32.js.map → chunk-KYTRF64R.js.map} +0 -0
  415. /package/dist/{chunk-R74NCKEY.js.map → chunk-LX4TNSAE.js.map} +0 -0
  416. /package/dist/{chunk-H6ZXNH5I.js.map → chunk-MUJ4QFUQ.js.map} +0 -0
  417. /package/dist/{chunk-4NMVX5U7.js.map → chunk-NA56NSKL.js.map} +0 -0
  418. /package/dist/{chunk-MR5HWQHS.js.map → chunk-NKB43PGI.js.map} +0 -0
  419. /package/dist/{chunk-DLQQU4EG.js.map → chunk-NS5ETDYD.js.map} +0 -0
  420. /package/dist/{chunk-KWN6NOHQ.js.map → chunk-PB4WVYGC.js.map} +0 -0
  421. /package/dist/{chunk-Q35XGIEM.js.map → chunk-PBRCYYO7.js.map} +0 -0
  422. /package/dist/{chunk-QYN5PXDZ.js.map → chunk-PMVPCZJZ.js.map} +0 -0
  423. /package/dist/{chunk-AJSZ2EK6.js.map → chunk-QI5RDDEL.js.map} +0 -0
  424. /package/dist/{chunk-I6OQCT3Y.js.map → chunk-QRWMS6SI.js.map} +0 -0
  425. /package/dist/{chunk-ITYAXU4S.js.map → chunk-R6UMNP5C.js.map} +0 -0
  426. /package/dist/{chunk-5W62VEFH.js.map → chunk-RWMSMTQP.js.map} +0 -0
  427. /package/dist/{chunk-FKJVEW6O.js.map → chunk-SYVGVK4S.js.map} +0 -0
  428. /package/dist/{chunk-XZPSBGHA.js.map → chunk-UCLMKNHA.js.map} +0 -0
  429. /package/dist/{chunk-ZMSZVISA.js.map → chunk-UFKPQBXH.js.map} +0 -0
  430. /package/dist/{chunk-B2OOJCUX.js.map → chunk-UGHCZS6K.js.map} +0 -0
  431. /package/dist/{chunk-E2GYBTSP.js.map → chunk-VYEPACWY.js.map} +0 -0
  432. /package/dist/{chunk-KMAP7SNQ.js.map → chunk-XCB6QDL6.js.map} +0 -0
  433. /package/dist/{chunk-WDUG2CH3.js.map → chunk-YEQCMA5L.js.map} +0 -0
  434. /package/dist/{chunk-LZCSOUJ7.js.map → chunk-YFCEBB5P.js.map} +0 -0
  435. /package/dist/{chunk-IKXUG6KC.js.map → chunk-YXMHUBN2.js.map} +0 -0
  436. /package/dist/{chunk-GFNS3BHV.js.map → chunk-ZUPKNWRZ.js.map} +0 -0
  437. /package/dist/{chunk-GSTIBXBW.js.map → chunk-ZVPVTPGI.js.map} +0 -0
@@ -0,0 +1,167 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { SmartBuffer } from "../buffer.js";
4
+ import { parseConfig } from "../config.js";
5
+ import type { BufferState, BufferTurn } from "../types.js";
6
+ import {
7
+ TurnIngestionCoordinator,
8
+ type TurnIngestionDeps,
9
+ } from "./turn-ingestion.js";
10
+
11
+ class FakeStorage {
12
+ constructor(private readonly initial: BufferState) {}
13
+ async loadBuffer(): Promise<BufferState> {
14
+ return structuredClone(this.initial);
15
+ }
16
+ async saveBuffer(_state: BufferState): Promise<void> {}
17
+ }
18
+
19
+ function makeTurn(content: string): BufferTurn {
20
+ return {
21
+ role: "user",
22
+ content,
23
+ timestamp: "2026-08-17T00:00:00.000Z",
24
+ sessionKey: "k",
25
+ };
26
+ }
27
+
28
+ test("#2468 extract trigger returns the mutation snapshot", async () => {
29
+ const buffer = new SmartBuffer(
30
+ parseConfig({ triggerMode: "every_n", bufferMaxTurns: 1 }),
31
+ new FakeStorage({ turns: [], lastExtractionAt: null, extractionCount: 0 }) as never,
32
+ );
33
+ const outcome = await buffer.addTurnWithOutcome("k", makeTurn("only"));
34
+ assert.equal(outcome.decision, "extract_batch");
35
+ assert.equal(outcome.extractionTurns?.length, 1);
36
+ assert.equal(outcome.extractionTurns?.[0]?.content, "only");
37
+ });
38
+
39
+ test("#2468 built-in trigger includes retained turns in the snapshot", async () => {
40
+ const buffer = new SmartBuffer(
41
+ parseConfig({ triggerMode: "every_n", bufferMaxTurns: 1 }),
42
+ new FakeStorage({ turns: [], lastExtractionAt: null, extractionCount: 0 }) as never,
43
+ );
44
+ await buffer.retainDeferredTurns("k", [makeTurn("retained")], 10);
45
+ const outcome = await buffer.addTurnWithOutcome("k", makeTurn("live"));
46
+ assert.equal(outcome.decision, "extract_batch");
47
+ assert.deepEqual(
48
+ outcome.extractionTurns?.map((turn) => turn.content),
49
+ ["retained", "live"],
50
+ );
51
+ });
52
+
53
+ test("#2468 processTurn does not adopt a later getTurns() batch", async () => {
54
+ const snapshot = [makeTurn("first")];
55
+ const later = [makeTurn("first"), makeTurn("later")];
56
+ const queued: BufferTurn[][] = [];
57
+ const buffer = {
58
+ addTurnWithOutcome: async () => ({
59
+ decision: "extract_now" as const,
60
+ extractionTurns: snapshot,
61
+ }),
62
+ getTurns: () => later,
63
+ };
64
+ const deps = {
65
+ buffer,
66
+ config: parseConfig({}),
67
+ getStorage: async () => {
68
+ throw new Error("unexpected getStorage");
69
+ },
70
+ bulkImportWriteNamespace: () => "default",
71
+ get extractionQueueCoordinator(): never {
72
+ throw new Error("unexpected extractionQueueCoordinator");
73
+ },
74
+ heartbeatObserverChains: new Map(),
75
+ lcmEngine: null,
76
+ passiveCorrectionDedup: new Set(),
77
+ passiveCorrectionService: () => {
78
+ throw new Error("unexpected passiveCorrectionService");
79
+ },
80
+ passiveCorrectionTelemetry: {
81
+ detected: 0,
82
+ queued: 0,
83
+ autoApplied: 0,
84
+ suppressedReasonCounts: {},
85
+ },
86
+ queueBufferedExtraction: async (turns: BufferTurn[]) => {
87
+ queued.push(turns);
88
+ },
89
+ resolveMemoryIdOrHandle: () => {
90
+ throw new Error("unexpected resolveMemoryIdOrHandle");
91
+ },
92
+ runExtraction: async () => {
93
+ throw new Error("unexpected runExtraction");
94
+ },
95
+ get sessionObserver(): never {
96
+ throw new Error("unexpected sessionObserver");
97
+ },
98
+ shouldQueueExtraction: () => {
99
+ throw new Error("unexpected shouldQueueExtraction");
100
+ },
101
+ get transcript(): never {
102
+ throw new Error("unexpected transcript");
103
+ },
104
+ } as unknown as TurnIngestionDeps;
105
+ await new TurnIngestionCoordinator(deps).processTurn("user", "first", "k");
106
+ assert.equal(queued.length, 1);
107
+ assert.equal(queued[0]?.length, 1);
108
+ assert.equal(queued[0]?.[0]?.content, "first");
109
+ });
110
+ test("#2468 concurrent processTurn first trigger keeps its mutation snapshot", async () => {
111
+ const queued: BufferTurn[][] = [];
112
+ const buffer = new SmartBuffer(
113
+ parseConfig({ triggerMode: "every_n", bufferMaxTurns: 1, bufferSaveDebounceMs: 0 }),
114
+ new FakeStorage({ turns: [], lastExtractionAt: null, extractionCount: 0 }) as never,
115
+ );
116
+ const deps = {
117
+ buffer,
118
+ config: parseConfig({ triggerMode: "every_n", bufferMaxTurns: 1 }),
119
+ getStorage: async () => {
120
+ throw new Error("unexpected getStorage");
121
+ },
122
+ bulkImportWriteNamespace: () => "default",
123
+ get extractionQueueCoordinator(): never {
124
+ throw new Error("unexpected extractionQueueCoordinator");
125
+ },
126
+ heartbeatObserverChains: new Map(),
127
+ lcmEngine: null,
128
+ passiveCorrectionDedup: new Set(),
129
+ passiveCorrectionService: () => {
130
+ throw new Error("unexpected passiveCorrectionService");
131
+ },
132
+ passiveCorrectionTelemetry: {
133
+ detected: 0,
134
+ queued: 0,
135
+ autoApplied: 0,
136
+ suppressedReasonCounts: {},
137
+ },
138
+ queueBufferedExtraction: async (turns: BufferTurn[]) => {
139
+ queued.push(turns);
140
+ },
141
+ resolveMemoryIdOrHandle: () => {
142
+ throw new Error("unexpected resolveMemoryIdOrHandle");
143
+ },
144
+ runExtraction: async () => {
145
+ throw new Error("unexpected runExtraction");
146
+ },
147
+ get sessionObserver(): never {
148
+ throw new Error("unexpected sessionObserver");
149
+ },
150
+ shouldQueueExtraction: () => {
151
+ throw new Error("unexpected shouldQueueExtraction");
152
+ },
153
+ get transcript(): never {
154
+ throw new Error("unexpected transcript");
155
+ },
156
+ } as unknown as TurnIngestionDeps;
157
+ const coordinator = new TurnIngestionCoordinator(deps);
158
+ await Promise.all([
159
+ coordinator.processTurn("user", "alpha", "shared-key"),
160
+ coordinator.processTurn("user", "beta", "shared-key"),
161
+ ]);
162
+ assert.equal(queued.length, 2);
163
+ assert.ok(
164
+ queued.some((batch) => batch.length === 1),
165
+ "the first trigger must extract only its mutation snapshot",
166
+ );
167
+ });
@@ -201,8 +201,9 @@ export class TurnIngestionCoordinator {
201
201
  : { decision: await this.deps.buffer.addTurn(bufferKey, turn) };
202
202
 
203
203
  if (outcome.decision === "keep_buffering") return;
204
+ if (!outcome.extractionTurns) return;
204
205
  await this.deps.queueBufferedExtraction(
205
- outcome.extractionTurns ?? this.deps.buffer.getTurns(bufferKey),
206
+ outcome.extractionTurns,
206
207
  "trigger_mode",
207
208
  { bufferKey },
208
209
  );
@@ -110,6 +110,20 @@ export interface ContentHashPathEntry {
110
110
  */
111
111
  export class ContentHashIndex {
112
112
  private hashes: Set<string> = new Set();
113
+ /**
114
+ * Fact-ONLY hash partition (issue #2474). `hashes` above is category-blind
115
+ * (every write category registers there); this subset carries only
116
+ * `category === "fact"` hashes so fact-only membership checks
117
+ * (`hasFact*`) can never be satisfied by an unrelated decision/preference
118
+ * sharing the same normalized body. In-memory only — never serialized to
119
+ * fact-hashes.txt; `clear()` drops it and every authoritative rebuild
120
+ * repopulates it via `addFactByHash`. Subset invariant: `factHashes ⊆
121
+ * hashes` — `addFact*` registers in both, and the removal sites that drop
122
+ * a shared hash also drop the partition entry (removal stays caller-paired
123
+ * because shared-index removal is category-blind: archiving a non-fact
124
+ * must not evict an active fact's fact-only membership).
125
+ */
126
+ private factHashes: Set<string> = new Set();
113
127
  private dirty = false;
114
128
  /** True when load() found the pre-Unicode, markerless on-disk format. */
115
129
  private formatMigrationRequired = false;
@@ -290,6 +304,9 @@ export class ContentHashIndex {
290
304
  if (this.hashes.size > 0) {
291
305
  this.hashes.clear();
292
306
  }
307
+ // The fact-only partition is rebuilt with the shared set on every
308
+ // authoritative corpus rebuild, so it clears here too (issue #2474).
309
+ this.factHashes.clear();
293
310
  // A full clear is always paired with a plain overwrite save() (rebuild);
294
311
  // pending per-hash add/remove deltas are subsumed by writing the rebuilt set.
295
312
  // Cancel any armed deferred-reconcile retry (PR #2016) so it cannot fire in
@@ -693,6 +710,43 @@ export class ContentHashIndex {
693
710
  this.dirty = true;
694
711
  }
695
712
 
713
+ // ── Fact-only partition (issue #2474) ─────────────────────────────────
714
+ // Folded here from StorageManager's parallel `factOnlyHashes` set, which had
715
+ // to be kept in lockstep by hand on every add/remove/rebuild site. The
716
+ // partition lives on the index instance, so every path that mutates the
717
+ // shared set and needs fact-only truth mutates it in the same breath.
718
+
719
+ /** Register fact content in BOTH the shared index and the fact-only partition. */
720
+ addFact(content: string): void {
721
+ this.addFactByHash(ContentHashIndex.computeHash(content));
722
+ }
723
+
724
+ /** Register a pre-computed fact hash in both the shared index and the fact-only partition. */
725
+ addFactByHash(hash: string): void {
726
+ this.addByHash(hash);
727
+ this.factHashes.add(hash);
728
+ }
729
+
730
+ /** Fact-ONLY membership: has this content been registered as a fact? */
731
+ hasFact(content: string): boolean {
732
+ return this.factHashes.has(ContentHashIndex.computeHash(content));
733
+ }
734
+
735
+ /** Fact-ONLY membership for a pre-computed SHA-256 hash. */
736
+ hasFactByHash(hash: string): boolean {
737
+ return this.factHashes.has(hash);
738
+ }
739
+
740
+ /**
741
+ * Drop fact-only partition membership WITHOUT touching the shared index.
742
+ * The shared removal stays caller-owned: a shared hash is dropped only when
743
+ * no other active memory holds it, while fact-only membership follows the
744
+ * fact's own lifecycle (supersede/archive/promotion).
745
+ */
746
+ removeFactByHash(hash: string): void {
747
+ this.factHashes.delete(hash);
748
+ }
749
+
696
750
  /**
697
751
  * Resolve a pre-computed semantic hash to one deterministic corpus path.
698
752
  *
@@ -11,7 +11,7 @@
11
11
  import assert from "node:assert/strict";
12
12
  import test from "node:test";
13
13
 
14
- import { ContentHashIndex } from "../storage.js";
14
+ import { ContentHashIndex, StorageManager } from "../storage.js";
15
15
  import { makeStorage } from "./harness.js";
16
16
 
17
17
  test("content-hash: ContentHashIndex.computeHash is deterministic for the same input", () => {
@@ -158,3 +158,61 @@ test("content-hash: the frontmatter contentHash matches computeHash of the raw c
158
158
  await cleanup();
159
159
  }
160
160
  });
161
+
162
+ test("content-hash: fact-only membership across write, supersede, and rebuild — no stale true (#2474)", async () => {
163
+ const { storage, baseDir, cleanup } = await makeStorage();
164
+ try {
165
+ const supersededBody = "the staging region retires on friday";
166
+ const activeBody = "the production region stays";
167
+
168
+ // Write: both facts register fact-only membership on the shared index.
169
+ await storage.writeMemory("fact", supersededBody);
170
+ await storage.writeMemory("fact", activeBody);
171
+ assert.equal(
172
+ await storage.hasFactContentHash(supersededBody),
173
+ true,
174
+ "write registers the fact-only hash",
175
+ );
176
+ assert.equal(await storage.hasFactContentHash(activeBody), true);
177
+
178
+ // Supersede: the frontmatter rewrite runs syncFactHashIndexAfterRewrite →
179
+ // removeFactContentHashesForMemories, which must drop BOTH the shared hash
180
+ // and the fact-only partition. A stale partition entry is the PR #2016
181
+ // stale-true bug class: wearable / explicit-capture / promotion callers
182
+ // would skip a valid re-write.
183
+ const mem = (await storage.readAllMemories()).find((m) =>
184
+ (m.content ?? "").includes(supersededBody),
185
+ );
186
+ assert.ok(mem, "the fact to supersede must exist");
187
+ const ok = await storage.writeMemoryFrontmatter(mem!, { status: "superseded" });
188
+ assert.equal(ok, true, "frontmatter rewrite must succeed");
189
+ assert.equal(
190
+ await storage.hasFactContentHash(supersededBody),
191
+ false,
192
+ "no stale hasFactContentHash true after supersede",
193
+ );
194
+ assert.equal(
195
+ await storage.hasFactContentHash(activeBody),
196
+ true,
197
+ "the untouched fact keeps its fact-only membership",
198
+ );
199
+
200
+ // Rebuild: a fresh instance repopulates the index from the corpus. The
201
+ // superseded fact must stay out of the fact-only partition; the active
202
+ // fact must survive.
203
+ const reopened = new StorageManager(baseDir);
204
+ await reopened.ensureDirectories();
205
+ assert.equal(
206
+ await reopened.hasFactContentHash(supersededBody),
207
+ false,
208
+ "superseded fact stays out of fact-only membership after rebuild",
209
+ );
210
+ assert.equal(
211
+ await reopened.hasFactContentHash(activeBody),
212
+ true,
213
+ "active fact survives the rebuild",
214
+ );
215
+ } finally {
216
+ await cleanup();
217
+ }
218
+ });
@@ -308,10 +308,10 @@ test("direct writeMemory('fact') without the flag persists the hash via the LOCK
308
308
  });
309
309
 
310
310
  test("#2016 thread SDzOT: a fact hash added during the authoritative rebuild's corpus scan is not lost", async () => {
311
- // The rebuild used to build a fresh `factOnly` set and publish it with
312
- // `this.factOnlyHashes = factOnly`, dropping any concurrent in-process
313
- // writeMemory that added to the LIVE set during the readAllMemories /
314
- // readAllColdMemories awaits. The rebuild now repopulates the live set in place
311
+ // The rebuild used to build a fresh fact-only set and publish it with a
312
+ // reassignment, dropping any concurrent in-process writeMemory that added to
313
+ // the LIVE membership during the readAllMemories / readAllColdMemories
314
+ // awaits. The fact-only partition on ContentHashIndex repopulates in place
315
315
  // (clear + add), so a concurrent add survives publication — exactly as the
316
316
  // shared index preserves concurrent adds by mutating its `hashes` set in place.
317
317
  await withMemoryDir(async (dir) => {
@@ -320,7 +320,7 @@ test("#2016 thread SDzOT: a fact hash added during the authoritative rebuild's c
320
320
  await storage.writeMemory("fact", "alpha established fact", { source: "extraction" });
321
321
 
322
322
  const s = storage as unknown as {
323
- factOnlyHashes: Set<string>;
323
+ factHashIndex: ContentHashIndex | null;
324
324
  factHashIndexAuthoritative: boolean | null;
325
325
  readAllColdMemories: () => Promise<unknown[]>;
326
326
  ensureFactHashIndexAuthoritative: () => Promise<boolean>;
@@ -329,13 +329,13 @@ test("#2016 thread SDzOT: a fact hash added during the authoritative rebuild's c
329
329
  const realCold = s.readAllColdMemories.bind(storage);
330
330
  let injected = false;
331
331
  // Interpose on the SECOND corpus await inside the rebuild (after clear()):
332
- // simulate a concurrent writeMemory adding a fact hash to the live set while
333
- // the rebuild is mid-scan.
332
+ // simulate a concurrent writeMemory adding a fact hash to the live
333
+ // partition while the rebuild is mid-scan.
334
334
  s.readAllColdMemories = async () => {
335
335
  const res = await realCold();
336
336
  if (!injected) {
337
337
  injected = true;
338
- s.factOnlyHashes.add(sentinel);
338
+ s.factHashIndex?.addFactByHash(sentinel);
339
339
  }
340
340
  return res;
341
341
  };
@@ -345,7 +345,7 @@ test("#2016 thread SDzOT: a fact hash added during the authoritative rebuild's c
345
345
  assert.equal(await s.ensureFactHashIndexAuthoritative(), true, "rebuild published");
346
346
 
347
347
  assert.equal(
348
- s.factOnlyHashes.has(sentinel),
348
+ s.factHashIndex?.hasFactByHash(sentinel),
349
349
  true,
350
350
  "a fact hash added during the rebuild scan must survive publication (lost under reassign)"
351
351
  );
package/src/storage.ts CHANGED
@@ -1867,19 +1867,15 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
1867
1867
  private factHashIndexAuthoritative: boolean | null = null;
1868
1868
  private factHashIndexAuthoritativePromise: Promise<boolean> | null = null;
1869
1869
  /**
1870
- * Fact-ONLY hash membership (PR #2016). The shared `factHashIndex` above is
1871
- * category-agnostic (the round-15 corpus rebuild + addContentHashDedup index
1872
- * every category), so it cannot answer a fact-only question. This set carries
1873
- * only `category === "fact"` hashes and is the sole source for
1874
- * `hasFactContentHash`, so an over-included non-fact body can never suppress a
1875
- * real fact candidate. Kept in lockstep with the shared index on EVERY path:
1876
- * the authoritative corpus rebuild (repopulated in place), the write path
1877
- * (`writeMemory` / `addActiveFactContentHash`), the storage-owned removal
1878
- * (`removeFactContentHashesForMemories`), AND the orchestrator's archival /
1879
- * consolidation removal (`removeContentHashForMemory` ->
1880
- * `removeFactOnlyHashForMemory`). In-memory only; never persisted.
1870
+ * Fact-ONLY hash membership (PR #2016 / issue #2474) lives on the shared
1871
+ * `ContentHashIndex` fact-only partition (`addFact*` / `hasFact*` /
1872
+ * `removeFactByHash`), not a parallel set here. The partition carries only
1873
+ * `category === "fact"` hashes and is the sole source for
1874
+ * `hasFactContentHash`, so an over-included non-fact body can never
1875
+ * suppress a real fact candidate. In-memory only; never persisted every
1876
+ * authoritative corpus rebuild repopulates it via
1877
+ * `ContentHashIndex.clear()` + `addFactByHash`.
1881
1878
  */
1882
- private factOnlyHashes: Set<string> = new Set();
1883
1879
  /** Optional lock/retry tuning for the fact-hash index cross-process lock (PR #2016; tests inject tight budgets). */
1884
1880
  factHashIndexLockOptions: ContentHashIndexLockOptions = {};
1885
1881
  private readonly secureAppendChains = new Map<string, Promise<void>>();
@@ -3328,15 +3324,14 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
3328
3324
  */
3329
3325
  private async rebuildFactHashIndexFromCorpus(factHashIndex: ContentHashIndex): Promise<void> {
3330
3326
  factHashIndex.clear();
3331
- // Fact-ONLY membership rebuilt in lockstep (PR #2016): hasFactContentHash
3332
- // reads THIS set, never the category-agnostic shared index below, so an
3333
- // over-included non-fact body can never satisfy a fact-hash check. Repopulate
3334
- // the LIVE set in place (clear + add) rather than building a fresh set and
3335
- // reassigning: a concurrent in-process writeMemory that adds a fact hash
3336
- // during the corpus-read awaits below would be lost by a publish-time
3337
- // reassignment (PR #2016 thread SDzOT), exactly as the shared index avoids
3338
- // by mutating its `hashes` set in place.
3339
- this.factOnlyHashes.clear();
3327
+ // Fact-ONLY membership is rebuilt in lockstep (PR #2016 / issue #2474):
3328
+ // hasFactContentHash reads the index's fact-only partition, never the
3329
+ // category-agnostic shared set, so an over-included non-fact body can
3330
+ // never satisfy a fact-hash check. `factHashIndex.clear()` above cleared
3331
+ // the partition too, and it repopulates in place below a concurrent
3332
+ // in-process writeMemory that adds a fact hash during the corpus-read
3333
+ // awaits survives publication (PR #2016 thread SDzOT), exactly as the
3334
+ // shared index preserves by mutating its `hashes` set in place.
3340
3335
  // #1909 review round 14: index the HOT and COLD tiers together. A fact or
3341
3336
  // procedure demoted to cold/ is still active and its content-hash must
3342
3337
  // survive the corpus rebuild, or a restart would drop the hash and let the
@@ -3371,8 +3366,11 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
3371
3366
  continue;
3372
3367
  }
3373
3368
  for (const hash of hashes) {
3374
- factHashIndex.addByHash(hash);
3375
- if (memory.frontmatter.category === "fact") this.factOnlyHashes.add(hash);
3369
+ if (memory.frontmatter.category === "fact") {
3370
+ factHashIndex.addFactByHash(hash);
3371
+ } else {
3372
+ factHashIndex.addByHash(hash);
3373
+ }
3376
3374
  }
3377
3375
  }
3378
3376
  if (legacyRecovered > 0) {
@@ -3896,8 +3894,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
3896
3894
  options.contentHashSource !== undefined && options.contentHashSource.length > 0
3897
3895
  ? sanitizeMemoryContent(options.contentHashSource).text
3898
3896
  : sanitized.text;
3899
- factHashIndex.add(hashText);
3900
- this.factOnlyHashes.add(ContentHashIndex.computeHash(hashText));
3897
+ factHashIndex.addFact(hashText);
3901
3898
  // Gate only the flush (issue #1909): the `.add(...)` above already set
3902
3899
  // dirty=true. When the caller defers, it owns the batch save
3903
3900
  // (extraction persist -> saveContentHashIndexes()). Single-write callers
@@ -3973,7 +3970,8 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
3973
3970
  // upkeep); otherwise the snapshot may be stale, so verify against the durable
3974
3971
  // fact corpus (ground truth) so a lock-contended read never suppresses a fact.
3975
3972
  if (authoritative) {
3976
- return this.factOnlyHashes.has(hash);
3973
+ const factHashIndex = await this.getFactHashIndex();
3974
+ return factHashIndex.hasFact(sanitized.text);
3977
3975
  }
3978
3976
  return await this.factContentHashPresentInCorpus(hash);
3979
3977
  }
@@ -4002,8 +4000,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
4002
4000
  await this.ensureFactHashIndexAuthoritative();
4003
4001
  const factHashIndex = await this.getFactHashIndex();
4004
4002
  for (const hash of hashes) {
4005
- factHashIndex.addByHash(hash);
4006
- this.factOnlyHashes.add(hash);
4003
+ factHashIndex.addFactByHash(hash);
4007
4004
  }
4008
4005
  // PR #2016 thread SDzOP: flush through the SAME cross-process locked
4009
4006
  // reconcile the write/batch/rebuild paths use, never the unlocked whole-file
@@ -4089,7 +4086,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
4089
4086
  for (const hash of removedHashes) {
4090
4087
  if (!remainingActiveHashes.has(hash)) {
4091
4088
  factHashIndex.removeByHash(hash);
4092
- this.factOnlyHashes.delete(hash);
4089
+ factHashIndex.removeFactByHash(hash);
4093
4090
  }
4094
4091
  }
4095
4092
  // PR #2016 thread SDzOP: serialize the removal with the per-index lock via
@@ -4102,21 +4099,23 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
4102
4099
  }
4103
4100
 
4104
4101
  /**
4105
- * Remove a memory's fact-ONLY hash membership in lockstep with the shared,
4106
- * category-agnostic index removal the orchestrator's
4107
- * `removeContentHashForMemory` performs on archival / semantic consolidation
4108
- * (PR #2016 threads SDzOP / SDzOR). Without this, `factOnlyHashes` kept a
4109
- * removed/superseded fact's hash and `hasFactContentHash` returned a stale
4110
- * `true` until the next corpus rebuild, so wearable / explicit-capture /
4111
- * promotion callers skipped a valid write. In-memory only — `factOnlyHashes`
4112
- * is never persisted; it is rebuilt from the corpus. No-op for non-facts.
4113
- * Matches the shared index's unconditional per-hash removal so the two stay
4114
- * coherent.
4102
+ * Remove a memory's fact-ONLY partition membership in lockstep with the
4103
+ * shared, category-agnostic index removal the orchestrator's
4104
+ * `removeContentHashForMemory` performs on archival / semantic
4105
+ * consolidation (PR #2016 threads SDzOP / SDzOR). Without this, the
4106
+ * partition kept a removed/superseded fact's hash and `hasFactContentHash`
4107
+ * returned a stale `true` until the next corpus rebuild, so wearable /
4108
+ * explicit-capture / promotion callers skipped a valid write. No-op when
4109
+ * the fact-hash index has not been loaded in this process yet (the
4110
+ * partition is empty then and the corpus rebuild excludes the removed
4111
+ * memory). No-op for non-facts.
4115
4112
  */
4116
4113
  removeFactOnlyHashForMemory(memory: MemoryFile): void {
4117
4114
  if (memory.frontmatter.category !== "fact") return;
4115
+ const factHashIndex = this.factHashIndex;
4116
+ if (!factHashIndex) return;
4118
4117
  for (const hash of this.factContentHashesForRemoval(memory)) {
4119
- this.factOnlyHashes.delete(hash);
4118
+ factHashIndex.removeFactByHash(hash);
4120
4119
  }
4121
4120
  }
4122
4121