@remnic/core 9.45.4 → 9.45.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/dist/access-admin-ops-surface.d.ts +5 -5
  2. package/dist/access-admin-ops-surface.js +20 -19
  3. package/dist/access-authorization-probe.d.ts +5 -5
  4. package/dist/access-authorization-probe.js +21 -20
  5. package/dist/access-boundary.d.ts +5 -5
  6. package/dist/access-boundary.js +20 -19
  7. package/dist/access-cli.js +60 -58
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +5 -5
  10. package/dist/access-extraction-force-flush.js +20 -19
  11. package/dist/access-http-lcm-compaction.d.ts +5 -5
  12. package/dist/access-http-lifecycle-flush.d.ts +5 -5
  13. package/dist/access-http-offline-stream.d.ts +5 -5
  14. package/dist/access-http-offline-stream.js +1 -1
  15. package/dist/access-http-query.js +20 -19
  16. package/dist/access-http.d.ts +5 -6
  17. package/dist/access-http.js +32 -31
  18. package/dist/access-identity-continuity-surface.d.ts +4 -4
  19. package/dist/access-identity-continuity-surface.js +20 -19
  20. package/dist/access-lcm-surface.d.ts +5 -5
  21. package/dist/access-lcm-surface.js +20 -19
  22. package/dist/access-mcp.d.ts +5 -5
  23. package/dist/access-mcp.js +26 -25
  24. package/dist/access-namespace-preflight.js +20 -19
  25. package/dist/access-observe-write-surface.d.ts +5 -5
  26. package/dist/access-observe-write-surface.js +20 -19
  27. package/dist/access-offline-manifest.d.ts +4 -4
  28. package/dist/access-operations-batch.js +21 -20
  29. package/dist/access-operations.d.ts +8 -8
  30. package/dist/access-operations.js +25 -24
  31. package/dist/access-recall-concurrency.d.ts +5 -5
  32. package/dist/access-recall-concurrency.js +20 -19
  33. package/dist/access-recall-response.d.ts +5 -5
  34. package/dist/access-recall-response.js +20 -19
  35. package/dist/access-recall-surface.d.ts +5 -5
  36. package/dist/access-recall-surface.js +20 -19
  37. package/dist/access-schema.d.ts +84 -84
  38. package/dist/{access-service-CsU-ljFD.d.ts → access-service-CNN89xyn.d.ts} +3 -3
  39. package/dist/access-service-helpers.d.ts +5 -5
  40. package/dist/access-service.d.ts +5 -5
  41. package/dist/access-service.js +20 -19
  42. package/dist/access-surface-catalog.d.ts +5 -5
  43. package/dist/access-wearables-meetings-surface.d.ts +2 -2
  44. package/dist/adapters/index.js +4 -4
  45. package/dist/adapters/registry.js +2 -2
  46. package/dist/bootstrap.d.ts +4 -4
  47. package/dist/briefing.d.ts +1 -1
  48. package/dist/briefing.js +3 -2
  49. package/dist/buffer.d.ts +1 -1
  50. package/dist/buffer.js +4 -4
  51. package/dist/causal-consolidation.js +4 -3
  52. package/dist/causal-consolidation.js.map +1 -1
  53. package/dist/{chunk-7SHJHPTY.js → chunk-2FSTB6BJ.js} +2 -2
  54. package/dist/{chunk-ULVR5KG7.js → chunk-2X2T2UVE.js} +2 -2
  55. package/dist/{chunk-QVSBTCVP.js → chunk-3COYXTGM.js} +2 -2
  56. package/dist/{chunk-XTAUXTDO.js → chunk-4FBVAGV3.js} +2 -2
  57. package/dist/{chunk-R5RFK3CB.js → chunk-5QJQHBLE.js} +2 -2
  58. package/dist/{chunk-YMAQDHQM.js → chunk-6ISC4AVB.js} +2 -2
  59. package/dist/{chunk-7CITSYSH.js → chunk-7T4TOGMS.js} +2 -2
  60. package/dist/{chunk-ZMAYKGPN.js → chunk-7YQ6ESEA.js} +12 -41
  61. package/dist/chunk-7YQ6ESEA.js.map +1 -0
  62. package/dist/{chunk-TYISDI6B.js → chunk-A4IJCD2Z.js} +2 -2
  63. package/dist/{chunk-JH6BPLOP.js → chunk-AC5OWJLV.js} +4 -4
  64. package/dist/{chunk-CLB32OHM.js → chunk-AMAUBUKY.js} +2 -2
  65. package/dist/{chunk-WGP57SR3.js → chunk-CK5KOVHW.js} +3 -2
  66. package/dist/{chunk-WGP57SR3.js.map → chunk-CK5KOVHW.js.map} +1 -1
  67. package/dist/{chunk-XSFHWBQO.js → chunk-CX4ZUMC6.js} +7 -61
  68. package/dist/{chunk-XSFHWBQO.js.map → chunk-CX4ZUMC6.js.map} +1 -1
  69. package/dist/{chunk-UQWIKLQK.js → chunk-DAJPRXBR.js} +6 -6
  70. package/dist/{chunk-U2VLVBBH.js → chunk-E5XQIWAL.js} +2 -2
  71. package/dist/{chunk-NTOIP2E6.js → chunk-ERZ2R42X.js} +2 -2
  72. package/dist/{chunk-5CEECY6P.js → chunk-FIK3CQNA.js} +3 -3
  73. package/dist/{chunk-EJHEWCGQ.js → chunk-FR27HBBA.js} +2 -2
  74. package/dist/{chunk-FZP32336.js → chunk-FUCYDRE5.js} +43 -21
  75. package/dist/chunk-FUCYDRE5.js.map +1 -0
  76. package/dist/{chunk-P7NGM24P.js → chunk-GFCVUY6G.js} +2 -2
  77. package/dist/{chunk-DYVMXPCF.js → chunk-GODSPTOT.js} +41 -41
  78. package/dist/{chunk-AJQ57VV3.js → chunk-GRUYA45P.js} +4 -4
  79. package/dist/chunk-GRUYA45P.js.map +1 -0
  80. package/dist/{chunk-2MRHJNWL.js → chunk-GUAL4PQH.js} +2 -2
  81. package/dist/{chunk-EITZHSX6.js → chunk-HC3PBX23.js} +2 -2
  82. package/dist/{chunk-NUEQKLNB.js → chunk-JZH4LWHB.js} +2 -2
  83. package/dist/{chunk-7RZJWZ46.js → chunk-LEPOP46W.js} +5 -5
  84. package/dist/{chunk-TQ4GD737.js → chunk-LPYDOLSM.js} +2 -2
  85. package/dist/{chunk-TN76AKO3.js → chunk-MO4HSXHZ.js} +2 -2
  86. package/dist/{chunk-WQIHRA5F.js → chunk-N3LL5NEU.js} +2 -2
  87. package/dist/{chunk-D3I2MCN7.js → chunk-NEF7LR5J.js} +3 -3
  88. package/dist/{chunk-C26TE27X.js → chunk-QR6G5KF4.js} +3 -3
  89. package/dist/{chunk-ZI32MKDW.js → chunk-QUENPGWZ.js} +18 -21
  90. package/dist/chunk-QUENPGWZ.js.map +1 -0
  91. package/dist/{chunk-5SNZSWWR.js → chunk-QVJPH7SH.js} +21 -21
  92. package/dist/{chunk-MDISBSYA.js → chunk-R3KHKU7M.js} +2 -2
  93. package/dist/{chunk-2QSZNTDO.js → chunk-RKNJBZ55.js} +4 -4
  94. package/dist/{chunk-KXEFRMCF.js → chunk-RNHVVMFN.js} +2 -2
  95. package/dist/{chunk-QCECHYZL.js → chunk-RVO6TCTU.js} +6 -6
  96. package/dist/chunk-S2HLHAZ4.js +16 -0
  97. package/dist/chunk-S2HLHAZ4.js.map +1 -0
  98. package/dist/{chunk-ZFGZ6PZ2.js → chunk-UW66OZTD.js} +2 -2
  99. package/dist/{chunk-BGHFOD5A.js → chunk-V2TNYF6Q.js} +3 -3
  100. package/dist/chunk-VL35ZFSZ.js +102 -0
  101. package/dist/chunk-VL35ZFSZ.js.map +1 -0
  102. package/dist/{chunk-Y7HRYCNW.js → chunk-W2V7UESE.js} +2 -2
  103. package/dist/{chunk-DSUAAZZX.js → chunk-WZ3TOIDW.js} +2 -2
  104. package/dist/{chunk-7YERSTN7.js → chunk-XAGYS7X6.js} +7 -7
  105. package/dist/{chunk-VOUOLGIP.js → chunk-YRFAYOFQ.js} +11 -13
  106. package/dist/chunk-YRFAYOFQ.js.map +1 -0
  107. package/dist/{chunk-6NNNURLK.js → chunk-Z54EM5YZ.js} +4 -4
  108. package/dist/{cli-BBHDtG36.d.ts → cli-BHBswmUa.d.ts} +3 -3
  109. package/dist/cli.d.ts +6 -6
  110. package/dist/cli.js +43 -42
  111. package/dist/compounding/engine.d.ts +1 -1
  112. package/dist/compounding/engine.js +3 -2
  113. package/dist/connectors/codex-materialize-runner.js +3 -2
  114. package/dist/connectors/index.js +3 -2
  115. package/dist/consolidation-provenance-check.d.ts +1 -1
  116. package/dist/consolidation-undo.d.ts +1 -1
  117. package/dist/contradiction/index.d.ts +1 -1
  118. package/dist/convergence-refresh.d.ts +1 -1
  119. package/dist/convergence-refresh.js +5 -4
  120. package/dist/conversation-index/backend.js +2 -2
  121. package/dist/corpus-watermark.js +12 -11
  122. package/dist/entity-retrieval.d.ts +1 -1
  123. package/dist/entity-retrieval.js +3 -2
  124. package/dist/explicit-capture.d.ts +4 -4
  125. package/dist/external-wiki-access.d.ts +5 -5
  126. package/dist/external-wiki-access.js +23 -22
  127. package/dist/external-wiki-cli.js +4 -90
  128. package/dist/external-wiki-cli.js.map +1 -1
  129. package/dist/external-wiki-mcp-tools.d.ts +5 -5
  130. package/dist/external-wiki-search.js +2 -2
  131. package/dist/external-wiki.d.ts +1 -5
  132. package/dist/external-wiki.js +1 -3
  133. package/dist/extraction.js +8 -7
  134. package/dist/{first-start-migration-F2QJD66E.js → first-start-migration-ZSHEFEI3.js} +10 -12
  135. package/dist/{first-start-migration-F2QJD66E.js.map → first-start-migration-ZSHEFEI3.js.map} +1 -1
  136. package/dist/index.d.ts +688 -687
  137. package/dist/index.js +81 -78
  138. package/dist/lcm/engine.js +2 -2
  139. package/dist/lcm/index.js +2 -2
  140. package/dist/maintenance/memory-governance.js +3 -2
  141. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +1 -1
  142. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -2
  143. package/dist/maintenance/rebuild-memory-projection.d.ts +1 -1
  144. package/dist/maintenance/rebuild-memory-projection.js +4 -3
  145. package/dist/{maintenance-D2mveyCd.d.ts → maintenance-CoRikzIt.d.ts} +1 -1
  146. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  147. package/dist/memory-snapshot.d.ts +10 -0
  148. package/dist/memory-snapshot.js +8 -0
  149. package/dist/memory-snapshot.js.map +1 -0
  150. package/dist/memory-worth-outcomes.d.ts +1 -1
  151. package/dist/namespaces/migrate.d.ts +1 -1
  152. package/dist/namespaces/migrate.js +11 -10
  153. package/dist/namespaces/search.js +7 -7
  154. package/dist/namespaces/storage.d.ts +1 -1
  155. package/dist/namespaces/storage.js +3 -2
  156. package/dist/operator-doctor-corpus.js +13 -12
  157. package/dist/operator-toolkit.d.ts +1 -1
  158. package/dist/operator-toolkit.js +17 -16
  159. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  160. package/dist/orchestration/maintenance.d.ts +2 -2
  161. package/dist/orchestration/maintenance.js +8 -7
  162. package/dist/{orchestrator-DJYlwiUv.d.ts → orchestrator-BJeq7Pw1.d.ts} +3 -3
  163. package/dist/orchestrator.d.ts +4 -4
  164. package/dist/orchestrator.js +61 -59
  165. package/dist/qmd.js +4 -4
  166. package/dist/schemas.d.ts +76 -76
  167. package/dist/search/factory.js +6 -6
  168. package/dist/search/index.js +8 -8
  169. package/dist/semantic-consolidation.js +4 -3
  170. package/dist/semantic-rule-promotion.js +3 -2
  171. package/dist/semantic-rule-verifier.js +3 -2
  172. package/dist/{service-BeDxSqE-.d.ts → service-DWC4tq7p.d.ts} +1 -1
  173. package/dist/shared-context/manager.d.ts +8 -8
  174. package/dist/source-agent-qualifier.js +7 -6
  175. package/dist/{storage-DfjxusTE.d.ts → storage-DPGjB-8e.d.ts} +4 -1
  176. package/dist/storage.d.ts +1 -1
  177. package/dist/storage.js +2 -1
  178. package/dist/temporal-supersession.d.ts +1 -1
  179. package/dist/tier-migration.d.ts +1 -1
  180. package/dist/tier-migration.js +1 -1
  181. package/dist/transfer/types.d.ts +66 -66
  182. package/dist/verified-recall.js +3 -2
  183. package/package.json +2 -2
  184. package/src/access-http-offline-stream.ts +1 -0
  185. package/src/access-http.ts +0 -57
  186. package/src/access-operations-batch.ts +1 -1
  187. package/src/access-service-observe-lcm-parity.test.ts +45 -20
  188. package/src/access-service.ts +3 -4
  189. package/src/external-wiki-cli.ts +28 -20
  190. package/src/external-wiki-search.test.ts +68 -2
  191. package/src/external-wiki.ts +12 -38
  192. package/src/index.ts +1 -5
  193. package/src/maintenance/first-start-migration.ts +11 -11
  194. package/src/memory-snapshot.ts +15 -0
  195. package/src/storage-contract/cache-coherence.test.ts +99 -0
  196. package/src/storage-fact-hash-index-defer.test.ts +14 -7
  197. package/src/storage.ts +47 -48
  198. package/src/testing/subjects/first-start-tier-migration.test.ts +75 -0
  199. package/src/tier-migration.ts +10 -12
  200. package/dist/chunk-AJQ57VV3.js.map +0 -1
  201. package/dist/chunk-FZP32336.js.map +0 -1
  202. package/dist/chunk-VOUOLGIP.js.map +0 -1
  203. package/dist/chunk-ZI32MKDW.js.map +0 -1
  204. package/dist/chunk-ZMAYKGPN.js.map +0 -1
  205. /package/dist/{chunk-7SHJHPTY.js.map → chunk-2FSTB6BJ.js.map} +0 -0
  206. /package/dist/{chunk-ULVR5KG7.js.map → chunk-2X2T2UVE.js.map} +0 -0
  207. /package/dist/{chunk-QVSBTCVP.js.map → chunk-3COYXTGM.js.map} +0 -0
  208. /package/dist/{chunk-XTAUXTDO.js.map → chunk-4FBVAGV3.js.map} +0 -0
  209. /package/dist/{chunk-R5RFK3CB.js.map → chunk-5QJQHBLE.js.map} +0 -0
  210. /package/dist/{chunk-YMAQDHQM.js.map → chunk-6ISC4AVB.js.map} +0 -0
  211. /package/dist/{chunk-7CITSYSH.js.map → chunk-7T4TOGMS.js.map} +0 -0
  212. /package/dist/{chunk-TYISDI6B.js.map → chunk-A4IJCD2Z.js.map} +0 -0
  213. /package/dist/{chunk-JH6BPLOP.js.map → chunk-AC5OWJLV.js.map} +0 -0
  214. /package/dist/{chunk-CLB32OHM.js.map → chunk-AMAUBUKY.js.map} +0 -0
  215. /package/dist/{chunk-UQWIKLQK.js.map → chunk-DAJPRXBR.js.map} +0 -0
  216. /package/dist/{chunk-U2VLVBBH.js.map → chunk-E5XQIWAL.js.map} +0 -0
  217. /package/dist/{chunk-NTOIP2E6.js.map → chunk-ERZ2R42X.js.map} +0 -0
  218. /package/dist/{chunk-5CEECY6P.js.map → chunk-FIK3CQNA.js.map} +0 -0
  219. /package/dist/{chunk-EJHEWCGQ.js.map → chunk-FR27HBBA.js.map} +0 -0
  220. /package/dist/{chunk-P7NGM24P.js.map → chunk-GFCVUY6G.js.map} +0 -0
  221. /package/dist/{chunk-DYVMXPCF.js.map → chunk-GODSPTOT.js.map} +0 -0
  222. /package/dist/{chunk-2MRHJNWL.js.map → chunk-GUAL4PQH.js.map} +0 -0
  223. /package/dist/{chunk-EITZHSX6.js.map → chunk-HC3PBX23.js.map} +0 -0
  224. /package/dist/{chunk-NUEQKLNB.js.map → chunk-JZH4LWHB.js.map} +0 -0
  225. /package/dist/{chunk-7RZJWZ46.js.map → chunk-LEPOP46W.js.map} +0 -0
  226. /package/dist/{chunk-TQ4GD737.js.map → chunk-LPYDOLSM.js.map} +0 -0
  227. /package/dist/{chunk-TN76AKO3.js.map → chunk-MO4HSXHZ.js.map} +0 -0
  228. /package/dist/{chunk-WQIHRA5F.js.map → chunk-N3LL5NEU.js.map} +0 -0
  229. /package/dist/{chunk-D3I2MCN7.js.map → chunk-NEF7LR5J.js.map} +0 -0
  230. /package/dist/{chunk-C26TE27X.js.map → chunk-QR6G5KF4.js.map} +0 -0
  231. /package/dist/{chunk-5SNZSWWR.js.map → chunk-QVJPH7SH.js.map} +0 -0
  232. /package/dist/{chunk-MDISBSYA.js.map → chunk-R3KHKU7M.js.map} +0 -0
  233. /package/dist/{chunk-2QSZNTDO.js.map → chunk-RKNJBZ55.js.map} +0 -0
  234. /package/dist/{chunk-KXEFRMCF.js.map → chunk-RNHVVMFN.js.map} +0 -0
  235. /package/dist/{chunk-QCECHYZL.js.map → chunk-RVO6TCTU.js.map} +0 -0
  236. /package/dist/{chunk-ZFGZ6PZ2.js.map → chunk-UW66OZTD.js.map} +0 -0
  237. /package/dist/{chunk-BGHFOD5A.js.map → chunk-V2TNYF6Q.js.map} +0 -0
  238. /package/dist/{chunk-Y7HRYCNW.js.map → chunk-W2V7UESE.js.map} +0 -0
  239. /package/dist/{chunk-DSUAAZZX.js.map → chunk-WZ3TOIDW.js.map} +0 -0
  240. /package/dist/{chunk-7YERSTN7.js.map → chunk-XAGYS7X6.js.map} +0 -0
  241. /package/dist/{chunk-6NNNURLK.js.map → chunk-Z54EM5YZ.js.map} +0 -0
