@remnic/core 9.3.553 → 9.3.555

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 (41) hide show
  1. package/dist/access-cli.js +4 -4
  2. package/dist/{chunk-MGVIEM2O.js → chunk-2IT7WFYE.js} +2 -2
  3. package/dist/{chunk-XEKAG3FM.js → chunk-452WDNFO.js} +2 -2
  4. package/dist/{chunk-2NM43EWN.js → chunk-D6RIFG4O.js} +2 -2
  5. package/dist/{chunk-GEL3F3RV.js → chunk-I2K6KCVC.js} +6 -6
  6. package/dist/{chunk-Y4YATXHL.js → chunk-ILJXM3FV.js} +2 -2
  7. package/dist/{chunk-RUZOJKNF.js → chunk-JCK7V6SN.js} +2 -2
  8. package/dist/{chunk-XR6DNK4U.js → chunk-LZZNTPLR.js} +2 -2
  9. package/dist/{chunk-M3BAMVAE.js → chunk-O4M4WH6V.js} +2 -2
  10. package/dist/{chunk-NYV435HC.js → chunk-RLPIT4YI.js} +3 -3
  11. package/dist/{chunk-4426WSWL.js → chunk-SFQ6QNL7.js} +6 -2
  12. package/dist/chunk-SFQ6QNL7.js.map +1 -0
  13. package/dist/{chunk-S7WU3Y3D.js → chunk-WMWVO45V.js} +15 -3
  14. package/dist/chunk-WMWVO45V.js.map +1 -0
  15. package/dist/cli.js +8 -8
  16. package/dist/index.js +11 -11
  17. package/dist/maintenance/archive-observations.d.ts +2 -0
  18. package/dist/maintenance/archive-observations.js +2 -1
  19. package/dist/maintenance/migrate-observations.js +3 -3
  20. package/dist/maintenance/observation-ledger-utils.d.ts +1 -1
  21. package/dist/maintenance/observation-ledger-utils.js +2 -2
  22. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +2 -2
  23. package/dist/maintenance/rebuild-memory-projection.js +2 -2
  24. package/dist/maintenance/rebuild-observations.js +3 -3
  25. package/dist/orchestrator.js +4 -4
  26. package/dist/recall-state.js +2 -2
  27. package/dist/relevance.js +2 -2
  28. package/package.json +1 -1
  29. package/src/maintenance/archive-observations.ts +15 -2
  30. package/src/maintenance/atomic-file.ts +6 -2
  31. package/dist/chunk-4426WSWL.js.map +0 -1
  32. package/dist/chunk-S7WU3Y3D.js.map +0 -1
  33. /package/dist/{chunk-MGVIEM2O.js.map → chunk-2IT7WFYE.js.map} +0 -0
  34. /package/dist/{chunk-XEKAG3FM.js.map → chunk-452WDNFO.js.map} +0 -0
  35. /package/dist/{chunk-2NM43EWN.js.map → chunk-D6RIFG4O.js.map} +0 -0
  36. /package/dist/{chunk-GEL3F3RV.js.map → chunk-I2K6KCVC.js.map} +0 -0
  37. /package/dist/{chunk-Y4YATXHL.js.map → chunk-ILJXM3FV.js.map} +0 -0
  38. /package/dist/{chunk-RUZOJKNF.js.map → chunk-JCK7V6SN.js.map} +0 -0
  39. /package/dist/{chunk-XR6DNK4U.js.map → chunk-LZZNTPLR.js.map} +0 -0
  40. /package/dist/{chunk-M3BAMVAE.js.map → chunk-O4M4WH6V.js.map} +0 -0
  41. /package/dist/{chunk-NYV435HC.js.map → chunk-RLPIT4YI.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Orchestrator
3
- } from "./chunk-NYV435HC.js";
3
+ } from "./chunk-RLPIT4YI.js";
4
4
  import "./chunk-5RIRL3XL.js";
5
5
  import "./chunk-BFBF3XEF.js";
6
6
  import "./chunk-KVEVLBKC.js";
@@ -32,12 +32,12 @@ import "./chunk-USYGGIJZ.js";
32
32
  import "./chunk-V3RXWQIE.js";
33
33
  import "./chunk-5IZL4DCV.js";
34
34
  import "./chunk-X7XN6YU4.js";
35
- import "./chunk-XEKAG3FM.js";
35
+ import "./chunk-452WDNFO.js";
36
36
  import "./chunk-TDKQGLJW.js";
37
37
  import "./chunk-OZKZ2TRP.js";
38
38
  import "./chunk-YDBIWGNI.js";
39
39
  import "./chunk-7DHTMOND.js";
40
- import "./chunk-MGVIEM2O.js";
40
+ import "./chunk-2IT7WFYE.js";
41
41
  import "./chunk-YCN4BVDK.js";
42
42
  import "./chunk-ZZTOURJI.js";
43
43
  import "./chunk-XKXKSQU7.js";
@@ -81,7 +81,7 @@ import "./chunk-FADZBOR4.js";
81
81
  import "./chunk-XPXEJRUB.js";
82
82
  import "./chunk-A6D7A2FW.js";
83
83
  import "./chunk-FF4KLI5W.js";
84
- import "./chunk-4426WSWL.js";
84
+ import "./chunk-SFQ6QNL7.js";
85
85
  import "./chunk-A2Z6UCWT.js";
86
86
  import "./chunk-KXULCVOC.js";
87
87
  import "./chunk-SML26KED.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  writeFileAtomically
3
- } from "./chunk-4426WSWL.js";
3
+ } from "./chunk-SFQ6QNL7.js";
4
4
  import {
5
5
  log
6
6
  } from "./chunk-2ODBA7MQ.js";
@@ -257,4 +257,4 @@ export {
257
257
  LastRecallStore,
258
258
  TierMigrationStatusStore
259
259
  };
260
- //# sourceMappingURL=chunk-MGVIEM2O.js.map
260
+ //# sourceMappingURL=chunk-2IT7WFYE.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  writeFileAtomically
3
- } from "./chunk-4426WSWL.js";
3
+ } from "./chunk-SFQ6QNL7.js";
4
4
  import {
5
5
  log
6
6
  } from "./chunk-2ODBA7MQ.js";
@@ -75,4 +75,4 @@ var RelevanceStore = class {
75
75
  export {
76
76
  RelevanceStore
77
77
  };
78
- //# sourceMappingURL=chunk-XEKAG3FM.js.map
78
+ //# sourceMappingURL=chunk-452WDNFO.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  backupAndWriteRebuiltObservations,
3
3
  toHourBucketIso
4
- } from "./chunk-RUZOJKNF.js";
4
+ } from "./chunk-JCK7V6SN.js";
5
5
 
6
6
  // src/maintenance/migrate-observations.ts
7
7
  import path from "path";
