@remnic/core 9.6.0 → 9.6.2

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 (333) hide show
  1. package/dist/access-admin-ops-surface.d.ts +7 -8
  2. package/dist/access-admin-ops-surface.js +8 -8
  3. package/dist/access-boundary.d.ts +9 -8
  4. package/dist/access-boundary.js +9 -9
  5. package/dist/access-cli.js +40 -40
  6. package/dist/access-http.d.ts +47 -16
  7. package/dist/access-http.js +13 -13
  8. package/dist/access-identity-continuity-surface.d.ts +6 -7
  9. package/dist/access-identity-continuity-surface.js +8 -8
  10. package/dist/access-lcm-surface.d.ts +7 -8
  11. package/dist/access-lcm-surface.js +8 -8
  12. package/dist/access-mcp.d.ts +13 -8
  13. package/dist/access-mcp.js +12 -12
  14. package/dist/access-observe-write-surface.d.ts +7 -8
  15. package/dist/access-observe-write-surface.js +8 -8
  16. package/dist/access-operations-batch.js +10 -10
  17. package/dist/access-operations.d.ts +8 -9
  18. package/dist/access-operations.js +11 -11
  19. package/dist/access-recall-surface.d.ts +7 -8
  20. package/dist/access-recall-surface.js +8 -8
  21. package/dist/access-schema.d.ts +6 -6
  22. package/dist/{access-service-CXJaql3A.d.ts → access-service-B_sc1w_k.d.ts} +9 -9
  23. package/dist/access-service.d.ts +7 -8
  24. package/dist/access-service.js +8 -8
  25. package/dist/access-surface-catalog.d.ts +7 -8
  26. package/dist/action-confidence.d.ts +1 -2
  27. package/dist/active-memory-bridge.d.ts +1 -2
  28. package/dist/active-recall.d.ts +1 -2
  29. package/dist/behavior-learner.d.ts +1 -2
  30. package/dist/behavior-signals.d.ts +1 -2
  31. package/dist/bootstrap.d.ts +6 -7
  32. package/dist/briefing.d.ts +2 -3
  33. package/dist/briefing.js +3 -3
  34. package/dist/buffer-surprise-report.d.ts +1 -2
  35. package/dist/buffer.d.ts +2 -3
  36. package/dist/buffer.js +1 -1
  37. package/dist/bulk-import/index.d.ts +3 -3
  38. package/dist/bulk-import/index.js +2 -2
  39. package/dist/calibration.d.ts +1 -2
  40. package/dist/capabilities.d.ts +1 -2
  41. package/dist/{catalog-C9cu67Ig.d.ts → catalog-9WanSGtt.d.ts} +1 -1
  42. package/dist/causal-behavior.d.ts +1 -2
  43. package/dist/causal-consolidation.d.ts +1 -2
  44. package/dist/causal-consolidation.js +4 -4
  45. package/dist/causal-trajectory-graph.d.ts +1 -2
  46. package/dist/{chunk-PNLFN2PZ.js → chunk-23G3T2Q5.js} +2 -2
  47. package/dist/{chunk-SIRPLF54.js → chunk-2K3OSLHE.js} +2 -2
  48. package/dist/{chunk-JS2HKKOK.js → chunk-3AC5UYKI.js} +1 -1
  49. package/dist/{chunk-JS2HKKOK.js.map → chunk-3AC5UYKI.js.map} +1 -1
  50. package/dist/{chunk-FKCRGLRD.js → chunk-4WRKKRTD.js} +266 -160
  51. package/dist/chunk-4WRKKRTD.js.map +1 -0
  52. package/dist/{chunk-LQHDIS7L.js → chunk-54BGIBCR.js} +2 -2
  53. package/dist/{chunk-PVUJ6WVV.js → chunk-5MH5NF3U.js} +5 -5
  54. package/dist/{chunk-PCLIWBGD.js → chunk-7ARV32PI.js} +8 -6
  55. package/dist/chunk-7ARV32PI.js.map +1 -0
  56. package/dist/{chunk-Y7UNNAZD.js → chunk-7ZYBDQ7V.js} +2 -2
  57. package/dist/{chunk-2PRQG7PV.js → chunk-AJVLDJU6.js} +1 -1
  58. package/dist/chunk-AJVLDJU6.js.map +1 -0
  59. package/dist/{chunk-LR5DZ56F.js → chunk-AXALUFAH.js} +2 -2
  60. package/dist/{chunk-AYZJID4S.js → chunk-B5GBWBCZ.js} +2 -2
  61. package/dist/{chunk-TLUDFPZL.js → chunk-CAZ3Z5M6.js} +2 -2
  62. package/dist/{chunk-RGK27ELN.js → chunk-DEKIXXIG.js} +2 -2
  63. package/dist/{chunk-2KK5WNQB.js → chunk-DQ42IQSK.js} +2 -2
  64. package/dist/{chunk-UFUKHGZD.js → chunk-F4I5NYBI.js} +89 -33
  65. package/dist/chunk-F4I5NYBI.js.map +1 -0
  66. package/dist/{chunk-HOJZMQ4J.js → chunk-FGDKJJZS.js} +2 -2
  67. package/dist/{chunk-ABP6QMVM.js → chunk-FQ7HAWWC.js} +2 -2
  68. package/dist/{chunk-CYWA2CXR.js → chunk-FVTLSFWU.js} +2 -2
  69. package/dist/{chunk-JJEJJ7RK.js → chunk-FXZTL7F7.js} +2 -2
  70. package/dist/{chunk-LADFWYHY.js → chunk-GOEV7CYF.js} +6 -6
  71. package/dist/chunk-GOEV7CYF.js.map +1 -0
  72. package/dist/{chunk-DANV2HTH.js → chunk-GQGDRLDM.js} +3 -3
  73. package/dist/{chunk-7F7Z6MOS.js → chunk-H4CKS5B2.js} +2 -2
  74. package/dist/{chunk-SVOHGUMI.js → chunk-H4FHR4UM.js} +174 -197
  75. package/dist/chunk-H4FHR4UM.js.map +1 -0
  76. package/dist/{chunk-CKITWVWJ.js → chunk-HSSERO3E.js} +2 -2
  77. package/dist/{chunk-23JFRB73.js → chunk-JODHPNLN.js} +2 -2
  78. package/dist/{chunk-DS7MM2ES.js → chunk-JZKR6ZAV.js} +2 -2
  79. package/dist/{chunk-BEM4D2QG.js → chunk-KJIJNLXT.js} +3 -3
  80. package/dist/{chunk-JSNVWNGX.js → chunk-KVSVVKHA.js} +2 -2
  81. package/dist/{chunk-4GNEDXDI.js → chunk-M67TLMP6.js} +2 -2
  82. package/dist/chunk-M67TLMP6.js.map +1 -0
  83. package/dist/{chunk-MC4FJXPA.js → chunk-MMACM5G2.js} +2 -2
  84. package/dist/{chunk-OUELRE5E.js → chunk-NOUJNHWG.js} +1 -1
  85. package/dist/chunk-NOUJNHWG.js.map +1 -0
  86. package/dist/{chunk-3XIY7MDQ.js → chunk-O6YI4CVI.js} +2 -2
  87. package/dist/{chunk-F53UF7CI.js → chunk-QLVLW7UD.js} +6 -2
  88. package/dist/{chunk-F53UF7CI.js.map → chunk-QLVLW7UD.js.map} +1 -1
  89. package/dist/{chunk-XCL57M6Q.js → chunk-RRKPLLCC.js} +21 -20
  90. package/dist/chunk-RRKPLLCC.js.map +1 -0
  91. package/dist/{chunk-72WG5QKN.js → chunk-SDAXPXER.js} +2 -2
  92. package/dist/{chunk-4LV23CHK.js → chunk-VHJARF5R.js} +2 -2
  93. package/dist/{chunk-H2DXDQCQ.js → chunk-VRJG3HIZ.js} +46 -42
  94. package/dist/chunk-VRJG3HIZ.js.map +1 -0
  95. package/dist/{chunk-6MMONPHM.js → chunk-W2AHSCKY.js} +2 -2
  96. package/dist/{chunk-P454KXD6.js → chunk-YAWJMR3Y.js} +21 -21
  97. package/dist/{chunk-K5LLP4CY.js → chunk-ZGPDSEKG.js} +20 -9
  98. package/dist/chunk-ZGPDSEKG.js.map +1 -0
  99. package/dist/{cli-CqdPA6z9.d.ts → cli-CnRsWREp.d.ts} +4 -5
  100. package/dist/cli.d.ts +9 -10
  101. package/dist/cli.js +32 -32
  102. package/dist/compounding/engine.d.ts +2 -3
  103. package/dist/compounding/engine.js +3 -3
  104. package/dist/compounding/preference-consolidator.d.ts +1 -2
  105. package/dist/compression-optimizer.d.ts +1 -2
  106. package/dist/config.d.ts +1 -2
  107. package/dist/connectors/codex-materialize-runner.d.ts +1 -2
  108. package/dist/connectors/codex-materialize-runner.js +3 -3
  109. package/dist/connectors/codex-materialize.d.ts +1 -2
  110. package/dist/connectors/index.d.ts +1 -2
  111. package/dist/connectors/index.js +3 -3
  112. package/dist/consolidation-provenance-check.d.ts +2 -3
  113. package/dist/consolidation-undo.d.ts +2 -3
  114. package/dist/contradiction/index.d.ts +3 -4
  115. package/dist/conversation-index/backend.d.ts +1 -2
  116. package/dist/conversation-index/chunker.d.ts +1 -2
  117. package/dist/conversation-index/faiss-adapter.d.ts +1 -2
  118. package/dist/conversation-index/indexer.d.ts +1 -2
  119. package/dist/conversation-index/search.d.ts +1 -2
  120. package/dist/day-summary.d.ts +1 -2
  121. package/dist/delinearize.d.ts +1 -2
  122. package/dist/direct-answer-wiring.d.ts +1 -2
  123. package/dist/direct-answer.d.ts +1 -2
  124. package/dist/embedding-fallback.d.ts +1 -2
  125. package/dist/enrichment/index.d.ts +1 -2
  126. package/dist/entity-retrieval.d.ts +2 -3
  127. package/dist/entity-retrieval.js +3 -3
  128. package/dist/entity-schema.d.ts +1 -2
  129. package/dist/explicit-capture.d.ts +8 -7
  130. package/dist/explicit-capture.js +1 -1
  131. package/dist/extraction-faithfulness.d.ts +1 -2
  132. package/dist/extraction-judge-telemetry.d.ts +1 -2
  133. package/dist/extraction-judge-training.d.ts +1 -2
  134. package/dist/extraction-judge.d.ts +1 -2
  135. package/dist/extraction.d.ts +1 -2
  136. package/dist/fallback-llm.d.ts +1 -2
  137. package/dist/graph-dashboard-diff.d.ts +1 -2
  138. package/dist/graph-dashboard-key.d.ts +1 -2
  139. package/dist/graph-dashboard-parser.d.ts +1 -2
  140. package/dist/graph-edge-reinforcement.d.ts +1 -2
  141. package/dist/graph-snapshot.d.ts +1 -2
  142. package/dist/graph.d.ts +1 -2
  143. package/dist/identity-continuity.d.ts +1 -2
  144. package/dist/importance.d.ts +1 -2
  145. package/dist/importers/index.d.ts +1 -1
  146. package/dist/importers/index.js +2 -2
  147. package/dist/index.d.ts +14 -15
  148. package/dist/index.js +40 -40
  149. package/dist/intent.d.ts +1 -2
  150. package/dist/lcm/engine.d.ts +1 -2
  151. package/dist/lcm/index.d.ts +1 -2
  152. package/dist/lcm/tools.d.ts +1 -2
  153. package/dist/lifecycle.d.ts +1 -2
  154. package/dist/live-connectors-runner.d.ts +1 -2
  155. package/dist/local-llm.d.ts +1 -2
  156. package/dist/local-model-endpoint.d.ts +1 -2
  157. package/dist/maintenance/memory-governance.d.ts +1 -2
  158. package/dist/maintenance/memory-governance.js +3 -3
  159. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
  160. package/dist/maintenance/rebuild-memory-projection.js +4 -4
  161. package/dist/mcp-memory-inspector-app.d.ts +7 -8
  162. package/dist/memory-action-policy.d.ts +1 -2
  163. package/dist/memory-cache.d.ts +1 -2
  164. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -2
  165. package/dist/memory-projection-store.d.ts +1 -2
  166. package/dist/memory-provenance.d.ts +1 -2
  167. package/dist/memory-worth-outcomes.d.ts +2 -3
  168. package/dist/models-json.d.ts +1 -2
  169. package/dist/namespaces/migrate.d.ts +3 -4
  170. package/dist/namespaces/migrate.js +4 -4
  171. package/dist/namespaces/principal.d.ts +1 -2
  172. package/dist/namespaces/search.d.ts +1 -2
  173. package/dist/namespaces/storage.d.ts +3 -4
  174. package/dist/namespaces/storage.js +3 -3
  175. package/dist/native-knowledge.d.ts +1 -2
  176. package/dist/operator-toolkit.d.ts +2 -3
  177. package/dist/operator-toolkit.js +7 -7
  178. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -3
  179. package/dist/orchestration/maintenance.d.ts +2 -3
  180. package/dist/orchestration/maintenance.js +5 -5
  181. package/dist/{orchestrator-CWFrT8AF.d.ts → orchestrator-NRLVXPpH.d.ts} +40 -15
  182. package/dist/orchestrator.d.ts +6 -7
  183. package/dist/orchestrator.js +40 -40
  184. package/dist/patterns-cli.d.ts +1 -2
  185. package/dist/{pipeline-DmqtvION.d.ts → pipeline-CiD86zIk.d.ts} +1 -1
  186. package/dist/policy-runtime.d.ts +1 -2
  187. package/dist/provenance.d.ts +1 -2
  188. package/dist/{qmd--fnPMK60.d.ts → qmd-Bef7DDuQ.d.ts} +1 -1
  189. package/dist/qmd-preflight.d.ts +2 -3
  190. package/dist/qmd-recall-cache.d.ts +1 -2
  191. package/dist/qmd.d.ts +2 -3
  192. package/dist/recall-disclosure-escalation.d.ts +1 -2
  193. package/dist/recall-explain-renderer.d.ts +1 -2
  194. package/dist/recall-explain-renderer.js +3 -3
  195. package/dist/recall-planner-llm.d.ts +1 -2
  196. package/dist/recall-state.d.ts +1 -2
  197. package/dist/recall-tag-filter.d.ts +1 -2
  198. package/dist/recall-timings.d.ts +1 -2
  199. package/dist/recall-xray-cli.d.ts +1 -2
  200. package/dist/recall-xray-cli.js +4 -4
  201. package/dist/recall-xray-renderer.d.ts +1 -2
  202. package/dist/recall-xray-renderer.js +3 -3
  203. package/dist/recall-xray.d.ts +1 -2
  204. package/dist/recall-xray.js +2 -2
  205. package/dist/replay/normalizers/chatgpt.d.ts +1 -0
  206. package/dist/replay/normalizers/chatgpt.js +3 -3
  207. package/dist/replay/normalizers/claude.d.ts +1 -0
  208. package/dist/replay/normalizers/claude.js +3 -3
  209. package/dist/replay/normalizers/openclaw.d.ts +1 -0
  210. package/dist/replay/normalizers/openclaw.js +3 -3
  211. package/dist/replay/normalizers/shared.d.ts +1 -0
  212. package/dist/replay/normalizers/shared.js +2 -2
  213. package/dist/replay/runner.d.ts +1 -0
  214. package/dist/replay/runner.js +2 -2
  215. package/dist/replay/types.d.ts +2 -1
  216. package/dist/replay/types.js +1 -1
  217. package/dist/resolve-auth-token.d.ts +1 -2
  218. package/dist/retrieval-agents.d.ts +2 -3
  219. package/dist/retrieval-tiers.d.ts +1 -2
  220. package/dist/routing/engine.d.ts +1 -2
  221. package/dist/routing/store.d.ts +1 -2
  222. package/dist/schemas.d.ts +44 -44
  223. package/dist/search/embed-helper.d.ts +1 -2
  224. package/dist/search/factory.d.ts +1 -2
  225. package/dist/search/index.d.ts +1 -2
  226. package/dist/search/lancedb-backend.d.ts +1 -2
  227. package/dist/search/meilisearch-backend.d.ts +1 -2
  228. package/dist/search/noop-backend.d.ts +1 -2
  229. package/dist/search/orama-backend.d.ts +1 -2
  230. package/dist/search/port.d.ts +1 -2
  231. package/dist/search/remote-backend.d.ts +1 -2
  232. package/dist/{semantic-DJR8_DMQ.d.ts → semantic-TddhF0y7.d.ts} +17 -1
  233. package/dist/{semantic-consolidation-O5lMZ4LG.d.ts → semantic-consolidation-BTShF2Fo.d.ts} +1 -1
  234. package/dist/semantic-consolidation.d.ts +2 -3
  235. package/dist/semantic-consolidation.js +4 -4
  236. package/dist/semantic-rule-promotion.js +3 -3
  237. package/dist/semantic-rule-verifier.d.ts +1 -2
  238. package/dist/semantic-rule-verifier.js +3 -3
  239. package/dist/session-observer-bands.d.ts +1 -2
  240. package/dist/session-observer-state.d.ts +1 -2
  241. package/dist/shared-context/manager.d.ts +3 -4
  242. package/dist/signal.d.ts +1 -2
  243. package/dist/{storage-C1maCNbc.d.ts → storage-DxPDAiU9.d.ts} +5 -1
  244. package/dist/storage.d.ts +2 -3
  245. package/dist/storage.js +2 -2
  246. package/dist/summarizer.d.ts +1 -2
  247. package/dist/summary-snapshot.d.ts +1 -2
  248. package/dist/temporal-supersession.d.ts +2 -3
  249. package/dist/temporal-validity.d.ts +1 -2
  250. package/dist/threading.d.ts +1 -2
  251. package/dist/tier-migration.d.ts +2 -3
  252. package/dist/tier-routing.d.ts +1 -2
  253. package/dist/topics.d.ts +1 -2
  254. package/dist/transcript.d.ts +1 -2
  255. package/dist/transfer/types.d.ts +12 -12
  256. package/dist/trust-score-stage.d.ts +1 -2
  257. package/dist/trust-score.d.ts +1 -2
  258. package/dist/{types-CGgcNWCG.d.ts → types-DDUDgd7T.d.ts} +93 -4
  259. package/dist/types.d.ts +1 -2
  260. package/dist/types.js +1 -1
  261. package/dist/utility-runtime.d.ts +1 -2
  262. package/dist/verified-recall.js +3 -3
  263. package/package.json +2 -2
  264. package/src/access-admin-ops-surface.ts +1 -0
  265. package/src/access-boundary.ts +2 -0
  266. package/src/access-http.test.ts +129 -0
  267. package/src/access-http.ts +92 -23
  268. package/src/access-mcp.ts +11 -2
  269. package/src/access-observe-write-surface.ts +87 -113
  270. package/src/access-operations-batch.ts +2 -2
  271. package/src/access-operations.ts +17 -16
  272. package/src/access-service.ts +11 -3
  273. package/src/admin/admin-surfaces.ts +2 -0
  274. package/src/buffer.ts +6 -1
  275. package/src/bulk-import/types.ts +2 -1
  276. package/src/coding/architecture-surfaces.test.ts +79 -5
  277. package/src/coding/architecture-surfaces.ts +7 -1
  278. package/src/coding/decision-surfaces.test.ts +1 -0
  279. package/src/coding/decision-surfaces.ts +4 -0
  280. package/src/connector-provenance-lifecycle.test.ts +618 -0
  281. package/src/connector-provenance.test.ts +219 -0
  282. package/src/dedup/semantic.test.ts +105 -0
  283. package/src/dedup/semantic.ts +69 -1
  284. package/src/explicit-capture.ts +21 -4
  285. package/src/orchestration/extraction-persist.ts +154 -6
  286. package/src/orchestration/extraction-run.ts +138 -228
  287. package/src/orchestration/persistence-index.ts +40 -5
  288. package/src/orchestration/turn-ingestion.ts +16 -9
  289. package/src/orchestrator-connector-dedup.test.ts +1082 -0
  290. package/src/orchestrator.ts +7 -11
  291. package/src/replay/types.ts +2 -1
  292. package/src/storage.ts +426 -553
  293. package/src/types.ts +11 -2
  294. package/src/utils/yaml-scalar.ts +20 -0
  295. package/dist/chunk-2PRQG7PV.js.map +0 -1
  296. package/dist/chunk-4GNEDXDI.js.map +0 -1
  297. package/dist/chunk-FKCRGLRD.js.map +0 -1
  298. package/dist/chunk-H2DXDQCQ.js.map +0 -1
  299. package/dist/chunk-K5LLP4CY.js.map +0 -1
  300. package/dist/chunk-LADFWYHY.js.map +0 -1
  301. package/dist/chunk-OUELRE5E.js.map +0 -1
  302. package/dist/chunk-PCLIWBGD.js.map +0 -1
  303. package/dist/chunk-SVOHGUMI.js.map +0 -1
  304. package/dist/chunk-UFUKHGZD.js.map +0 -1
  305. package/dist/chunk-XCL57M6Q.js.map +0 -1
  306. package/dist/types-gb_SNtjR.d.ts +0 -85
  307. /package/dist/{chunk-PNLFN2PZ.js.map → chunk-23G3T2Q5.js.map} +0 -0
  308. /package/dist/{chunk-SIRPLF54.js.map → chunk-2K3OSLHE.js.map} +0 -0
  309. /package/dist/{chunk-LQHDIS7L.js.map → chunk-54BGIBCR.js.map} +0 -0
  310. /package/dist/{chunk-PVUJ6WVV.js.map → chunk-5MH5NF3U.js.map} +0 -0
  311. /package/dist/{chunk-Y7UNNAZD.js.map → chunk-7ZYBDQ7V.js.map} +0 -0
  312. /package/dist/{chunk-LR5DZ56F.js.map → chunk-AXALUFAH.js.map} +0 -0
  313. /package/dist/{chunk-AYZJID4S.js.map → chunk-B5GBWBCZ.js.map} +0 -0
  314. /package/dist/{chunk-TLUDFPZL.js.map → chunk-CAZ3Z5M6.js.map} +0 -0
  315. /package/dist/{chunk-RGK27ELN.js.map → chunk-DEKIXXIG.js.map} +0 -0
  316. /package/dist/{chunk-2KK5WNQB.js.map → chunk-DQ42IQSK.js.map} +0 -0
  317. /package/dist/{chunk-HOJZMQ4J.js.map → chunk-FGDKJJZS.js.map} +0 -0
  318. /package/dist/{chunk-ABP6QMVM.js.map → chunk-FQ7HAWWC.js.map} +0 -0
  319. /package/dist/{chunk-CYWA2CXR.js.map → chunk-FVTLSFWU.js.map} +0 -0
  320. /package/dist/{chunk-JJEJJ7RK.js.map → chunk-FXZTL7F7.js.map} +0 -0
  321. /package/dist/{chunk-DANV2HTH.js.map → chunk-GQGDRLDM.js.map} +0 -0
  322. /package/dist/{chunk-7F7Z6MOS.js.map → chunk-H4CKS5B2.js.map} +0 -0
  323. /package/dist/{chunk-CKITWVWJ.js.map → chunk-HSSERO3E.js.map} +0 -0
  324. /package/dist/{chunk-23JFRB73.js.map → chunk-JODHPNLN.js.map} +0 -0
  325. /package/dist/{chunk-DS7MM2ES.js.map → chunk-JZKR6ZAV.js.map} +0 -0
  326. /package/dist/{chunk-BEM4D2QG.js.map → chunk-KJIJNLXT.js.map} +0 -0
  327. /package/dist/{chunk-JSNVWNGX.js.map → chunk-KVSVVKHA.js.map} +0 -0
  328. /package/dist/{chunk-MC4FJXPA.js.map → chunk-MMACM5G2.js.map} +0 -0
  329. /package/dist/{chunk-3XIY7MDQ.js.map → chunk-O6YI4CVI.js.map} +0 -0
  330. /package/dist/{chunk-72WG5QKN.js.map → chunk-SDAXPXER.js.map} +0 -0
  331. /package/dist/{chunk-4LV23CHK.js.map → chunk-VHJARF5R.js.map} +0 -0
  332. /package/dist/{chunk-6MMONPHM.js.map → chunk-W2AHSCKY.js.map} +0 -0
  333. /package/dist/{chunk-P454KXD6.js.map → chunk-YAWJMR3Y.js.map} +0 -0
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Phase 1 connector-provenance tests.
3
+ *
4
+ * Verifies that a server-resolved `sourceConnector` identity threads through
5
+ * the memory_store and suggestion_submit write paths — from the MCP request
6
+ * boundary, through the operation handler (where it overrides any client-
7
+ * supplied value), down to YAML frontmatter on disk.
8
+ *
9
+ * All fixtures are synthetic — no real user data.
10
+ */
11
+
12
+ import assert from "node:assert/strict";
13
+ import { mkdtemp, rm } from "node:fs/promises";
14
+ import os from "node:os";
15
+ import path from "node:path";
16
+ import test from "node:test";
17
+
18
+ import { EngramMcpServer } from "./access-mcp.js";
19
+ import { memoryStoreOperation } from "./access-operations.js";
20
+ import type {
21
+ EngramAccessMemoryStoreRequest,
22
+ EngramAccessService,
23
+ EngramAccessWriteResponse,
24
+ } from "./access-service.js";
25
+ import { StorageManager } from "./storage.js";
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Mock service that captures memoryStore calls
29
+ // ---------------------------------------------------------------------------
30
+
31
+ function makeCaptureService(): {
32
+ captured: EngramAccessMemoryStoreRequest[];
33
+ service: EngramAccessService;
34
+ } {
35
+ const captured: EngramAccessMemoryStoreRequest[] = [];
36
+ const service = {
37
+ memoryStore: (
38
+ req: EngramAccessMemoryStoreRequest,
39
+ ): Promise<EngramAccessWriteResponse> => {
40
+ captured.push(req);
41
+ return Promise.resolve({
42
+ schemaVersion: 1,
43
+ operation: "memory_store",
44
+ namespace: "default",
45
+ dryRun: false,
46
+ accepted: true,
47
+ queued: false,
48
+ status: "stored",
49
+ });
50
+ },
51
+ } as unknown as EngramAccessService;
52
+ return { captured, service };
53
+ }
54
+
55
+ function memoryStoreRequest(
56
+ overrides: Record<string, unknown> = {},
57
+ ): { jsonrpc: "2.0"; id: number; method: "tools/call"; params: Record<string, unknown> } {
58
+ return {
59
+ jsonrpc: "2.0",
60
+ id: 1,
61
+ method: "tools/call",
62
+ params: {
63
+ name: "engram.memory_store",
64
+ arguments: {
65
+ content: "The user prefers dark mode for all coding tools",
66
+ schemaVersion: 1,
67
+ idempotencyKey: `key-${overrides.idempotencyKey ?? Math.random().toString(36).slice(2)}`,
68
+ ...overrides,
69
+ },
70
+ },
71
+ };
72
+ }
73
+
74
+ // ---------------------------------------------------------------------------
75
+ // Tests 1–3: MCP layer threads sourceConnector to the service
76
+ // ---------------------------------------------------------------------------
77
+
78
+ test("memory_store via MCP with sourceConnector 'chatgpt' → service receives it", async () => {
79
+ const { captured, service } = makeCaptureService();
80
+ const server = new EngramMcpServer(service, { principal: "test" });
81
+
82
+ await server.handleRequest(memoryStoreRequest(), {
83
+ sourceConnector: "chatgpt",
84
+ });
85
+
86
+ assert.equal(captured.length, 1, "memoryStore should have been called once");
87
+ assert.equal(
88
+ captured[0]!.sourceConnector,
89
+ "chatgpt",
90
+ "service should receive the server-resolved sourceConnector",
91
+ );
92
+ });
93
+
94
+ test("memory_store via MCP with sourceConnector 'codex-cli' → service receives it", async () => {
95
+ const { captured, service } = makeCaptureService();
96
+ const server = new EngramMcpServer(service, { principal: "test" });
97
+
98
+ await server.handleRequest(memoryStoreRequest(), {
99
+ sourceConnector: "codex-cli",
100
+ });
101
+
102
+ assert.equal(captured.length, 1);
103
+ assert.equal(captured[0]!.sourceConnector, "codex-cli");
104
+ });
105
+
106
+ test("memory_store via MCP with no sourceConnector (operator) → service receives undefined", async () => {
107
+ const { captured, service } = makeCaptureService();
108
+ const server = new EngramMcpServer(service, { principal: "test" });
109
+
110
+ await server.handleRequest(memoryStoreRequest(), {});
111
+
112
+ assert.equal(captured.length, 1);
113
+ assert.equal(
114
+ captured[0]!.sourceConnector,
115
+ undefined,
116
+ "operator calls should not carry a sourceConnector",
117
+ );
118
+ });
119
+
120
+ // ---------------------------------------------------------------------------
121
+ // Test 4: client-supplied sourceConnector in args is IGNORED
122
+ // ---------------------------------------------------------------------------
123
+
124
+ test("client-supplied sourceConnector in args → IGNORED, server value wins", async () => {
125
+ const captured: EngramAccessMemoryStoreRequest[] = [];
126
+ const service = {
127
+ memoryStore: (req: EngramAccessMemoryStoreRequest) => {
128
+ captured.push(req);
129
+ return Promise.resolve({
130
+ schemaVersion: 1,
131
+ operation: "memory_store",
132
+ namespace: "default",
133
+ dryRun: false,
134
+ accepted: true,
135
+ queued: false,
136
+ status: "stored",
137
+ } satisfies EngramAccessWriteResponse);
138
+ },
139
+ } as unknown as EngramAccessService;
140
+
141
+ // Call the handler directly, simulating a malicious client that managed to
142
+ // inject sourceConnector: "evil" into the parsed input. The handler must
143
+ // override it with the server-resolved ctx.sourceConnector.
144
+ await memoryStoreOperation.spec.handler(
145
+ {
146
+ content: "The user prefers vim over emacs",
147
+ schemaVersion: 1,
148
+ idempotencyKey: "evil-key",
149
+ sourceConnector: "evil",
150
+ } as unknown as Parameters<typeof memoryStoreOperation.spec.handler>[0],
151
+ {
152
+ service,
153
+ sourceConnector: "chatgpt",
154
+ },
155
+ );
156
+
157
+ assert.equal(captured.length, 1);
158
+ assert.equal(
159
+ captured[0]!.sourceConnector,
160
+ "chatgpt",
161
+ "server-resolved sourceConnector must override client-supplied value",
162
+ );
163
+ });
164
+
165
+ // ---------------------------------------------------------------------------
166
+ // Tests 5–6: StorageManager.writeMemory persists sourceConnector to frontmatter
167
+ // ---------------------------------------------------------------------------
168
+
169
+ test("StorageManager.writeMemory with sourceConnector 'omp' → frontmatter contains it", async () => {
170
+ StorageManager.clearAllStaticCaches();
171
+ const baseDir = await mkdtemp(path.join(os.tmpdir(), "prov-connector-"));
172
+ try {
173
+ const storage = new StorageManager(baseDir);
174
+ await storage.ensureDirectories();
175
+
176
+ const { id } = await storage.writeMemory(
177
+ "fact",
178
+ "The user works from the Pacific time zone",
179
+ { sourceConnector: "omp" },
180
+ );
181
+
182
+ const memory = await storage.getMemoryById(id);
183
+ assert.ok(memory, "getMemoryById must find the just-written memory");
184
+ assert.equal(
185
+ memory!.frontmatter.sourceConnector,
186
+ "omp",
187
+ "frontmatter should contain the sourceConnector",
188
+ );
189
+ } finally {
190
+ StorageManager.clearAllStaticCaches();
191
+ await rm(baseDir, { recursive: true, force: true });
192
+ }
193
+ });
194
+
195
+ test("StorageManager.writeMemory without sourceConnector → frontmatter omits it", async () => {
196
+ StorageManager.clearAllStaticCaches();
197
+ const baseDir = await mkdtemp(path.join(os.tmpdir(), "prov-connector-"));
198
+ try {
199
+ const storage = new StorageManager(baseDir);
200
+ await storage.ensureDirectories();
201
+
202
+ const { id } = await storage.writeMemory(
203
+ "fact",
204
+ "The user enjoys hiking on weekends",
205
+ {},
206
+ );
207
+
208
+ const memory = await storage.getMemoryById(id);
209
+ assert.ok(memory, "getMemoryById must find the just-written memory");
210
+ assert.equal(
211
+ memory!.frontmatter.sourceConnector,
212
+ undefined,
213
+ "frontmatter should omit sourceConnector when not provided",
214
+ );
215
+ } finally {
216
+ StorageManager.clearAllStaticCaches();
217
+ await rm(baseDir, { recursive: true, force: true });
218
+ }
219
+ });
@@ -245,6 +245,111 @@ test("semantic dedup: normalizes malformed numeric options before lookup", async
245
245
  assert.equal(clampedLowThreshold.action, "skip");
246
246
  });