@@ -3424,63 +3424,6 @@ export class EngramAccessHttpServer {
3424
3424
  res.end(body);
3425
3425
  }
3426
3426
 
3427
- private async respondOfflineSnapshotStream(
3428
- res: ServerResponse,
3429
- snapshot: Awaited<ReturnType<EngramAccessService["offlineSyncSnapshotStream"]>>,
3430
- ): Promise<void> {
3431
- res.statusCode = 200;
3432
- res.setHeader("content-type", "application/x-ndjson; charset=utf-8");
3433
- res.setHeader("cache-control", "no-store");
3434
- const cid = correlationIdStore.getStore();
3435
- if (cid) {
3436
- res.setHeader("x-request-id", cid);
3437
- }
3438
- const waitForDrainOrClose = async (): Promise<boolean> => new Promise((resolve, reject) => {
3439
- const cleanup = () => {
3440
- res.off("drain", onDrain);
3441
- res.off("close", onClose);
3442
- res.off("error", onError);
3443
- };
3444
- const onDrain = () => {
3445
- cleanup();
3446
- resolve(true);
3447
- };
3448
- const onClose = () => {
3449
- cleanup();
3450
- resolve(false);
3451
- };
3452
- const onError = (error: Error) => {
3453
- cleanup();
3454
- reject(error);
3455
- };
3456
- res.once("drain", onDrain);
3457
- res.once("close", onClose);
3458
- res.once("error", onError);
3459
- });
3460
- const writeLine = async (payload: unknown): Promise<boolean> => {
3461
- if (res.destroyed || res.writableEnded) return false;
3462
- if (res.write(`${JSON.stringify(payload)}\n`)) return true;
3463
- if (res.destroyed || res.writableEnded) return false;
3464
- return waitForDrainOrClose();
3465
- };
3466
- if (!await writeLine({
3467
- type: "snapshot",
3468
- namespace: snapshot.namespace,
3469
- format: snapshot.format,
3470
- schemaVersion: snapshot.schemaVersion,
3471
- createdAt: snapshot.createdAt,
3472
- sourceId: snapshot.sourceId,
3473
- includeTranscripts: snapshot.includeTranscripts,
3474
- deletions: snapshot.deletions,
3475
- })) return;
3476
- for await (const file of snapshot.files) {
3477
- if (!await writeLine({ type: "file", file })) return;
3478
- }
3479
- if (!res.destroyed && !res.writableEnded) {
3480
- res.end();
3481
- }
3482
- }
3483
-
3484
3427
  private respondBinary(
3485
3428
  res: ServerResponse,
3486
3429
  status: number,
@@ -163,7 +163,7 @@ defineOperation({ name: "chatgpt_memory_inspector", description: "Memory inspect
163
163
  if (input.currentContextScopes !== undefined) ii.currentContextScopes = input.currentContextScopes as string[];
164
164
  if (input.allowUnverifiedPreview !== undefined) ii.allowUnverifiedPreview = input.allowUnverifiedPreview as boolean;
165
165
  const rsk = ii.sessionKey ?? (ctx.authenticatedPrincipal ? "remnic:chatgpt-memory-inspector:" + randomUUID() : undefined);
166
- const xr = await ctx.service.recallXray({ query: ii.query, sessionKey: rsk, namespace: ii.namespace, currentContextScopes: ii.currentContextScopes, authenticatedPrincipal: ctx.authenticatedPrincipal, sourceConnector: ctx.sourceConnector, mode: "full", disclosure: "chunk", includeRecall: true, ...(ctx.abortSignal ? { abortSignal: ctx.abortSignal } : {}) });
166
+ const xr = await ctx.service.recallXray({ query: ii.query, sessionKey: rsk, namespace: ii.namespace, currentContextScopes: ii.currentContextScopes, authenticatedPrincipal: ctx.authenticatedPrincipal, ...(ctx.sourceConnector ? { sourceConnector: ctx.sourceConnector } : {}), mode: "full", disclosure: "chunk", includeRecall: true, ...(ctx.abortSignal ? { abortSignal: ctx.abortSignal } : {}) });
167
167
  const x = xr.snapshotFound === true ? (xr.snapshot ?? null) : null;
168
168
  const r = xr.recall ?? { query: ii.query, namespace: ii.namespace ?? x?.namespace ?? "global", context: "", count: 0, memoryIds: [], results: [], fallbackUsed: false, sourcesUsed: [], disclosure: "chunk" as const };
169
169
  const ac = await ctx.service.actionConfidence(buildChatGptMemoryInspectorActionRequest(ii, r, x));
@@ -910,19 +910,28 @@ test("#2128: post-flush retained cleanup is best effort and receives lifecycle g
910
910
  }]);
911
911
  });