@@ -156,4 +156,4 @@ async function migrateObservations(options) {
156
156
  export {
157
157
  migrateObservations
158
158
  };
159
- //# sourceMappingURL=chunk-2NM43EWN.js.map
159
+ //# sourceMappingURL=chunk-D6RIFG4O.js.map
@@ -44,21 +44,21 @@ import {
44
44
  } from "./chunk-HOJZMQ4J.js";
45
45
  import {
46
46
  migrateObservations
47
- } from "./chunk-2NM43EWN.js";
47
+ } from "./chunk-D6RIFG4O.js";
48
48
  import {
49
49
  rebuildMemoryLifecycleLedger
50
- } from "./chunk-M3BAMVAE.js";
50
+ } from "./chunk-O4M4WH6V.js";
51
51
  import {
52
52
  rebuildMemoryProjection,
53
53
  repairMemoryProjection,
54
54
  verifyMemoryProjection
55
- } from "./chunk-Y4YATXHL.js";
55
+ } from "./chunk-ILJXM3FV.js";
56
56
  import {
57
57
  rebuildObservations
58
- } from "./chunk-XR6DNK4U.js";
58
+ } from "./chunk-LZZNTPLR.js";
59
59
  import {
60
60
  archiveObservations
61
- } from "./chunk-S7WU3Y3D.js";
61
+ } from "./chunk-WMWVO45V.js";
62
62
  import {
63
63
  getBulkImportSource,
64
64
  listBulkImportSources,
@@ -6616,4 +6616,4 @@ export {
6616
6616
  resolveMemoryDirForNamespace,
6617
6617
  registerCli
6618
6618
  };
6619
- //# sourceMappingURL=chunk-GEL3F3RV.js.map
6619
+ //# sourceMappingURL=chunk-I2K6KCVC.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-KJTKLXTH.js";
4
4
  import {
5
5
  commitPreparedFileAtomically
6
- } from "./chunk-4426WSWL.js";
6
+ } from "./chunk-SFQ6QNL7.js";
7
7
  import {
8
8
  loadPersistedNativeKnowledgeChunks
9
9
  } from "./chunk-BEUDU7Y4.js";
@@ -929,4 +929,4 @@ export {
929
929
  verifyMemoryProjection,
930
930
  repairMemoryProjection
931
931
  };
932
- //# sourceMappingURL=chunk-Y4YATXHL.js.map
932
+ //# sourceMappingURL=chunk-ILJXM3FV.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  writeFileAtomically
3
- } from "./chunk-4426WSWL.js";
3
+ } from "./chunk-SFQ6QNL7.js";
4
4
 
5
5
  // src/maintenance/observation-ledger-utils.ts
6
6
  import path from "path";
@@ -50,4 +50,4 @@ export {
50
50
  toHourBucketIso,
51
51
  backupAndWriteRebuiltObservations
52
52
  };
53
- //# sourceMappingURL=chunk-RUZOJKNF.js.map
53
+ //# sourceMappingURL=chunk-JCK7V6SN.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  backupAndWriteRebuiltObservations,
3
3
  toHourBucketIso
4
- } from "./chunk-RUZOJKNF.js";
4
+ } from "./chunk-JCK7V6SN.js";
5
5
 
6
6
  // src/maintenance/rebuild-observations.ts
7
7
  import path from "path";
@@ -124,4 +124,4 @@ async function rebuildObservations(options) {
124
124
  export {
125
125
  rebuildObservations
126
126
  };
127
- //# sourceMappingURL=chunk-XR6DNK4U.js.map
127
+ //# sourceMappingURL=chunk-LZZNTPLR.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-KJTKLXTH.js";
4
4
  import {
5
5
  writeFileAtomically
6
- } from "./chunk-4426WSWL.js";
6
+ } from "./chunk-SFQ6QNL7.js";
7
7
  import {
8
8
  StorageManager
9
9
  } from "./chunk-TVZ6LKKS.js";
@@ -74,4 +74,4 @@ export {
74
74
  backupExistingLedger,
75
75
  rebuildMemoryLifecycleLedger
76
76
  };
77
- //# sourceMappingURL=chunk-M3BAMVAE.js.map
77
+ //# sourceMappingURL=chunk-O4M4WH6V.js.map
@@ -87,7 +87,7 @@ import {
87
87
  } from "./chunk-X7XN6YU4.js";
