@remnic/plugin-openclaw 1.0.10 → 1.0.12

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 (70) hide show
  1. package/dist/{calibration-674TDQNV.js → calibration-WCHOK6DX.js} +12 -4
  2. package/dist/capsule-cli-GBM3WPAM.js +33 -0
  3. package/dist/capsule-crypto-K3IRTKRH.js +17 -0
  4. package/dist/capsule-export-IXVERCQG.js +17 -0
  5. package/dist/capsule-import-IA6VIOPQ.js +16 -0
  6. package/dist/capsule-merge-IWOQ34KL.js +189 -0
  7. package/dist/{causal-chain-OKDZSDEB.js → causal-chain-WYN5QOPS.js} +3 -2
  8. package/dist/{causal-consolidation-5BEXLQV5.js → causal-consolidation-YI53C2AO.js} +16 -12
  9. package/dist/{causal-retrieval-3BKBXVXD.js → causal-retrieval-NZHQOZOE.js} +6 -5
  10. package/dist/{causal-trajectory-graph-RQIT37DN.js → causal-trajectory-graph-VBPE2WPM.js} +1 -1
  11. package/dist/chunk-37NKFWSO.js +233 -0
  12. package/dist/chunk-3G7FAF6S.js +60 -0
  13. package/dist/{chunk-Z7GRLVK3.js → chunk-3GUF7RQI.js} +235 -19
  14. package/dist/chunk-4G2XCSD2.js +186 -0
  15. package/dist/chunk-4LYQ4ONL.js +185 -0
  16. package/dist/chunk-6F6EKSVP.js +453 -0
  17. package/dist/chunk-6IWEAUN6.js +148 -0
  18. package/dist/{chunk-LN5UZQVG.js → chunk-6UFI73TJ.js} +5 -3
  19. package/dist/chunk-7OQEPGQF.js +529 -0
  20. package/dist/{chunk-JJSNPSCD.js → chunk-7UZNLMW5.js} +652 -174
  21. package/dist/chunk-B52XADV3.js +244 -0
  22. package/dist/chunk-BU5KJVWF.js +78 -0
  23. package/dist/chunk-CDAZGIGT.js +720 -0
  24. package/dist/chunk-CXM7EBAO.js +289 -0
  25. package/dist/{chunk-HCFFXBLV.js → chunk-EXDYWXMB.js} +6 -1861
  26. package/dist/chunk-FGTYFLL5.js +274 -0
  27. package/dist/chunk-FQRSVYY4.js +110 -0
  28. package/dist/chunk-HRGFO6AW.js +349 -0
  29. package/dist/chunk-I6B2W2IY.js +47 -0
  30. package/dist/chunk-JZBOXOUC.js +259 -0
  31. package/dist/chunk-L6I4MQKO.js +227 -0
  32. package/dist/chunk-LLUROTZJ.js +328 -0
  33. package/dist/chunk-MBIFE6SA.js +250 -0
  34. package/dist/chunk-NKVIN6RD.js +118 -0
  35. package/dist/chunk-OAE7AQ6R.js +1832 -0
  36. package/dist/chunk-OEI7GLV2.js +17 -0
  37. package/dist/chunk-RKR6PTPA.js +308 -0
  38. package/dist/{chunk-7TENHBV2.js → chunk-RQCTMECT.js} +10 -48
  39. package/dist/chunk-SSFTU6LP.js +182 -0
  40. package/dist/{chunk-BXTMZDRT.js → chunk-SVSQAG6M.js} +7 -5
  41. package/dist/{chunk-S2ISS4AH.js → chunk-TILAJIJR.js} +10 -10
  42. package/dist/chunk-TLVIQLB4.js +874 -0
  43. package/dist/{chunk-YHH3SXKD.js → chunk-WPINX4MF.js} +1 -59
  44. package/dist/chunk-YGGGUTG3.js +125 -0
  45. package/dist/cipher-VHAFCG7Z.js +27 -0
  46. package/dist/dreams-ledger-3I52ISYR.js +285 -0
  47. package/dist/{engine-65C2J63X.js → engine-BIYI3P4J.js} +7 -2
  48. package/dist/{fallback-llm-LVK5PDIM.js → fallback-llm-WCWNGIQ3.js} +2 -1
  49. package/dist/first-start-migration-I24M2JEE.js +258 -0
  50. package/dist/forget-NI4RBDPB.js +68 -0
  51. package/dist/fs-utils-PZRI2HDZ.js +29 -0
  52. package/dist/graph-edge-decay-5CVKWBYH.js +203 -0
  53. package/dist/index.js +10654 -3067
  54. package/dist/kdf-H5B23ZM2.js +25 -0
  55. package/dist/memory-governance-SJ5DGRB3.js +25 -0
  56. package/dist/metadata-JAGIWHEA.js +20 -0
  57. package/dist/migrate-from-identity-anchor-N3354WMP.js +7 -0
  58. package/dist/path-5LCUBAAZ.js +8 -0
  59. package/dist/peers-JF2I6RCR.js +43 -0
  60. package/dist/purge-XN2VSPZ2.js +204 -0
  61. package/dist/secure-store-A4NGCNXV.js +155 -0
  62. package/dist/state-PVISYXRH.js +7 -0
  63. package/dist/state-store-LP5BO6SF.js +15 -0
  64. package/dist/{storage-DM4ZGOCN.js → storage-PTQ2H2YJ.js} +3 -1
  65. package/dist/tier-stats-IZNW66NC.js +147 -0
  66. package/dist/trace-NJESSGH7.js +289 -0
  67. package/dist/tui-MGK2LYJY.js +12 -0
  68. package/dist/types-R4DO7AKM.js +30 -0
  69. package/openclaw.plugin.json +519 -4
  70. package/package.json +2 -2