912
912
 
913
- test("#2128: post-flush retained cleanup stops on abort or deadline", async () => {
913
+ test("#2128: post-flush retained cleanup stops on abort or deadline", async (t) => {
914
914
  const probe = makeParityProbe(withSelfPolicyPrefix("pi-geek"));
915
- (probe.orch as unknown as {
916
- buffer: {
917
- clearRetainedTurnsForSession(
915
+ let cleanupStarted: (() => void) | undefined;
916
+ const cleanupCalls: Array<{
917
+ sessionKey: string;
918
+ ownerPrincipal: string | undefined;
919
+ options: { abortSignal?: AbortSignal; deadlineMs?: number } | undefined;
920
+ }> = [];
921
+ Object.defineProperty(probe.orch, "buffer", {
922
+ configurable: true,
923
+ value: {
924
+ clearRetainedTurnsForSession: async (
918
925
  sessionKey: string,
919
926
  ownerPrincipal?: string,
920
927
  options?: { abortSignal?: AbortSignal; deadlineMs?: number },
921
- ): Promise<void>;
922
- };
923
- }).buffer = {
924
- clearRetainedTurnsForSession: async () => new Promise<void>(() => {}),
925
- };
928
+ ) => {
929
+ cleanupCalls.push({ sessionKey, ownerPrincipal, options });
930
+ cleanupStarted?.();
931
+ return new Promise<void>(() => {});
932
+ },
933
+ },
934
+ });
926
935
  const service = new EngramAccessService(probe.orch);
927
936
  const abortController = new AbortController();
928
937
  setTimeout(() => abortController.abort(), 5).unref();
@@ -941,19 +950,35 @@ test("#2128: post-flush retained cleanup stops on abort or deadline", async () =
941
950
  ]),
942
951
  /extraction force-flush aborted/,
943
952
  );
953
+ assert.deepEqual(cleanupCalls[0], {
954
+ sessionKey: "pi-geek:cleanup-abort",
955
+ ownerPrincipal: "pi-geek",
956
+ options: { abortSignal: abortController.signal, deadlineMs: undefined },
957
+ });
944
958
 
959
+ const cleanupStartedPromise = new Promise<void>((resolve) => {
960
+ cleanupStarted = resolve;
961
+ });
962
+ t.mock.timers.enable({ apis: ["setTimeout", "Date"], now: 0 });
963
+ const deadlineFlush = service.extractionForceFlush({
964
+ sessionKey: "pi-geek:cleanup-deadline",
965
+ authenticatedPrincipal: "pi-geek",
966
+ deadlineMs: 5,
967
+ });
968
+ await Promise.race([
969
+ cleanupStartedPromise,
970
+ new Promise<never>((_resolve, reject) =>
971
+ setImmediate(() => reject(new Error("deadline cleanup did not start"))),
972
+ ),
973
+ ]);
974
+ assert.deepEqual(cleanupCalls[1], {
975
+ sessionKey: "pi-geek:cleanup-deadline",
976
+ ownerPrincipal: "pi-geek",
977
+ options: { abortSignal: undefined, deadlineMs: 5 },
978
+ });
979
+ t.mock.timers.tick(5);
945
980
  await assert.rejects(
946
- () =>
947
- Promise.race([
948
- service.extractionForceFlush({
949
- sessionKey: "pi-geek:cleanup-deadline",
950
- authenticatedPrincipal: "pi-geek",
951
- deadlineMs: Date.now() + 5,
952
- }),
953
- new Promise<never>((_resolve, reject) =>
954
- setTimeout(() => reject(new Error("deadline cleanup test timed out")), 100),
955
- ),
956
- ]),
981
+ deadlineFlush,
957
982
  /replay extraction deadline exceeded \(retained_turn_cleanup\)/,
958
983
  );
959
984
  });