88
88
  import {
89
89
  RelevanceStore
90
- } from "./chunk-XEKAG3FM.js";
90
+ } from "./chunk-452WDNFO.js";
91
91
  import {
92
92
  RerankCache,
93
93
  rerankLocalOrNoop
@@ -106,7 +106,7 @@ import {
106
106
  LastRecallStore,
107
107
  TierMigrationStatusStore,
108
108
  clampGraphRecallExpandedEntries
109
- } from "./chunk-MGVIEM2O.js";
109
+ } from "./chunk-2IT7WFYE.js";
110
110
  import {
111
111
  buildQmdRecallCacheKey,
112
112
  getCachedQmdRecall,
@@ -12405,4 +12405,4 @@ export {
12405
12405
  resolvePersistedMemoryRelativePath,
12406
12406
  Orchestrator
12407
12407
  };
12408
- //# sourceMappingURL=chunk-NYV435HC.js.map
12408
+ //# sourceMappingURL=chunk-RLPIT4YI.js.map
@@ -34,7 +34,11 @@ async function writeFileAtomically(outputPath, content, backupPath) {
34
34
  let resolvedBackupPath;
35
35
  try {
36
36
  handle = await open(tempPath, "w");
37
- await handle.writeFile(content, "utf-8");
37
+ if (typeof content === "string") {
38
+ await handle.writeFile(content, "utf-8");
39
+ } else {
40
+ await handle.writeFile(content);
41
+ }
38
42
  await handle.sync();
39
43
  await handle.close();
40
44
  handle = void 0;
@@ -70,4 +74,4 @@ export {
70
74
  writeFileAtomically,
71
75
  commitPreparedFileAtomically
72
76
  };
73
- //# sourceMappingURL=chunk-4426WSWL.js.map
77
+ //# sourceMappingURL=chunk-SFQ6QNL7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/maintenance/atomic-file.ts"],"sourcesContent":["import path from \"node:path\";\nimport { copyFile, mkdir, open, rename, rm, stat } from \"node:fs/promises\";\n\nasync function syncDirectory(dir: string): Promise<void> {\n let handle: Awaited<ReturnType<typeof open>> | undefined;\n try {\n handle = await open(dir, \"r\");\n await handle.sync();\n } catch {\n // Directory fsync is best-effort across platforms and filesystems.\n } finally {\n await handle?.close().catch(() => undefined);\n }\n}\n\nfunction tempPathFor(outputPath: string): string {\n const suffix = `${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;\n return path.join(path.dirname(outputPath), `.${path.basename(outputPath)}.${suffix}.tmp`);\n}\n\nexport async function copyExistingFileToBackup(\n sourcePath: string,\n backupPath: string,\n): Promise<string | undefined> {\n try {\n await stat(sourcePath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw err;\n }\n\n await mkdir(path.dirname(backupPath), { recursive: true });\n await copyFile(sourcePath, backupPath);\n return backupPath;\n}\n\nexport async function writeFileAtomically(\n outputPath: string,\n content: string | Uint8Array,\n backupPath?: string,\n): Promise<string | undefined> {\n const dir = path.dirname(outputPath);\n await mkdir(dir, { recursive: true });\n const tempPath = tempPathFor(outputPath);\n let handle: Awaited<ReturnType<typeof open>> | undefined;\n let resolvedBackupPath: string | undefined;\n try {\n handle = await open(tempPath, \"w\");\n if (typeof content === \"string\") {\n await handle.writeFile(content, \"utf-8\");\n } else {\n await handle.writeFile(content);\n }\n await handle.sync();\n await handle.close();\n handle = undefined;\n\n if (backupPath) {\n resolvedBackupPath = await copyExistingFileToBackup(outputPath, backupPath);\n }\n await rename(tempPath, outputPath);\n await syncDirectory(dir);\n return resolvedBackupPath;\n } catch (err) {\n await handle?.close().catch(() => undefined);\n await rm(tempPath, { force: true }).catch(() => undefined);\n throw err;\n }\n}\n\nexport async function commitPreparedFileAtomically(\n tempPath: string,\n outputPath: string,\n backupPath?: string,\n): Promise<string | undefined> {\n const dir = path.dirname(outputPath);\n let resolvedBackupPath: string | undefined;\n try {\n if (backupPath) {\n resolvedBackupPath = await copyExistingFileToBackup(outputPath, backupPath);\n }\n await rename(tempPath, outputPath);\n await syncDirectory(dir);\n return resolvedBackupPath;\n } catch (err) {\n await rm(tempPath, { force: true }).catch(() => undefined);\n throw err;\n }\n}\n"],"mappings":";AAAA,OAAO,UAAU;AACjB,SAAS,UAAU,OAAO,MAAM,QAAQ,IAAI,YAAY;AAExD,eAAe,cAAc,KAA4B;AACvD,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,KAAK,KAAK,GAAG;AAC5B,UAAM,OAAO,KAAK;AAAA,EACpB,QAAQ;AAAA,EAER,UAAE;AACA,UAAM,QAAQ,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,EAC7C;AACF;AAEA,SAAS,YAAY,YAA4B;AAC/C,QAAM,SAAS,GAAG,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAClF,SAAO,KAAK,KAAK,KAAK,QAAQ,UAAU,GAAG,IAAI,KAAK,SAAS,UAAU,CAAC,IAAI,MAAM,MAAM;AAC1F;AAEA,eAAsB,yBACpB,YACA,YAC6B;AAC7B,MAAI;AACF,UAAM,KAAK,UAAU;AAAA,EACvB,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,QAAO;AAC7D,UAAM;AAAA,EACR;AAEA,QAAM,MAAM,KAAK,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AACzD,QAAM,SAAS,YAAY,UAAU;AACrC,SAAO;AACT;AAEA,eAAsB,oBACpB,YACA,SACA,YAC6B;AAC7B,QAAM,MAAM,KAAK,QAAQ,UAAU;AACnC,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,QAAM,WAAW,YAAY,UAAU;AACvC,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,KAAK,UAAU,GAAG;AACjC,QAAI,OAAO,YAAY,UAAU;AAC/B,YAAM,OAAO,UAAU,SAAS,OAAO;AAAA,IACzC,OAAO;AACL,YAAM,OAAO,UAAU,OAAO;AAAA,IAChC;AACA,UAAM,OAAO,KAAK;AAClB,UAAM,OAAO,MAAM;AACnB,aAAS;AAET,QAAI,YAAY;AACd,2BAAqB,MAAM,yBAAyB,YAAY,UAAU;AAAA,IAC5E;AACA,UAAM,OAAO,UAAU,UAAU;AACjC,UAAM,cAAc,GAAG;AACvB,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,UAAM,QAAQ,MAAM,EAAE,MAAM,MAAM,MAAS;AAC3C,UAAM,GAAG,UAAU,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM,MAAS;AACzD,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,6BACpB,UACA,YACA,YAC6B;AAC7B,QAAM,MAAM,KAAK,QAAQ,UAAU;AACnC,MAAI;AACJ,MAAI;AACF,QAAI,YAAY;AACd,2BAAqB,MAAM,yBAAyB,YAAY,UAAU;AAAA,IAC5E;AACA,UAAM,OAAO,UAAU,UAAU;AACjC,UAAM,cAAc,GAAG;AACvB,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,UAAM,GAAG,UAAU,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM,MAAS;AACzD,UAAM;AAAA,EACR;AACF;","names":[]}
@@ -1,6 +1,10 @@
1
+ import {
2
+ writeFileAtomically
3
+ } from "./chunk-SFQ6QNL7.js";
4
+
1
5
  // src/maintenance/archive-observations.ts
2
6
  import path from "path";
3
- import { lstat, mkdir, readdir, readFile, realpath, unlink, writeFile } from "fs/promises";
7
+ import { lstat, mkdir, readdir, readFile, realpath, unlink } from "fs/promises";
4
8
  var DATE_FILE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})\.(jsonl|md)$/;
5
9
  function normalizeRetentionDays(value) {
6
10
  if (!Number.isFinite(value)) return 30;
@@ -17,6 +21,9 @@ function extractDateFromFilename(name) {
17
21
  function startOfUtcDay(value) {
18
22
  return Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate());
19
23
  }
24
+ async function writeArchiveFileAtomically(archivePath, content) {
25
+ await writeFileAtomically(archivePath, content);
26
+ }
20
27
  async function listFilesRecursive(root, relPrefix = "") {
21
28
  const out = [];
22
29
  let entries;
@@ -80,6 +87,7 @@ async function archiveObservations(options) {
80
87
  );
81
88
  const stamp = now.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
82
89
  const archiveRoot = path.join(options.memoryDir, "archive", "observations", stamp);
90
+ const archiveFileWriter = options.archiveFileWriter ?? writeArchiveFileAtomically;
83
91
  const candidates = retentionDays === 0 ? [] : await collectArchiveCandidates(
84
92
  options.memoryDir,
85
93
  cutoffDayStartUtc
@@ -96,7 +104,11 @@ async function archiveObservations(options) {
96
104
  const candidateInfo = await lstat(candidate.absolutePath).catch(() => null);
97
105
  if (!candidateInfo?.isFile() || candidateInfo.isSymbolicLink()) continue;
98
106
  const raw = await readFile(candidate.absolutePath);
99
- await writeFile(archivePath, raw);
107
+ await archiveFileWriter(archivePath, raw);
108
+ const archivedRaw = await readFile(archivePath);
109
+ if (!archivedRaw.equals(raw)) {
110
+ throw new Error(`Archive copy verification failed for ${candidate.relativePath}`);
111
+ }
100
112
  await unlink(candidate.absolutePath);
101
113
  archivedFiles += 1;
102
114
  archivedBytes += raw.byteLength;
@@ -119,4 +131,4 @@ async function archiveObservations(options) {
119
131
  export {
120
132
  archiveObservations
121
133
  };
122
- //# sourceMappingURL=chunk-S7WU3Y3D.js.map
134
+ //# sourceMappingURL=chunk-WMWVO45V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/maintenance/archive-observations.ts"],"sourcesContent":["import path from \"node:path\";\nimport { lstat, mkdir, readdir, readFile, realpath, unlink } from \"node:fs/promises\";\nimport { writeFileAtomically } from \"./atomic-file.js\";\n\nconst DATE_FILE_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})\\.(jsonl|md)$/;\n\ntype ArchiveFileWriter = (archivePath: string, content: Uint8Array) => Promise<void>;\n\nexport interface ArchiveObservationsOptions {\n memoryDir: string;\n retentionDays?: number;\n dryRun?: boolean;\n now?: Date;\n archiveFileWriter?: ArchiveFileWriter;\n}\n\nexport interface ArchiveObservationsResult {\n dryRun: boolean;\n retentionDays: number;\n scannedFiles: number;\n archivedFiles: number;\n archivedBytes: number;\n archiveRoot: string;\n archivedRelativePaths: string[];\n}\n\ninterface CandidateFile {\n absolutePath: string;\n relativePath: string;\n}\n\nfunction normalizeRetentionDays(value: number | undefined): number {\n if (!Number.isFinite(value as number)) return 30;\n return Math.max(0, Math.floor(value as number));\n}\n\nfunction extractDateFromFilename(name: string): Date | null {\n const match = DATE_FILE_PATTERN.exec(name);\n if (!match) return null;\n const iso = `${match[1]}-${match[2]}-${match[3]}T00:00:00.000Z`;\n const parsed = new Date(iso);\n if (Number.isNaN(parsed.getTime())) return null;\n return parsed;\n}\n\nfunction startOfUtcDay(value: Date): number {\n return Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate());\n}\n\nasync function writeArchiveFileAtomically(archivePath: string, content: Uint8Array): Promise<void> {\n await writeFileAtomically(archivePath, content);\n}\n\nasync function listFilesRecursive(root: string, relPrefix = \"\"): Promise<string[]> {\n const out: string[] = [];\n let entries: Array<{ name: string; isDirectory(): boolean; isFile(): boolean }>;\n try {\n entries = (await readdir(root, { withFileTypes: true })) as Array<{\n name: string;\n isDirectory(): boolean;\n isFile(): boolean;\n }>;\n } catch {\n return out;\n }\n\n for (const entry of entries) {\n const rel = relPrefix ? path.join(relPrefix, entry.name) : entry.name;\n const full = path.join(root, entry.name);\n if (entry.isDirectory()) {\n out.push(...(await listFilesRecursive(full, rel)));\n continue;\n }\n if (entry.isFile()) out.push(rel);\n }\n\n return out;\n}\n\nasync function collectArchiveCandidates(\n memoryDir: string,\n cutoffTimeMs: number,\n): Promise<CandidateFile[]> {\n const roots = [\"transcripts\", path.join(\"state\", \"tool-usage\"), path.join(\"summaries\", \"hourly\")];\n const out: CandidateFile[] = [];\n const memoryRoot = path.resolve(memoryDir);\n const memoryRealRoot = await realpath(memoryRoot).catch(() => memoryRoot);\n\n for (const relRoot of roots) {\n const absRoot = path.resolve(memoryRoot, relRoot);\n const rootInfo = await lstat(absRoot).catch(() => null);\n if (!rootInfo?.isDirectory() || rootInfo.isSymbolicLink()) continue;\n const absRootReal = await realpath(absRoot).catch(() => null);\n if (absRootReal === null) continue;\n const rootRelative = path.relative(memoryRealRoot, absRootReal);\n if (rootRelative === \"..\" || rootRelative.startsWith(`..${path.sep}`) || path.isAbsolute(rootRelative)) {\n continue;\n }\n const files = await listFilesRecursive(absRoot);\n for (const fileRel of files) {\n const filename = path.basename(fileRel);\n const parsedDate = extractDateFromFilename(filename);\n if (!parsedDate) continue;\n if (parsedDate.getTime() >= cutoffTimeMs) continue;\n const absolutePath = path.resolve(absRoot, fileRel);\n const relativeToMemory = path.relative(memoryRoot, absolutePath);\n if (\n relativeToMemory === \"..\" ||\n relativeToMemory.startsWith(`..${path.sep}`) ||\n path.isAbsolute(relativeToMemory)\n ) {\n continue;\n }\n out.push({\n absolutePath,\n relativePath: path.join(relRoot, fileRel),\n });\n }\n }\n\n out.sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n return out;\n}\n\nexport async function archiveObservations(\n options: ArchiveObservationsOptions,\n): Promise<ArchiveObservationsResult> {\n const retentionDays = normalizeRetentionDays(options.retentionDays);\n const dryRun = options.dryRun !== false;\n const now = options.now ?? new Date();\n const cutoffDayStartUtc = startOfUtcDay(\n new Date(now.getTime() - retentionDays * 24 * 60 * 60 * 1000),\n );\n const stamp = now.toISOString().replace(/[-:]/g, \"\").replace(/\\.\\d{3}Z$/, \"Z\");\n const archiveRoot = path.join(options.memoryDir, \"archive\", \"observations\", stamp);\n const archiveFileWriter = options.archiveFileWriter ?? writeArchiveFileAtomically;\n const candidates =\n retentionDays === 0\n ? []\n : await collectArchiveCandidates(\n options.memoryDir,\n cutoffDayStartUtc,\n );\n\n let archivedFiles = 0;\n let archivedBytes = 0;\n const archivedRelativePaths: string[] = [];\n\n if (!dryRun && candidates.length > 0) {\n await mkdir(archiveRoot, { recursive: true });\n for (const candidate of candidates) {\n const archivePath = path.join(archiveRoot, candidate.relativePath);\n const archiveDir = path.dirname(archivePath);\n await mkdir(archiveDir, { recursive: true });\n const candidateInfo = await lstat(candidate.absolutePath).catch(() => null);\n if (!candidateInfo?.isFile() || candidateInfo.isSymbolicLink()) continue;\n const raw = await readFile(candidate.absolutePath);\n await archiveFileWriter(archivePath, raw);\n const archivedRaw = await readFile(archivePath);\n if (!archivedRaw.equals(raw)) {\n throw new Error(`Archive copy verification failed for ${candidate.relativePath}`);\n }\n await unlink(candidate.absolutePath);\n archivedFiles += 1;\n archivedBytes += raw.byteLength;\n archivedRelativePaths.push(candidate.relativePath);\n }\n } else {\n archivedRelativePaths.push(...candidates.map((c) => c.relativePath));\n }\n\n return {\n dryRun,\n retentionDays,\n scannedFiles: candidates.length,\n archivedFiles,\n archivedBytes,\n archiveRoot,\n archivedRelativePaths,\n };\n}\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -89,7 +89,7 @@ import {
89
89
  runWorkProductStatusCliCommand,
90
90
  runWorkProjectCliCommand,
91
91
  runWorkTaskCliCommand
92
- } from "./chunk-GEL3F3RV.js";
92
+ } from "./chunk-I2K6KCVC.js";
93
93
  import "./chunk-7F7Z6MOS.js";
94
94
  import "./chunk-MC4FJXPA.js";
95
95
  import "./chunk-LQHDIS7L.js";
@@ -107,12 +107,12 @@ import "./chunk-765K3SAT.js";
107
107
  import "./chunk-TKWGAOLV.js";
108
108
  import "./chunk-UWY7GIVS.js";
109
109
  import "./chunk-HOJZMQ4J.js";
110
- import "./chunk-2NM43EWN.js";
111
- import "./chunk-M3BAMVAE.js";
112
- import "./chunk-Y4YATXHL.js";
113
- import "./chunk-XR6DNK4U.js";
114
- import "./chunk-RUZOJKNF.js";
115
- import "./chunk-S7WU3Y3D.js";
110
+ import "./chunk-D6RIFG4O.js";
111
+ import "./chunk-O4M4WH6V.js";
112
+ import "./chunk-ILJXM3FV.js";
113
+ import "./chunk-LZZNTPLR.js";
114
+ import "./chunk-JCK7V6SN.js";
115
+ import "./chunk-WMWVO45V.js";
116
116
  import "./chunk-KJTKLXTH.js";
117
117
  import "./chunk-H2NCNXMS.js";
118
118
  import "./chunk-PU44GBL4.js";
@@ -141,7 +141,7 @@ import "./chunk-FADZBOR4.js";
141
141
  import "./chunk-XPXEJRUB.js";
142
142
  import "./chunk-A6D7A2FW.js";
143
143
  import "./chunk-FF4KLI5W.js";
144
- import "./chunk-4426WSWL.js";
144
+ import "./chunk-SFQ6QNL7.js";
145
145
  import "./chunk-A2Z6UCWT.js";
146
146
  import "./chunk-KXULCVOC.js";
147
147
  import "./chunk-SML26KED.js";
package/dist/index.js CHANGED
@@ -93,7 +93,7 @@ import {
93
93
  listTrainingExportAdapters,
94
94
  registerTrainingExportAdapter,
95
95
  runBulkImportCliCommand
96
- } from "./chunk-GEL3F3RV.js";
96
+ } from "./chunk-I2K6KCVC.js";
97
97
  import "./chunk-7F7Z6MOS.js";
98
98
  import "./chunk-MC4FJXPA.js";
99
99
  import "./chunk-LQHDIS7L.js";
@@ -111,12 +111,12 @@ import "./chunk-765K3SAT.js";
111
111
  import "./chunk-TKWGAOLV.js";
112
112
  import "./chunk-UWY7GIVS.js";
113
113
  import "./chunk-HOJZMQ4J.js";
114
- import "./chunk-2NM43EWN.js";
115
- import "./chunk-M3BAMVAE.js";
116
- import "./chunk-Y4YATXHL.js";
117
- import "./chunk-XR6DNK4U.js";
118
- import "./chunk-RUZOJKNF.js";
119
- import "./chunk-S7WU3Y3D.js";
114
+ import "./chunk-D6RIFG4O.js";
115
+ import "./chunk-O4M4WH6V.js";
116
+ import "./chunk-ILJXM3FV.js";
117
+ import "./chunk-LZZNTPLR.js";
118
+ import "./chunk-JCK7V6SN.js";
119
+ import "./chunk-WMWVO45V.js";
120
120
  import "./chunk-KJTKLXTH.js";
121
121
  import {
122
122
  clearBulkImportSources,
@@ -182,7 +182,7 @@ import {
182
182
  saveTaxonomy,
183
183
  validateSlug,
184
184
  validateTaxonomy
185
- } from "./chunk-NYV435HC.js";
185
+ } from "./chunk-RLPIT4YI.js";
186
186
  import "./chunk-5RIRL3XL.js";
187
187
  import "./chunk-BFBF3XEF.js";
188
188
  import {
@@ -227,7 +227,7 @@ import "./chunk-USYGGIJZ.js";
227
227
  import "./chunk-V3RXWQIE.js";
228
228
  import "./chunk-5IZL4DCV.js";
229
229
  import "./chunk-X7XN6YU4.js";
230
- import "./chunk-XEKAG3FM.js";
230
+ import "./chunk-452WDNFO.js";
231
231
  import "./chunk-TDKQGLJW.js";
232
232
  import {
233
233
  buildResponseGuidanceRecallSection,
@@ -235,7 +235,7 @@ import {
235
235
  } from "./chunk-OZKZ2TRP.js";
236
236
  import "./chunk-YDBIWGNI.js";
237
237
  import "./chunk-7DHTMOND.js";
238
- import "./chunk-MGVIEM2O.js";
238
+ import "./chunk-2IT7WFYE.js";
239
239
  import "./chunk-YCN4BVDK.js";
240
240
  import {
241
241
  DEFAULT_REASONING_TRACE_BOOST,
@@ -360,7 +360,7 @@ import "./chunk-FADZBOR4.js";
360
360
  import "./chunk-XPXEJRUB.js";
361
361
  import "./chunk-A6D7A2FW.js";
362
362
  import "./chunk-FF4KLI5W.js";
363
- import "./chunk-4426WSWL.js";
363
+ import "./chunk-SFQ6QNL7.js";
364
364
  import "./chunk-A2Z6UCWT.js";
365
365
  import "./chunk-KXULCVOC.js";
366
366
  import "./chunk-SML26KED.js";
@@ -1,8 +1,10 @@
1
+ type ArchiveFileWriter = (archivePath: string, content: Uint8Array) => Promise<void>;
1
2
  interface ArchiveObservationsOptions {
2
3
  memoryDir: string;
3
4
  retentionDays?: number;
4
5
  dryRun?: boolean;
5
6
  now?: Date;
7
+ archiveFileWriter?: ArchiveFileWriter;
6
8
  }
7
9
  interface ArchiveObservationsResult {
8
10
  dryRun: boolean;
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  archiveObservations
3
- } from "../chunk-S7WU3Y3D.js";
3
+ } from "../chunk-WMWVO45V.js";
4
+ import "../chunk-SFQ6QNL7.js";
4
5
  import "../chunk-PZ5AY32C.js";
5
6
  export {
6
7
  archiveObservations
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  migrateObservations
3
- } from "../chunk-2NM43EWN.js";
4
- import "../chunk-RUZOJKNF.js";
5
- import "../chunk-4426WSWL.js";
3
+ } from "../chunk-D6RIFG4O.js";
4
+ import "../chunk-JCK7V6SN.js";
5
+ import "../chunk-SFQ6QNL7.js";
6
6
  import "../chunk-PZ5AY32C.js";
7
7
  export {
8
8
  migrateObservations
@@ -1,4 +1,4 @@
1
- declare function writeFileAtomically(outputPath: string, content: string, backupPath?: string): Promise<string | undefined>;
1
+ declare function writeFileAtomically(outputPath: string, content: string | Uint8Array, backupPath?: string): Promise<string | undefined>;
2
2
 
3
3
  interface LedgerWriteOptions<T extends object> {
4
4
  memoryDir: string;
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  backupAndWriteRebuiltObservations,
3
3
  toHourBucketIso
4
- } from "../chunk-RUZOJKNF.js";
5
- import "../chunk-4426WSWL.js";
4
+ } from "../chunk-JCK7V6SN.js";
5
+ import "../chunk-SFQ6QNL7.js";
6
6
  import "../chunk-PZ5AY32C.js";
7
7
  export {
8
8
  backupAndWriteRebuiltObservations,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  backupExistingLedger,
3
3
  rebuildMemoryLifecycleLedger
4
- } from "../chunk-M3BAMVAE.js";
4
+ } from "../chunk-O4M4WH6V.js";
5
5
  import "../chunk-KJTKLXTH.js";
6
- import "../chunk-4426WSWL.js";
6
+ import "../chunk-SFQ6QNL7.js";
7
7
  import "../chunk-TVZ6LKKS.js";
8
8
  import "../chunk-5UZXUTVO.js";
9
9
  import "../chunk-4H5ZJHEN.js";
@@ -3,9 +3,9 @@ import {
3
3
  rebuildMemoryProjection,
4
4
  repairMemoryProjection,
5
5
  verifyMemoryProjection
6
- } from "../chunk-Y4YATXHL.js";
6
+ } from "../chunk-ILJXM3FV.js";
7
7
  import "../chunk-KJTKLXTH.js";
8
- import "../chunk-4426WSWL.js";
8
+ import "../chunk-SFQ6QNL7.js";
9
9
  import "../chunk-BEUDU7Y4.js";
10
10
  import "../chunk-E5OECWZ5.js";
11
11
  import "../chunk-TVZ6LKKS.js";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  rebuildObservations
3
- } from "../chunk-XR6DNK4U.js";
4
- import "../chunk-RUZOJKNF.js";
5
- import "../chunk-4426WSWL.js";
3
+ } from "../chunk-LZZNTPLR.js";
4
+ import "../chunk-JCK7V6SN.js";
5
+ import "../chunk-SFQ6QNL7.js";
6
6
  import "../chunk-PZ5AY32C.js";
