@remnic/core 9.43.0 → 9.44.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 (208) hide show
  1. package/dist/access-admin-ops-surface.d.ts +2 -2
  2. package/dist/access-admin-ops-surface.js +39 -39
  3. package/dist/access-authorization-probe.d.ts +2 -2
  4. package/dist/access-authorization-probe.js +40 -40
  5. package/dist/access-boundary.d.ts +2 -2
  6. package/dist/access-boundary.js +39 -39
  7. package/dist/access-cli.js +97 -95
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +2 -2
  10. package/dist/access-extraction-force-flush.js +39 -39
  11. package/dist/access-http-lcm-compaction.d.ts +2 -2
  12. package/dist/access-http-lifecycle-flush.d.ts +2 -2
  13. package/dist/access-http-query.d.ts +8 -0
  14. package/dist/access-http-query.js +179 -0
  15. package/dist/access-http.d.ts +2 -2
  16. package/dist/access-http.js +47 -46
  17. package/dist/access-identity-continuity-surface.d.ts +1 -1
  18. package/dist/access-identity-continuity-surface.js +39 -39
  19. package/dist/access-lcm-surface.d.ts +2 -2
  20. package/dist/access-lcm-surface.js +39 -39
  21. package/dist/access-mcp.d.ts +2 -2
  22. package/dist/access-mcp.js +43 -43
  23. package/dist/access-namespace-preflight.js +39 -39
  24. package/dist/access-observe-write-surface.d.ts +2 -2
  25. package/dist/access-observe-write-surface.js +39 -39
  26. package/dist/access-operations-batch.js +41 -41
  27. package/dist/access-operations.d.ts +2 -2
  28. package/dist/access-operations.js +42 -42
  29. package/dist/access-recall-concurrency.d.ts +2 -2
  30. package/dist/access-recall-concurrency.js +39 -39
  31. package/dist/access-recall-response.d.ts +2 -2
  32. package/dist/access-recall-response.js +39 -39
  33. package/dist/access-recall-surface.d.ts +2 -2
  34. package/dist/access-recall-surface.js +39 -39
  35. package/dist/{access-service-D1BkxwSf.d.ts → access-service-BCZJbX0f.d.ts} +12 -2
  36. package/dist/access-service-helpers.d.ts +2 -2
  37. package/dist/access-service.d.ts +2 -2
  38. package/dist/access-service.js +39 -39
  39. package/dist/access-surface-catalog.d.ts +2 -2
  40. package/dist/access-surface-catalog.js +5 -0
  41. package/dist/access-surface-catalog.js.map +1 -1
  42. package/dist/{auto-sync-UPTUVE4X.js → auto-sync-5OE5QOZB.js} +3 -3
  43. package/dist/bootstrap.d.ts +1 -1
  44. package/dist/briefing.js +8 -8
  45. package/dist/buffer.js +6 -6
  46. package/dist/causal-behavior.js +2 -2
  47. package/dist/causal-chain.js +2 -2
  48. package/dist/causal-consolidation.js +12 -12
  49. package/dist/causal-retrieval.js +2 -2
  50. package/dist/causal-trajectory-graph.js +2 -2
  51. package/dist/causal-trajectory.js +1 -1
  52. package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
  53. package/dist/{chunk-BEQOZOYZ.js → chunk-2FTRRQKZ.js} +5 -5
  54. package/dist/{chunk-CMENJQ6I.js → chunk-2QR2RRH6.js} +2 -2
  55. package/dist/{chunk-3C2TGBDB.js → chunk-35IC3EVP.js} +2 -2
  56. package/dist/{chunk-L2DPF4DF.js → chunk-3SHB4YAW.js} +4 -4
  57. package/dist/{chunk-UV72DEZD.js → chunk-4B77XSG5.js} +5 -5
  58. package/dist/{chunk-GUQYMOPU.js → chunk-4LMA77JH.js} +5 -5
  59. package/dist/{chunk-AX2J2LC4.js → chunk-5ZE7QHTK.js} +2 -2
  60. package/dist/{chunk-YFHMW37V.js → chunk-6CZPDBJS.js} +5 -5
  61. package/dist/chunk-6ZYQ36IB.js +30 -0
  62. package/dist/chunk-6ZYQ36IB.js.map +1 -0
  63. package/dist/{chunk-QY66HJ4X.js → chunk-7PLHD7EO.js} +5 -5
  64. package/dist/{chunk-NRV4Y3PM.js → chunk-CAGPP5NB.js} +1 -1
  65. package/dist/{chunk-5TOV3D6U.js → chunk-CH2WTP6R.js} +6 -6
  66. package/dist/{chunk-YJHU5B3M.js → chunk-E6JYVPBK.js} +2 -2
  67. package/dist/{chunk-NF3U3MPG.js → chunk-ECK75GDJ.js} +2 -2
  68. package/dist/{chunk-NHRNYJPJ.js → chunk-EMC5GT4H.js} +7 -7
  69. package/dist/{chunk-5QZEVMLY.js → chunk-EUVPB5TA.js} +55 -37
  70. package/dist/chunk-EUVPB5TA.js.map +1 -0
  71. package/dist/{chunk-GS5UVGQK.js → chunk-G24HJJ67.js} +4 -4
  72. package/dist/{chunk-OEXKYYVH.js → chunk-HGFILS2Q.js} +6 -6
  73. package/dist/{chunk-BGXHVOBI.js → chunk-HLPD7B7P.js} +2 -2
  74. package/dist/{chunk-UP67AFRN.js → chunk-HXTUA7QM.js} +28 -28
  75. package/dist/chunk-HXTUA7QM.js.map +1 -0
  76. package/dist/{chunk-WGCTFGLW.js → chunk-I22U5YYD.js} +3 -3
  77. package/dist/{chunk-MSXWUXFE.js → chunk-IADUAH35.js} +2 -2
  78. package/dist/{chunk-JGXXPDM2.js → chunk-IXFI6E3Q.js} +3 -3
  79. package/dist/{chunk-ZVVASRUT.js → chunk-J43XN7N3.js} +90 -88
  80. package/dist/chunk-J43XN7N3.js.map +1 -0
  81. package/dist/{chunk-F2KMAFEB.js → chunk-JDDTNK5P.js} +2 -2
  82. package/dist/{chunk-KDXD2AM6.js → chunk-MUKLQDJP.js} +47 -47
  83. package/dist/{chunk-5N26WBPQ.js → chunk-MYFFOPO2.js} +5 -5
  84. package/dist/{chunk-Q53RLEW7.js → chunk-N7LPS4Z3.js} +2 -2
  85. package/dist/{chunk-EHKDORQN.js → chunk-NVRYW264.js} +9 -9
  86. package/dist/{chunk-MVW234LO.js → chunk-O4BADU6R.js} +2 -2
  87. package/dist/{chunk-ZERSIPFC.js → chunk-OHLNFI6Z.js} +17 -17
  88. package/dist/{chunk-AR2FSZBP.js → chunk-OPVOUBHT.js} +2 -2
  89. package/dist/{chunk-JDXDA5OO.js → chunk-OZL7KB6B.js} +2 -2
  90. package/dist/{chunk-4DYBLQZC.js → chunk-PJUHQC4T.js} +2 -2
  91. package/dist/{chunk-SEUSFKNS.js → chunk-PLQCPMJA.js} +14 -14
  92. package/dist/{chunk-MU7ZHSZE.js → chunk-PO5LSKQO.js} +2 -2
  93. package/dist/{chunk-ONHRRJZM.js → chunk-QJAQNXWI.js} +6 -6
  94. package/dist/{chunk-LZ5JKQCS.js → chunk-TRBIJS2T.js} +2 -2
  95. package/dist/{chunk-6GIMMNVK.js → chunk-U5SX74DV.js} +4 -4
  96. package/dist/{chunk-KPJQTSRJ.js → chunk-UUQLB2HJ.js} +2 -2
  97. package/dist/{chunk-JYIFGGEM.js → chunk-UZGJFIIG.js} +2 -2
  98. package/dist/{chunk-HNZKVLAN.js → chunk-W6ROK2KU.js} +2 -2
  99. package/dist/{chunk-EPQ76W5T.js → chunk-WMHO3WLC.js} +2 -2
  100. package/dist/{chunk-MBTPUVHZ.js → chunk-WUDWRUGK.js} +2 -2
  101. package/dist/{chunk-4VXGRIH6.js → chunk-WUNIWKY4.js} +5 -5
  102. package/dist/{chunk-BI6RE2ZS.js → chunk-WX6KOVVK.js} +2 -2
  103. package/dist/chunk-YUOKZ3LJ.js +24 -0
  104. package/dist/chunk-YUOKZ3LJ.js.map +1 -0
  105. package/dist/{cli-IUhV-lmk.d.ts → cli-U30A3jyx.d.ts} +2 -2
  106. package/dist/cli.d.ts +3 -3
  107. package/dist/cli.js +66 -65
  108. package/dist/compounding/engine.js +8 -8
  109. package/dist/connectors/codex-materialize-runner.js +8 -8
  110. package/dist/connectors/index.js +8 -8
  111. package/dist/convergence-refresh.d.ts +24 -0
  112. package/dist/convergence-refresh.js +74 -0
  113. package/dist/convergence-refresh.js.map +1 -0
  114. package/dist/conversation-index/backend.js +2 -2
  115. package/dist/corpus-watermark.js +19 -19
  116. package/dist/entity-retrieval.js +8 -8
  117. package/dist/explicit-capture.d.ts +1 -1
  118. package/dist/explicit-capture.js +3 -3
  119. package/dist/extraction.js +14 -14
  120. package/dist/{graph-edge-decay-Z6ENALU2.js → graph-edge-decay-GF3ZSGSP.js} +4 -4
  121. package/dist/graph-edge-decay-GF3ZSGSP.js.map +1 -0
  122. package/dist/graph-snapshot.js +3 -3
  123. package/dist/graph.js +2 -2
  124. package/dist/index.d.ts +4 -4
  125. package/dist/index.js +158 -156
  126. package/dist/lcm/index.js +3 -3
  127. package/dist/maintenance/memory-governance.js +9 -9
  128. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +8 -8
  129. package/dist/maintenance/rebuild-memory-projection.js +10 -10
  130. package/dist/mcp-memory-inspector-app.d.ts +2 -2
  131. package/dist/namespaces/migrate.js +18 -18
  132. package/dist/namespaces/search.js +9 -9
  133. package/dist/namespaces/storage.js +8 -8
  134. package/dist/offline-sync-impression-drain.js +4 -4
  135. package/dist/operator-doctor-corpus.js +20 -20
  136. package/dist/operator-toolkit.js +29 -29
  137. package/dist/orchestration/maintenance.js +15 -15
  138. package/dist/{orchestrator-fYTncnLy.d.ts → orchestrator-DUxbhhqO.d.ts} +1 -1
  139. package/dist/orchestrator.d.ts +1 -1
  140. package/dist/orchestrator.js +98 -96
  141. package/dist/qmd.js +4 -4
  142. package/dist/resume-bundles.js +1 -1
  143. package/dist/search/factory.js +8 -8
  144. package/dist/search/index.js +14 -14
  145. package/dist/semantic-consolidation.js +10 -10
  146. package/dist/semantic-rule-promotion.js +8 -8
  147. package/dist/semantic-rule-verifier.js +9 -9
  148. package/dist/source-agent-qualifier.js +13 -13
  149. package/dist/storage.js +7 -7
  150. package/dist/verified-recall.js +9 -9
  151. package/package.json +2 -2
  152. package/src/access-http-query.ts +25 -0
  153. package/src/access-http.test.ts +136 -0
  154. package/src/access-http.ts +26 -26
  155. package/src/access-service-offline-file-content.test.ts +40 -0
  156. package/src/access-service.ts +34 -0
  157. package/src/access-surface-catalog.ts +5 -0
  158. package/src/convergence-refresh.ts +28 -0
  159. package/src/orchestrator-convergence-refresh.test.ts +114 -0
  160. package/src/orchestrator.ts +5 -4
  161. package/dist/chunk-5QZEVMLY.js.map +0 -1
  162. package/dist/chunk-UP67AFRN.js.map +0 -1
  163. package/dist/chunk-ZVVASRUT.js.map +0 -1
  164. /package/dist/{graph-edge-decay-Z6ENALU2.js.map → access-http-query.js.map} +0 -0
  165. /package/dist/{auto-sync-UPTUVE4X.js.map → auto-sync-5OE5QOZB.js.map} +0 -0
  166. /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
  167. /package/dist/{chunk-BEQOZOYZ.js.map → chunk-2FTRRQKZ.js.map} +0 -0
  168. /package/dist/{chunk-CMENJQ6I.js.map → chunk-2QR2RRH6.js.map} +0 -0
  169. /package/dist/{chunk-3C2TGBDB.js.map → chunk-35IC3EVP.js.map} +0 -0
  170. /package/dist/{chunk-L2DPF4DF.js.map → chunk-3SHB4YAW.js.map} +0 -0
  171. /package/dist/{chunk-UV72DEZD.js.map → chunk-4B77XSG5.js.map} +0 -0
  172. /package/dist/{chunk-GUQYMOPU.js.map → chunk-4LMA77JH.js.map} +0 -0
  173. /package/dist/{chunk-AX2J2LC4.js.map → chunk-5ZE7QHTK.js.map} +0 -0
  174. /package/dist/{chunk-YFHMW37V.js.map → chunk-6CZPDBJS.js.map} +0 -0
  175. /package/dist/{chunk-QY66HJ4X.js.map → chunk-7PLHD7EO.js.map} +0 -0
  176. /package/dist/{chunk-NRV4Y3PM.js.map → chunk-CAGPP5NB.js.map} +0 -0
  177. /package/dist/{chunk-5TOV3D6U.js.map → chunk-CH2WTP6R.js.map} +0 -0
  178. /package/dist/{chunk-YJHU5B3M.js.map → chunk-E6JYVPBK.js.map} +0 -0
  179. /package/dist/{chunk-NF3U3MPG.js.map → chunk-ECK75GDJ.js.map} +0 -0
  180. /package/dist/{chunk-NHRNYJPJ.js.map → chunk-EMC5GT4H.js.map} +0 -0
  181. /package/dist/{chunk-GS5UVGQK.js.map → chunk-G24HJJ67.js.map} +0 -0
  182. /package/dist/{chunk-OEXKYYVH.js.map → chunk-HGFILS2Q.js.map} +0 -0
  183. /package/dist/{chunk-BGXHVOBI.js.map → chunk-HLPD7B7P.js.map} +0 -0
  184. /package/dist/{chunk-WGCTFGLW.js.map → chunk-I22U5YYD.js.map} +0 -0
  185. /package/dist/{chunk-MSXWUXFE.js.map → chunk-IADUAH35.js.map} +0 -0
  186. /package/dist/{chunk-JGXXPDM2.js.map → chunk-IXFI6E3Q.js.map} +0 -0
  187. /package/dist/{chunk-F2KMAFEB.js.map → chunk-JDDTNK5P.js.map} +0 -0
  188. /package/dist/{chunk-KDXD2AM6.js.map → chunk-MUKLQDJP.js.map} +0 -0
  189. /package/dist/{chunk-5N26WBPQ.js.map → chunk-MYFFOPO2.js.map} +0 -0
  190. /package/dist/{chunk-Q53RLEW7.js.map → chunk-N7LPS4Z3.js.map} +0 -0
  191. /package/dist/{chunk-EHKDORQN.js.map → chunk-NVRYW264.js.map} +0 -0
  192. /package/dist/{chunk-MVW234LO.js.map → chunk-O4BADU6R.js.map} +0 -0
  193. /package/dist/{chunk-ZERSIPFC.js.map → chunk-OHLNFI6Z.js.map} +0 -0
  194. /package/dist/{chunk-AR2FSZBP.js.map → chunk-OPVOUBHT.js.map} +0 -0
  195. /package/dist/{chunk-JDXDA5OO.js.map → chunk-OZL7KB6B.js.map} +0 -0
  196. /package/dist/{chunk-4DYBLQZC.js.map → chunk-PJUHQC4T.js.map} +0 -0
  197. /package/dist/{chunk-SEUSFKNS.js.map → chunk-PLQCPMJA.js.map} +0 -0
  198. /package/dist/{chunk-MU7ZHSZE.js.map → chunk-PO5LSKQO.js.map} +0 -0
  199. /package/dist/{chunk-ONHRRJZM.js.map → chunk-QJAQNXWI.js.map} +0 -0
  200. /package/dist/{chunk-LZ5JKQCS.js.map → chunk-TRBIJS2T.js.map} +0 -0
  201. /package/dist/{chunk-6GIMMNVK.js.map → chunk-U5SX74DV.js.map} +0 -0
  202. /package/dist/{chunk-KPJQTSRJ.js.map → chunk-UUQLB2HJ.js.map} +0 -0
  203. /package/dist/{chunk-JYIFGGEM.js.map → chunk-UZGJFIIG.js.map} +0 -0
  204. /package/dist/{chunk-HNZKVLAN.js.map → chunk-W6ROK2KU.js.map} +0 -0
  205. /package/dist/{chunk-EPQ76W5T.js.map → chunk-WMHO3WLC.js.map} +0 -0
  206. /package/dist/{chunk-MBTPUVHZ.js.map → chunk-WUDWRUGK.js.map} +0 -0
  207. /package/dist/{chunk-4VXGRIH6.js.map → chunk-WUNIWKY4.js.map} +0 -0
  208. /package/dist/{chunk-BI6RE2ZS.js.map → chunk-WX6KOVVK.js.map} +0 -0