@@ -368,67 +368,9 @@ function countRecallTokenOverlap(queryTokens, value, extraStopWords = []) {
368
368
  return matches;
369
369
  }
370
370
 
371
- // ../remnic-core/src/store-contract.ts
372
- function isRecord(value) {
373
- return typeof value === "object" && value !== null && !Array.isArray(value);
374
- }
375
- function assertString(value, field) {
376
- if (typeof value !== "string" || value.trim().length === 0) {
377
- throw new Error(`${field} must be a non-empty string`);
378
- }
379
- return value.trim();
380
- }
381
- function optionalString(value) {
382
- if (typeof value !== "string" || value.trim().length === 0) return void 0;
383
- return value.trim();
384
- }
385
- function assertSafePathSegment(value, field) {
386
- if (value === "." || value === ".." || value.includes("/") || value.includes("\\")) {
387
- throw new Error(`${field} must be a safe path segment`);
388
- }
389
- return value;
390
- }
391
- function assertIsoRecordedAt(value, field = "recordedAt") {
392
- if (!/^\d{4}-\d{2}-\d{2}T/.test(value)) {
393
- throw new Error(`${field} must be an ISO timestamp`);
394
- }
395
- return value;
396
- }
397
- function recordStoreDay(recordedAt) {
398
- const day = recordedAt.slice(0, 10);
399
- if (!/^\d{4}-\d{2}-\d{2}$/.test(day)) {
400
- throw new Error("recordedAt must start with a valid YYYY-MM-DD date");
401
- }
402
- return day;
403
- }
404
- function optionalStringArray(value, field) {
405
- if (value === void 0) return void 0;
406
- if (!Array.isArray(value)) throw new Error(`${field} must be an array of strings`);
407
- const items = value.map((item, index) => assertString(item, `${field}[${index}]`));
408
- return items.length > 0 ? items : void 0;
409
- }
410
- function validateStringRecord(raw, field = "metadata") {
411
- if (raw === void 0) return void 0;
412
- if (!isRecord(raw)) throw new Error(`${field} must be an object of strings`);
413
- const out = {};
414
- for (const [key, value] of Object.entries(raw)) {
415
- if (typeof value !== "string") throw new Error(`${field} must be an object of strings`);
416
- out[key] = value;
417
- }
418
- return Object.keys(out).length > 0 ? out : void 0;
419
- }
420
-
421
371
  export {
422
372
  topicOverlapScore,
423
373
  BoxBuilder,
424
374
  normalizeRecallTokens,
425
- countRecallTokenOverlap,
426
- isRecord,
427
- assertString,
428
- optionalString,
429
- assertSafePathSegment,
430
- assertIsoRecordedAt,
431
- recordStoreDay,
432
- optionalStringArray,
433
- validateStringRecord
375
+ countRecallTokenOverlap
434
376
  };