7
7
  export {
8
8
  rebuildObservations
@@ -26,7 +26,7 @@ import {
26
26
  sanitizeSessionKeyForFilename,
27
27
  shouldFilterLifecycleRecallCandidate,
28
28
  summarizeGraphShadowComparison
29
- } from "./chunk-NYV435HC.js";
29
+ } from "./chunk-RLPIT4YI.js";
30
30
  import "./chunk-5RIRL3XL.js";
31
31
  import "./chunk-BFBF3XEF.js";
32
32
  import "./chunk-KVEVLBKC.js";
@@ -58,12 +58,12 @@ import "./chunk-USYGGIJZ.js";
58
58
  import "./chunk-V3RXWQIE.js";
59
59
  import "./chunk-5IZL4DCV.js";
60
60
  import "./chunk-X7XN6YU4.js";
61
- import "./chunk-XEKAG3FM.js";
61
+ import "./chunk-452WDNFO.js";
62
62
  import "./chunk-TDKQGLJW.js";
63
63
  import "./chunk-OZKZ2TRP.js";
64
64
  import "./chunk-YDBIWGNI.js";
65
65
  import "./chunk-7DHTMOND.js";
66
- import "./chunk-MGVIEM2O.js";
66
+ import "./chunk-2IT7WFYE.js";
67
67
  import "./chunk-YCN4BVDK.js";