@@ -1,23 +1,23 @@
1
1
  import {
2
2
  promoteSemanticRuleFromMemory,
3
3
  setSemanticRulePromotionTestHooks
4
- } from "./chunk-MVW234LO.js";
5
- import "./chunk-ZERSIPFC.js";
6
- import "./chunk-UHVXE24Y.js";
4
+ } from "./chunk-O4BADU6R.js";
5
+ import "./chunk-OHLNFI6Z.js";
7
6
  import "./chunk-ENTCVTQR.js";
7
+ import "./chunk-UHVXE24Y.js";
8
8
  import "./chunk-WIPEXG6R.js";
9
9
  import "./chunk-J6A3CX5N.js";
10
10
  import "./chunk-GSL47NPM.js";
11
- import "./chunk-4VXGRIH6.js";
11
+ import "./chunk-WUNIWKY4.js";
12
12
  import "./chunk-EGGE52UU.js";
13
13
  import "./chunk-ZA53AZND.js";
14
- import "./chunk-7RJUVTVF.js";
15
- import "./chunk-SCU65EZI.js";
16
14
  import "./chunk-WRJVB3C2.js";
17
15
  import "./chunk-GCASGYIO.js";
16
+ import "./chunk-7RJUVTVF.js";
17
+ import "./chunk-SCU65EZI.js";
18
18
  import "./chunk-DM2T26WE.js";