@@ -2386,7 +2386,9 @@ export class EngramAccessService {
2386
2386
  } else if (extraction.degradedReason?.includes("buffer unreadable")) {
2387
2387
  scopedDegradedReason = "daemon extraction pipeline degraded; extraction buffer unreadable";
2388
2388
  } else {
2389
- scopedDegradedReason = "daemon extraction pipeline degraded; backlog pending extraction";
2389
+ scopedDegradedReason =
2390
+ `${extraction.bufferedSessionCount} buffered session(s), ` +
2391
+ `${extraction.pendingTurnCount} turn(s) pending extraction`;
2390
2392
  }
2391
2393
  }
2392
2394
  const visibleExtraction =
@@ -2394,9 +2396,6 @@ export class EngramAccessService {
2394
2396
  ? {
2395
2397
  ...extraction,
2396
2398
  lastExtractionAt: null,
2397
- bufferedSessionCount: 0,
2398
- pendingTurnCount: 0,
2399
- oldestBufferedTurnAgeMs: null,
2400
2399
  degradedReason: scopedDegradedReason,
2401
2400
  }
2402
2401
  : extraction;
@@ -1,4 +1,4 @@
1
- import { type ExternalWikiRoot, searchExternalWikis } from "./external-wiki-search.js";
1
+ import { type ExternalWikiRoot, type ExternalWikiSearchResult, searchExternalWikis } from "./external-wiki-search.js";
2
2
 
3
3
  interface ExternalWikiCliIo {
4
4
  readonly stdout: { write(chunk: string): unknown };
@@ -13,28 +13,25 @@ export async function runExternalWikiCliCommand(
13
13
  args: readonly string[],
14
14
  io: ExternalWikiCliIo
15
15
  ): Promise<number> {
16
- if (args.length === 0 || args[0] === "help" || args[0] === "--help" || args[0] === "-h") {
16
+ if (args[0] === "help" || args[0] === "--help" || args[0] === "-h") {
17
17
  io.stdout.write(USAGE);
18
18
  return 0;
19
19
  }
20
- if (args[0] !== "search") {
21
- io.stderr.write(`external-wiki: unknown command '${args[0]}'\n${USAGE}`);
22
- return 2;
23
- }
20
+ const searchArgs = args[0] === "search" ? args.slice(1) : args;
24
21
 
25
22
  let limit: number | undefined;
26
23
  let wikiId: string | undefined;
27
24
  let maxCharsPerHit: number | undefined;
28
25
  let json = false;
29
26
  const queryParts: string[] = [];
30
- for (let index = 1; index < args.length; index += 1) {
31
- const argument = args[index];
27
+ for (let index = 0; index < searchArgs.length; index += 1) {
28
+ const argument = searchArgs[index];
32
29
  if (argument === "--json") {
33
30
  json = true;
34
31
  continue;
35
32
  }
36
33
  if (argument === "--limit" || argument === "--wiki-id" || argument === "--max-chars-per-hit") {
37
- const value = args[index + 1];
34
+ const value = searchArgs[index + 1];
38
35
  if (value === undefined || value.startsWith("--")) {
39
36
  io.stderr.write(`external-wiki: ${argument} requires a value\n`);
40
37
  return 2;
@@ -68,25 +65,36 @@ export async function runExternalWikiCliCommand(
68
65
 
69
66
  const query = queryParts.join(" ").trim();
70
67
  if (query.length === 0) {
71
- io.stderr.write(`external-wiki: query is required\n${USAGE}`);
72
- return 2;
68
+ io.stderr.write("external-wiki: provide a search query\n");
69
+ return 1;
70
+ }
71
+ const enabled = roots.filter((root) => root.enabled !== false);
72
+ if (enabled.length === 0) {
73
+ io.stderr.write("external-wiki: no enabled wiki roots configured\n");
74
+ return 1;
73
75
  }
74
76
 
75
- const result = await searchExternalWikis(roots, { query, limit, wikiId, maxCharsPerHit });
77
+ let result: ExternalWikiSearchResult;
78
+ try {
79
+ result = await searchExternalWikis(enabled, { query, limit, wikiId, maxCharsPerHit });
80
+ } catch (error) {
81
+ io.stderr.write(`external-wiki: ${error instanceof Error ? error.message : "search failed"}\n`);
82
+ return 1;
83
+ }
76
84
  if (json) {
77
85
  io.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
78
86
  return 0;
79
87
  }
80
88
 
81
- io.stdout.write(`External wiki results for "${result.query}" (${result.count})\n`);
82
- for (const hit of result.hits) {
83
- const citation = hit.citations[0];
84
- const location = citation ? `${citation.path}:${citation.lineStart}-${citation.lineEnd}` : hit.path;
85
- io.stdout.write(`${hit.rank}. [${hit.wikiId}] ${hit.title} (${location})\n`);
86
- io.stdout.write(` ${hit.snippet.replace(/\s+/g, " ").trim()}\n`);
87
- }
88
89
  if (result.degradedWikiIds.length > 0) {
89
- io.stderr.write(`external-wiki: degraded roots: ${result.degradedWikiIds.join(", ")}\n`);
90
+ io.stderr.write(`Warning: degraded roots: ${result.degradedWikiIds.join(", ")}\n`);
91
+ }
92
+ if (result.hits.length === 0) {
93
+ io.stdout.write("No results.\n");
94
+ return 0;
95
+ }
96
+ for (const hit of result.hits) {
97
+ io.stdout.write(`[${hit.wikiId}] ${hit.path} (score ${hit.score})\n${hit.snippet}\n\n`);
90
98
  }
91
99
  return 0;
92
100
  }
@@ -257,7 +257,7 @@ test("external wiki search fails open to filesystem candidates when a dedicated
257
257
  }
258
258
  });
259
259
 
260
- test("external wiki CLI searches multi-word queries and renders cited JSON or text", async () => {
260
+ test("external wiki CLI preserves text contracts and supports cited JSON", async () => {
261
261
  const root = await createWiki("cli", {
262
262
  "INDEX.md": "- [[wiki/agents|Agent Planning]] - planner fan-out with citations\n",
263
263
  "wiki/agents.md": "# Agent Planning\n\nPlanner fan-out uses cited retrieval evidence.\n",
@@ -286,7 +286,7 @@ test("external wiki CLI searches multi-word queries and renders cited JSON or te
286
286
  stderr: { write: () => undefined },
287
287
  });
288
288
  assert.equal(textCode, 0);
289
- assert.match(textOutput.join(""), /\[cli\] Agent Planning \(wiki\/agents\.md:\d+-\d+\)/);
289
+ assert.match(textOutput.join(""), /\[cli\] wiki\/agents\.md \(score [\d.]+\)/);
290
290
 
291
291
  const invalidErrors: string[] = [];
292
292
  const invalidCode = await runExternalWikiCliCommand([root], ["search", "--limit", "0", "query"], {
@@ -295,6 +295,72 @@ test("external wiki CLI searches multi-word queries and renders cited JSON or te
295
295
  });
296
296
  assert.equal(invalidCode, 2);
297
297
  assert.match(invalidErrors.join(""), /--limit must be an integer from 1 to 20/);
298
+
299
+ const noQueryErrors: string[] = [];
300
+ const noQueryCode = await runExternalWikiCliCommand([root], ["search"], {
301
+ stdout: { write: () => undefined },
302
+ stderr: { write: (chunk) => noQueryErrors.push(chunk) },
303
+ });
304
+ assert.equal(noQueryCode, 1);
305
+ assert.equal(noQueryErrors.join(""), "external-wiki: provide a search query\n");
306
+
307
+ const disabledErrors: string[] = [];
308
+ const disabledCode = await runExternalWikiCliCommand([{ ...root, enabled: false }], ["search", "planner"], {
309
+ stdout: { write: () => undefined },
310
+ stderr: { write: (chunk) => disabledErrors.push(chunk) },
311
+ });
312
+ assert.equal(disabledCode, 1);
313
+ assert.equal(disabledErrors.join(""), "external-wiki: no enabled wiki roots configured\n");
314
+
315
+ const emptyOutput: string[] = [];
316
+ const emptyCode = await runExternalWikiCliCommand([root], ["search", "unmatched-token"], {
317
+ stdout: { write: (chunk) => emptyOutput.push(chunk) },
318
+ stderr: { write: () => undefined },
319
+ });
320
+ assert.equal(emptyCode, 0);
321
+ assert.equal(emptyOutput.join(""), "No results.\n");
322
+
323
+ const searchErrors: string[] = [];
324
+ const searchErrorCode = await runExternalWikiCliCommand([root], ["search", "planner", "--wiki-id", "missing"], {
325
+ stdout: { write: () => undefined },
326
+ stderr: { write: (chunk) => searchErrors.push(chunk) },
327
+ });
328
+ assert.equal(searchErrorCode, 1);
329
+ assert.equal(searchErrors.join(""), "external-wiki: unknown external wiki: missing\n");
330
+
331
+ const legacyOutput: string[] = [];
332
+ const legacyCode = await runExternalWikiCliCommand([root], ["planner", "fan-out"], {
333
+ stdout: { write: (chunk) => legacyOutput.push(chunk) },
334
+ stderr: { write: () => undefined },
335
+ });
336
+ assert.equal(legacyCode, 0);
337
+ assert.match(legacyOutput.join(""), /^\[cli\] wiki\/agents\.md \(score [\d.]+\)/);
338
+
339
+ const degradedErrors: string[] = [];
340
+ const degradedCode = await runExternalWikiCliCommand(
341
+ [root, { ...root, id: "broken", rootDir: path.join(root.rootDir, "missing") }],
342
+ ["search", "planner"],
343
+ {
344
+ stdout: { write: () => undefined },
345
+ stderr: { write: (chunk) => degradedErrors.push(chunk) },
346
+ }
347
+ );
348
+ assert.equal(degradedCode, 0);
349
+ assert.equal(degradedErrors.join(""), "Warning: degraded roots: broken\n");
350
+
351
+ const allDegradedOutput: string[] = [];
352
+ const allDegradedErrors: string[] = [];
353
+ const allDegradedCode = await runExternalWikiCliCommand(
354
+ [{ ...root, id: "broken", rootDir: path.join(root.rootDir, "missing") }],
355
+ ["search", "planner"],
356
+ {
357
+ stdout: { write: (chunk) => allDegradedOutput.push(chunk) },
358
+ stderr: { write: (chunk) => allDegradedErrors.push(chunk) },
359
+ }
360
+ );
361
+ assert.equal(allDegradedCode, 0);
362
+ assert.equal(allDegradedOutput.join(""), "No results.\n");
363
+ assert.equal(allDegradedErrors.join(""), "Warning: degraded roots: broken\n");
298
364
  } finally {
299
365
  await removeWikis([root]);
300
366
  }
@@ -170,9 +170,18 @@ function normalizeCatalogPath(target: string, config: ExternalWikiRoot, base: Ca
170
170
  }
171
171
 
172
172
  const pagesDir = path.posix.normalize(config.pagesDir);
173
- const baseDir = base === "index" ? path.posix.dirname(config.indexFile) : pagesDir;
174
- const rootRelativeTarget = path.posix.normalize(path.posix.join(baseDir, withoutFragment));
175
- const relative = path.posix.relative(pagesDir, rootRelativeTarget);
173
+ let relative: string;
174
+ if (base === "index") {
175
+ const baseDir = path.posix.dirname(config.indexFile);
176
+ const rootRelativeTarget = path.posix.normalize(path.posix.join(baseDir, withoutFragment));
177
+ relative = path.posix.relative(pagesDir, rootRelativeTarget);
178
+ } else {
179
+ const pagesPrefix = pagesDir === "." ? "" : `${pagesDir}/`;
180
+ const stripped = pagesPrefix.length > 0 && withoutFragment.startsWith(pagesPrefix)
181
+ ? withoutFragment.slice(pagesPrefix.length)
182
+ : withoutFragment;
183
+ relative = path.posix.normalize(stripped);
184
+ }
176
185
  if (
177
186
  relative === ".." ||
178
187
  relative.startsWith("../") ||
@@ -416,38 +425,3 @@ export async function readExternalWikiPage(
416
425
  bytes: page.bytes,
417
426
  };
418
427
  }
419
-
420
- export async function runExternalWikiCliCommand(
421
- roots: readonly ExternalWikiRoot[],
422
- rest: readonly string[],
423
- io: { stdout: NodeJS.WritableStream; stderr: NodeJS.WritableStream },
424
- ): Promise<number> {
425
- const { searchExternalWikis } = await import("./external-wiki-search.js");
426
- const query = rest.filter((a) => !a.startsWith("-")).join(" ").trim();
427
- if (!query) {
428
- io.stderr.write("external-wiki: provide a search query\n");
429
- return 1;
430
- }
431
- const enabled = roots.filter((r) => r.enabled !== false);
432
- if (enabled.length === 0) {
433
- io.stderr.write("external-wiki: no enabled wiki roots configured\n");
434
- return 1;
435
- }
436
- try {
437
- const result = await searchExternalWikis(enabled, { query });
438
- if (result.hits.length === 0) {
439
- io.stdout.write("No results.\n");
440
- return 0;
441
- }
442
- for (const hit of result.hits) {
443
- io.stdout.write(`[${hit.wikiId}] ${hit.path} (score ${hit.score})\n${hit.snippet}\n\n`);
444
- }
445
- if (result.degradedWikiIds.length > 0) {
446
- io.stderr.write(`Warning: degraded roots: ${result.degradedWikiIds.join(", ")}\n`);
447
- }
448
- return 0;
449
- } catch (error) {
450
- io.stderr.write(`external-wiki: ${error instanceof Error ? error.message : "search failed"}\n`);
451
- return 1;
452
- }
453
- }
package/src/index.ts CHANGED
@@ -9,11 +9,6 @@
9
9
  * This package has ZERO OpenClaw imports — it can be consumed by
10
10
  * any host adapter (CLI, HTTP server, MCP server, etc.).
11
11
  *
12
- * Usage:
13
- * import { Orchestrator, parseConfig } from "@remnic/core";
14
- * const config = parseConfig({ memoryDir: "/tmp/mem" });
15
- * const orch = new Orchestrator(config);
16
- * await orch.initialize();
17
12
  */
18
13
 
19
14
  // ---------------------------------------------------------------------------
@@ -29,6 +24,7 @@ export { resolvePluginEntry, type PluginEntryResolverOptions } from "./plugin-en
29
24
  export { parseConfig, isOpenaiApiKeyDisabled, resolveEnvVars } from "./config.js";
30
25
  export { resolveRemnicConfigRecord } from "./config-record.js";
31
26
  export * from "./external-wiki.js";
27
+ export * from "./external-wiki-cli.js";
32
28
  export {
33
29
  parseFlexibleIsoTimestamp,
34
30
  parseIsoOffsetTimestamp,
@@ -278,7 +278,7 @@ export async function runFirstStartMigration(
278
278
  qmd,
279
279
  hotCollection: options.hotCollection ?? config.qmdCollection ?? "openclaw-engram",
280
280
  coldCollection: options.coldCollection ?? config.qmdColdCollection ?? "openclaw-engram-cold",
281
- })
281
+ })
282
282
  : null;
283
283
  const coldCollection = options.coldCollection ?? config.qmdColdCollection ?? "openclaw-engram-cold";
284
284
 
@@ -287,17 +287,17 @@ export async function runFirstStartMigration(
287
287
  return abortedResult(candidateCount, demotedCount, failureCount);
288
288
  }
289
289
  try {
290
- if (executor) {
291
- await executor.migrateMemory({
292
- memory,
293
- fromTier: "hot",
294
- toTier: "cold",
295
- reason: "first-start-lifecycle-migration",
296
- });
297
- } else {
298
- await storage.migrateMemoryToTier(memory, "cold");
290
+ const result = executor
291
+ ? await executor.migrateMemory({
292
+ memory,
293
+ fromTier: "hot",
294
+ toTier: "cold",
295
+ reason: "first-start-lifecycle-migration",
296
+ })
297
+ : await storage.migrateMemoryToTier(memory, "cold");
298
+ if (result.changed) {
299
+ demotedCount += 1;
299
300
  }
300
- demotedCount += 1;
301
301
  } catch {
302
302
  const targetPath = storage.buildTierMemoryPath(memory, "cold");
303
303
  const [targetExists, sourceExists] = await Promise.all([
@@ -0,0 +1,15 @@
1
+ import type { MemoryFile } from "./types.js";
2
+
3
+ function sortSnapshotObject(_key: string, candidate: unknown): unknown {
4
+ if (candidate === null || typeof candidate !== "object" || Array.isArray(candidate)) return candidate;
5
+ return Object.keys(candidate)
6
+ .sort()
7
+ .reduce<Record<string, unknown>>((sorted, key) => {
8
+ sorted[key] = (candidate as Record<string, unknown>)[key];
9
+ return sorted;
10
+ }, {});
11
+ }
12
+
13
+ export function createMemorySnapshot(memory: MemoryFile): string {
14
+ return JSON.stringify([memory.frontmatter, memory.content], sortSnapshotObject);
15
+ }
@@ -435,3 +435,102 @@ test("citation path lookup resolves collection-prefixed QMD paths", async () =>
435
435
  await rm(dir, { recursive: true, force: true });
436
436
  }
437
437
  });
438
+ test("memory snapshots ignore object key order", async () => {
439
+ const { createMemorySnapshot } = await import("../memory-snapshot.js");
440
+ type SnapshotInput = Parameters<typeof createMemorySnapshot>[0];
441
+ const first = {
442
+ content: "payload",
443
+ frontmatter: { z: 1, nested: { y: 2, x: 3 } },
444
+ } as unknown as SnapshotInput;
445
+ const second = {
446
+ frontmatter: { nested: { x: 3, y: 2 }, z: 1 },
447
+ content: "payload",
448
+ } as unknown as SnapshotInput;
449
+ assert.equal(createMemorySnapshot(first), createMemorySnapshot(second));
450
+ });
451
+
452
+ test("tier move: caller-only mutation is not persisted by moveMemoryToPath", async () => {
453
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-caller-mut-"));
454
+ try {
455
+ resetStaticCaches();
456
+ const storage = new StorageManager(dir);
457
+ await storage.ensureDirectories();
458
+
459
+ const { id } = await storage.writeMemory("fact", "original disk content");
460
+ const memories = await storage.readAllMemories();
461
+ const memory = memories.find((m) => m.frontmatter.id === id);
462
+ assert.ok(memory, "memory must exist");
463
+
464
+ memory.content = "caller mutated unpersisted content";
465
+
466
+ const targetPath = storage.buildTierMemoryPath(memory, "cold");
467
+ await storage.moveMemoryToPath(memory, targetPath);
468
+
469
+ const onDisk = await readFile(targetPath, "utf8");
470
+ assert.ok(onDisk.includes("original disk content"), "Moved file on disk must retain original content");
471
+ assert.ok(!onDisk.includes("caller mutated unpersisted content"), "Moved file on disk must not carry caller's unpersisted content mutation");
472
+ } finally {
473
+ resetStaticCaches();
474
+ await rm(dir, { recursive: true, force: true });
475
+ }
476
+ });
477
+
478
+ test("tier move: stale on-disk mutation fails snapshot check during move", async () => {
479
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-stale-disk-"));
480
+ try {
481
+ resetStaticCaches();
482
+ const storage = new StorageManager(dir);
483
+ await storage.ensureDirectories();
484
+
485
+ const { id } = await storage.writeMemory("fact", "unmodified content");
486
+ const memories = await storage.readAllMemories();
487
+ const memory = memories.find((m) => m.frontmatter.id === id);
488
+ assert.ok(memory, "memory must exist");
489
+
490
+ const diskContent = await readFile(memory.path, "utf8");
491
+ await writeFile(memory.path, diskContent.replace("unmodified content", "external edit on disk"));
492
+
493
+ const targetPath = storage.buildTierMemoryPath(memory, "cold");
494
+ await assert.rejects(
495
+ async () => {
496
+ await storage.moveMemoryToPath(memory, targetPath);
497
+ },
498
+ (err: Error) => {
499
+ return err.message.includes("changed before its tier move");
500
+ }
501
+ );
502
+ } finally {
503
+ resetStaticCaches();
504
+ await rm(dir, { recursive: true, force: true });
505
+ }
506
+ });
507
+
508
+ test("tier move: cold-to-hot move invalidates cold cache and cannot remain in readAllColdMemories", async () => {
509
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-cold-to-hot-"));
510
+ try {
511
+ resetStaticCaches();
512
+ const storage = new StorageManager(dir);
513
+ await storage.ensureDirectories();
514
+
515
+ const { id } = await storage.writeMemory("fact", "demoted to cold then promoted");
516
+ const memories = await storage.readAllMemories();
517
+ const memory = memories.find((m) => m.frontmatter.id === id);
518
+ assert.ok(memory, "memory must exist");
519
+
520
+ const { targetPath: coldPath } = await storage.migrateMemoryToTier(memory, "cold");
521
+
522
+ const coldMemories = await storage.readAllColdMemories();
523
+ const coldMem = coldMemories.find((m) => m.frontmatter.id === id);
524
+ assert.ok(coldMem, "memory must be present in cold tier read");
525
+
526
+ const { changed } = await storage.migrateMemoryToTier(coldMem, "hot");
527
+ assert.equal(changed, true, "migration from cold to hot must succeed");
528
+
529
+ const coldMemoriesAfter = await storage.readAllColdMemories();
530
+ const foundInCold = coldMemoriesAfter.some((m) => m.frontmatter.id === id);
531
+ assert.equal(foundInCold, false, "promoted memory must not remain in readAllColdMemories cache");
532
+ } finally {
533
+ resetStaticCaches();
534
+ await rm(dir, { recursive: true, force: true });
535
+ }
536
+ });