68
68
  import "./chunk-ZZTOURJI.js";
69
69
  import "./chunk-XKXKSQU7.js";
@@ -107,7 +107,7 @@ import "./chunk-FADZBOR4.js";
107
107
  import "./chunk-XPXEJRUB.js";
108
108
  import "./chunk-A6D7A2FW.js";
109
109
  import "./chunk-FF4KLI5W.js";
110
- import "./chunk-4426WSWL.js";
110
+ import "./chunk-SFQ6QNL7.js";
111
111
  import "./chunk-A2Z6UCWT.js";
112
112
  import "./chunk-KXULCVOC.js";
113
113
  import "./chunk-SML26KED.js";
@@ -2,8 +2,8 @@ import {
2
2
  LastRecallStore,
3
3
  TierMigrationStatusStore,
4
4
  clampGraphRecallExpandedEntries
5
- } from "./chunk-MGVIEM2O.js";
6
- import "./chunk-4426WSWL.js";
5
+ } from "./chunk-2IT7WFYE.js";
6
+ import "./chunk-SFQ6QNL7.js";
7
7
  import "./chunk-2ODBA7MQ.js";
8
8
  import "./chunk-PZ5AY32C.js";
9
9
  export {
package/dist/relevance.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  RelevanceStore
3
- } from "./chunk-XEKAG3FM.js";
4
- import "./chunk-4426WSWL.js";
3
+ } from "./chunk-452WDNFO.js";
4
+ import "./chunk-SFQ6QNL7.js";
5
5
  import "./chunk-2ODBA7MQ.js";