19
19
  import "./chunk-LDXUBPMO.js";
20
- import "./chunk-BEQOZOYZ.js";
20
+ import "./chunk-2FTRRQKZ.js";
21
21
  import "./chunk-CGASUJVP.js";
22
22
  import "./chunk-R3DJVOSM.js";
23
23
  import "./chunk-BT7NVCML.js";
@@ -26,6 +26,7 @@ import "./chunk-RL6NEVXT.js";
26
26
  import "./chunk-JYIJNNN3.js";
27
27
  import "./chunk-AAD2ZS6P.js";
28
28
  import "./chunk-YXZG5TVN.js";
29
+ import "./chunk-W5H6ZRPT.js";
29
30
  import "./chunk-G7D6GZ5J.js";
30
31
  import "./chunk-DLVPUX7U.js";
31
32
  import "./chunk-IJ7HK452.js";
@@ -34,7 +35,6 @@ import "./chunk-4J7G5SY4.js";
34
35
  import "./chunk-DNHVPZOD.js";
35
36
  import "./chunk-6CIAGZ6X.js";
36
37
  import "./chunk-FFAZ2XFU.js";
37
- import "./chunk-W5H6ZRPT.js";
38
38
  import "./chunk-XMMESCPD.js";
39
39
  import "./chunk-42JKGUFJ.js";