247
247
 
248
+ // ── Connector-aware semantic dedup (PR #1852 review finding on 7e0eb1a0) ──────
249
+ //
250
+ // A provenance-bearing candidate (sourceConnector present) may be suppressed
251
+ // only by a near-duplicate from the SAME connector. A different or absent
252
+ // neighbor connector must NOT suppress the write. Operator/unattributed
253
+ // writes (no candidate connector) preserve the original behavior.
254
+
255
+ test("semantic dedup connector-aware: skips same-connector paraphrase", async () => {
256
+ // Candidate from chatgpt; top neighbor is also chatgpt at 0.96 → skip.
257
+ const decision = await decideSemanticDedup(
258
+ "tabs are preferred by the user for indentation",
259
+ makeLookup([{ id: "existing-pref", score: 0.96, sourceConnector: "chatgpt" }]),
260
+ { ...DEFAULT_OPTS, sourceConnector: "chatgpt" },
261
+ );
262
+ assert.equal(decision.action, "skip");
263
+ if (decision.action === "skip") {
264
+ assert.equal(decision.reason, "near_duplicate");
265
+ assert.equal(decision.topId, "existing-pref");
266
+ assert.equal(decision.topScore, 0.96);
267
+ }
268
+ });
269
+
270
+ test("semantic dedup connector-aware: keeps different-connector paraphrase (B vs A)", async () => {
271
+ // Candidate from chatgpt; only neighbor is codex at 0.96 → must NOT skip.
272
+ const decision = await decideSemanticDedup(
273
+ "tabs are preferred by the user for indentation",
274
+ makeLookup([{ id: "codex-pref", score: 0.96, sourceConnector: "codex" }]),
275
+ { ...DEFAULT_OPTS, sourceConnector: "chatgpt" },
276
+ );
277
+ assert.equal(decision.action, "keep");
278
+ assert.equal(decision.reason, "connector_mismatch");
279
+ if (decision.action === "keep") {
280
+ assert.equal(decision.topId, "codex-pref");
281
+ }
282
+ });
283
+
284
+ test("semantic dedup connector-aware: keeps provenance candidate when neighbor connector absent", async () => {
285
+ // Candidate from chatgpt; neighbor has no connector at 0.97 → must NOT skip.
286
+ const decision = await decideSemanticDedup(
287
+ "tabs are preferred by the user for indentation",
288
+ makeLookup([{ id: "operator-pref", score: 0.97 }]),
289
+ { ...DEFAULT_OPTS, sourceConnector: "chatgpt" },
290
+ );
291
+ assert.equal(decision.action, "keep");
292
+ assert.equal(decision.reason, "connector_mismatch");
293
+ });
294
+
295
+ test("semantic dedup connector-aware: operator (no candidate connector) preserves skip regardless of neighbor connector", async () => {
296
+ // No candidate connector → existing behavior: skip on any near-duplicate,
297
+ // even one tagged with a different connector.
298
+ const decision = await decideSemanticDedup(
299
+ "tabs are preferred by the user for indentation",
300
+ makeLookup([{ id: "codex-pref", score: 0.96, sourceConnector: "codex" }]),
301
+ DEFAULT_OPTS,
302
+ );
303
+ assert.equal(decision.action, "skip");
304
+ if (decision.action === "skip") {
305
+ assert.equal(decision.topId, "codex-pref");
306
+ }
307
+ });
308
+
309
+ test("semantic dedup connector-aware: same-connector dedup survives when a different-connector hit scores higher", async () => {
310
+ // Candidate from chatgpt; codex neighbor scores 0.98 (higher) but a chatgpt
311
+ // neighbor also clears threshold at 0.94 → skip against the chatgpt hit,
312
+ // not the codex one. This preserves same-connector dedup.
313
+ const decision = await decideSemanticDedup(
314
+ "tabs are preferred by the user for indentation",
315
+ makeLookup([
316
+ { id: "codex-pref", score: 0.98, sourceConnector: "codex" },
317
+ { id: "chatgpt-pref", score: 0.94, sourceConnector: "chatgpt" },
318
+ ]),
319
+ { ...DEFAULT_OPTS, sourceConnector: "chatgpt" },
320
+ );
321
+ assert.equal(decision.action, "skip");
322
+ if (decision.action === "skip") {
323
+ assert.equal(decision.topId, "chatgpt-pref");
324
+ assert.equal(decision.topScore, 0.94);
325
+ }
326
+ });
327
+
328
+ test("semantic dedup connector-aware: keeps when candidate connector set but no same-connector neighbor clears threshold", async () => {
329
+ // Candidate from chatgpt; codex neighbor at 0.97 clears threshold, but the
330
+ // only chatgpt neighbor is at 0.80 (below) → keep (connector_mismatch).
331
+ const decision = await decideSemanticDedup(
332
+ "tabs are preferred by the user for indentation",
333
+ makeLookup([
334
+ { id: "codex-pref", score: 0.97, sourceConnector: "codex" },
335
+ { id: "chatgpt-unrelated", score: 0.8, sourceConnector: "chatgpt" },
336
+ ]),
337
+ { ...DEFAULT_OPTS, sourceConnector: "chatgpt" },
338
+ );
339
+ assert.equal(decision.action, "keep");
340
+ assert.equal(decision.reason, "connector_mismatch");
341
+ });
342
+
343
+ test("semantic dedup connector-aware: empty/whitespace candidate connector treated as operator", async () => {
344
+ // A whitespace-only candidate connector is absent → operator behavior → skip.
345
+ const wsDecision = await decideSemanticDedup(
346
+ "tabs are preferred by the user for indentation",
347
+ makeLookup([{ id: "codex-pref", score: 0.96, sourceConnector: "codex" }]),
348
+ { ...DEFAULT_OPTS, sourceConnector: " " },
349
+ );
350
+ assert.equal(wsDecision.action, "skip");
351
+ });
352
+
248
353
  test("semantic dedup: candidates=0 short-circuits without calling lookup", async () => {
249
354
  let called = 0;
250
355
  const decision = await decideSemanticDedup(
@@ -23,6 +23,13 @@ export interface SemanticDedupHit {
23
23
  score: number;
24
24
  /** Optional source path, purely informational. */
25
25
  path?: string;
26
+ /**
27
+ * Source connector of the existing neighbor memory's provenance, used by
28
+ * the connector-aware skip gate (PR #1852 review finding on 7e0eb1a0).
29
+ * Absent when the neighbor is operator/unattributed or its frontmatter
30
+ * could not be read.
31
+ */
32
+ sourceConnector?: string;
26
33
  }
27
34
 
28
35
  /**
@@ -45,6 +52,15 @@ export interface SemanticDedupOptions {
45
52
  threshold: number;
46
53
  /** How many nearest neighbors to compare against. */
47
54
  candidates: number;
55
+ /**
56
+ * Source connector of the CANDIDATE fact being evaluated (its provenance).
57
+ * When present, a near-duplicate skip is permitted only against a neighbor
58
+ * carrying the SAME connector; a different or absent neighbor connector
59
+ * must NOT suppress the write (PR #1852 review finding on 7e0eb1a0).
60
+ * Absent for operator / unattributed writes, which preserve the original
61
+ * behavior (skip on any near-duplicate regardless of neighbor connector).
62
+ */
63
+ sourceConnector?: string;
48
64
  }
49
65
 
50
66
  export type SemanticDedupDecision =
@@ -54,7 +70,8 @@ export type SemanticDedupDecision =
54
70
  | "disabled"
55
71
  | "backend_unavailable"
56
72
  | "no_candidates"
57
- | "no_near_duplicate";
73
+ | "no_near_duplicate"
74
+ | "connector_mismatch";
58
75
  topScore?: number;
59
76
  topId?: string;
60
77
  }
@@ -135,8 +152,21 @@ export async function decideSemanticDedup(
135
152
  return { action: "keep", reason: "no_candidates" };
136
153
  }
137
154
 
155
+ // Resolve the candidate's provenance connector. An empty/whitespace
156
+ // value is treated as absent (operator / unattributed).
157
+ const candidateConnector =
158
+ typeof options.sourceConnector === "string" &&
159
+ options.sourceConnector.trim().length > 0
160
+ ? options.sourceConnector.trim()
161
+ : undefined;
162
+
138
163
  // Defensive: callers ought to return sorted, but don't trust it.
139
164
  let top: SemanticDedupHit | undefined;
165
+ // Best same-connector neighbor — only tracked when the candidate is
166
+ // provenance-bearing. Tracked in the same pass so a connector-aware skip
167
+ // matches the best neighbor from the SAME connector even when a higher-
168
+ // scoring neighbor from a DIFFERENT connector would otherwise win.
169
+ let sameConnectorTop: SemanticDedupHit | undefined;
140
170
  for (const hit of hits) {
141
171
  if (
142
172
  !hit ||
@@ -150,12 +180,50 @@ export async function decideSemanticDedup(
150
180
  if (!top || hit.score > top.score) {
151
181
  top = hit;
152
182
  }
183
+ if (
184
+ candidateConnector !== undefined &&
185
+ typeof hit.sourceConnector === "string" &&
186
+ hit.sourceConnector.trim() === candidateConnector &&
187
+ (!sameConnectorTop || hit.score > sameConnectorTop.score)
188
+ ) {
189
+ sameConnectorTop = hit;
190
+ }
153
191
  }
154
192
  if (!top) {
155
193
  return { action: "keep", reason: "no_near_duplicate" };
156
194
  }
157
195
 
158
196
  if (top.score >= threshold) {
197
+ // Connector-aware skip gate (PR #1852 review finding on 7e0eb1a0):
198
+ // A provenance-bearing candidate may be suppressed ONLY by a near-
199
+ // duplicate from the SAME connector. A different or absent neighbor
200
+ // connector must NOT suppress the write — otherwise a connector B
201
+ // paraphrase would be dropped against connector A's memory before the
202
+ // write ever happens. When the candidate carries no connector (operator
203
+ // / unattributed), preserve the original behavior and skip on any match.
204
+ if (candidateConnector !== undefined) {
205
+ const match =
206
+ sameConnectorTop !== undefined && sameConnectorTop.score >= threshold
207
+ ? sameConnectorTop
208
+ : undefined;
209
+ if (match) {
210
+ return {
211
+ action: "skip",
212
+ reason: "near_duplicate",
213
+ topScore: match.score,
214
+ topId: match.id,
215
+ topPath: match.path,
216
+ };
217
+ }
218
+ // Best overall hit cleared threshold but came from a different or
219
+ // absent connector; no same-connector near-duplicate exists. Keep.
220
+ return {
221
+ action: "keep",
222
+ reason: "connector_mismatch",
223
+ topScore: top.score,
224
+ topId: top.id,
225
+ };
226
+ }
159
227
  return {
160
228
  action: "skip",
161
229
  reason: "near_duplicate",
@@ -13,6 +13,7 @@ export type ExplicitCaptureInput = {
13
13
  namespace?: string;
14
14
  tags?: string[];
15
15
  entityRef?: string;
16
+ sourceConnector?: string;
16
17
  ttl?: string;
17
18
  sourceReason?: string;
18
19
  };
@@ -24,6 +25,7 @@ export type ValidExplicitCapture = {
24
25
  namespace?: string;
25
26
  tags: string[];
26
27
  entityRef?: string;
28
+ sourceConnector?: string;
27
29
  expiresAt?: string;
28
30
  sourceReason?: string;
29
31
  /**
@@ -371,8 +373,9 @@ export function validateExplicitCaptureInput(
371
373
  namespace: asTrimmed(input.namespace),
372
374
  tags: Array.from(new Set((input.tags ?? []).map((tag) => tag.trim()).filter(Boolean))),
373
375
  entityRef: asTrimmed(input.entityRef),
374
- expiresAt,
375
376
  sourceReason: asTrimmed(input.sourceReason),
377
+ sourceConnector: input.sourceConnector,
378
+ expiresAt,
376
379
  };
377
380
  }
378
381
 
@@ -410,7 +413,14 @@ async function findDuplicateExplicitCapture(
410
413
  const status = memory.frontmatter.status ?? "active";
411
414
  if (status !== "active") return false;
412
415
  if (memory.frontmatter.category !== candidate.category) return false;
413
- return normalizeCaptureContent(memory.content) === normalizedCandidate;
416
+ if (normalizeCaptureContent(memory.content) !== normalizedCandidate) return false;
417
+ // Connector-aware dedup: same content from different connectors is NOT
418
+ // a duplicate. Operator (undefined) and connector-tagged memories are
419
+ // always distinct. Normalize empty strings to undefined.
420
+ const existingConnector = memory.frontmatter.sourceConnector?.trim() || undefined;
421
+ const newConnector = candidate.sourceConnector?.trim() || undefined;
422
+ if (existingConnector !== newConnector) return false;
423
+ return true;
414
424
  });
415
425
  return match?.frontmatter.id ?? null;
416
426
  }
@@ -438,6 +448,7 @@ export async function persistExplicitCapture(
438
448
  entityRef: candidate.entityRef,
439
449
  expiresAt: candidate.expiresAt,
440
450
  source: source === "inline" ? "explicit-inline" : "explicit",
451
+ ...(candidate.sourceConnector ? { sourceConnector: candidate.sourceConnector } : {}),
441
452
  });
442
453
  // #1522: catalog touch handled at the storage chokepoint — the StorageManager's
443
454
  // post-write hook records the namespace touch automatically.
@@ -492,6 +503,7 @@ async function findQueuedExplicitCaptureDuplicate(
492
503
  orchestrator: Orchestrator,
493
504
  namespace: string | undefined,
494
505
  content: string,
506
+ sourceConnector?: string,
495
507
  ): Promise<string | null> {
496
508
  const storage = await orchestrator.getStorage(namespace);
497
509
  const existing = await storage.readAllMemories();
@@ -500,7 +512,11 @@ async function findQueuedExplicitCaptureDuplicate(
500
512
  const status = memory.frontmatter.status ?? "active";
501
513
  if (status !== "pending_review") return false;
502
514
  if (!(memory.frontmatter.tags ?? []).includes("queued-review")) return false;
503
- return normalizeCaptureContent(memory.content) === normalized;
515
+ if (normalizeCaptureContent(memory.content) !== normalized) return false;
516
+ const existingConnector = memory.frontmatter.sourceConnector?.trim() || undefined;
517
+ const newConnector = sourceConnector?.trim() || undefined;
518
+ if (existingConnector !== newConnector) return false;
519
+ return true;
504
520
  });
505
521
  return match?.frontmatter.id ?? null;
506
522
  }
@@ -520,7 +536,7 @@ export async function queueExplicitCaptureForReview(
520
536
  ? requestedNamespace
521
537
  : resolveExplicitCaptureReviewNamespace(orchestrator, requestedNamespace);
522
538
  const content = buildExplicitCaptureReviewContent(input, reason);
523
- const duplicateOf = await findQueuedExplicitCaptureDuplicate(orchestrator, queueNamespace, content);
539
+ const duplicateOf = await findQueuedExplicitCaptureDuplicate(orchestrator, queueNamespace, content, input.sourceConnector);
524
540
  if (duplicateOf) {
525
541
  return { id: duplicateOf, duplicateOf };
526
542
  }
@@ -536,6 +552,7 @@ export async function queueExplicitCaptureForReview(
536
552
  tags: Array.from(new Set([...EXPLICIT_CAPTURE_REVIEW_TAGS, ...requestedTags])),
537
553
  entityRef: sanitizeReviewMetadata(input.entityRef),
538
554
  source: source === "inline" ? "explicit-inline-review" : "explicit-review",
555
+ ...(input.sourceConnector ? { sourceConnector: input.sourceConnector } : {}),
539
556
  });
540
557
  try {
541
558
  const created = await storage.getMemoryById(id);