6
6
  import "./chunk-PZ5AY32C.js";
7
7
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "9.3.553",
3
+ "version": "9.3.555",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,13 +1,17 @@
1
1
  import path from "node:path";
2
- import { lstat, mkdir, readdir, readFile, realpath, unlink, writeFile } from "node:fs/promises";
2
+ import { lstat, mkdir, readdir, readFile, realpath, unlink } from "node:fs/promises";
3
+ import { writeFileAtomically } from "./atomic-file.js";
3
4
 
4
5
  const DATE_FILE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})\.(jsonl|md)$/;
5
6
 
7
+ type ArchiveFileWriter = (archivePath: string, content: Uint8Array) => Promise<void>;
8
+
6
9
  export interface ArchiveObservationsOptions {
7
10
  memoryDir: string;
8
11
  retentionDays?: number;
9
12
  dryRun?: boolean;
10
13
  now?: Date;
14
+ archiveFileWriter?: ArchiveFileWriter;
11
15
  }
12
16
 
13
17
  export interface ArchiveObservationsResult {
@@ -43,6 +47,10 @@ function startOfUtcDay(value: Date): number {
43
47
  return Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate());
44
48
  }
45
49
 
50
+ async function writeArchiveFileAtomically(archivePath: string, content: Uint8Array): Promise<void> {
51
+ await writeFileAtomically(archivePath, content);
52
+ }
53
+
46
54
  async function listFilesRecursive(root: string, relPrefix = ""): Promise<string[]> {
47
55
  const out: string[] = [];
48
56
  let entries: Array<{ name: string; isDirectory(): boolean; isFile(): boolean }>;
@@ -125,6 +133,7 @@ export async function archiveObservations(
125
133
  );
126
134
  const stamp = now.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
127
135
  const archiveRoot = path.join(options.memoryDir, "archive", "observations", stamp);
136
+ const archiveFileWriter = options.archiveFileWriter ?? writeArchiveFileAtomically;
128
137
  const candidates =
129
138
  retentionDays === 0
130
139
  ? []
@@ -146,7 +155,11 @@ export async function archiveObservations(
146
155
  const candidateInfo = await lstat(candidate.absolutePath).catch(() => null);
147
156
  if (!candidateInfo?.isFile() || candidateInfo.isSymbolicLink()) continue;
148
157
  const raw = await readFile(candidate.absolutePath);
149
- await writeFile(archivePath, raw);
158
+ await archiveFileWriter(archivePath, raw);
159
+ const archivedRaw = await readFile(archivePath);
160
+ if (!archivedRaw.equals(raw)) {
161
+ throw new Error(`Archive copy verification failed for ${candidate.relativePath}`);
162
+ }
150
163
  await unlink(candidate.absolutePath);
151
164
  archivedFiles += 1;
152
165
  archivedBytes += raw.byteLength;
@@ -36,7 +36,7 @@ export async function copyExistingFileToBackup(
36
36
 
37
37
  export async function writeFileAtomically(
38
38
  outputPath: string,
39
- content: string,
39
+ content: string | Uint8Array,
40
40
  backupPath?: string,
41
41
  ): Promise<string | undefined> {
42
42
  const dir = path.dirname(outputPath);
@@ -46,7 +46,11 @@ export async function writeFileAtomically(
46
46
  let resolvedBackupPath: string | undefined;
47
47
  try {
48
48
  handle = await open(tempPath, "w");
49
- await handle.writeFile(content, "utf-8");
49
+ if (typeof content === "string") {
50
+ await handle.writeFile(content, "utf-8");
51
+ } else {
52
+ await handle.writeFile(content);
53
+ }
50
54
  await handle.sync();
51
55
  await handle.close();
52
56
  handle = undefined;
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/maintenance/atomic-file.ts"],"sourcesContent":["import path from \"node:path\";\nimport { copyFile, mkdir, open, rename, rm, stat } from \"node:fs/promises\";\n\nasync function syncDirectory(dir: string): Promise<void> {\n let handle: Awaited<ReturnType<typeof open>> | undefined;\n try {\n handle = await open(dir, \"r\");\n await handle.sync();\n } catch {\n // Directory fsync is best-effort across platforms and filesystems.\n } finally {\n await handle?.close().catch(() => undefined);\n }\n}\n\nfunction tempPathFor(outputPath: string): string {\n const suffix = `${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;\n return path.join(path.dirname(outputPath), `.${path.basename(outputPath)}.${suffix}.tmp`);\n}\n\nexport async function copyExistingFileToBackup(\n sourcePath: string,\n backupPath: string,\n): Promise<string | undefined> {\n try {\n await stat(sourcePath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw err;\n }\n\n await mkdir(path.dirname(backupPath), { recursive: true });\n await copyFile(sourcePath, backupPath);\n return backupPath;\n}\n\nexport async function writeFileAtomically(\n outputPath: string,\n content: string,\n backupPath?: string,\n): Promise<string | undefined> {\n const dir = path.dirname(outputPath);\n await mkdir(dir, { recursive: true });\n const tempPath = tempPathFor(outputPath);\n let handle: Awaited<ReturnType<typeof open>> | undefined;\n let resolvedBackupPath: string | undefined;\n try {\n handle = await open(tempPath, \"w\");\n await handle.writeFile(content, \"utf-8\");\n await handle.sync();\n await handle.close();\n handle = undefined;\n\n if (backupPath) {\n resolvedBackupPath = await copyExistingFileToBackup(outputPath, backupPath);\n }\n await rename(tempPath, outputPath);\n await syncDirectory(dir);\n return resolvedBackupPath;\n } catch (err) {\n await handle?.close().catch(() => undefined);\n await rm(tempPath, { force: true }).catch(() => undefined);\n throw err;\n }\n}\n\nexport async function commitPreparedFileAtomically(\n tempPath: string,\n outputPath: string,\n backupPath?: string,\n): Promise<string | undefined> {\n const dir = path.dirname(outputPath);\n let resolvedBackupPath: string | undefined;\n try {\n if (backupPath) {\n resolvedBackupPath = await copyExistingFileToBackup(outputPath, backupPath);\n }\n await rename(tempPath, outputPath);\n await syncDirectory(dir);\n return resolvedBackupPath;\n } catch (err) {\n await rm(tempPath, { force: true }).catch(() => undefined);\n throw err;\n }\n}\n"],"mappings":";AAAA,OAAO,UAAU;AACjB,SAAS,UAAU,OAAO,MAAM,QAAQ,IAAI,YAAY;AAExD,eAAe,cAAc,KAA4B;AACvD,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,KAAK,KAAK,GAAG;AAC5B,UAAM,OAAO,KAAK;AAAA,EACpB,QAAQ;AAAA,EAER,UAAE;AACA,UAAM,QAAQ,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,EAC7C;AACF;AAEA,SAAS,YAAY,YAA4B;AAC/C,QAAM,SAAS,GAAG,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAClF,SAAO,KAAK,KAAK,KAAK,QAAQ,UAAU,GAAG,IAAI,KAAK,SAAS,UAAU,CAAC,IAAI,MAAM,MAAM;AAC1F;AAEA,eAAsB,yBACpB,YACA,YAC6B;AAC7B,MAAI;AACF,UAAM,KAAK,UAAU;AAAA,EACvB,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,QAAO;AAC7D,UAAM;AAAA,EACR;AAEA,QAAM,MAAM,KAAK,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AACzD,QAAM,SAAS,YAAY,UAAU;AACrC,SAAO;AACT;AAEA,eAAsB,oBACpB,YACA,SACA,YAC6B;AAC7B,QAAM,MAAM,KAAK,QAAQ,UAAU;AACnC,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,QAAM,WAAW,YAAY,UAAU;AACvC,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,KAAK,UAAU,GAAG;AACjC,UAAM,OAAO,UAAU,SAAS,OAAO;AACvC,UAAM,OAAO,KAAK;AAClB,UAAM,OAAO,MAAM;AACnB,aAAS;AAET,QAAI,YAAY;AACd,2BAAqB,MAAM,yBAAyB,YAAY,UAAU;AAAA,IAC5E;AACA,UAAM,OAAO,UAAU,UAAU;AACjC,UAAM,cAAc,GAAG;AACvB,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,UAAM,QAAQ,MAAM,EAAE,MAAM,MAAM,MAAS;AAC3C,UAAM,GAAG,UAAU,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM,MAAS;AACzD,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,6BACpB,UACA,YACA,YAC6B;AAC7B,QAAM,MAAM,KAAK,QAAQ,UAAU;AACnC,MAAI;AACJ,MAAI;AACF,QAAI,YAAY;AACd,2BAAqB,MAAM,yBAAyB,YAAY,UAAU;AAAA,IAC5E;AACA,UAAM,OAAO,UAAU,UAAU;AACjC,UAAM,cAAc,GAAG;AACvB,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,UAAM,GAAG,UAAU,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM,MAAS;AACzD,UAAM;AAAA,EACR;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/maintenance/archive-observations.ts"],"sourcesContent":["import path from \"node:path\";\nimport { lstat, mkdir, readdir, readFile, realpath, unlink, writeFile } from \"node:fs/promises\";\n\nconst DATE_FILE_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})\\.(jsonl|md)$/;\n\nexport interface ArchiveObservationsOptions {\n memoryDir: string;\n retentionDays?: number;\n dryRun?: boolean;\n now?: Date;\n}\n\nexport interface ArchiveObservationsResult {\n dryRun: boolean;\n retentionDays: number;\n scannedFiles: number;\n archivedFiles: number;\n archivedBytes: number;\n archiveRoot: string;\n archivedRelativePaths: string[];\n}\n\ninterface CandidateFile {\n absolutePath: string;\n relativePath: string;\n}\n\nfunction normalizeRetentionDays(value: number | undefined): number {\n if (!Number.isFinite(value as number)) return 30;\n return Math.max(0, Math.floor(value as number));\n}\n\nfunction extractDateFromFilename(name: string): Date | null {\n const match = DATE_FILE_PATTERN.exec(name);\n if (!match) return null;\n const iso = `${match[1]}-${match[2]}-${match[3]}T00:00:00.000Z`;\n const parsed = new Date(iso);\n if (Number.isNaN(parsed.getTime())) return null;\n return parsed;\n}\n\nfunction startOfUtcDay(value: Date): number {\n return Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate());\n}\n\nasync function listFilesRecursive(root: string, relPrefix = \"\"): Promise<string[]> {\n const out: string[] = [];\n let entries: Array<{ name: string; isDirectory(): boolean; isFile(): boolean }>;\n try {\n entries = (await readdir(root, { withFileTypes: true })) as Array<{\n name: string;\n isDirectory(): boolean;\n isFile(): boolean;\n }>;\n } catch {\n return out;\n }\n\n for (const entry of entries) {\n const rel = relPrefix ? path.join(relPrefix, entry.name) : entry.name;\n const full = path.join(root, entry.name);\n if (entry.isDirectory()) {\n out.push(...(await listFilesRecursive(full, rel)));\n continue;\n }\n if (entry.isFile()) out.push(rel);\n }\n\n return out;\n}\n\nasync function collectArchiveCandidates(\n memoryDir: string,\n cutoffTimeMs: number,\n): Promise<CandidateFile[]> {\n const roots = [\"transcripts\", path.join(\"state\", \"tool-usage\"), path.join(\"summaries\", \"hourly\")];\n const out: CandidateFile[] = [];\n const memoryRoot = path.resolve(memoryDir);\n const memoryRealRoot = await realpath(memoryRoot).catch(() => memoryRoot);\n\n for (const relRoot of roots) {\n const absRoot = path.resolve(memoryRoot, relRoot);\n const rootInfo = await lstat(absRoot).catch(() => null);\n if (!rootInfo?.isDirectory() || rootInfo.isSymbolicLink()) continue;\n const absRootReal = await realpath(absRoot).catch(() => null);\n if (absRootReal === null) continue;\n const rootRelative = path.relative(memoryRealRoot, absRootReal);\n if (rootRelative === \"..\" || rootRelative.startsWith(`..${path.sep}`) || path.isAbsolute(rootRelative)) {\n continue;\n }\n const files = await listFilesRecursive(absRoot);\n for (const fileRel of files) {\n const filename = path.basename(fileRel);\n const parsedDate = extractDateFromFilename(filename);\n if (!parsedDate) continue;\n if (parsedDate.getTime() >= cutoffTimeMs) continue;\n const absolutePath = path.resolve(absRoot, fileRel);\n const relativeToMemory = path.relative(memoryRoot, absolutePath);\n if (\n relativeToMemory === \"..\" ||\n relativeToMemory.startsWith(`..${path.sep}`) ||\n path.isAbsolute(relativeToMemory)\n ) {\n continue;\n }\n out.push({\n absolutePath,\n relativePath: path.join(relRoot, fileRel),\n });\n }\n }\n\n out.sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n return out;\n}\n\nexport async function archiveObservations(\n options: ArchiveObservationsOptions,\n): Promise<ArchiveObservationsResult> {\n const retentionDays = normalizeRetentionDays(options.retentionDays);\n const dryRun = options.dryRun !== false;\n const now = options.now ?? new Date();\n const cutoffDayStartUtc = startOfUtcDay(\n new Date(now.getTime() - retentionDays * 24 * 60 * 60 * 1000),\n );\n const stamp = now.toISOString().replace(/[-:]/g, \"\").replace(/\\.\\d{3}Z$/, \"Z\");\n const archiveRoot = path.join(options.memoryDir, \"archive\", \"observations\", stamp);\n const candidates =\n retentionDays === 0\n ? []\n : await collectArchiveCandidates(\n options.memoryDir,\n cutoffDayStartUtc,\n );\n\n let archivedFiles = 0;\n let archivedBytes = 0;\n const archivedRelativePaths: string[] = [];\n\n if (!dryRun && candidates.length > 0) {\n await mkdir(archiveRoot, { recursive: true });\n for (const candidate of candidates) {\n const archivePath = path.join(archiveRoot, candidate.relativePath);\n const archiveDir = path.dirname(archivePath);\n await mkdir(archiveDir, { recursive: true });\n const candidateInfo = await lstat(candidate.absolutePath).catch(() => null);\n if (!candidateInfo?.isFile() || candidateInfo.isSymbolicLink()) continue;\n const raw = await readFile(candidate.absolutePath);\n await writeFile(archivePath, raw);\n await unlink(candidate.absolutePath);\n archivedFiles += 1;\n archivedBytes += raw.byteLength;\n archivedRelativePaths.push(candidate.relativePath);\n }\n } else {\n archivedRelativePaths.push(...candidates.map((c) => c.relativePath));\n }\n\n return {\n dryRun,\n retentionDays,\n scannedFiles: candidates.length,\n archivedFiles,\n archivedBytes,\n archiveRoot,\n archivedRelativePaths,\n };\n}\n"],"mappings":"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","names":[]}