40
40
  import "./chunk-C23BYTJV.js";
@@ -1,23 +1,24 @@
1
1
  import {
2
2
  compareVerifiedSemanticRuleResults,
3
3
  searchVerifiedSemanticRules
4
- } from "./chunk-5TOV3D6U.js";
5
- import "./chunk-ZERSIPFC.js";
6
- import "./chunk-UHVXE24Y.js";
4
+ } from "./chunk-CH2WTP6R.js";
5
+ import "./chunk-ZBJMUXZH.js";
6
+ import "./chunk-OHLNFI6Z.js";
7
7
  import "./chunk-ENTCVTQR.js";
8
+ import "./chunk-UHVXE24Y.js";
8
9
  import "./chunk-WIPEXG6R.js";
9
10
  import "./chunk-J6A3CX5N.js";
10
11
  import "./chunk-GSL47NPM.js";
11
- import "./chunk-4VXGRIH6.js";
12
+ import "./chunk-WUNIWKY4.js";
12
13
  import "./chunk-EGGE52UU.js";
13
14
  import "./chunk-ZA53AZND.js";
14
- import "./chunk-7RJUVTVF.js";
15
- import "./chunk-SCU65EZI.js";
16
15
  import "./chunk-WRJVB3C2.js";
17
16
  import "./chunk-GCASGYIO.js";
17
+ import "./chunk-7RJUVTVF.js";
18
+ import "./chunk-SCU65EZI.js";
18
19
  import "./chunk-DM2T26WE.js";
19
20
  import "./chunk-LDXUBPMO.js";
20
- import "./chunk-BEQOZOYZ.js";
21
+ import "./chunk-2FTRRQKZ.js";
21
22
  import "./chunk-CGASUJVP.js";
22
23
  import "./chunk-R3DJVOSM.js";
23
24
  import "./chunk-BT7NVCML.js";
@@ -26,6 +27,7 @@ import "./chunk-RL6NEVXT.js";
26
27
  import "./chunk-JYIJNNN3.js";
27
28
  import "./chunk-AAD2ZS6P.js";
28
29
  import "./chunk-YXZG5TVN.js";
30
+ import "./chunk-W5H6ZRPT.js";
29
31
  import "./chunk-G7D6GZ5J.js";
30
32
  import "./chunk-DLVPUX7U.js";
31
33
  import "./chunk-IJ7HK452.js";
@@ -34,7 +36,6 @@ import "./chunk-4J7G5SY4.js";
34
36
  import "./chunk-DNHVPZOD.js";
35
37
  import "./chunk-6CIAGZ6X.js";
36
38
  import "./chunk-FFAZ2XFU.js";
37
- import "./chunk-W5H6ZRPT.js";
38
39
  import "./chunk-XMMESCPD.js";
39
40
  import "./chunk-42JKGUFJ.js";
40
41
  import "./chunk-C23BYTJV.js";
@@ -51,7 +52,6 @@ import "./chunk-EYIEWJNI.js";
51
52
  import "./chunk-JUC24CTX.js";
52
53
  import "./chunk-6MKAMLQL.js";
53
54
  import "./chunk-JAKIDQB2.js";
54
- import "./chunk-ZBJMUXZH.js";
55
55
  import "./chunk-BJMBJZ2Y.js";
56
56
  import "./chunk-UKJAGEXH.js";
57
57
  import "./chunk-FP2373TW.js";
@@ -3,7 +3,7 @@ import {
3
3
  headerConnector,
4
4
  renderExtractionConversation,
5
5
  resolveSourceConnector
6
- } from "./chunk-AX2J2LC4.js";
6
+ } from "./chunk-5ZE7QHTK.js";
7
7
  import "./chunk-YIAA2X3D.js";
8
8
  import "./chunk-WOCNN776.js";
9
9
  import "./chunk-P2BM76KT.js";
@@ -11,33 +11,34 @@ import "./chunk-VEWZZM3H.js";
11
11
  import "./chunk-T2TTP3KU.js";
12
12
  import "./chunk-7TWUCYER.js";
13
13
  import "./chunk-EMDLM3LW.js";
14
- import "./chunk-NF3U3MPG.js";
14
+ import "./chunk-ECK75GDJ.js";
15
15
  import "./chunk-BUE5E2HL.js";
16
16
  import "./chunk-PD6O7AXF.js";
17
- import "./chunk-ONHRRJZM.js";
17
+ import "./chunk-QJAQNXWI.js";
18
18
  import "./chunk-YV32N67O.js";
19
- import "./chunk-IUM3VSHI.js";
20
19
  import "./chunk-64UDOIMI.js";
20
+ import "./chunk-IUM3VSHI.js";
21
21
  import "./chunk-O75CRYGF.js";
22
22
  import "./chunk-OD4FM2U7.js";
23
- import "./chunk-KPJQTSRJ.js";
23
+ import "./chunk-UUQLB2HJ.js";
24
24
  import "./chunk-KSXJOC4F.js";
25
- import "./chunk-ZERSIPFC.js";
26
- import "./chunk-UHVXE24Y.js";
25
+ import "./chunk-TBBDFYXW.js";
26
+ import "./chunk-OHLNFI6Z.js";
27
27
  import "./chunk-ENTCVTQR.js";
28
+ import "./chunk-UHVXE24Y.js";
28
29
  import "./chunk-WIPEXG6R.js";
29
30
  import "./chunk-J6A3CX5N.js";
30
31
  import "./chunk-GSL47NPM.js";
31
- import "./chunk-4VXGRIH6.js";
32
+ import "./chunk-WUNIWKY4.js";
32
33
  import "./chunk-EGGE52UU.js";
33
34
  import "./chunk-ZA53AZND.js";
