@remnic/core 9.50.2 → 9.51.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 (483) hide show
  1. package/dist/access-admin-ops-surface.d.ts +13 -11
  2. package/dist/access-admin-ops-surface.js +41 -39
  3. package/dist/access-authorization-probe.d.ts +13 -11
  4. package/dist/access-authorization-probe.js +42 -40
  5. package/dist/access-boundary.d.ts +13 -11
  6. package/dist/access-boundary.js +41 -39
  7. package/dist/access-cli.js +109 -104
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-coding-context-resolution.d.ts +3 -1
  10. package/dist/access-extraction-force-flush.d.ts +13 -11
  11. package/dist/access-extraction-force-flush.js +41 -39
  12. package/dist/access-health-types.d.ts +3 -1
  13. package/dist/access-http-lcm-compaction.d.ts +13 -11
  14. package/dist/access-http-lifecycle-flush.d.ts +13 -11
  15. package/dist/access-http-offline-stream.d.ts +13 -11
  16. package/dist/access-http-query.js +41 -39
  17. package/dist/access-http.d.ts +13 -11
  18. package/dist/access-http.js +52 -50
  19. package/dist/access-identity-continuity-surface.d.ts +11 -9
  20. package/dist/access-identity-continuity-surface.js +41 -39
  21. package/dist/access-lcm-surface.d.ts +13 -11
  22. package/dist/access-lcm-surface.js +41 -39
  23. package/dist/access-mcp.d.ts +13 -11
  24. package/dist/access-mcp.js +47 -45
  25. package/dist/access-memory-search-fanout.d.ts +4 -2
  26. package/dist/{access-namespace-preflight-Dj2QolFE.d.ts → access-namespace-preflight-Ds6CGlCP.d.ts} +1 -1
  27. package/dist/access-namespace-preflight.d.ts +5 -3
  28. package/dist/access-namespace-preflight.js +41 -39
  29. package/dist/access-observe-write-surface.d.ts +13 -11
  30. package/dist/access-observe-write-surface.js +41 -39
  31. package/dist/access-offline-manifest.d.ts +11 -9
  32. package/dist/access-operations-batch.js +43 -41
  33. package/dist/access-operations.d.ts +13 -11
  34. package/dist/access-operations.js +46 -44
  35. package/dist/access-recall-concurrency.d.ts +13 -11
  36. package/dist/access-recall-concurrency.js +41 -39
  37. package/dist/access-recall-response.d.ts +13 -11
  38. package/dist/access-recall-response.js +41 -39
  39. package/dist/access-recall-surface.d.ts +13 -11
  40. package/dist/access-recall-surface.js +41 -39
  41. package/dist/access-schema.js +3 -3
  42. package/dist/{access-service-DesbnTSa.d.ts → access-service-BY0KJ44c.d.ts} +7 -7
  43. package/dist/access-service-helpers.d.ts +13 -11
  44. package/dist/access-service.d.ts +13 -11
  45. package/dist/access-service.js +41 -39
  46. package/dist/access-surface-catalog.d.ts +13 -11
  47. package/dist/access-wearables-meetings-surface.d.ts +5 -3
  48. package/dist/action-confidence.d.ts +3 -1
  49. package/dist/active-memory-bridge.d.ts +3 -1
  50. package/dist/active-recall.d.ts +3 -1
  51. package/dist/active-recall.js +5 -3
  52. package/dist/active-recall.js.map +1 -1
  53. package/dist/adapters/index.js +4 -4
  54. package/dist/adapters/registry.js +2 -2
  55. package/dist/ambient-provenance.d.ts +3 -1
  56. package/dist/archive-mutation-version.d.ts +9 -0
  57. package/dist/archive-mutation-version.js +20 -0
  58. package/dist/artifact-search.d.ts +3 -1
  59. package/dist/behavior-learner.d.ts +3 -1
  60. package/dist/behavior-signals.d.ts +3 -1
  61. package/dist/bootstrap.d.ts +11 -9
  62. package/dist/briefing.d.ts +4 -2
  63. package/dist/briefing.js +10 -9
  64. package/dist/buffer-surprise-report.d.ts +3 -1
  65. package/dist/buffer-turn-helpers.d.ts +3 -1
  66. package/dist/buffer.d.ts +4 -2
  67. package/dist/buffer.js +5 -5
  68. package/dist/bulk-import/index.d.ts +5 -3
  69. package/dist/calibration.d.ts +3 -1
  70. package/dist/capabilities.d.ts +3 -1
  71. package/dist/{catalog-D-G7RgXR.d.ts → catalog-D3B4RDy1.d.ts} +1 -1
  72. package/dist/causal-behavior.d.ts +3 -1
  73. package/dist/causal-behavior.js +2 -2
  74. package/dist/causal-chain.js +2 -2
  75. package/dist/causal-consolidation.d.ts +3 -1
  76. package/dist/causal-consolidation.js +13 -12
  77. package/dist/causal-consolidation.js.map +1 -1
  78. package/dist/causal-retrieval.js +2 -2
  79. package/dist/causal-trajectory-graph.d.ts +4 -2
  80. package/dist/causal-trajectory-graph.js +2 -1
  81. package/dist/causal-trajectory-graph.js.map +1 -1
  82. package/dist/causal-trajectory.js +1 -1
  83. package/dist/{chunk-KDG2KTWW.js → chunk-33SV3E43.js} +4 -4
  84. package/dist/{chunk-2HGUDBRJ.js → chunk-37ZO6LLJ.js} +2 -2
  85. package/dist/{chunk-QW3WFHKU.js → chunk-45BRYON6.js} +2 -2
  86. package/dist/{chunk-GZICBRWK.js → chunk-4F6X3RXW.js} +2 -2
  87. package/dist/{chunk-7BAYBYY5.js → chunk-4PC4PRJE.js} +2 -2
  88. package/dist/{chunk-VJXY5ZCT.js → chunk-52UKFTUK.js} +2 -2
  89. package/dist/{chunk-ESG7Z255.js → chunk-5UDMFE3Q.js} +2 -2
  90. package/dist/{chunk-JPHEOE6Z.js → chunk-6MTSFX7A.js} +15 -15
  91. package/dist/chunk-6ZN34ISG.js +44 -0
  92. package/dist/chunk-6ZN34ISG.js.map +1 -0
  93. package/dist/{chunk-M4MP34AQ.js → chunk-AHZOMHWN.js} +1 -1
  94. package/dist/{chunk-Z3RHPGSY.js → chunk-AIUBBHSF.js} +3 -3
  95. package/dist/{chunk-S3AYIQCU.js → chunk-AXIDQG5A.js} +12 -12
  96. package/dist/{chunk-QN7NTKRC.js → chunk-AZ2QBGYB.js} +1 -1
  97. package/dist/{chunk-47J4EDGR.js → chunk-AZM4CCAC.js} +8 -8
  98. package/dist/{chunk-IXXABW5A.js → chunk-BHXYAVUM.js} +11 -5
  99. package/dist/chunk-BHXYAVUM.js.map +1 -0
  100. package/dist/{chunk-L2DPF4DF.js → chunk-BIJAWZYW.js} +54 -12
  101. package/dist/chunk-BIJAWZYW.js.map +1 -0
  102. package/dist/{chunk-LEJPSMKM.js → chunk-C5QLI33R.js} +3 -3
  103. package/dist/{chunk-SV3PSA7Y.js → chunk-CV6BBVYV.js} +5 -5
  104. package/dist/{chunk-V7X767RT.js → chunk-DCZBSE4F.js} +52 -52
  105. package/dist/chunk-FC67T4E6.js +70 -0
  106. package/dist/chunk-FC67T4E6.js.map +1 -0
  107. package/dist/{chunk-7PKFPLLZ.js → chunk-FXTYIA46.js} +2 -2
  108. package/dist/{chunk-64BHFFKZ.js → chunk-HLYR2TQL.js} +5 -5
  109. package/dist/{chunk-5C2HNJMO.js → chunk-J5LLX6IL.js} +32 -32
  110. package/dist/{chunk-RKNJBZ55.js → chunk-JBPKEARU.js} +4 -4
  111. package/dist/{chunk-PLKFO2HJ.js → chunk-JL43BVDE.js} +2 -2
  112. package/dist/{chunk-2S72LWKX.js → chunk-JYL3BVVZ.js} +2 -2
  113. package/dist/{chunk-IPLYGWQF.js → chunk-KQAFEZQX.js} +5 -5
  114. package/dist/chunk-LXY5VVGM.js +61 -0
  115. package/dist/chunk-LXY5VVGM.js.map +1 -0
  116. package/dist/{chunk-PYKKWQZ2.js → chunk-M7BXDKPR.js} +6 -6
  117. package/dist/{chunk-Z54EM5YZ.js → chunk-MAXVH44E.js} +7 -7
  118. package/dist/{chunk-LYMNZZIM.js → chunk-NIS256NW.js} +2 -2
  119. package/dist/{chunk-67QG75MJ.js → chunk-NLK2VZYZ.js} +2 -2
  120. package/dist/{chunk-A4QMKFFO.js → chunk-O5FFBO2M.js} +14 -28
  121. package/dist/chunk-O5FFBO2M.js.map +1 -0
  122. package/dist/{chunk-JYIFGGEM.js → chunk-OUKBMQ2O.js} +2 -2
  123. package/dist/{chunk-75XOWNRS.js → chunk-OYESWJ43.js} +4 -4
  124. package/dist/{chunk-TS4AJ2GI.js → chunk-PA45XCUD.js} +3 -3
  125. package/dist/{chunk-BJYET5TX.js → chunk-PRDJMOST.js} +7 -1
  126. package/dist/chunk-PRDJMOST.js.map +1 -0
  127. package/dist/{chunk-4MBPIL4V.js → chunk-PUSLMZBQ.js} +2 -2
  128. package/dist/{chunk-RVO6TCTU.js → chunk-QCECHYZL.js} +6 -6
  129. package/dist/{chunk-GFIKG4FR.js → chunk-QGR6OVGT.js} +2 -2
  130. package/dist/{chunk-NSGU76YO.js → chunk-QHFV6VNU.js} +6 -2
  131. package/dist/chunk-QHFV6VNU.js.map +1 -0
  132. package/dist/{chunk-PDEKQWDV.js → chunk-QT2FRYI4.js} +18 -2
  133. package/dist/chunk-QT2FRYI4.js.map +1 -0
  134. package/dist/{chunk-HNZKVLAN.js → chunk-S354QO4R.js} +2 -2
  135. package/dist/{chunk-NO37MR45.js → chunk-SOEN6KCF.js} +2 -2
  136. package/dist/{chunk-FXX6RQYC.js → chunk-TPTECFWR.js} +2 -2
  137. package/dist/{chunk-GDDGZVFI.js → chunk-UEVLYVNW.js} +2 -2
  138. package/dist/{chunk-YQ4IQ2GA.js → chunk-UT5BV5OG.js} +2 -2
  139. package/dist/{chunk-LAQ33B5D.js → chunk-UU3G6GUP.js} +1 -1
  140. package/dist/chunk-UU3G6GUP.js.map +1 -0
  141. package/dist/{chunk-LNTUXKBT.js → chunk-UYYW2KPU.js} +2 -2
  142. package/dist/{chunk-BOFVT6P3.js → chunk-VBHPOWBJ.js} +175 -98
  143. package/dist/chunk-VBHPOWBJ.js.map +1 -0
  144. package/dist/{chunk-QSYL5CXK.js → chunk-VKXWK44Q.js} +3 -3
  145. package/dist/{chunk-KMWYZTIE.js → chunk-VMMQDEN5.js} +2 -2
  146. package/dist/{chunk-JB6D7EFB.js → chunk-VVG2BOKA.js} +2 -2
  147. package/dist/chunk-W5BIQOAJ.js +69 -0
  148. package/dist/chunk-W5BIQOAJ.js.map +1 -0
  149. package/dist/{chunk-V5H6OJCR.js → chunk-W5XVQFLM.js} +2 -2
  150. package/dist/{chunk-OIOZ6MOP.js → chunk-W6FNX2LP.js} +2 -2
  151. package/dist/{chunk-6QPHF6RR.js → chunk-WQM326GS.js} +2 -2
  152. package/dist/{chunk-TQFHQPWD.js → chunk-XADV5IZ3.js} +8 -8
  153. package/dist/{chunk-DATDLJAO.js → chunk-XAPMEU3K.js} +2 -2
  154. package/dist/chunk-XXSOVESA.js +42 -0
  155. package/dist/chunk-XXSOVESA.js.map +1 -0
  156. package/dist/{chunk-IK6X5QPO.js → chunk-ZHY5TMJG.js} +1193 -443
  157. package/dist/chunk-ZHY5TMJG.js.map +1 -0
  158. package/dist/{chunk-N3LL5NEU.js → chunk-ZMYDYNI4.js} +2 -2
  159. package/dist/{cli-D4vvtxjY.d.ts → cli-CnOkH9hA.d.ts} +6 -6
  160. package/dist/cli.d.ts +15 -13
  161. package/dist/cli.js +74 -70
  162. package/dist/coding/pre-action-gate.d.ts +3 -1
  163. package/dist/coding/pre-action-gate.js +2 -2
  164. package/dist/compounding/engine.d.ts +4 -2
  165. package/dist/compounding/engine.js +10 -9
  166. package/dist/compounding/preference-consolidator.d.ts +3 -1
  167. package/dist/compression-optimizer.d.ts +3 -1
  168. package/dist/config.d.ts +3 -1
  169. package/dist/config.js +5 -3
  170. package/dist/connectors/codex-materialize-runner.d.ts +3 -1
  171. package/dist/connectors/codex-materialize-runner.js +10 -9
  172. package/dist/connectors/codex-materialize.d.ts +3 -1
  173. package/dist/connectors/index.d.ts +3 -1
  174. package/dist/connectors/index.js +10 -9
  175. package/dist/consolidation-provenance-check.d.ts +4 -2
  176. package/dist/consolidation-undo.d.ts +4 -2
  177. package/dist/contradiction/index.d.ts +4 -2
  178. package/dist/contradiction-config.d.ts +29 -0
  179. package/dist/contradiction-config.js +12 -0
  180. package/dist/contradiction-config.js.map +1 -0
  181. package/dist/converge-config.d.ts +3 -1
  182. package/dist/convergence-refresh.d.ts +4 -2
  183. package/dist/convergence-refresh.js +12 -11
  184. package/dist/conversation-index/backend.d.ts +3 -1
  185. package/dist/conversation-index/chunker.d.ts +3 -1
  186. package/dist/conversation-index/faiss-adapter.d.ts +3 -1
  187. package/dist/conversation-index/indexer.d.ts +3 -1
  188. package/dist/conversation-index/search.d.ts +3 -1
  189. package/dist/corpus-watermark.d.ts +3 -1
  190. package/dist/corpus-watermark.js +21 -20
  191. package/dist/day-summary.d.ts +3 -1
  192. package/dist/delinearize.d.ts +3 -1
  193. package/dist/dependency-propagation-config.d.ts +3 -1
  194. package/dist/direct-answer-wiring.d.ts +3 -1
  195. package/dist/direct-answer.d.ts +3 -1
  196. package/dist/embedding-fallback.d.ts +3 -1
  197. package/dist/enrichment/index.d.ts +3 -1
  198. package/dist/entity-retrieval.d.ts +4 -2
  199. package/dist/entity-retrieval.js +10 -9
  200. package/dist/entity-schema.d.ts +3 -1
  201. package/dist/explicit-capture.d.ts +11 -9
  202. package/dist/explicit-capture.js +3 -2
  203. package/dist/external-wiki-access.d.ts +13 -11
  204. package/dist/external-wiki-access.js +42 -40
  205. package/dist/external-wiki-collection-registration.d.ts +3 -1
  206. package/dist/external-wiki-collection.d.ts +3 -1
  207. package/dist/external-wiki-mcp-tools.d.ts +13 -11
  208. package/dist/extraction-error-classification.d.ts +3 -1
  209. package/dist/extraction-faithfulness.d.ts +3 -1
  210. package/dist/extraction-judge-telemetry.d.ts +3 -1
  211. package/dist/extraction-judge-training.d.ts +3 -1
  212. package/dist/extraction-judge.d.ts +3 -1
  213. package/dist/extraction-liveness.d.ts +3 -1
  214. package/dist/extraction-normalization.d.ts +3 -1
  215. package/dist/extraction-prompt.d.ts +3 -1
  216. package/dist/extraction-source-grounding-rules.d.ts +3 -1
  217. package/dist/extraction-source-grounding.d.ts +3 -1
  218. package/dist/extraction.d.ts +3 -1
  219. package/dist/extraction.js +22 -21
  220. package/dist/fallback-llm.d.ts +3 -1
  221. package/dist/graph-444E-DrF.d.ts +349 -0
  222. package/dist/graph-dashboard-diff.d.ts +4 -2
  223. package/dist/graph-dashboard-key.d.ts +4 -2
  224. package/dist/graph-dashboard-parser.d.ts +4 -2
  225. package/dist/{graph-edge-decay-Z6ENALU2.js → graph-edge-decay-65KMOJWY.js} +4 -3
  226. package/dist/graph-edge-decay-65KMOJWY.js.map +1 -0
  227. package/dist/graph-edge-reinforcement.d.ts +4 -2
  228. package/dist/graph-path-reconstruction.d.ts +10 -0
  229. package/dist/graph-path-reconstruction.js +12 -0
  230. package/dist/graph-path-reconstruction.js.map +1 -0
  231. package/dist/graph-path-scoring-config.d.ts +8 -0
  232. package/dist/graph-path-scoring-config.js +10 -0
  233. package/dist/graph-path-scoring-config.js.map +1 -0
  234. package/dist/graph-path-scoring.d.ts +36 -0
  235. package/dist/graph-path-scoring.js +11 -0
  236. package/dist/graph-path-scoring.js.map +1 -0
  237. package/dist/graph-snapshot.d.ts +4 -2
  238. package/dist/graph-snapshot.js +3 -2
  239. package/dist/graph.d.ts +5 -318
  240. package/dist/graph.js +5 -1
  241. package/dist/harmonic-retrieval.js +1 -1
  242. package/dist/importance.d.ts +3 -1
  243. package/dist/importers/index.d.ts +3 -1
  244. package/dist/in-flight-reads.d.ts +3 -1
  245. package/dist/index.d.ts +22 -20
  246. package/dist/index.js +149 -144
  247. package/dist/intent.d.ts +3 -1
  248. package/dist/lcm/engine.d.ts +3 -1
  249. package/dist/lcm/engine.js +3 -3
  250. package/dist/lcm/index.d.ts +3 -1
  251. package/dist/lcm/index.js +6 -6
  252. package/dist/lcm/tools.d.ts +3 -1
  253. package/dist/lifecycle.d.ts +3 -1
  254. package/dist/live-connectors-runner.d.ts +3 -1
  255. package/dist/local-llm.d.ts +3 -1
  256. package/dist/local-model-endpoint.d.ts +3 -1
  257. package/dist/maintenance/memory-governance.d.ts +3 -1
  258. package/dist/maintenance/memory-governance.js +10 -9
  259. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +4 -2
  260. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +10 -9
  261. package/dist/maintenance/rebuild-memory-projection.d.ts +4 -2
  262. package/dist/maintenance/rebuild-memory-projection.js +11 -10
  263. package/dist/{maintenance-ClmUVpGI.d.ts → maintenance-CKwxpdRx.d.ts} +3 -3
  264. package/dist/mcp-memory-inspector-app.d.ts +13 -11
  265. package/dist/memory-action-policy.d.ts +3 -1
  266. package/dist/memory-cache.d.ts +3 -1
  267. package/dist/memory-lifecycle-ledger-utils.d.ts +3 -1
  268. package/dist/memory-projection-store.d.ts +3 -1
  269. package/dist/memory-provenance.d.ts +3 -1
  270. package/dist/memory-snapshot.d.ts +3 -1
  271. package/dist/memory-worth-outcomes.d.ts +4 -2
  272. package/dist/models-json.d.ts +3 -1
  273. package/dist/namespaces/migrate.d.ts +5 -3
  274. package/dist/namespaces/migrate.js +20 -19
  275. package/dist/namespaces/principal.d.ts +3 -1
  276. package/dist/namespaces/search.d.ts +3 -1
  277. package/dist/namespaces/search.js +7 -7
  278. package/dist/namespaces/storage.d.ts +5 -3
  279. package/dist/namespaces/storage.js +10 -9
  280. package/dist/native-knowledge.d.ts +3 -1
  281. package/dist/offline-sync-impression-drain.d.ts +3 -1
  282. package/dist/operator-doctor-corpus.d.ts +3 -1
  283. package/dist/operator-doctor-corpus.js +22 -21
  284. package/dist/operator-doctor-replica.d.ts +3 -1
  285. package/dist/operator-toolkit.d.ts +6 -4
  286. package/dist/operator-toolkit.js +33 -29
  287. package/dist/orchestration/compression-guideline-coordinator.d.ts +4 -2
  288. package/dist/orchestration/maintenance.d.ts +6 -4
  289. package/dist/orchestration/maintenance.js +15 -14
  290. package/dist/{orchestrator-qJ07zI8H.d.ts → orchestrator-BshGam-o.d.ts} +45 -19
  291. package/dist/orchestrator.d.ts +11 -9
  292. package/dist/orchestrator.js +109 -104
  293. package/dist/patterns-cli.d.ts +3 -1
  294. package/dist/{pipeline-WFCxhHOn.d.ts → pipeline-D21Rs6gW.d.ts} +1 -1
  295. package/dist/policy-runtime.d.ts +3 -1
  296. package/dist/proactive-contention.d.ts +3 -1
  297. package/dist/provenance.d.ts +3 -1
  298. package/dist/{qmd-5tzkQ44y.d.ts → qmd-Dhle1P4X.d.ts} +1 -1
  299. package/dist/qmd-preflight.d.ts +4 -2
  300. package/dist/qmd-recall-cache.d.ts +3 -1
  301. package/dist/qmd.d.ts +4 -2
  302. package/dist/qmd.js +4 -4
  303. package/dist/recall-concurrency-config.d.ts +3 -1
  304. package/dist/recall-disclosure-escalation.d.ts +3 -1
  305. package/dist/recall-explain-renderer.d.ts +3 -1
  306. package/dist/recall-explain-renderer.js +3 -3
  307. package/dist/recall-memory-map.d.ts +3 -1
  308. package/dist/recall-planner-llm.d.ts +3 -1
  309. package/dist/recall-planner-llm.js +3 -3
  310. package/dist/recall-state.d.ts +7 -1
  311. package/dist/recall-state.js +1 -1
  312. package/dist/recall-tag-filter.d.ts +3 -1
  313. package/dist/recall-timings.d.ts +3 -1
  314. package/dist/recall-xray-cli.d.ts +3 -1
  315. package/dist/recall-xray-cli.js +4 -4
  316. package/dist/recall-xray-renderer.d.ts +3 -1
  317. package/dist/recall-xray-renderer.js +3 -3
  318. package/dist/recall-xray.d.ts +7 -1
  319. package/dist/recall-xray.js +2 -2
  320. package/dist/reconcile/cursor.d.ts +3 -1
  321. package/dist/reconcile/manifest.d.ts +3 -1
  322. package/dist/reconcile/plan.d.ts +3 -1
  323. package/dist/replay/normalizers/chatgpt.d.ts +3 -1
  324. package/dist/replay/normalizers/claude.d.ts +3 -1
  325. package/dist/replay/normalizers/openclaw.d.ts +3 -1
  326. package/dist/replay/normalizers/shared.d.ts +3 -1
  327. package/dist/replay/runner.d.ts +3 -1
  328. package/dist/replay/types.d.ts +3 -1
  329. package/dist/replica-divergence.d.ts +3 -1
  330. package/dist/replica-peers-config.d.ts +3 -1
  331. package/dist/resolve-auth-token.d.ts +3 -1
  332. package/dist/resume-bundles.js +6 -4
  333. package/dist/retrieval-agents.d.ts +4 -2
  334. package/dist/retrieval-tiers.d.ts +3 -1
  335. package/dist/routing/engine.d.ts +3 -1
  336. package/dist/routing/store.d.ts +3 -1
  337. package/dist/salvage-envelope.d.ts +3 -1
  338. package/dist/{scope-profiles--vfXPl3X.d.ts → scope-profiles-NzGPDXLn.d.ts} +1 -1
  339. package/dist/search/embed-helper.d.ts +3 -1
  340. package/dist/search/factory.d.ts +3 -1
  341. package/dist/search/factory.js +6 -6
  342. package/dist/search/index.d.ts +3 -1
  343. package/dist/search/index.js +12 -12
  344. package/dist/search/lancedb-backend.d.ts +3 -1
  345. package/dist/search/meilisearch-backend.d.ts +3 -1
  346. package/dist/search/noop-backend.d.ts +3 -1
  347. package/dist/search/orama-backend.d.ts +3 -1
  348. package/dist/search/port.d.ts +3 -1
  349. package/dist/search/remote-backend.d.ts +3 -1
  350. package/dist/{semantic-consolidation-BBDuP9nJ.d.ts → semantic-consolidation-DLDKvyy5.d.ts} +1 -1
  351. package/dist/semantic-consolidation.d.ts +4 -2
  352. package/dist/semantic-consolidation.js +11 -10
  353. package/dist/semantic-rule-promotion.js +10 -9
  354. package/dist/semantic-rule-verifier.d.ts +3 -1
  355. package/dist/semantic-rule-verifier.js +10 -9
  356. package/dist/{service-B8DtbpCM.d.ts → service-BIgVM7fL.d.ts} +2 -2
  357. package/dist/session-observer-bands.d.ts +3 -1
  358. package/dist/session-observer-state.d.ts +3 -1
  359. package/dist/shared-context/manager.d.ts +3 -1
  360. package/dist/signal.d.ts +3 -1
  361. package/dist/source-agent-qualifier.d.ts +3 -1
  362. package/dist/source-agent-qualifier.js +18 -17
  363. package/dist/{storage-BkYN1RIy.d.ts → storage-CVfGWqCI.d.ts} +7 -6
  364. package/dist/storage.d.ts +4 -2
  365. package/dist/storage.js +9 -8
  366. package/dist/summarizer.d.ts +3 -1
  367. package/dist/summary-snapshot.d.ts +3 -1
  368. package/dist/temporal-supersession.d.ts +4 -2
  369. package/dist/temporal-timeline-recall.d.ts +3 -1
  370. package/dist/temporal-validity.d.ts +3 -1
  371. package/dist/threading.d.ts +3 -1
  372. package/dist/tier-migration.d.ts +4 -2
  373. package/dist/tier-routing.d.ts +3 -1
  374. package/dist/topics.d.ts +3 -1
  375. package/dist/transcript.d.ts +3 -1
  376. package/dist/transfer/autodetect.js +1 -1
  377. package/dist/transfer/backup.js +1 -1
  378. package/dist/transfer/capsule-export.js +2 -2
  379. package/dist/trust-score-stage.d.ts +3 -1
  380. package/dist/trust-score.d.ts +3 -1
  381. package/dist/{types-u2s9j1uD.d.ts → types-CkiDUorT.d.ts} +10 -16
  382. package/dist/types.d.ts +3 -1
  383. package/dist/types.js +1 -1
  384. package/dist/utility-runtime.d.ts +3 -1
  385. package/dist/verified-recall.js +10 -9
  386. package/dist/write-envelope.d.ts +3 -1
  387. package/package.json +2 -2
  388. package/src/archive-mutation-version.ts +59 -0
  389. package/src/config.test.ts +45 -0
  390. package/src/config.ts +10 -30
  391. package/src/contradiction/contradiction.test.ts +86 -1
  392. package/src/contradiction-config.ts +92 -0
  393. package/src/graph-path-reconstruction.ts +91 -0
  394. package/src/graph-path-scoring-config.ts +55 -0
  395. package/src/graph-path-scoring.test.ts +238 -0
  396. package/src/graph-path-scoring.ts +77 -0
  397. package/src/graph.test.ts +225 -5
  398. package/src/graph.ts +72 -5
  399. package/src/orchestration/contradiction-linking-coordinator.ts +246 -76
  400. package/src/orchestration/contradiction-localization.integration.test.ts +1953 -0
  401. package/src/orchestration/extraction-anchor-snapshot.ts +83 -0
  402. package/src/orchestration/extraction-persist-deps.ts +8 -2
  403. package/src/orchestration/extraction-persist.ts +43 -34
  404. package/src/orchestration/graph-path-state-loader.test.ts +801 -0
  405. package/src/orchestration/graph-path-state-loader.ts +318 -0
  406. package/src/orchestration/graph-recall-coordinator.integration.test.ts +1163 -0
  407. package/src/orchestration/graph-recall-coordinator.ts +206 -29
  408. package/src/orchestration/graph-recall-seam.ts +19 -0
  409. package/src/orchestration/recall-internal-deps.ts +7 -13
  410. package/src/orchestration/recall-internal.ts +5 -0
  411. package/src/orchestration/recall-introspection.ts +9 -1
  412. package/src/orchestration/recall-search-pipeline.ts +8 -13
  413. package/src/orchestration/update-localization.test.ts +784 -0
  414. package/src/orchestration/update-localization.ts +173 -0
  415. package/src/orchestrator.ts +19 -18
  416. package/src/recall-state.test.ts +29 -1
  417. package/src/recall-state.ts +13 -0
  418. package/src/recall-xray-renderer.test.ts +45 -0
  419. package/src/recall-xray-renderer.ts +16 -0
  420. package/src/recall-xray.ts +13 -0
  421. package/src/storage/supersession-side-effects.ts +97 -0
  422. package/src/storage/tombstone-blocked-capture-sync.ts +13 -5
  423. package/src/storage-contract/cache-coherence.test.ts +299 -0
  424. package/src/storage.ts +86 -88
  425. package/src/types.ts +12 -15
  426. package/dist/chunk-A4QMKFFO.js.map +0 -1
  427. package/dist/chunk-BJYET5TX.js.map +0 -1
  428. package/dist/chunk-BOFVT6P3.js.map +0 -1
  429. package/dist/chunk-IK6X5QPO.js.map +0 -1
  430. package/dist/chunk-IXXABW5A.js.map +0 -1
  431. package/dist/chunk-L2DPF4DF.js.map +0 -1
  432. package/dist/chunk-LAQ33B5D.js.map +0 -1
  433. package/dist/chunk-NSGU76YO.js.map +0 -1
  434. package/dist/chunk-PDEKQWDV.js.map +0 -1
  435. /package/dist/{graph-edge-decay-Z6ENALU2.js.map → archive-mutation-version.js.map} +0 -0
  436. /package/dist/{chunk-KDG2KTWW.js.map → chunk-33SV3E43.js.map} +0 -0
  437. /package/dist/{chunk-2HGUDBRJ.js.map → chunk-37ZO6LLJ.js.map} +0 -0
  438. /package/dist/{chunk-QW3WFHKU.js.map → chunk-45BRYON6.js.map} +0 -0
  439. /package/dist/{chunk-GZICBRWK.js.map → chunk-4F6X3RXW.js.map} +0 -0
  440. /package/dist/{chunk-7BAYBYY5.js.map → chunk-4PC4PRJE.js.map} +0 -0
  441. /package/dist/{chunk-VJXY5ZCT.js.map → chunk-52UKFTUK.js.map} +0 -0
  442. /package/dist/{chunk-ESG7Z255.js.map → chunk-5UDMFE3Q.js.map} +0 -0
  443. /package/dist/{chunk-JPHEOE6Z.js.map → chunk-6MTSFX7A.js.map} +0 -0
  444. /package/dist/{chunk-M4MP34AQ.js.map → chunk-AHZOMHWN.js.map} +0 -0
  445. /package/dist/{chunk-Z3RHPGSY.js.map → chunk-AIUBBHSF.js.map} +0 -0
  446. /package/dist/{chunk-S3AYIQCU.js.map → chunk-AXIDQG5A.js.map} +0 -0
  447. /package/dist/{chunk-QN7NTKRC.js.map → chunk-AZ2QBGYB.js.map} +0 -0
  448. /package/dist/{chunk-47J4EDGR.js.map → chunk-AZM4CCAC.js.map} +0 -0
  449. /package/dist/{chunk-LEJPSMKM.js.map → chunk-C5QLI33R.js.map} +0 -0
  450. /package/dist/{chunk-SV3PSA7Y.js.map → chunk-CV6BBVYV.js.map} +0 -0
  451. /package/dist/{chunk-V7X767RT.js.map → chunk-DCZBSE4F.js.map} +0 -0
  452. /package/dist/{chunk-7PKFPLLZ.js.map → chunk-FXTYIA46.js.map} +0 -0
  453. /package/dist/{chunk-64BHFFKZ.js.map → chunk-HLYR2TQL.js.map} +0 -0
  454. /package/dist/{chunk-5C2HNJMO.js.map → chunk-J5LLX6IL.js.map} +0 -0
  455. /package/dist/{chunk-RKNJBZ55.js.map → chunk-JBPKEARU.js.map} +0 -0
  456. /package/dist/{chunk-PLKFO2HJ.js.map → chunk-JL43BVDE.js.map} +0 -0
  457. /package/dist/{chunk-2S72LWKX.js.map → chunk-JYL3BVVZ.js.map} +0 -0
  458. /package/dist/{chunk-IPLYGWQF.js.map → chunk-KQAFEZQX.js.map} +0 -0
  459. /package/dist/{chunk-PYKKWQZ2.js.map → chunk-M7BXDKPR.js.map} +0 -0
  460. /package/dist/{chunk-Z54EM5YZ.js.map → chunk-MAXVH44E.js.map} +0 -0
  461. /package/dist/{chunk-LYMNZZIM.js.map → chunk-NIS256NW.js.map} +0 -0
  462. /package/dist/{chunk-67QG75MJ.js.map → chunk-NLK2VZYZ.js.map} +0 -0
  463. /package/dist/{chunk-JYIFGGEM.js.map → chunk-OUKBMQ2O.js.map} +0 -0
  464. /package/dist/{chunk-75XOWNRS.js.map → chunk-OYESWJ43.js.map} +0 -0
  465. /package/dist/{chunk-TS4AJ2GI.js.map → chunk-PA45XCUD.js.map} +0 -0
  466. /package/dist/{chunk-4MBPIL4V.js.map → chunk-PUSLMZBQ.js.map} +0 -0
  467. /package/dist/{chunk-RVO6TCTU.js.map → chunk-QCECHYZL.js.map} +0 -0
  468. /package/dist/{chunk-GFIKG4FR.js.map → chunk-QGR6OVGT.js.map} +0 -0
  469. /package/dist/{chunk-HNZKVLAN.js.map → chunk-S354QO4R.js.map} +0 -0
  470. /package/dist/{chunk-NO37MR45.js.map → chunk-SOEN6KCF.js.map} +0 -0
  471. /package/dist/{chunk-FXX6RQYC.js.map → chunk-TPTECFWR.js.map} +0 -0
  472. /package/dist/{chunk-GDDGZVFI.js.map → chunk-UEVLYVNW.js.map} +0 -0
  473. /package/dist/{chunk-YQ4IQ2GA.js.map → chunk-UT5BV5OG.js.map} +0 -0
  474. /package/dist/{chunk-LNTUXKBT.js.map → chunk-UYYW2KPU.js.map} +0 -0
  475. /package/dist/{chunk-QSYL5CXK.js.map → chunk-VKXWK44Q.js.map} +0 -0
  476. /package/dist/{chunk-KMWYZTIE.js.map → chunk-VMMQDEN5.js.map} +0 -0
  477. /package/dist/{chunk-JB6D7EFB.js.map → chunk-VVG2BOKA.js.map} +0 -0
  478. /package/dist/{chunk-V5H6OJCR.js.map → chunk-W5XVQFLM.js.map} +0 -0
  479. /package/dist/{chunk-OIOZ6MOP.js.map → chunk-W6FNX2LP.js.map} +0 -0
  480. /package/dist/{chunk-6QPHF6RR.js.map → chunk-WQM326GS.js.map} +0 -0
  481. /package/dist/{chunk-TQFHQPWD.js.map → chunk-XADV5IZ3.js.map} +0 -0
  482. /package/dist/{chunk-DATDLJAO.js.map → chunk-XAPMEU3K.js.map} +0 -0
  483. /package/dist/{chunk-N3LL5NEU.js.map → chunk-ZMYDYNI4.js.map} +0 -0