@@ -0,0 +1,125 @@
1
+ // ../remnic-core/src/secure-store/cipher.ts
2
+ import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
3
+ var ENVELOPE_VERSION = 1;
4
+ var IV_LENGTH = 12;
5
+ var AUTH_TAG_LENGTH = 16;
6
+ var ENVELOPE_SALT_LENGTH = 16;
7
+ var AES_KEY_LENGTH = 32;
8
+ var ENVELOPE_LAYOUT = Object.freeze({
9
+ version: 0,
10
+ salt: 1,
11
+ iv: 1 + ENVELOPE_SALT_LENGTH,
12
+ authTag: 1 + ENVELOPE_SALT_LENGTH + IV_LENGTH,
13
+ ciphertext: 1 + ENVELOPE_SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH
14
+ });
15
+ var ENVELOPE_HEADER_SIZE = ENVELOPE_LAYOUT.ciphertext;
16
+ function assertAesKey(key) {
17
+ if (!(key instanceof Uint8Array)) {
18
+ throw new Error("key must be a Uint8Array");
19
+ }
20
+ if (key.length !== AES_KEY_LENGTH) {
21
+ throw new Error(
22
+ `AES-256-GCM requires a ${AES_KEY_LENGTH}-byte key, got ${key.length}`
23
+ );
24
+ }
25
+ }
26
+ function seal(key, salt, plaintext, options = {}) {
27
+ assertAesKey(key);
28
+ if (!(salt instanceof Uint8Array) || salt.length !== ENVELOPE_SALT_LENGTH) {
29
+ throw new Error(
30
+ `salt must be ${ENVELOPE_SALT_LENGTH} bytes, got ${salt?.length ?? "non-buffer"}`
31
+ );
32
+ }
33
+ if (!(plaintext instanceof Uint8Array)) {
34
+ throw new Error("plaintext must be a Uint8Array");
35
+ }
36
+ let iv;
37
+ if (options.iv) {
38
+ if (options.iv.length !== IV_LENGTH) {
39
+ throw new Error(`iv must be ${IV_LENGTH} bytes, got ${options.iv.length}`);
40
+ }
41
+ iv = options.iv;
42
+ } else {
43
+ iv = randomBytes(IV_LENGTH);
44
+ }
45
+ const cipher = createCipheriv("aes-256-gcm", Buffer.from(key), Buffer.from(iv), {
46
+ authTagLength: AUTH_TAG_LENGTH
47
+ });
48
+ const headerAad = buildHeaderAad(salt);
49
+ const finalAad = options.aad ? Buffer.concat([headerAad, Buffer.from(options.aad)]) : headerAad;
50
+ cipher.setAAD(finalAad);
51
+ const ciphertext = Buffer.concat([cipher.update(Buffer.from(plaintext)), cipher.final()]);
52
+ const authTag = cipher.getAuthTag();
53
+ if (authTag.length !== AUTH_TAG_LENGTH) {
54
+ throw new Error(`unexpected auth tag length: ${authTag.length}`);
55
+ }
56
+ const envelope = Buffer.alloc(ENVELOPE_HEADER_SIZE + ciphertext.length);
57
+ envelope.writeUInt8(ENVELOPE_VERSION, ENVELOPE_LAYOUT.version);
58
+ Buffer.from(salt).copy(envelope, ENVELOPE_LAYOUT.salt);
59
+ Buffer.from(iv).copy(envelope, ENVELOPE_LAYOUT.iv);
60
+ authTag.copy(envelope, ENVELOPE_LAYOUT.authTag);
61
+ ciphertext.copy(envelope, ENVELOPE_LAYOUT.ciphertext);
62
+ return envelope;
63
+ }
64
+ function parseEnvelope(envelope) {
65
+ if (!(envelope instanceof Uint8Array)) {
66
+ throw new Error("envelope must be a Uint8Array");
67
+ }
68
+ if (envelope.length < ENVELOPE_HEADER_SIZE) {
69
+ throw new Error(
70
+ `envelope too short: need \u2265 ${ENVELOPE_HEADER_SIZE} bytes, got ${envelope.length}`
71
+ );
72
+ }
73
+ const buf = Buffer.from(envelope.buffer, envelope.byteOffset, envelope.byteLength);
74
+ const version = buf.readUInt8(ENVELOPE_LAYOUT.version);
75
+ if (version !== ENVELOPE_VERSION) {
76
+ throw new Error(
77
+ `unsupported envelope version: ${version} (this build supports ${ENVELOPE_VERSION})`
78
+ );
79
+ }
80
+ return {
81
+ version,
82
+ salt: buf.subarray(ENVELOPE_LAYOUT.salt, ENVELOPE_LAYOUT.salt + ENVELOPE_SALT_LENGTH),
83
+ iv: buf.subarray(ENVELOPE_LAYOUT.iv, ENVELOPE_LAYOUT.iv + IV_LENGTH),
84
+ authTag: buf.subarray(
85
+ ENVELOPE_LAYOUT.authTag,
86
+ ENVELOPE_LAYOUT.authTag + AUTH_TAG_LENGTH
87
+ ),
88
+ ciphertext: buf.subarray(ENVELOPE_LAYOUT.ciphertext)
89
+ };
90
+ }
91
+ function open(key, envelope, options = {}) {
92
+ assertAesKey(key);
93
+ const parsed = parseEnvelope(envelope);
94
+ const decipher = createDecipheriv("aes-256-gcm", Buffer.from(key), parsed.iv, {
95
+ authTagLength: AUTH_TAG_LENGTH
96
+ });
97
+ decipher.setAuthTag(parsed.authTag);
98
+ const headerAad = buildHeaderAad(parsed.salt);
99
+ const finalAad = options.aad ? Buffer.concat([headerAad, Buffer.from(options.aad)]) : headerAad;
100
+ decipher.setAAD(finalAad);
101
+ return Buffer.concat([decipher.update(parsed.ciphertext), decipher.final()]);
102
+ }
103
+ function buildHeaderAad(salt) {
104
+ const out = Buffer.alloc(1 + ENVELOPE_SALT_LENGTH);
105
+ out.writeUInt8(ENVELOPE_VERSION, 0);
106
+ Buffer.from(salt).copy(out, 1);
107
+ return out;
108
+ }
109
+ function generateSalt() {
110
+ return randomBytes(ENVELOPE_SALT_LENGTH);
111
+ }
112
+
113
+ export {
114
+ ENVELOPE_VERSION,
115
+ IV_LENGTH,
116
+ AUTH_TAG_LENGTH,
117
+ ENVELOPE_SALT_LENGTH,
118
+ AES_KEY_LENGTH,
119
+ ENVELOPE_LAYOUT,
120
+ ENVELOPE_HEADER_SIZE,
121
+ seal,
122
+ parseEnvelope,
123
+ open,
124
+ generateSalt
125
+ };
@@ -0,0 +1,27 @@
1
+ import {
2
+ AES_KEY_LENGTH,
3
+ AUTH_TAG_LENGTH,
4
+ ENVELOPE_HEADER_SIZE,
5
+ ENVELOPE_LAYOUT,
6
+ ENVELOPE_SALT_LENGTH,
7
+ ENVELOPE_VERSION,
8
+ IV_LENGTH,
9
+ generateSalt,
10
+ open,
11
+ parseEnvelope,
12
+ seal
13
+ } from "./chunk-YGGGUTG3.js";
14
+ import "./chunk-MLKGABMK.js";
15
+ export {
16
+ AES_KEY_LENGTH,
17
+ AUTH_TAG_LENGTH,
18
+ ENVELOPE_HEADER_SIZE,
19
+ ENVELOPE_LAYOUT,
20
+ ENVELOPE_SALT_LENGTH,
21
+ ENVELOPE_VERSION,
22
+ IV_LENGTH,
23
+ generateSalt,
24
+ open,
25
+ parseEnvelope,
26
+ seal
27
+ };
@@ -0,0 +1,285 @@
1
+ import "./chunk-MLKGABMK.js";
2
+
3
+ // ../remnic-core/src/maintenance/dreams-ledger.ts
4
+ import path from "path";
5
+ import { appendFile, lstat, mkdir, readdir, readFile } from "fs/promises";
6
+ function dreamsLedgerPath(memoryDir) {
7
+ return path.join(memoryDir, "state", "dreams-ledger.jsonl");
8
+ }
9
+ async function appendDreamsLedgerEntry(memoryDir, entry) {
10
+ const ledgerPath = dreamsLedgerPath(memoryDir);
11
+ await mkdir(path.dirname(ledgerPath), { recursive: true });
12
+ await appendFile(ledgerPath, JSON.stringify(entry) + "\n", "utf-8");
13
+ }
14
+ async function readDreamsLedgerEntries(memoryDir) {
15
+ const ledgerPath = dreamsLedgerPath(memoryDir);
16
+ let raw;
17
+ try {
18
+ raw = await readFile(ledgerPath, "utf-8");
19
+ } catch (err) {
20
+ const code = err.code;
21
+ if (code === "ENOENT") return [];
22
+ throw err;
23
+ }
24
+ const entries = [];
25
+ for (const line of raw.split("\n")) {
26
+ const trimmed = line.trim();
27
+ if (!trimmed) continue;
28
+ try {
29
+ const parsed = JSON.parse(trimmed);
30
+ if (typeof parsed !== "object" || parsed === null) continue;
31
+ if (typeof parsed.phase === "string" && (parsed.phase === "lightSleep" || parsed.phase === "rem" || parsed.phase === "deepSleep") && typeof parsed.startedAt === "string" && typeof parsed.completedAt === "string" && typeof parsed.durationMs === "number" && typeof parsed.itemsProcessed === "number") {
32
+ entries.push({
33
+ schemaVersion: 1,
34
+ startedAt: parsed.startedAt,
35
+ completedAt: parsed.completedAt,
36
+ durationMs: parsed.durationMs,
37
+ phase: parsed.phase,
38
+ itemsProcessed: parsed.itemsProcessed,
39
+ dryRun: parsed.dryRun === true,
40
+ trigger: parsed.trigger === "manual" ? "manual" : "scheduled",
41
+ notes: typeof parsed.notes === "string" ? parsed.notes : void 0
42
+ });
43
+ }
44
+ } catch {
45
+ }
46
+ }
47
+ return entries;
48
+ }
49
+ var ALL_PHASES = ["lightSleep", "rem", "deepSleep"];
50
+ var MAX_WINDOW_HOURS = 24 * 365 * 100;
51
+ function normalizeDreamsStatusWindowHours(value, fallback = 24) {
52
+ const raw = value === void 0 || value === null ? fallback : value;
53
+ if (typeof raw !== "number" || !Number.isFinite(raw) || !Number.isInteger(raw) || raw < 1 || raw > MAX_WINDOW_HOURS) {
54
+ throw new RangeError(`windowHours must be a positive integer no greater than ${MAX_WINDOW_HOURS}`);
55
+ }
56
+ return raw;
57
+ }
58
+ async function getDreamsStatus(memoryDir, windowHours = 24, now = /* @__PURE__ */ new Date()) {
59
+ const boundedWindowHours = normalizeDreamsStatusWindowHours(windowHours);
60
+ const nowMs = now.getTime();
61
+ if (!Number.isFinite(nowMs)) {
62
+ throw new RangeError("now must be a valid Date");
63
+ }
64
+ const windowMs = boundedWindowHours * 60 * 60 * 1e3;
65
+ const windowStart = new Date(nowMs - windowMs);
66
+ const windowEnd = now;
67
+ if (!Number.isFinite(windowStart.getTime())) {
68
+ throw new RangeError("windowHours produces an invalid status window");
69
+ }
70
+ const entries = await readDreamsLedgerEntries(memoryDir);
71
+ const windowEntries = entries.filter((e) => {
72
+ const ts = Date.parse(e.completedAt);
73
+ return Number.isFinite(ts) && ts >= windowStart.getTime() && ts < windowEnd.getTime();
74
+ });
75
+ const statusMap = /* @__PURE__ */ new Map();
76
+ for (const phase of ALL_PHASES) {
77
+ statusMap.set(phase, {
78
+ phase,
79
+ runCount: 0,
80
+ totalDurationMs: 0,
81
+ totalItemsProcessed: 0,
82
+ lastRunAt: null,
83
+ lastDurationMs: null
84
+ });
85
+ }
86
+ for (const entry of windowEntries) {
87
+ const status = statusMap.get(entry.phase);
88
+ if (!status) continue;
89
+ status.runCount += 1;
90
+ status.totalDurationMs += entry.durationMs;
91
+ status.totalItemsProcessed += entry.itemsProcessed;
92
+ if (status.lastRunAt === null || Date.parse(entry.completedAt) > Date.parse(status.lastRunAt)) {
93
+ status.lastRunAt = entry.completedAt;
94
+ status.lastDurationMs = entry.durationMs;
95
+ }
96
+ }
97
+ return {
98
+ windowStart: windowStart.toISOString(),
99
+ windowEnd: windowEnd.toISOString(),
100
+ phases: {
101
+ lightSleep: statusMap.get("lightSleep"),
102
+ rem: statusMap.get("rem"),
103
+ deepSleep: statusMap.get("deepSleep")
104
+ }
105
+ };
106
+ }
107
+ async function recordDreamsPhaseRun(options) {
108
+ const startedAt = options.startedAt ?? (/* @__PURE__ */ new Date()).toISOString();
109
+ const completedAt = options.completedAt ?? (/* @__PURE__ */ new Date()).toISOString();
110
+ const durationMs = Math.max(0, Date.parse(completedAt) - Date.parse(startedAt));
111
+ const ledgerEntry = {
112
+ schemaVersion: 1,
113
+ startedAt,
114
+ completedAt,
115
+ durationMs: Number.isFinite(durationMs) ? durationMs : 0,
116
+ phase: options.phase,
117
+ itemsProcessed: Math.max(0, Math.floor(options.itemsProcessed)),
118
+ dryRun: options.dryRun === true,
119
+ trigger: options.trigger,
120
+ notes: options.notes
121
+ };
122
+ if (!ledgerEntry.dryRun) {
123
+ await appendDreamsLedgerEntry(options.memoryDir, ledgerEntry);
124
+ }
125
+ return ledgerEntry;
126
+ }
127
+ async function runDreamsPhase(options, governanceRunner, phaseRunner) {
128
+ const { memoryDir, phase, dryRun = false } = options;
129
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
130
+ let itemsProcessed = 0;
131
+ let notes;
132
+ if (phase === "lightSleep") {
133
+ if (!dryRun) {
134
+ if (!phaseRunner) {
135
+ throw new Error("light-sleep manual runs require a phase runner");
136
+ }
137
+ const result = await phaseRunner({ memoryDir, phase });
138
+ itemsProcessed = Math.max(0, Math.floor(result.itemsProcessed));
139
+ notes = result.notes ?? `scored ${itemsProcessed} memories`;
140
+ } else {
141
+ try {
142
+ const ledgerPath = path.join(memoryDir, "state", "observation-ledger", "rebuilt-observations.jsonl");
143
+ let raw = "";
144
+ try {
145
+ raw = await readFile(ledgerPath, "utf-8");
146
+ } catch {
147
+ }
148
+ const lines = raw.split("\n").filter((l) => l.trim().length > 0);
149
+ const cutoff = Date.now() - 24 * 60 * 60 * 1e3;
150
+ itemsProcessed = lines.filter((line) => {
151
+ try {
152
+ const obj = JSON.parse(line);
153
+ const timestamp = typeof obj.ts === "string" ? obj.ts : typeof obj.timestamp === "string" ? obj.timestamp : null;
154
+ if (!timestamp) return false;
155
+ const ms = Date.parse(timestamp);
156
+ return Number.isFinite(ms) && ms >= cutoff;
157
+ } catch {
158
+ return false;
159
+ }
160
+ }).length;
161
+ notes = `dry-run: would score ${itemsProcessed} observation entries`;
162
+ } catch (err) {
163
+ throw new Error(`light-sleep scan failed: ${err instanceof Error ? err.message : String(err)}`);
164
+ }
165
+ }
166
+ } else if (phase === "rem") {
167
+ if (!dryRun) {
168
+ if (!phaseRunner) {
169
+ throw new Error("REM manual runs require a phase runner");
170
+ }
171
+ const result = await phaseRunner({ memoryDir, phase });
172
+ itemsProcessed = Math.max(0, Math.floor(result.itemsProcessed));
173
+ notes = result.notes ?? `REM pass assessed ${itemsProcessed} memories`;
174
+ } else {
175
+ try {
176
+ const stateFilePath = path.join(memoryDir, "state", "semantic-consolidation-last-run.json");
177
+ let lastRunAt = null;
178
+ try {
179
+ const stateRaw = await readFile(stateFilePath, "utf-8");
180
+ const stateData = JSON.parse(stateRaw);
181
+ lastRunAt = stateData.lastRunAt ?? null;
182
+ } catch {
183
+ }
184
+ const memFiles = await listMemoryFiles(memoryDir);
185
+ itemsProcessed = memFiles.length;
186
+ notes = `dry-run: ${itemsProcessed} memories would enter REM consolidation pass${lastRunAt ? ` (last run: ${lastRunAt})` : " (never run)"}`;
187
+ } catch (err) {
188
+ throw new Error(`REM scan failed: ${err instanceof Error ? err.message : String(err)}`);
189
+ }
190
+ }
191
+ } else {
192
+ if (governanceRunner) {
193
+ try {
194
+ const result = await governanceRunner({ memoryDir, dryRun });
195
+ itemsProcessed = result.scannedMemories;
196
+ notes = result.notes ?? (dryRun ? `dry-run: ${result.appliedActionCount} actions proposed` : `${result.appliedActionCount} actions applied`);
197
+ } catch (err) {
198
+ throw new Error(`deep-sleep governance run failed: ${err instanceof Error ? err.message : String(err)}`);
199
+ }
200
+ } else {
201
+ const memFiles = await listMemoryFiles(memoryDir);
202
+ itemsProcessed = memFiles.length;
203
+ notes = dryRun ? `dry-run: ${itemsProcessed} memories eligible for deep-sleep governance` : `assessed ${itemsProcessed} memories for deep-sleep governance`;
204
+ }
205
+ }
206
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
207
+ const durationMs = Math.max(0, Date.parse(completedAt) - Date.parse(startedAt));
208
+ let ledgerEntry;
209
+ try {
210
+ ledgerEntry = await recordDreamsPhaseRun({
211
+ memoryDir,
212
+ startedAt,
213
+ completedAt,
214
+ phase,
215
+ itemsProcessed,
216
+ dryRun,
217
+ trigger: "manual",
218
+ notes
219
+ });
220
+ } catch {
221
+ }
222
+ return {
223
+ phase,
224
+ dryRun,
225
+ durationMs: ledgerEntry?.durationMs ?? durationMs,
226
+ itemsProcessed,
227
+ notes,
228
+ ledgerEntry
229
+ };
230
+ }
231
+ function summarizeGovernanceResultForDreams(govResult, dryRun) {
232
+ const proposedCount = govResult.proposedActions.length;
233
+ const appliedCount = govResult.appliedActions.length;
234
+ const scannedCount = typeof govResult.summary?.scannedMemories === "number" && Number.isFinite(govResult.summary.scannedMemories) ? Math.max(0, Math.floor(govResult.summary.scannedMemories)) : govResult.reviewQueue.length;
235
+ return {
236
+ scannedMemories: scannedCount,
237
+ appliedActionCount: appliedCount,
238
+ notes: dryRun ? `shadow mode: ${proposedCount} actions proposed` : `applied ${appliedCount} actions`
239
+ };
240
+ }
241
+ async function listMemoryFiles(memoryDir) {
242
+ const out = [];
243
+ try {
244
+ const root = await lstat(memoryDir);
245
+ if (root.isSymbolicLink()) {
246
+ throw new Error(`memoryDir must not be a symlink: ${memoryDir}`);
247
+ }
248
+ if (!root.isDirectory()) return out;
249
+ } catch (err) {
250
+ if (err instanceof Error && /must not be a symlink/.test(err.message)) {
251
+ throw err;
252
+ }
253
+ return out;
254
+ }
255
+ async function walk(dir) {
256
+ let entries;
257
+ try {
258
+ entries = await readdir(dir, { withFileTypes: true });
259
+ } catch {
260
+ return;
261
+ }
262
+ for (const entry of entries) {
263
+ if (entry.isSymbolicLink()) continue;
264
+ const full = path.join(dir, entry.name);
265
+ if (entry.isDirectory()) {
266
+ if (entry.name === "state" || entry.name === "archive" || entry.name === "namespaces" || entry.name === ".git") continue;
267
+ await walk(full);
268
+ } else if (entry.isFile() && entry.name.endsWith(".md")) {
269
+ out.push(full);
270
+ }
271
+ }
272
+ }
273
+ await walk(memoryDir);
274
+ return out;
275
+ }
276
+ export {
277
+ appendDreamsLedgerEntry,
278
+ dreamsLedgerPath,
279
+ getDreamsStatus,
280
+ normalizeDreamsStatusWindowHours,
281
+ readDreamsLedgerEntries,
282
+ recordDreamsPhaseRun,
283
+ runDreamsPhase,
284
+ summarizeGovernanceResultForDreams
285
+ };
@@ -1,10 +1,15 @@
1
1
  import {
2
2
  CompoundingEngine,
3
3
  defaultTierMigrationCycleBudget
4
- } from "./chunk-HCFFXBLV.js";
5
- import "./chunk-JJSNPSCD.js";
4
+ } from "./chunk-OAE7AQ6R.js";
5
+ import "./chunk-EXDYWXMB.js";
6
+ import "./chunk-7UZNLMW5.js";
6
7
  import "./chunk-6OJAU466.js";
8
+ import "./chunk-RKR6PTPA.js";
7
9
  import "./chunk-UFU5GGGA.js";
10
+ import "./chunk-YGGGUTG3.js";
11
+ import "./chunk-OEI7GLV2.js";
12
+ import "./chunk-I6B2W2IY.js";
8
13
  import "./chunk-MLKGABMK.js";
9
14
  export {
10
15
  CompoundingEngine,
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  FallbackLlmClient
3
- } from "./chunk-7TENHBV2.js";
3
+ } from "./chunk-RQCTMECT.js";
4
4
  import "./chunk-3A5ELHTT.js";
5
5
  import "./chunk-UFU5GGGA.js";
6
+ import "./chunk-I6B2W2IY.js";
6
7
  import "./chunk-MLKGABMK.js";
7
8
  export {
8
9
  FallbackLlmClient