34
- import "./chunk-7RJUVTVF.js";
35
- import "./chunk-SCU65EZI.js";
36
35
  import "./chunk-WRJVB3C2.js";
37
36
  import "./chunk-GCASGYIO.js";
37
+ import "./chunk-7RJUVTVF.js";
38
+ import "./chunk-SCU65EZI.js";
38
39
  import "./chunk-DM2T26WE.js";
39
40
  import "./chunk-LDXUBPMO.js";
40
- import "./chunk-BEQOZOYZ.js";
41
+ import "./chunk-2FTRRQKZ.js";
41
42
  import "./chunk-CGASUJVP.js";
42
43
  import "./chunk-R3DJVOSM.js";
43
44
  import "./chunk-BT7NVCML.js";
@@ -46,6 +47,7 @@ import "./chunk-RL6NEVXT.js";
46
47
  import "./chunk-JYIJNNN3.js";
47
48
  import "./chunk-AAD2ZS6P.js";
48
49
  import "./chunk-YXZG5TVN.js";
50
+ import "./chunk-W5H6ZRPT.js";
49
51
  import "./chunk-G7D6GZ5J.js";
50
52
  import "./chunk-DLVPUX7U.js";
51
53
  import "./chunk-IJ7HK452.js";
@@ -54,7 +56,6 @@ import "./chunk-4J7G5SY4.js";
54
56
  import "./chunk-DNHVPZOD.js";
55
57
  import "./chunk-6CIAGZ6X.js";
56
58
  import "./chunk-FFAZ2XFU.js";
57
- import "./chunk-W5H6ZRPT.js";
58
59
  import "./chunk-XMMESCPD.js";
59
60
  import "./chunk-42JKGUFJ.js";
60
61
  import "./chunk-C23BYTJV.js";
@@ -73,7 +74,6 @@ import "./chunk-EYIEWJNI.js";
73
74
  import "./chunk-JUC24CTX.js";
74
75
  import "./chunk-6MKAMLQL.js";
75
76
  import "./chunk-JAKIDQB2.js";
76
- import "./chunk-TBBDFYXW.js";
77
77
  import "./chunk-BJMBJZ2Y.js";
78
78
  import "./chunk-UKJAGEXH.js";
79
79
  import "./chunk-FP2373TW.js";
package/dist/storage.js CHANGED
@@ -13,25 +13,25 @@ import {
13
13
  parseFrontmatter,
14
14
  parseFrontmatterStringValue,
15
15
  serializeEntityFile
16
- } from "./chunk-ZERSIPFC.js";
17
- import "./chunk-UHVXE24Y.js";
16
+ } from "./chunk-OHLNFI6Z.js";
18
17
  import "./chunk-ENTCVTQR.js";
18
+ import "./chunk-UHVXE24Y.js";
19
19
  import "./chunk-WIPEXG6R.js";
20
20
  import "./chunk-J6A3CX5N.js";
21
21
  import "./chunk-GSL47NPM.js";
22
- import "./chunk-4VXGRIH6.js";
22
+ import "./chunk-WUNIWKY4.js";
23
23
  import "./chunk-EGGE52UU.js";
24
24
  import "./chunk-ZA53AZND.js";
25
- import "./chunk-7RJUVTVF.js";
26
- import "./chunk-SCU65EZI.js";
27
25
  import "./chunk-WRJVB3C2.js";
28
26
  import "./chunk-GCASGYIO.js";
27
+ import "./chunk-7RJUVTVF.js";
28
+ import "./chunk-SCU65EZI.js";
29
29
  import "./chunk-DM2T26WE.js";
30
30
  import "./chunk-LDXUBPMO.js";
31
31
  import {
32
32
  ContentHashIndex,
33
33
  FactHashIndexNotAuthoritativeError
34
- } from "./chunk-BEQOZOYZ.js";
34
+ } from "./chunk-2FTRRQKZ.js";
35
35
  import "./chunk-CGASUJVP.js";
36
36
  import {
37
37
  normalizeAttributePairs,
@@ -45,6 +45,7 @@ import "./chunk-AAD2ZS6P.js";
45
45
  import {
46
46
  normalizeEntityName
47
47
  } from "./chunk-YXZG5TVN.js";
48
+ import "./chunk-W5H6ZRPT.js";
48
49
  import "./chunk-G7D6GZ5J.js";
49
50
  import "./chunk-DLVPUX7U.js";
50
51
  import "./chunk-IJ7HK452.js";
@@ -53,7 +54,6 @@ import "./chunk-4J7G5SY4.js";
53
54
  import "./chunk-DNHVPZOD.js";
54
55
  import "./chunk-6CIAGZ6X.js";
55
56
  import "./chunk-FFAZ2XFU.js";
56
- import "./chunk-W5H6ZRPT.js";
57
57
  import "./chunk-XMMESCPD.js";
58
58
  import "./chunk-42JKGUFJ.js";
59
59
  import "./chunk-C23BYTJV.js";
@@ -1,24 +1,25 @@
1
1
  import {
2
2
  compareVerifiedEpisodeResults,
3
3
  searchVerifiedEpisodes
4
- } from "./chunk-OEXKYYVH.js";
4
+ } from "./chunk-HGFILS2Q.js";
5
5
  import "./chunk-B7RWBZXW.js";
6
- import "./chunk-ZERSIPFC.js";
7
- import "./chunk-UHVXE24Y.js";
6
+ import "./chunk-ZBJMUXZH.js";
7
+ import "./chunk-OHLNFI6Z.js";
8
8
  import "./chunk-ENTCVTQR.js";
9
+ import "./chunk-UHVXE24Y.js";
9
10
  import "./chunk-WIPEXG6R.js";
10
11
  import "./chunk-J6A3CX5N.js";
11
12
  import "./chunk-GSL47NPM.js";
12
- import "./chunk-4VXGRIH6.js";
13
+ import "./chunk-WUNIWKY4.js";
13
14
  import "./chunk-EGGE52UU.js";
14
15
  import "./chunk-ZA53AZND.js";
15
- import "./chunk-7RJUVTVF.js";
16
- import "./chunk-SCU65EZI.js";
17
16
  import "./chunk-WRJVB3C2.js";
18
17
  import "./chunk-GCASGYIO.js";
18
+ import "./chunk-7RJUVTVF.js";
19
+ import "./chunk-SCU65EZI.js";
19
20
  import "./chunk-DM2T26WE.js";
20
21
  import "./chunk-LDXUBPMO.js";
21
- import "./chunk-BEQOZOYZ.js";
22
+ import "./chunk-2FTRRQKZ.js";
22
23
  import "./chunk-CGASUJVP.js";