@@ -24,7 +24,7 @@ import { _pairKey, _contentHash } from "./contradiction-judge.js";
24
24
  import { executeResolution, isValidResolutionVerb } from "./resolution.js";
25
25
  import { ACTIVE_STATUSES, runContradictionScan } from "./contradiction-scan.js";
26
26
  import { parseConfig } from "../config.js";
27
- import type { StorageManager } from "../storage.js";
27
+ import { StorageManager } from "../storage.js";
28
28
  import { sealedWriteToLegacyArgs, type SealedMemoryEnvelope } from "../write-envelope.js";
29
29
  import type { MemoryCategory, MemoryFile, MemoryFrontmatter } from "../types.js";
30
30
 
@@ -1780,6 +1780,91 @@ test("executeResolution merge supersedes both sources to a verified merged memor
1780
1780
  }
1781
1781
  });
1782
1782
 
1783
+ test("supersedeMemory chooses the canonically active cold duplicate over an archived hot duplicate", async () => {
1784
+ const { dir, cleanup } = await makeTempDir("contradiction-storage-");
1785
+ try {
1786
+ const hotPath = path.join(dir, "facts", "duplicate-hot.md");
1787
+ const coldPath = path.join(dir, "cold", "facts", "duplicate-cold.md");
1788
+ const hotContent = `---
1789
+ id: duplicate-memory
1790
+ category: fact
1791
+ created: 2026-05-17T00:00:00.000Z
1792
+ updated: 2026-05-17T00:00:00.000Z
1793
+ status: active
1794
+ archivedAt: 2026-05-17T00:01:00.000Z
1795
+ ---
1796
+
1797
+ duplicate content
1798
+ `;
1799
+ const coldContent = hotContent.replace("archivedAt: 2026-05-17T00:01:00.000Z\n", "");
1800
+ await mkdir(path.dirname(hotPath), { recursive: true });
1801
+ await mkdir(path.dirname(coldPath), { recursive: true });
1802
+ await writeFile(hotPath, hotContent, "utf8");
1803
+ await writeFile(coldPath, coldContent, "utf8");
1804
+
1805
+ const storage = new StorageManager(dir);
1806
+ assert.equal(await storage.supersedeMemory("duplicate-memory", "replacement-memory", "regression"), true);
1807
+
1808
+ const hot = await storage.readMemoryByPath(hotPath);
1809
+ const cold = await storage.readMemoryByPath(coldPath);
1810
+ assert.equal(hot?.frontmatter.status, "active");
1811
+ assert.equal(hot?.frontmatter.supersededBy, undefined);
1812
+ assert.equal(cold?.frontmatter.status, "superseded");
1813
+ assert.equal(cold?.frontmatter.supersededBy, "replacement-memory");
1814
+ } finally {
1815
+ await cleanup();
1816
+ }
1817
+ });
1818
+
1819
+ test("supersedeMemory refuses a target that becomes archived before the locked write", async () => {
1820
+ const { dir, cleanup } = await makeTempDir("contradiction-storage-race-");
1821
+ try {
1822
+ const memoryPath = path.join(dir, "facts", "race-memory.md");
1823
+ const activeContent = `---
1824
+ id: race-memory
1825
+ category: fact
1826
+ created: 2026-05-17T00:00:00.000Z
1827
+ updated: 2026-05-17T00:00:00.000Z
1828
+ status: active
1829
+ ---
1830
+
1831
+ race content
1832
+ `;
1833
+ const archivedContent = activeContent.replace(
1834
+ "status: active\n",
1835
+ "status: active\narchivedAt: 2026-05-17T00:01:00.000Z\n",
1836
+ );
1837
+ await mkdir(path.dirname(memoryPath), { recursive: true });
1838
+ await writeFile(memoryPath, activeContent, "utf8");
1839
+
1840
+ const storage = new StorageManager(dir);
1841
+ const privateStorage = storage as unknown as {
1842
+ withTombstoneBlockedMemoryPathLock: <T>(
1843
+ pathname: string,
1844
+ task: (current: MemoryFile | null) => Promise<T>,
1845
+ ) => Promise<T>;
1846
+ };
1847
+ const originalLock = privateStorage.withTombstoneBlockedMemoryPathLock;
1848
+ privateStorage.withTombstoneBlockedMemoryPathLock = async (pathname, task) => {
1849
+ await writeFile(pathname, archivedContent, "utf8");
1850
+ return task(await storage.readMemoryByPath(pathname));
1851
+ };
1852
+
1853
+ try {
1854
+ assert.equal(await storage.supersedeMemory("race-memory", "replacement-memory", "race"), false);
1855
+ } finally {
1856
+ privateStorage.withTombstoneBlockedMemoryPathLock = originalLock;
1857
+ }
1858
+
1859
+ const raced = await storage.readMemoryByPath(memoryPath);
1860
+ assert.equal(raced?.frontmatter.status, "active");
1861
+ assert.equal(raced?.frontmatter.archivedAt, "2026-05-17T00:01:00.000Z");
1862
+ assert.equal(raced?.frontmatter.supersededBy, undefined);
1863
+ } finally {
1864
+ await cleanup();
1865
+ }
1866
+ });
1867
+
1783
1868
  test("executeResolution merge can create and verify a merged memory from content", async () => {
1784
1869
  const { dir, cleanup } = await makeTempDir();
1785
1870
  try {
@@ -0,0 +1,92 @@
1
+ import { coerceBool, coerceNumber } from "./connectors/coerce.js";
2
+
3
+ /** Configuration for the nightly contradiction-scan cron (issue #520). */
4
+ export interface ContradictionScanConfig {
5
+ /** Master switch for the contradiction scan cron. Default true. */
6
+ enabled: boolean;
7
+ /** Embedding cosine similarity floor for candidate pair generation. Default 0.82. */
8
+ similarityFloor: number;
9
+ /** Minimum topic-token Jaccard overlap for unstructured pairs. Default 0.4. */
10
+ topicOverlapFloor: number;
11
+ /** Cap on candidate pairs evaluated per cron run. Default 500. */
12
+ maxPairsPerRun: number;
13
+ /** Cooldown in days before re-evaluating a pair judged independent/both-valid. Default 14. */
14
+ cooldownDays: number;
15
+ /** When true, pairs judged "duplicates" are auto-flagged for dedup (still need user approval). Default false. */
16
+ autoMergeDuplicates: boolean;
17
+ }
18
+
19
+ export interface ContradictionLocalizationConfig {
20
+ /** Enable the entity/category anchor pass before QMD search. */
21
+ anchorEnabled: boolean;
22
+ /** Maximum anchor candidates. Zero disables the anchor pass. */
23
+ anchorCandidates: number;
24
+ /** Maximum QMD search candidates. Zero disables text search. */
25
+ searchCandidates: number;
26
+ /** Maximum merged candidates passed to contradiction verification. */
27
+ maxCandidates: number;
28
+ }
29
+
30
+ export function parseContradictionScanConfig(raw: unknown): ContradictionScanConfig {
31
+ if (!raw || typeof raw !== "object") {
32
+ return {
33
+ enabled: false,
34
+ similarityFloor: 0.82,
35
+ topicOverlapFloor: 0.4,
36
+ maxPairsPerRun: 500,
37
+ cooldownDays: 14,
38
+ autoMergeDuplicates: false,
39
+ };
40
+ }
41
+ const src = raw as Record<string, unknown>;
42
+ const simFloor = coerceNumber(src.similarityFloor) ?? 0.82;
43
+ const topicFloor = coerceNumber(src.topicOverlapFloor) ?? 0.4;
44
+ const maxPairs = coerceNumber(src.maxPairsPerRun) ?? 500;
45
+ const cooldown = coerceNumber(src.cooldownDays) ?? 14;
46
+ return {
47
+ enabled: coerceBool(src.enabled) === true,
48
+ similarityFloor: Math.min(1, Math.max(0, simFloor)),
49
+ topicOverlapFloor: Math.min(1, Math.max(0, topicFloor)),
50
+ maxPairsPerRun: Math.max(1, maxPairs),
51
+ cooldownDays: Math.max(0, cooldown),
52
+ autoMergeDuplicates: coerceBool(src.autoMergeDuplicates) === true,
53
+ };
54
+ }
55
+
56
+ export function parseContradictionLocalizationConfig(raw: unknown): ContradictionLocalizationConfig {
57
+ const defaults: ContradictionLocalizationConfig = {
58
+ anchorEnabled: true,
59
+ anchorCandidates: 5,
60
+ searchCandidates: 5,
61
+ maxCandidates: 8,
62
+ };
63
+ if (raw === undefined || raw === null) return defaults;
64
+ if (typeof raw !== "object" || Array.isArray(raw)) {
65
+ throw new Error("contradictionLocalization must be an object");
66
+ }
67
+ const src = raw as Record<string, unknown>;
68
+ const rawEnabled = src.anchorEnabled;
69
+ const anchorEnabled = rawEnabled === undefined || rawEnabled === null ? true : coerceBool(rawEnabled);
70
+ if (anchorEnabled === undefined) {
71
+ throw new Error("contradictionLocalization.anchorEnabled must be a boolean-like value");
72
+ }
73
+
74
+ const parseCap = (
75
+ key: keyof Pick<ContradictionLocalizationConfig, "anchorCandidates" | "searchCandidates" | "maxCandidates">,
76
+ ): number => {
77
+ const rawValue = src[key];
78
+ if (rawValue === undefined) return defaults[key];
79
+ const parsed = coerceNumber(rawValue);
80
+ if (parsed === undefined || !Number.isInteger(parsed) || parsed < 0) {
81
+ throw new Error(`contradictionLocalization.${key} must be an integer >= 0`);
82
+ }
83
+ return parsed;
84
+ };
85
+
86
+ return {
87
+ anchorEnabled,
88
+ anchorCandidates: parseCap("anchorCandidates"),
89
+ searchCandidates: parseCap("searchCandidates"),
90
+ maxCandidates: parseCap("maxCandidates"),
91
+ };
92
+ }
@@ -0,0 +1,91 @@
1
+ import type { ActivationPath, GraphType } from "./graph.js";
2
+
3
+ export interface ActivationPredecessor {
4
+ prev: string;
5
+ edgeConfidence: number;
6
+ graphType: GraphType;
7
+ }
8
+
9
+ export interface ActivationPathCandidate {
10
+ hopDepth: number;
11
+ landingStrength: number;
12
+ pathKey: string;
13
+ }
14
+
15
+ /** Compare path winners: fewer hops, stronger landing, then lexical path order. */
16
+ export function compareActivationPathCandidates(
17
+ left: ActivationPathCandidate,
18
+ right: ActivationPathCandidate,
19
+ ): number {
20
+ if (left.hopDepth !== right.hopDepth) return right.hopDepth - left.hopDepth;
21
+ if (left.landingStrength !== right.landingStrength) return left.landingStrength - right.landingStrength;
22
+ if (left.pathKey === right.pathKey) return 0;
23
+ return left.pathKey < right.pathKey ? 1 : -1;
24
+ }
25
+
26
+ export class ActivationPathTracker {
27
+ readonly predecessors = new Map<string, ActivationPredecessor>();
28
+ private readonly winners = new Map<string, ActivationPathCandidate>();
29
+ private readonly pathKeys = new Map<string, string>();
30
+
31
+ constructor(seeds: Iterable<string>) {
32
+ for (const seed of seeds) {
33
+ this.pathKeys.set(`${seed}\0${seed}`, seed);
34
+ }
35
+ }
36
+
37
+ consider(
38
+ seed: string,
39
+ node: string,
40
+ neighbor: string,
41
+ hopDepth: number,
42
+ landingStrength: number,
43
+ edgeConfidence: number,
44
+ graphType: GraphType,
45
+ ): string {
46
+ const sourcePathKey = this.pathKeys.get(`${seed}\0${node}`);
47
+ if (!sourcePathKey) return "";
48
+
49
+ const key = `${seed}\0${neighbor}`;
50
+ const pathKey = `${sourcePathKey}\0${neighbor}`;
51
+ const candidate: ActivationPathCandidate = { hopDepth, landingStrength, pathKey };
52
+ const previous = this.winners.get(key);
53
+ if (!previous || compareActivationPathCandidates(candidate, previous) > 0) {
54
+ this.winners.set(key, candidate);
55
+ this.pathKeys.set(key, pathKey);
56
+ this.predecessors.set(key, { prev: node, edgeConfidence, graphType });
57
+ }
58
+ return pathKey;
59
+ }
60
+ }
61
+ export function reconstructActivationPath(
62
+ seed: string,
63
+ candidate: string,
64
+ predecessors: Map<string, ActivationPredecessor>,
65
+ maxSteps: number,
66
+ ): ActivationPath | null {
67
+ const nodeIds = [candidate];
68
+ const edgeConfidences: number[] = [];
69
+ const graphTypes: GraphType[] = [];
70
+ let current = candidate;
71
+ const stepCap = Number.isFinite(maxSteps)
72
+ ? Math.max(0, Math.ceil(maxSteps))
73
+ : predecessors.size + 1;
74
+ for (let step = 0; step < stepCap && current !== seed; step += 1) {
75
+ const predecessor = predecessors.get(`${seed}\0${current}`);
76
+ if (!predecessor) return null;
77
+ nodeIds.push(predecessor.prev);
78
+ edgeConfidences.push(predecessor.edgeConfidence);
79
+ graphTypes.push(predecessor.graphType);
80
+ current = predecessor.prev;
81
+ }
82
+
83
+ if (current !== seed) return null;
84
+ nodeIds.reverse();
85
+ edgeConfidences.reverse();
86
+ graphTypes.reverse();
87
+ if (edgeConfidences.length !== nodeIds.length - 1 || graphTypes.length !== nodeIds.length - 1) {
88
+ return null;
89
+ }
90
+ return { nodeIds, edgeConfidences, graphTypes };
91
+ }
@@ -0,0 +1,55 @@
1
+ import { coerceBool, coerceNumber } from "./connectors/coerce.js";
2
+
3
+ export interface GraphPathScoringConfig {
4
+ enabled: boolean;
5
+ invalidNodePenalty: number;
6
+ includePathInProvenance: boolean;
7
+ }
8
+
9
+ function resolveBooleanConfig(value: unknown, defaultValue: boolean, keyName: string): boolean {
10
+ if (value === undefined || value === null) return defaultValue;
11
+ const coerced = coerceBool(value);
12
+ if (coerced === undefined) {
13
+ throw new Error(
14
+ `${keyName} must be a boolean-like value (true/false/1/0/yes/no/on/off); got ${JSON.stringify(value)}`,
15
+ );
16
+ }
17
+ return coerced;
18
+ }
19
+
20
+ export function parseGraphPathScoringConfig(
21
+ cfg: Record<string, unknown> | undefined,
22
+ ): GraphPathScoringConfig {
23
+ if (cfg !== undefined && (typeof cfg !== "object" || Array.isArray(cfg))) {
24
+ throw new Error("graphPathScoring must be a plain object");
25
+ }
26
+ const block = cfg ?? {};
27
+ const invalidNodePenalty = coerceNumber(block.invalidNodePenalty);
28
+ if (
29
+ invalidNodePenalty === undefined ||
30
+ !Number.isFinite(invalidNodePenalty) ||
31
+ invalidNodePenalty <= 0 ||
32
+ invalidNodePenalty > 1
33
+ ) {
34
+ if (block.invalidNodePenalty !== undefined && block.invalidNodePenalty !== null) {
35
+ throw new Error(
36
+ `graphPathScoring.invalidNodePenalty must be a number in (0,1]; got ${JSON.stringify(block.invalidNodePenalty)}`,
37
+ );
38
+ }
39
+ }
40
+ return {
41
+ enabled: resolveBooleanConfig(block.enabled, false, "graphPathScoring.enabled"),
42
+ invalidNodePenalty:
43
+ invalidNodePenalty !== undefined &&
44
+ Number.isFinite(invalidNodePenalty) &&
45
+ invalidNodePenalty > 0 &&
46
+ invalidNodePenalty <= 1
47
+ ? invalidNodePenalty
48
+ : 0.2,
49
+ includePathInProvenance: resolveBooleanConfig(
50
+ block.includePathInProvenance,
51
+ true,
52
+ "graphPathScoring.includePathInProvenance",
53
+ ),
54
+ };
55
+ }
@@ -0,0 +1,238 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import type { ActivationPath } from "./graph.js";
4
+ import { scoreEvidencePath, type PathNodeState, type PathScoringOptions } from "./graph-path-scoring.js";
5
+
6
+ const activationPath = (nodeIds: string[], edgeConfidences: number[]): ActivationPath => ({
7
+ nodeIds,
8
+ edgeConfidences,
9
+ graphTypes: edgeConfidences.map(() => "entity"),
10
+ });
11
+
12
+ const state = (
13
+ id: string,
14
+ status: PathNodeState["status"] = "active",
15
+ invalidAt: string | null = null,
16
+ temporal: Record<string, string | null | undefined> = {},
17
+ ): PathNodeState => ({
18
+ id,
19
+ status,
20
+ created: "2025-01-01T00:00:00.000Z",
21
+ ...(invalidAt !== null ? { invalid_at: invalidAt } : {}),
22
+ ...temporal,
23
+ });
24
+
25
+ const score = (
26
+ evidencePath: ActivationPath | null,
27
+ states: ReadonlyMap<string, PathNodeState>,
28
+ options: Partial<PathScoringOptions> = {},
29
+ ): number =>
30
+ scoreEvidencePath(evidencePath, states, {
31
+ asOf: "2026-01-01T00:00:00.000Z",
32
+ invalidNodePenalty: 0.2,
33
+ ...options,
34
+ });
35
+
36
+ test("scores the edge confidence product across a clean path", () => {
37
+ assert.equal(score(activationPath(["seed", "mid", "candidate"], [0.8, 0.5]), new Map()), 0.4);
38
+ });
39
+
40
+ test("penalizes one invalid intermediate memory", () => {
41
+ const states = new Map([["mid", state("mid", "superseded")]]);
42
+ assert.equal(
43
+ score(activationPath(["seed", "mid", "candidate"], [0.8, 0.5]), states),
44
+ 0.8 * 0.5 * 0.2,
45
+ );
46
+ });
47
+
48
+ test("squares the penalty for two invalid intermediate memories", () => {
49
+ const states = new Map([
50
+ ["mid", state("mid", "superseded")],
51
+ ["mid-2", state("mid-2", "active", "2025-01-01T00:00:00.000Z")],
52
+ ]);
53
+ assert.equal(
54
+ score(activationPath(["seed", "mid", "mid-2", "candidate"], [0.8, 0.5, 0.25]), states),
55
+ 0.8 * 0.5 * 0.25 * 0.2 * 0.2,
56
+ );
57
+ });
58
+
59
+ test("ignores seed and candidate state", () => {
60
+ const states = new Map([
61
+ ["seed", state("seed", "rejected", "2025-01-01T00:00:00.000Z")],
62
+ ["candidate", state("candidate", "archived", "2025-01-01T00:00:00.000Z")],
63
+ ]);
64
+ assert.equal(score(activationPath(["seed", "candidate"], [0.7]), states), 0.7);
65
+ });
66
+
67
+ test("treats null status as neutral even with invalidAt", () => {
68
+ const states = new Map([
69
+ ["entity-mid", state("entity-mid", null, "2020-01-01T00:00:00.000Z")],
70
+ ]);
71
+ assert.equal(
72
+ score(activationPath(["seed", "entity-mid", "candidate"], [0.7, 0.6]), states),
73
+ 0.7 * 0.6,
74
+ );
75
+ });
76
+ test("treats malformed invalidAt as neutral", () => {
77
+ const states = new Map([
78
+ ["entity-mid", state("entity-mid", "superseded", "not-a-date")],
79
+ ]);
80
+ assert.equal(
81
+ score(activationPath(["seed", "entity-mid", "candidate"], [0.7, 0.6]), states),
82
+ 0.7 * 0.6,
83
+ );
84
+ });
85
+
86
+ test("treats an unknown intermediate id as neutral", () => {
87
+ assert.equal(
88
+ score(activationPath(["seed", "unknown", "candidate"], [0.7, 0.6]), new Map()),
89
+ 0.7 * 0.6,
90
+ );
91
+ });
92
+
93
+ test("treats invalidAt equal to asOf as invalid", () => {
94
+ const states = new Map([
95
+ ["boundary", state("boundary", "active", "2026-01-01T00:00:00.000Z")],
96
+ ]);
97
+ assert.equal(
98
+ score(activationPath(["seed", "boundary", "candidate"], [1, 1]), states),
99
+ 0.2,
100
+ );
101
+ });
102
+
103
+ test("treats a future invalidAt as valid", () => {
104
+ const states = new Map([
105
+ ["future", state("future", "active", "2026-01-02T00:00:00.000Z")],
106
+ ]);
107
+ assert.equal(
108
+ score(activationPath(["seed", "future", "candidate"], [1, 1]), states),
109
+ 1,
110
+ );
111
+ });
112
+ test("penalizes inactive intermediate nodes with a future invalidAt", () => {
113
+ for (const status of ["rejected", "quarantined", "pending_review", "archived", "forgotten"] as const) {
114
+ const states = new Map([
115
+ [status, state(status, status, "2026-01-02T00:00:00.000Z")],
116
+ ]);
117
+ assert.equal(
118
+ score(activationPath(["seed", status, "candidate"], [1, 1]), states),
119
+ 0.2,
120
+ `${status} intermediate node must remain invalid before invalidAt`,
121
+ );
122
+ }
123
+ });
124
+
125
+ test("keeps penalty one as a no-op", () => {
126
+ const states = new Map([["mid", state("mid", "rejected")]]);
127
+ assert.equal(
128
+ score(activationPath(["seed", "mid", "candidate"], [0.8, 0.5]), states, {
129
+ invalidNodePenalty: 1,
130
+ }),
131
+ 0.8 * 0.5,
132
+ );
133
+ });
134
+
135
+ test("returns one for a missing path", () => {
136
+ assert.equal(score(null, new Map()), 1);
137
+ });
138
+ test("reports path penalty only for invalid intermediate state", async () => {
139
+ const { scoreEvidencePathDetail } = await import("./graph-path-scoring.js");
140
+ const validDetail = scoreEvidencePathDetail(
141
+ activationPath(["seed", "mid", "candidate"], [0.2, 0.3]),
142
+ new Map([["mid", state("mid", "active")]]),
143
+ {
144
+ asOf: "2026-01-01T00:00:00.000Z",
145
+ invalidNodePenalty: 0.2,
146
+ },
147
+ );
148
+ assert.equal(validDetail.score, 0.2 * 0.3);
149
+ assert.equal(validDetail.pathPenaltyApplied, false);
150
+
151
+ const invalidDetail = scoreEvidencePathDetail(
152
+ activationPath(["seed", "mid", "candidate"], [1, 1]),
153
+ new Map([["mid", state("mid", "superseded")]]),
154
+ {
155
+ asOf: "2026-01-01T00:00:00.000Z",
156
+ invalidNodePenalty: 0.2,
157
+ },
158
+ );
159
+ assert.equal(invalidDetail.pathPenaltyApplied, true);
160
+ });
161
+
162
+ test("uses invalidAt for historical supersession validity", () => {
163
+ const states = new Map([
164
+ ["mid", state("mid", "superseded", "2026-02-01T00:00:00.000Z")],
165
+ ]);
166
+ assert.equal(
167
+ score(
168
+ activationPath(["seed", "mid", "candidate"], [1, 1]),
169
+ states,
170
+ { asOf: "2026-01-01T00:00:00.000Z" },
171
+ ),
172
+ 1,
173
+ );
174
+ assert.equal(
175
+ score(
176
+ activationPath(["seed", "mid", "candidate"], [1, 1]),
177
+ states,
178
+ { asOf: "2026-03-01T00:00:00.000Z" },
179
+ ),
180
+ 0.2,
181
+ );
182
+ });
183
+
184
+ test("penalizes an active intermediate that begins after historical asOf", () => {
185
+ const states = new Map([
186
+ [
187
+ "mid",
188
+ state("mid", "active", null, {
189
+ valid_at: "2026-02-01T00:00:00.000Z",
190
+ created: "2026-02-01T00:00:00.000Z",
191
+ }),
192
+ ],
193
+ ]);
194
+ assert.equal(
195
+ score(
196
+ activationPath(["seed", "mid", "candidate"], [1, 1]),
197
+ states,
198
+ { asOf: "2026-01-01T00:00:00.000Z" },
199
+ ),
200
+ 0.2,
201
+ );
202
+ });
203
+
204
+ test("uses legacy supersededAt as the historical end bound", () => {
205
+ const states = new Map([
206
+ [
207
+ "mid",
208
+ state("mid", "superseded", null, {
209
+ created: "2025-01-01T00:00:00.000Z",
210
+ supersededAt: "2026-02-01T00:00:00.000Z",
211
+ }),
212
+ ],
213
+ ]);
214
+ const path = activationPath(["seed", "mid", "candidate"], [1, 1]);
215
+ assert.equal(score(path, states, { asOf: "2026-01-01T00:00:00.000Z" }), 1);
216
+ assert.equal(score(path, states, { asOf: "2026-03-01T00:00:00.000Z" }), 0.2);
217
+ });
218
+
219
+ test("rejects a non-finite asOf", () => {
220
+ assert.throws(
221
+ () =>
222
+ score(
223
+ activationPath(["seed", "mid", "candidate"], [1, 1]),
224
+ new Map(),
225
+ { asOf: "not-a-date" },
226
+ ),
227
+ /asOf must be a finite timestamp/,
228
+ );
229
+ assert.throws(
230
+ () =>
231
+ scoreEvidencePath(
232
+ null,
233
+ new Map(),
234
+ { asOf: "not-a-date", invalidNodePenalty: 0.2 },
235
+ ),
236
+ /asOf must be a finite timestamp/,
237
+ );
238
+ });
@@ -0,0 +1,77 @@
1
+ import type { ActivationPath } from "./graph.js";
2
+ import type { MemoryFrontmatter, MemoryStatus } from "./types.js";
3
+ import { isValidAsOf } from "./temporal-validity.js";
4
+
5
+ /** Memory state used to score an intermediate path node. */
6
+ export interface PathNodeState
7
+ extends Pick<
8
+ MemoryFrontmatter,
9
+ "valid_at" | "invalid_at" | "created" | "supersededAt" | "eventTimeSource"
10
+ > {
11
+ id: string;
12
+ status: MemoryStatus | null;
13
+ }
14
+
15
+ /** Configuration for graph-path evidence scoring. */
16
+ export interface PathScoringOptions {
17
+ asOf: string;
18
+ invalidNodePenalty: number;
19
+ }
20
+
21
+ function isInvalidIntermediate(state: PathNodeState | undefined, asOfMs: number): boolean {
22
+ if (!state || state.status === null) return false;
23
+ if (!isValidAsOf({ ...state, status: state.status }, asOfMs)) return true;
24
+
25
+ const hasSupersessionEnd =
26
+ state.status === "superseded" &&
27
+ ((state.invalid_at?.trim().length ?? 0) > 0 ||
28
+ (state.supersededAt?.trim().length ?? 0) > 0);
29
+ return state.status !== "active" && !hasSupersessionEnd;
30
+ }
31
+
32
+ export interface PathScoreDetail {
33
+ score: number;
34
+ pathPenaltyApplied: boolean;
35
+ }
36
+
37
+ export function scoreEvidencePathDetail(
38
+ evidencePath: ActivationPath | null,
39
+ nodeStates: ReadonlyMap<string, PathNodeState>,
40
+ options: PathScoringOptions,
41
+ ): PathScoreDetail {
42
+ const asOfMs = Date.parse(options.asOf);
43
+ if (!Number.isFinite(asOfMs)) {
44
+ throw new Error("asOf must be a finite timestamp");
45
+ }
46
+ if (!evidencePath) return { score: 1, pathPenaltyApplied: false };
47
+ let multiplier = evidencePath.edgeConfidences.reduce(
48
+ (product, confidence) => product * confidence,
49
+ 1,
50
+ );
51
+ let invalidIntermediateCount = 0;
52
+ for (const nodeId of evidencePath.nodeIds.slice(1, -1)) {
53
+ if (isInvalidIntermediate(nodeStates.get(nodeId), asOfMs)) {
54
+ invalidIntermediateCount += 1;
55
+ multiplier *= options.invalidNodePenalty;
56
+ }
57
+ }
58
+ return {
59
+ score: multiplier,
60
+ pathPenaltyApplied: invalidIntermediateCount > 0 && options.invalidNodePenalty !== 1,
61
+ };
62
+ }
63
+
64
+ /**
65
+ * Return the multiplicative evidence factor for one graph activation path.
66
+ *
67
+ * Edge confidence is multiplied for every hop. Invalid intermediate memories
68
+ * receive the configured penalty once each. Seed and candidate states do not
69
+ * affect the result because the caller already scored those memories.
70
+ */
71
+ export function scoreEvidencePath(
72
+ evidencePath: ActivationPath | null,
73
+ nodeStates: ReadonlyMap<string, PathNodeState>,
74
+ options: PathScoringOptions,
75
+ ): number {
76
+ return scoreEvidencePathDetail(evidencePath, nodeStates, options).score;
77
+ }