23
24
  import "./chunk-R3DJVOSM.js";
24
25
  import "./chunk-BT7NVCML.js";
@@ -27,6 +28,7 @@ import "./chunk-RL6NEVXT.js";
27
28
  import "./chunk-JYIJNNN3.js";
28
29
  import "./chunk-AAD2ZS6P.js";
29
30
  import "./chunk-YXZG5TVN.js";
31
+ import "./chunk-W5H6ZRPT.js";
30
32
  import "./chunk-G7D6GZ5J.js";
31
33
  import "./chunk-DLVPUX7U.js";
32
34
  import "./chunk-IJ7HK452.js";
@@ -35,7 +37,6 @@ import "./chunk-4J7G5SY4.js";
35
37
  import "./chunk-DNHVPZOD.js";
36
38
  import "./chunk-6CIAGZ6X.js";
37
39
  import "./chunk-FFAZ2XFU.js";
38
- import "./chunk-W5H6ZRPT.js";
39
40
  import "./chunk-XMMESCPD.js";
40
41
  import "./chunk-42JKGUFJ.js";
41
42
  import "./chunk-C23BYTJV.js";
@@ -52,7 +53,6 @@ import "./chunk-EYIEWJNI.js";
52
53
  import "./chunk-JUC24CTX.js";
53
54
  import "./chunk-6MKAMLQL.js";
54
55
  import "./chunk-JAKIDQB2.js";
55
- import "./chunk-ZBJMUXZH.js";
56
56
  import "./chunk-BJMBJZ2Y.js";
57
57
  import "./chunk-UKJAGEXH.js";
58
58
  import "./chunk-FP2373TW.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "9.43.0",
3
+ "version": "9.44.0",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -3096,7 +3096,7 @@
3096
3096
  "core"
3097
3097
  ],
3098
3098
  "peerDependencies": {
3099
- "@remnic/coding-graph": "^9.43.0"
3099
+ "@remnic/coding-graph": "^9.44.0"
3100
3100
  },
3101
3101
  "peerDependenciesMeta": {
3102
3102
  "@remnic/coding-graph": {
@@ -0,0 +1,25 @@
1
+ import { EngramAccessInputError } from "./access-service.js";
2
+
3
+ /** Optional string field from a JSON body: absent/null/"" → undefined. */
4
+ export function optionalQueryString(value: unknown, label: string): string | undefined {
5
+ if (value === undefined || value === null || value === "") return undefined;
6
+ if (typeof value !== "string") {
7
+ throw new EngramAccessInputError(`${label} must be a string (got ${JSON.stringify(value)})`);
8
+ }
9
+ return value;
10
+ }
11
+
12
+ /** Optional non-empty query param: null/"" → undefined. */
13
+ export function nonEmptyQueryParam(value: string | null): string | undefined {
14
+ return value !== null && value.length > 0 ? value : undefined;
15
+ }
16
+
17
+ /** Optional positive-integer query param; rejects invalid values. */
18
+ export function positiveIntQueryParam(value: string | null, label: string): number | undefined {
19
+ if (value === null || value.length === 0) return undefined;
20
+ const parsed = Number(value);
21
+ if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
22
+ throw new EngramAccessInputError(`${label} expects a positive integer`);
23
+ }
24
+ return parsed;
25
+ }
@@ -3648,3 +3648,139 @@ test("HTTP authorization probe verifies requested operation grants without invok
3648
3648
  await server.stop();
3649
3649
  }
3650
3650
  });
3651
+
3652
+ test("HTTP convergence completion forwards one authenticated namespace batch refresh", async () => {
3653
+ const calls: Array<{ namespaces: string[]; principal?: string; sourceId: string }> = [];
3654
+ const service = {
3655
+ offlineSyncFinalizeConvergence: async (options: {
3656
+ namespaces: string[];
3657
+ principal?: string;
3658
+ sourceId: string;
3659
+ }) => {
3660
+ calls.push(options);
3661
+ return { namespaces: options.namespaces, refreshed: true as const };
3662
+ },
3663
+ } as unknown as EngramAccessService;
3664
+ const server = new EngramAccessHttpServer({
3665
+ service,
3666
+ port: 0,
3667
+ authToken: "test-token",
3668
+ principal: "writer",
3669
+ adminConsoleEnabled: false,
3670
+ });
3671
+ const route = "/remnic/v1/offline-sync/convergence-complete?namespace=team&namespace=shared";
3672
+
3673
+ const status = await server.start();
3674
+ try {
3675
+ const denied = await fetch(`http://127.0.0.1:${status.port}${route}`, {
3676
+ method: "POST",
3677
+ headers: { "x-remnic-source-id": encodeURIComponent("remnic-converge") },
3678
+ });
3679
+ assert.equal(denied.status, 401);
3680
+
3681
+ const response = await fetch(`http://127.0.0.1:${status.port}${route}`, {
3682
+ method: "POST",
3683
+ headers: {
3684
+ authorization: "Bearer test-token",
3685
+ "x-remnic-source-id": encodeURIComponent("remnic-converge"),
3686
+ },
3687
+ });
3688
+
3689
+ assert.equal(response.status, 200);
3690
+ assert.deepEqual(await response.json(), {
3691
+ namespaces: ["team", "shared"],
3692
+ refreshed: true,
3693
+ });
3694
+ assert.deepEqual(calls, [{
3695
+ namespaces: ["team", "shared"],
3696
+ principal: "writer",
3697
+ sourceId: "remnic-converge",
3698
+ }]);
3699
+ } finally {
3700
+ await server.stop();
3701
+ }
3702
+ });
3703
+
3704
+ test("HTTP convergence completion enforces the per-principal write rate limit", async () => {
3705
+ let completions = 0;
3706
+ const service = {
3707
+ offlineSyncFinalizeConvergence: async () => {
3708
+ completions += 1;
3709
+ return { namespaces: ["team"], refreshed: true as const };
3710
+ },
3711
+ } as unknown as EngramAccessService;
3712
+ const server = new EngramAccessHttpServer({
3713
+ service,
3714
+ port: 0,
3715
+ authToken: "test-token",
3716
+ adminConsoleEnabled: false,
3717
+ writeRateLimitMaxRequests: 1,
3718
+ });
3719
+ const status = await server.start();
3720
+ const route = `http://127.0.0.1:${status.port}/remnic/v1/offline-sync/convergence-complete?namespace=team`;
3721
+ const requestOptions: RequestInit = {
3722
+ method: "POST",
3723
+ headers: {
3724
+ authorization: "Bearer test-token",
3725
+ "x-remnic-source-id": encodeURIComponent("remnic-converge"),
3726
+ },
3727
+ };
3728
+
3729
+ try {
3730
+ const first = await fetch(route, requestOptions);
3731
+ assert.equal(first.status, 200);
3732
+ await first.text();
3733
+
3734
+ const second = await fetch(route, requestOptions);
3735
+ assert.equal(second.status, 429);
3736
+ const rateLimited: unknown = await second.json();
3737
+ assert.ok(rateLimited && typeof rateLimited === "object" && "code" in rateLimited);
3738
+ assert.equal(rateLimited.code, "write_rate_limited");
3739
+ assert.equal(completions, 1, "the rate-limited completion must not reach the service");
3740
+ } finally {
3741
+ await server.stop();
3742
+ }
3743
+ });
3744
+
3745
+ test("HTTP convergence completion denies scoped tokens that omit the namespace", async () => {
3746
+ let completions = 0;
3747
+ const service = {
3748
+ configRef: parseConfig({
3749
+ memoryDir: "/tmp/remnic-http-convergence-completion-namespace",
3750
+ namespacesEnabled: true,
3751
+ defaultNamespace: "default",
3752
+ }),
3753
+ offlineSyncFinalizeConvergence: async () => {
3754
+ completions += 1;
3755
+ return { namespaces: ["default"], refreshed: true as const };
3756
+ },
3757
+ } as unknown as EngramAccessService;
3758
+ const server = new EngramAccessHttpServer({
3759
+ service,
3760
+ port: 0,
3761
+ authTokenEntriesGetter: () => [
3762
+ { token: "scoped-token", capabilities: { version: 1, namespaces: ["team"] } },
3763
+ ],
3764
+ adminConsoleEnabled: false,
3765
+ });
3766
+ const status = await server.start();
3767
+
3768
+ try {
3769
+ const response = await fetch(
3770
+ `http://127.0.0.1:${status.port}/remnic/v1/offline-sync/convergence-complete`,
3771
+ {
3772
+ method: "POST",
3773
+ headers: {
3774
+ authorization: "Bearer scoped-token",
3775
+ "x-remnic-source-id": encodeURIComponent("remnic-converge"),
3776
+ },
3777
+ },
3778
+ );
3779
+
3780
+ assert.equal(response.status, 403);
3781
+ await response.text();
3782
+ assert.equal(completions, 0, "the denied completion must not reach the service");
3783
+ } finally {
3784
+ await server.stop();
3785
+ }
3786
+ });
@@ -18,6 +18,7 @@ import {
18
18
  type EngramAccessWriteResponse,
19
19
  } from "./access-service.js";
20
20
  import { maybeHandleLifecycleFlush, type LifecycleFlushHttpDeps } from "./access-http-lifecycle-flush.js";
21
+ import { nonEmptyQueryParam, optionalQueryString, positiveIntQueryParam } from "./access-http-query.js";
21
22
  import { CorrectionContractError } from "./correction/correction-contract.js";
22
23
  import { WearablesInputError } from "./wearables/errors.js"; import { respondMeetingsList, respondMeetingsGet, respondMeetingsBuild } from "./meetings/http-glue.js";
23
24
  import { EngramMcpServer, MCP_SUPPORTED_PROTOCOL_VERSIONS } from "./access-mcp.js";
@@ -1322,6 +1323,31 @@ export class EngramAccessHttpServer {
1322
1323
  return;
1323
1324
  }
1324
1325
 
1326
+ if (
1327
+ req.method === "POST" &&
1328
+ (
1329
+ pathname === "/engram/v1/offline-sync/convergence-complete" ||
1330
+ pathname === "/remnic/v1/offline-sync/convergence-complete"
1331
+ )
1332
+ ) {
1333
+ this.enforceTokenOp("offline_sync_apply_file_content");
1334
+ const namespaceParams = parsed.searchParams.getAll("namespace").filter(Boolean);
1335
+ const requestedNamespaces: Array<string | undefined> =
1336
+ namespaceParams.length > 0 ? namespaceParams : [undefined];
1337
+ const namespaces = requestedNamespaces
1338
+ .map((namespace) => this.resolveNamespace(req, namespace))
1339
+ .filter((namespace): namespace is string => namespace !== undefined);
1340
+ this.ensureWriteRateLimitAvailable(req);
1341
+ const result = await this.service.offlineSyncFinalizeConvergence({
1342
+ ...(namespaces.length > 0 ? { namespaces } : {}),
1343
+ principal: this.resolveRequestPrincipal(req),
1344
+ sourceId: this.readRequiredDecodedHeader(req, "x-remnic-source-id"),
1345
+ });
1346
+ this.recordWriteRateLimitHit(req);
1347
+ this.respondJson(res, 200, result);
1348
+ return;
1349
+ }
1350
+
1325
1351
  if (
1326
1352
  req.method === "POST" &&
1327
1353
  (pathname === "/engram/v1/offline-sync/apply" || pathname === "/remnic/v1/offline-sync/apply")
@@ -3925,29 +3951,3 @@ export class EngramAccessHttpServer {
3925
3951
  return false;
3926
3952
  }
3927
3953
  }
3928
-
3929
- /** Optional string field from a JSON body: absent/null/"" → undefined. */
3930
- function optionalQueryString(value: unknown, label: string): string | undefined {
3931
- if (value === undefined || value === null || value === "") return undefined;
3932
- if (typeof value !== "string") {
3933
- throw new EngramAccessInputError(
3934
- `${label} must be a string (got ${JSON.stringify(value)})`,
3935
- );
3936
- }
3937
- return value;
3938
- }
3939
-
3940
- /** Optional non-empty query param: null/"" → undefined. */
3941
- function nonEmptyQueryParam(value: string | null): string | undefined {
3942
- return value !== null && value.length > 0 ? value : undefined;
3943
- }
3944
-
3945
- /** Optional positive-integer query param; rejects invalid values. */
3946
- function positiveIntQueryParam(value: string | null, label: string): number | undefined {
3947
- if (value === null || value.length === 0) return undefined;
3948
- const parsed = Number(value);
3949
- if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
3950
- throw new EngramAccessInputError(`${label} expects a positive integer`);
3951
- }
3952
- return parsed;
3953
- }
@@ -52,3 +52,43 @@ test("offline apply-file-content reports invalid metadata as input errors", asyn
52
52
  /mtimeMs must be within JavaScript Date range/.test(error.message),
53
53
  );
54
54
  });
55
+
56
+ test("offline convergence completion refreshes authorized namespaces as one batch and rejects other sources", async () => {
57
+ const refreshed: string[][] = [];
58
+ const orchestratorStub = {
59
+ config: {
60
+ memoryDir: "/tmp/remnic-access-service-convergence-test",
61
+ namespacesEnabled: false,
62
+ defaultNamespace: "global",
63
+ sharedNamespace: "shared",
64
+ },
65
+ refreshNamespacesAfterConvergence: async (namespaces: readonly string[]) => {
66
+ refreshed.push([...namespaces]);
67
+ },
68
+ };
69
+ const service = new EngramAccessService(
70
+ orchestratorStub as unknown as ConstructorParameters<typeof EngramAccessService>[0],
71
+ );
72
+ const convergenceService = service as unknown as {
73
+ offlineSyncFinalizeConvergence(options: {
74
+ namespaces?: string[];
75
+ principal?: string;
76
+ sourceId: string;
77
+ }): Promise<{ namespaces: string[]; refreshed: true }>;
78
+ };
79
+
80
+ await assert.rejects(
81
+ () => convergenceService.offlineSyncFinalizeConvergence({ sourceId: "laptop" }),
82
+ (error) =>
83
+ error instanceof EngramAccessInputError
84
+ && /sourceId must be remnic-converge/.test(error.message),
85
+ );
86
+ assert.deepEqual(refreshed, []);
87
+
88
+ const result = await convergenceService.offlineSyncFinalizeConvergence({
89
+ sourceId: "remnic-converge",
90
+ });
91
+
92
+ assert.deepEqual(result, { namespaces: ["global"], refreshed: true });
93
+ assert.deepEqual(refreshed, [["global"]]);
94
+ });
@@ -818,6 +818,12 @@ export interface EngramAccessOfflineSyncApplyRequest {
818
818
  returnCurrentFiles?: boolean;
819
819
  }
820
820
 
821
+ export interface EngramAccessOfflineSyncFinalizeConvergenceRequest {
822
+ namespaces?: string[];
823
+ principal?: string;
824
+ sourceId: string;
825
+ }
826
+
821
827
  export interface EngramAccessOfflineSyncSnapshotResponse extends OfflineSyncSnapshot {
822
828
  namespace: string;
823
829
  }
@@ -843,6 +849,11 @@ export interface EngramAccessOfflineSyncApplyResponse extends OfflineSyncApplyCh
843
849
  namespace: string;
844
850
  }
845
851
 
852
+ export interface EngramAccessOfflineSyncFinalizeConvergenceResponse {
853
+ namespaces: string[];
854
+ refreshed: true;
855
+ }
856
+
846
857
  export type EngramAccessActionConfidenceRequest = ActionConfidenceInput;
847
858
  export type EngramAccessActionConfidenceResponse = ActionConfidenceResult;
848
859
 
@@ -5621,6 +5632,29 @@ export class EngramAccessService {
5621
5632
  }
5622
5633
  }
5623
5634
 
5635
+ async offlineSyncFinalizeConvergence(
5636
+ options: EngramAccessOfflineSyncFinalizeConvergenceRequest,
5637
+ ): Promise<EngramAccessOfflineSyncFinalizeConvergenceResponse> {
5638
+ if (options.sourceId !== "remnic-converge") {
5639
+ throw new EngramAccessInputError("sourceId must be remnic-converge");
5640
+ }
5641
+ const requestedNamespaces = options.namespaces?.length
5642
+ ? options.namespaces
5643
+ : [undefined];
5644
+ const resolvedNamespaces = Array.from(new Set(
5645
+ requestedNamespaces.map((namespace) => this.writableNamespaceFor(
5646
+ namespace,
5647
+ undefined,
5648
+ options.principal,
5649
+ )),
5650
+ ));
5651
+ await this.orchestrator.refreshNamespacesAfterConvergence(resolvedNamespaces);
5652
+ return {
5653
+ namespaces: resolvedNamespaces,
5654
+ refreshed: true,
5655
+ };
5656
+ }
5657
+
5624
5658
  async offlineSyncApply(
5625
5659
  options: EngramAccessOfflineSyncApplyRequest,
5626
5660
  ): Promise<EngramAccessOfflineSyncApplyResponse> {
@@ -183,6 +183,11 @@ export const HTTP_ROUTES: readonly HttpRouteEntry[] = [
183
183
  { method: "POST", pathname: "/engram/v1/offline-sync/files", operation: "offline_sync_files" },
184
184
  { method: "POST", pathname: "/engram/v1/offline-sync/file-content", operation: "offline_sync_file_content" },
185
185
  { method: "POST", pathname: "/engram/v1/offline-sync/apply-file-content", operation: "offline_sync_apply_file_content" },
186
+ {
187
+ method: "POST",
188
+ pathname: "/engram/v1/offline-sync/convergence-complete",
189
+ operation: "offline_sync_apply_file_content",
190
+ },
186
191
  { method: "POST", pathname: "/engram/v1/offline-sync/apply", operation: "offline_sync_apply" },
187
192
  { method: "POST", pathname: "/engram/v1/recall/explain", operation: "recall_explain" },
188
193
  { method: "POST", pathname: "/engram/v1/action-confidence", operation: "action_confidence" },
@@ -0,0 +1,28 @@
1
+ import {
2
+ type RebuildMemoryProjectionOptions,
3
+ rebuildMemoryProjection,
4
+ } from "./maintenance/rebuild-memory-projection.js";
5
+ import type { NamespaceSearchRouter } from "./namespaces/search.js";
6
+
7
+ type ConvergenceStorage = NonNullable<RebuildMemoryProjectionOptions["storage"]>;
8
+
9
+ export async function refreshConvergedNamespaces(
10
+ namespaces: readonly string[],
11
+ namespaceSearchRouter: Pick<NamespaceSearchRouter, "updateNamespacesDetailed">,
12
+ getStorage: (namespace: string) => Promise<ConvergenceStorage>
13
+ ): Promise<void> {
14
+ const targetNamespaces = Array.from(new Set(namespaces.map((namespace) => namespace.trim()).filter(Boolean)));
15
+ if (targetNamespaces.length === 0) return;
16
+
17
+ await namespaceSearchRouter.updateNamespacesDetailed(targetNamespaces, undefined, { strict: true });
18
+
19
+ for (const namespace of targetNamespaces) {
20
+ const storage = await getStorage(namespace);
21
+ await rebuildMemoryProjection({
22
+ memoryDir: storage.dir,
23
+ storage,
24
+ defaultNamespace: namespace,
25
+ dryRun: false,
26
+ });
27
+ }
28
+ }