@remnic/cli 9.65.1 → 9.65.3

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 (2) hide show
  1. package/dist/index.js +660 -450
  2. package/package.json +31 -31
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ async function persistEnrichmentCandidate(storage, entityName, candidate) {
18
18
  }
19
19
 
20
20
  // src/index.ts
21
- import fs17 from "fs";
21
+ import fs19 from "fs";
22
22
  import os3 from "os";
23
23
  import path18 from "path";
24
24
  import { createHash as createHash4 } from "crypto";
@@ -27,13 +27,13 @@ import * as childProcess2 from "child_process";
27
27
  import { fileURLToPath as fileURLToPath5 } from "url";
28
28
  import { gzipSync } from "zlib";
29
29
  import {
30
- parseConfig as parseConfig8,
30
+ parseConfig as parseConfig10,
31
31
  isOpenaiApiKeyDisabled,
32
32
  resolveEnvVars,
33
- resolveRemnicConfigRecord as resolveRemnicConfigRecord7,
34
- Orchestrator as Orchestrator5,
33
+ resolveRemnicConfigRecord as resolveRemnicConfigRecord9,
34
+ Orchestrator as Orchestrator6,
35
35
  EngramAccessService as EngramAccessService2,
36
- initLogger as initLogger3,
36
+ initLogger as initLogger5,
37
37
  onboard,
38
38
  curate,
39
39
  listReviewItems,
@@ -105,9 +105,7 @@ import {
105
105
  discoverMemoryExtensions,
106
106
  resolveExtensionsRoot,
107
107
  coerceInstallExtension,
108
- StorageManager as StorageManager2,
109
- computeProcedureStats,
110
- formatProcedureStatsText,
108
+ StorageManager as StorageManager3,
111
109
  parseXrayCliOptions,
112
110
  renderXray,
113
111
  extractWhoKnowsRawArgs,
@@ -119,6 +117,7 @@ import {
119
117
  OFFLINE_SYNC_SNAPSHOT_BASE_MAX_BODY_BYTES,
120
118
  applyOfflineSyncFileContentChunk as applyOfflineSyncFileContentChunk2,
121
119
  applyOfflineSyncSnapshot,
120
+ runPromotionCandidatesCommand,
122
121
  buildOfflineSyncChangesetFromSnapshot,
123
122
  drainPendingLifecycleForOfflineSync,
124
123
  compileOfflineSyncExcludeGlobs,
@@ -259,6 +258,330 @@ async function runExternalWikiBinaryCommand(rest) {
259
258
  }
260
259
  }
261
260
 
261
+ // src/commands/procedural.ts
262
+ import fs4 from "fs";
263
+ import {
264
+ StorageManager,
265
+ computeProcedureStats,
266
+ formatProcedureStatsText,
267
+ initLogger,
268
+ parseConfig as parseConfig4,
269
+ resolveRemnicConfigRecord as resolveRemnicConfigRecord4,
270
+ runProcedureLibraryMaintenance
271
+ } from "@remnic/core";
272
+
273
+ // src/cli-args.ts
274
+ function resolveFlag(args, flag) {
275
+ const idx = args.indexOf(flag);
276
+ if (idx === -1 || idx + 1 >= args.length) return void 0;
277
+ const value = args[idx + 1];
278
+ return isOptionToken(value) ? void 0 : value;
279
+ }
280
+ function isOptionToken(value) {
281
+ if (!value.startsWith("-")) return false;
282
+ if (/^-\d/.test(value) || /^-\.\d/.test(value)) return false;
283
+ return true;
284
+ }
285
+ function hasFlag(args, flag) {
286
+ return args.indexOf(flag) !== -1;
287
+ }
288
+ var TAXONOMY_RESOLVE_BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--json"]);
289
+ var TAXONOMY_RESOLVE_VALUE_FLAGS = /* @__PURE__ */ new Set(["--category"]);
290
+ function stripResolveFlags(args, booleanFlags = TAXONOMY_RESOLVE_BOOLEAN_FLAGS, valueFlags = TAXONOMY_RESOLVE_VALUE_FLAGS) {
291
+ return parseTaxonomyResolveArgs(args, booleanFlags, valueFlags).textParts;
292
+ }
293
+ function parseTaxonomyResolveArgs(args, booleanFlags = TAXONOMY_RESOLVE_BOOLEAN_FLAGS, valueFlags = TAXONOMY_RESOLVE_VALUE_FLAGS) {
294
+ const textParts = [];
295
+ const values = {};
296
+ const booleans = /* @__PURE__ */ new Set();
297
+ let literalText = false;
298
+ for (let i = 0; i < args.length; i++) {
299
+ const arg = args[i];
300
+ if (literalText) {
301
+ textParts.push(arg);
302
+ continue;
303
+ }
304
+ if (arg === "--") {
305
+ literalText = true;
306
+ continue;
307
+ }
308
+ if (arg.startsWith("--")) {
309
+ if (booleanFlags.has(arg)) {
310
+ booleans.add(arg);
311
+ continue;
312
+ }
313
+ if (valueFlags.has(arg)) {
314
+ const value = args[i + 1];
315
+ if (value === void 0 || value.startsWith("--")) {
316
+ throw new Error(`${arg} requires a value`);
317
+ }
318
+ values[arg] = value;
319
+ i++;
320
+ continue;
321
+ }
322
+ throw new Error(`Unknown flag: ${arg}`);
323
+ }
324
+ textParts.push(arg);
325
+ }
326
+ return { textParts, values, booleans };
327
+ }
328
+
329
+ // src/path-utils.ts
330
+ function resolveHomeDir() {
331
+ return process.env.HOME ?? process.env.USERPROFILE ?? "~";
332
+ }
333
+ function expandTilde(p) {
334
+ if (p === "~" || p.startsWith("~/") || p.startsWith("~\\")) {
335
+ return resolveHomeDir() + p.slice(1);
336
+ }
337
+ const home = resolveHomeDir();
338
+ if (p === "$HOME" || p.startsWith("$HOME/") || p.startsWith("$HOME\\")) {
339
+ return home + p.slice(5);
340
+ }
341
+ if (p === "${HOME}" || p.startsWith("${HOME}/") || p.startsWith("${HOME}\\")) {
342
+ return home + p.slice(7);
343
+ }
344
+ return p;
345
+ }
346
+
347
+ // src/commands/procedural.ts
348
+ async function runProceduralBinaryCommand(rest) {
349
+ initLogger();
350
+ const subcommand = rest[0];
351
+ if (!subcommand || subcommand === "--help" || subcommand === "-h") {
352
+ console.log(`remnic procedural \u2014 Procedural memory operations (issue #567)
353
+
354
+ Usage:
355
+ remnic procedural stats [--format json|text] [--memory-dir <path>]
356
+ remnic procedural maintain [--apply] [--format json|text] [--memory-dir <path>]
357
+
358
+ Subcommands:
359
+ stats Print counts by status + recent activity + active config.
360
+ maintain Run library-health maintenance (issue #2370): shadow
361
+ report of merge / repair-flag / retire proposals.
362
+ --apply executes them (requires
363
+ procedural.maintenance.enabled in config).
364
+
365
+ Shared with:
366
+ GET /engram/v1/procedural/stats
367
+ MCP remnic.procedural_stats (alias engram.procedural_stats)
368
+ MCP remnic.procedure_library_maintenance (alias engram.procedure_library_maintenance)`);
369
+ return;
370
+ }
371
+ if (subcommand !== "stats" && subcommand !== "maintain") {
372
+ console.error(
373
+ `Unknown procedural subcommand "${subcommand}". Run \`remnic procedural --help\` for usage.`
374
+ );
375
+ process.exit(1);
376
+ }
377
+ const args = rest.slice(1);
378
+ const formatPresent = hasFlag(args, "--format");
379
+ const formatRaw = resolveFlag(args, "--format");
380
+ if (formatPresent && (formatRaw === void 0 || formatRaw === null)) {
381
+ console.error("--format requires a value. Use `--format json` or `--format text`.");
382
+ process.exit(1);
383
+ }
384
+ const format = (() => {
385
+ if (!formatPresent || formatRaw === void 0 || formatRaw === null) return "text";
386
+ const normalized = String(formatRaw).trim().toLowerCase();
387
+ if (normalized !== "text" && normalized !== "json") {
388
+ console.error(`Invalid --format "${formatRaw}". Allowed: text, json.`);
389
+ process.exit(1);
390
+ }
391
+ return normalized;
392
+ })();
393
+ const memoryDirPresent = hasFlag(args, "--memory-dir");
394
+ const memoryDirOverride = resolveFlag(args, "--memory-dir");
395
+ if (memoryDirPresent && (memoryDirOverride === void 0 || memoryDirOverride === null)) {
396
+ console.error("--memory-dir requires a path. Omit the flag to use the resolved default.");
397
+ process.exit(1);
398
+ }
399
+ const configPath = resolveConfigPath();
400
+ const raw = fs4.existsSync(configPath) ? JSON.parse(fs4.readFileSync(configPath, "utf8")) : {};
401
+ const config = parseConfig4(resolveRemnicConfigRecord4(raw));
402
+ const memoryDir = expandTilde(
403
+ typeof memoryDirOverride === "string" && memoryDirOverride.length > 0 ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
404
+ );
405
+ const storage = new StorageManager(memoryDir);
406
+ if (subcommand === "maintain") {
407
+ const report2 = await runProcedureLibraryMaintenance({
408
+ memoryDir,
409
+ storage,
410
+ config,
411
+ apply: hasFlag(args, "--apply")
412
+ });
413
+ if (format === "json") {
414
+ process.stdout.write(JSON.stringify(report2, null, 2) + "\n");
415
+ return;
416
+ }
417
+ process.stdout.write(formatProcedureMaintenanceText(report2));
418
+ return;
419
+ }
420
+ const report = await computeProcedureStats({ storage, config });
421
+ if (format === "json") {
422
+ process.stdout.write(JSON.stringify(report, null, 2) + "\n");
423
+ return;
424
+ }
425
+ process.stdout.write(formatProcedureStatsText(report));
426
+ }
427
+ function formatProcedureMaintenanceText(report) {
428
+ const lines = [
429
+ `Procedure library maintenance (schema v${report.schemaVersion}, ${report.mode})`,
430
+ ` generated: ${report.generatedAt}`,
431
+ ` scanned: ${report.scannedProcedures}`
432
+ ];
433
+ if (report.skippedReason) {
434
+ lines.push(` skipped: ${report.skippedReason}`);
435
+ }
436
+ lines.push(` proposed: ${report.proposed.length}`);
437
+ lines.push(` applied: ${report.appliedCount}`);
438
+ for (const action of report.proposed) {
439
+ lines.push("");
440
+ lines.push(` [${action.action}] ${action.reasonCode}`);
441
+ lines.push(` ids: ${action.memoryIds.join(", ")}`);
442
+ if (action.canonicalId) {
443
+ lines.push(` canonical: ${action.canonicalId}`);
444
+ }
445
+ lines.push(` reason: ${action.reason}`);
446
+ for (const ev of action.evidence) {
447
+ lines.push(
448
+ ` ${ev.memoryId}: mw_success=${ev.mwSuccess} mw_fail=${ev.mwFail} lastAccessed=${ev.lastAccessed ?? "(none)"}`
449
+ );
450
+ }
451
+ }
452
+ return lines.join("\n") + "\n";
453
+ }
454
+
455
+ // src/commands/drift.ts
456
+ import fs5 from "fs";
457
+ import {
458
+ Orchestrator as Orchestrator3,
459
+ initLogger as initLogger2,
460
+ parseConfig as parseConfig5,
461
+ resolveRemnicConfigRecord as resolveRemnicConfigRecord5,
462
+ runPreferenceDriftScan
463
+ } from "@remnic/core";
464
+ async function runDriftBinaryCommand(rest) {
465
+ initLogger2();
466
+ const subcommand = rest[0];
467
+ if (!subcommand || subcommand === "--help" || subcommand === "-h") {
468
+ console.log(`remnic drift \u2014 Preference drift detection (issue #2371)
469
+
470
+ Usage:
471
+ remnic drift scan [--apply] [--namespace <ns>] [--format json|text] [--memory-dir <path>]
472
+
473
+ Subcommands:
474
+ scan Classify aging preference memories as corroborated /
475
+ stale / drifted from recent evidence. Reports only by
476
+ default. --apply stamps lastCorroborated / driftState
477
+ and opens one review item per drifted preference
478
+ (requires driftDetection.enabled in config). Never
479
+ auto-deletes and never auto-supersedes.
480
+
481
+ Shared with:
482
+ MCP remnic.preference_drift_scan (alias engram.preference_drift_scan)
483
+
484
+ Resolve a drifted item with the existing review surface:
485
+ remnic.review_list / remnic.review_resolve, verbs: keep, supersede, archive`);
486
+ return;
487
+ }
488
+ if (subcommand !== "scan") {
489
+ console.error(`Unknown drift subcommand "${subcommand}". Run \`remnic drift --help\` for usage.`);
490
+ process.exit(1);
491
+ }
492
+ const args = rest.slice(1);
493
+ const formatPresent = hasFlag(args, "--format");
494
+ const formatRaw = resolveFlag(args, "--format");
495
+ if (formatPresent && (formatRaw === void 0 || formatRaw === null)) {
496
+ console.error("--format requires a value. Use `--format json` or `--format text`.");
497
+ process.exit(1);
498
+ }
499
+ const format = (() => {
500
+ if (!formatPresent || formatRaw === void 0 || formatRaw === null) return "text";
501
+ const normalized = String(formatRaw).trim().toLowerCase();
502
+ if (normalized !== "text" && normalized !== "json") {
503
+ console.error(`Invalid --format "${formatRaw}". Allowed: text, json.`);
504
+ process.exit(1);
505
+ }
506
+ return normalized;
507
+ })();
508
+ const memoryDirPresent = hasFlag(args, "--memory-dir");
509
+ const memoryDirOverride = resolveFlag(args, "--memory-dir");
510
+ if (memoryDirPresent && (memoryDirOverride === void 0 || memoryDirOverride === null)) {
511
+ console.error("--memory-dir requires a path. Omit the flag to use the resolved default.");
512
+ process.exit(1);
513
+ }
514
+ const namespacePresent = hasFlag(args, "--namespace");
515
+ const namespaceOverride = resolveFlag(args, "--namespace");
516
+ if (namespacePresent && (namespaceOverride === void 0 || namespaceOverride === null)) {
517
+ console.error("--namespace requires a value. Omit the flag to scan the default namespace.");
518
+ process.exit(1);
519
+ }
520
+ const configPath = resolveConfigPath();
521
+ const raw = fs5.existsSync(configPath) ? JSON.parse(fs5.readFileSync(configPath, "utf8")) : {};
522
+ const config = parseConfig5(resolveRemnicConfigRecord5(raw));
523
+ const memoryDirOverridden = typeof memoryDirOverride === "string" && memoryDirOverride.length > 0;
524
+ const memoryDir = expandTilde(
525
+ memoryDirOverridden ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
526
+ );
527
+ const orchestrator = new Orchestrator3(
528
+ memoryDirOverridden ? { ...config, memoryDir } : config
529
+ );
530
+ await orchestrator.initialize();
531
+ const storage = await orchestrator.getStorageForNamespace(
532
+ typeof namespaceOverride === "string" && namespaceOverride.length > 0 ? namespaceOverride : void 0
533
+ );
534
+ const report = await runPreferenceDriftScan({
535
+ storage,
536
+ config: orchestrator.config,
537
+ memoryDir,
538
+ // Deliberately NOT wrapped in a swallowing try/catch: the drift scan's
539
+ // §22 contract is that a thrown lookup means `backend_unavailable`, and
540
+ // returning `[]` on failure would misreport a live preference as stale.
541
+ embeddingLookupFactory: (scanStorage) => (content, limit) => orchestrator.semanticDedupLookup(content, limit, scanStorage),
542
+ storageForNamespace: async (namespace) => {
543
+ const resolvedNamespace = namespace?.trim() || void 0;
544
+ return {
545
+ storage: await orchestrator.getStorageForNamespace(resolvedNamespace),
546
+ namespace: resolvedNamespace
547
+ };
548
+ },
549
+ localLlm: orchestrator.localLlm ?? null,
550
+ fallbackLlm: orchestrator.fastGatewayLlm ?? null,
551
+ namespace: typeof namespaceOverride === "string" ? namespaceOverride : void 0,
552
+ apply: hasFlag(args, "--apply")
553
+ });
554
+ if (format === "json") {
555
+ process.stdout.write(JSON.stringify(report, null, 2) + "\n");
556
+ return;
557
+ }
558
+ process.stdout.write(formatPreferenceDriftText(report));
559
+ }
560
+ function formatPreferenceDriftText(report) {
561
+ const lines = [];
562
+ lines.push(`Preference drift \u2014 ${report.mode} run at ${report.generatedAt}`);
563
+ if (report.skippedReason) {
564
+ lines.push(
565
+ report.skippedReason === "drift_disabled" ? " skipped: driftDetection.enabled is false" : " skipped: driftDetection.maxCandidatesPerRun is 0"
566
+ );
567
+ return lines.join("\n") + "\n";
568
+ }
569
+ if (report.namespace) lines.push(` namespace: ${report.namespace}`);
570
+ lines.push(` eligible preferences: ${report.eligible} (classified ${report.scanned})`);
571
+ lines.push(
572
+ ` corroborated=${report.counts.corroborated} stale=${report.counts.stale} drifted=${report.counts.drifted} skipped=${report.counts.skipped}`
573
+ );
574
+ lines.push(` applied writes: ${report.appliedCount} (review items opened: ${report.reviewItemsOpened})`);
575
+ for (const finding of report.findings) {
576
+ const skip = finding.skipped ? ` [${finding.skipped}]` : "";
577
+ lines.push(` - ${finding.memoryId}: ${finding.classification}${skip} (${finding.ageDays}d old)`);
578
+ lines.push(` ${finding.reason}`);
579
+ if (finding.reviewPairId) lines.push(` review item: ${finding.reviewPairId}`);
580
+ }
581
+ lines.push(` elapsed: ${report.elapsedMs}ms`);
582
+ return lines.join("\n") + "\n";
583
+ }
584
+
262
585
  // src/optional-module-loader.ts
263
586
  function isSpecifierNotFoundError(err, specifier) {
264
587
  if (!err || typeof err !== "object") {
@@ -309,13 +632,13 @@ async function loadWecloneExportModule() {
309
632
  }
310
633
 
311
634
  // src/converge.ts
312
- import * as fs5 from "fs";
635
+ import * as fs7 from "fs";
313
636
  import { createHash as createHash3 } from "crypto";
314
637
  import * as path2 from "path";
315
638
  import {
316
639
  CONVERGE_CONFLICT_POLICIES,
317
640
  DEFAULT_CONVERGE_CONFLICT_POLICY,
318
- parseConfig as parseConfig4,
641
+ parseConfig as parseConfig6,
319
642
  buildOfflineSyncSnapshotFromBase,
320
643
  applyOfflineSyncFileContentChunk,
321
644
  isInternalRemnicStatePath as isInternalRemnicStatePath3,
@@ -341,12 +664,12 @@ import {
341
664
 
342
665
  // src/offline-storage-io.ts
343
666
  import { createDecipheriv, createHash } from "crypto";
344
- import fs4 from "fs";
667
+ import fs6 from "fs";
345
668
  import { lstat, mkdtemp, readdir, rm } from "fs/promises";
346
669
  import path from "path";
347
670
  import {
348
671
  OFFLINE_SYNC_FILE_CONTENT_TRANSFER_CHUNK_BYTES,
349
- StorageManager,
672
+ StorageManager as StorageManager2,
350
673
  createSupportPassportPrivateFileExclusion
351
674
  } from "@remnic/core";
352
675
  import { OFFLINE_DECRYPT_STAGING_DIR_PREFIX } from "@remnic/core/offline-sync-exclude-globs";
@@ -391,7 +714,7 @@ async function filterOfflineSyncBaseFiles(memoryDir, files, excludeFile) {
391
714
  return files.filter((_file, index) => excluded[index] === false);
392
715
  }
393
716
  async function createConfiguredOfflineStorage(memoryDir, secureStoreEncryptOnWrite = true) {
394
- const storage = new StorageManager(memoryDir);
717
+ const storage = new StorageManager2(memoryDir);
395
718
  const header = await readHeader(memoryDir);
396
719
  let secureStoreKey = null;
397
720
  let secureStoreRequired = false;
@@ -416,7 +739,7 @@ async function createOfflineStorageForPath(memoryDir, filePath, configured, secu
416
739
  if (storageRoot !== memoryRoot && !storageRoot.startsWith(`${memoryRoot}${path.sep}`)) {
417
740
  throw new Error(`lifecycle ledger path is outside the offline memory directory: ${filePath}`);
418
741
  }
419
- const storage = new StorageManager(storageRoot);
742
+ const storage = new StorageManager2(storageRoot);
420
743
  if (configured.secureStoreRequired) {
421
744
  storage.setSecureStoreRequired(true);
422
745
  }
@@ -503,7 +826,7 @@ async function* readOfflineSyncFileChunks(options) {
503
826
  });
504
827
  }
505
828
  async function readFilePrefix(filePath, length) {
506
- const handle = await fs4.promises.open(filePath, "r");
829
+ const handle = await fs6.promises.open(filePath, "r");
507
830
  try {
508
831
  const out = Buffer.alloc(length);
509
832
  const { bytesRead } = await handle.read(out, 0, length, 0);
@@ -513,7 +836,7 @@ async function readFilePrefix(filePath, length) {
513
836
  }
514
837
  }
515
838
  async function* readPlainOfflineFileChunks(filePath, chunkSize) {
516
- const stream = fs4.createReadStream(filePath, { highWaterMark: chunkSize });
839
+ const stream = fs6.createReadStream(filePath, { highWaterMark: chunkSize });
517
840
  for await (const chunk of stream) {
518
841
  yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
519
842
  }
@@ -550,9 +873,9 @@ async function* readEncryptedOfflineFileChunks(options) {
550
873
  });
551
874
  decipher.setAuthTag(authTag);
552
875
  decipher.setAAD(Buffer.concat([secureStoreEnvelopeHeaderAad(salt), aad]));
553
- const output = fs4.createWriteStream(tempPath, { mode: 384 });
876
+ const output = fs6.createWriteStream(tempPath, { mode: 384 });
554
877
  try {
555
- const stream = fs4.createReadStream(options.filePath, {
878
+ const stream = fs6.createReadStream(options.filePath, {
556
879
  start: MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE,
557
880
  highWaterMark: options.chunkSize
558
881
  });
@@ -1162,7 +1485,7 @@ async function readLocalTombstoneEvidence(rootDir) {
1162
1485
  for (const relativePath of TOMBSTONE_PATHS) {
1163
1486
  let content;
1164
1487
  try {
1165
- content = await fs5.promises.readFile(path2.join(rootDir, relativePath), "utf-8");
1488
+ content = await fs7.promises.readFile(path2.join(rootDir, relativePath), "utf-8");
1166
1489
  } catch (error) {
1167
1490
  if (error.code === "ENOENT") continue;
1168
1491
  throw error;
@@ -1177,7 +1500,7 @@ async function discoverCursorNamespaces(memoryDir, peerUrl) {
1177
1500
  const cursorDir = path2.join(path2.resolve(memoryDir), ".remnic", "state", "converge-cursors");
1178
1501
  let entries;
1179
1502
  try {
1180
- entries = await fs5.promises.readdir(cursorDir, { withFileTypes: true });
1503
+ entries = await fs7.promises.readdir(cursorDir, { withFileTypes: true });
1181
1504
  } catch (error) {
1182
1505
  if (error.code === "ENOENT") return [];
1183
1506
  throw error;
@@ -1253,7 +1576,7 @@ async function computeConvergePlan(options = {}) {
1253
1576
  let config = options.config;
1254
1577
  if (!config) {
1255
1578
  try {
1256
- config = parseConfig4({});
1579
+ config = parseConfig6({});
1257
1580
  } catch {
1258
1581
  }
1259
1582
  }
@@ -1504,7 +1827,7 @@ async function executeConvergeApply(options = {}) {
1504
1827
  let config = options.config;
1505
1828
  if (!config) {
1506
1829
  try {
1507
- config = parseConfig4({});
1830
+ config = parseConfig6({});
1508
1831
  } catch {
1509
1832
  }
1510
1833
  }
@@ -1667,7 +1990,7 @@ async function executeConvergeApply(options = {}) {
1667
1990
  if (current.sha256 !== entry.localSha256) {
1668
1991
  throw new Error(`local file changed during push: ${localPath}`);
1669
1992
  }
1670
- const stat2 = await fs5.promises.stat(filePath);
1993
+ const stat2 = await fs7.promises.stat(filePath);
1671
1994
  let chunks;
1672
1995
  let chunkOffset = 0;
1673
1996
  const resetChunks = async () => {
@@ -1944,7 +2267,7 @@ function formatConvergeApplyReport(result) {
1944
2267
  lines.push(formatConvergeReport(result.plan));
1945
2268
  return lines.join("\n");
1946
2269
  }
1947
- async function cmdConverge(action, rest, json, config = parseConfig4({})) {
2270
+ async function cmdConverge(action, rest, json, config = parseConfig6({})) {
1948
2271
  if (action === "help" || action === "--help" || action === "-h" || rest.includes("--help") || rest.includes("-h")) {
1949
2272
  console.log(`Usage: remnic converge <plan|apply> [options]
1950
2273
 
@@ -2150,8 +2473,8 @@ function renderReplayResult(result, targetNamespace, format) {
2150
2473
  }
2151
2474
 
2152
2475
  // src/quarantine-replay.ts
2153
- import * as fs6 from "fs";
2154
- import { EngramAccessService, Orchestrator as Orchestrator3, initLogger, parseConfig as parseConfig5, resolveRemnicConfigRecord as resolveRemnicConfigRecord4 } from "@remnic/core";
2476
+ import * as fs8 from "fs";
2477
+ import { EngramAccessService, Orchestrator as Orchestrator4, initLogger as initLogger3, parseConfig as parseConfig7, resolveRemnicConfigRecord as resolveRemnicConfigRecord6 } from "@remnic/core";
2155
2478
  import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
2156
2479
  function valueFlag(args, flag) {
2157
2480
  const occurrences = args.filter((a) => a === flag).length;
@@ -2195,13 +2518,13 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
2195
2518
  process.exitCode = 2;
2196
2519
  return;
2197
2520
  }
2198
- initLogger();
2521
+ initLogger3();
2199
2522
  let orchestrator;
2200
2523
  try {
2201
2524
  const configPath = resolveConfigPath2();
2202
- const raw = fs6.existsSync(configPath) ? JSON.parse(fs6.readFileSync(configPath, "utf8")) : {};
2203
- const config = parseConfig5(resolveRemnicConfigRecord4(raw));
2204
- orchestrator = new Orchestrator3(config);
2525
+ const raw = fs8.existsSync(configPath) ? JSON.parse(fs8.readFileSync(configPath, "utf8")) : {};
2526
+ const config = parseConfig7(resolveRemnicConfigRecord6(raw));
2527
+ orchestrator = new Orchestrator4(config);
2205
2528
  await orchestrator.initialize();
2206
2529
  await orchestrator.deferredReady;
2207
2530
  const service = new EngramAccessService(orchestrator);
@@ -2231,15 +2554,15 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
2231
2554
  }
2232
2555
 
2233
2556
  // src/offline-impression-rotation.ts
2234
- import fs7 from "fs";
2235
- import { parseConfig as parseConfig6, resolveRemnicConfigRecord as resolveRemnicConfigRecord5, drainPendingImpressionsForOfflineSync } from "@remnic/core";
2557
+ import fs9 from "fs";
2558
+ import { parseConfig as parseConfig8, resolveRemnicConfigRecord as resolveRemnicConfigRecord7, drainPendingImpressionsForOfflineSync } from "@remnic/core";
2236
2559
  import { LastRecallStore } from "@remnic/core/recall-state";
2237
2560
  function parseConfigQuietly(raw) {
2238
2561
  const originalWarn = console.warn;
2239
2562
  console.warn = () => {
2240
2563
  };
2241
2564
  try {
2242
- return parseConfig6(resolveRemnicConfigRecord5(raw));
2565
+ return parseConfig8(resolveRemnicConfigRecord7(raw));
2243
2566
  } finally {
2244
2567
  console.warn = originalWarn;
2245
2568
  }
@@ -2253,7 +2576,7 @@ var OFFLINE_CONFIG_KEYS = [
2253
2576
  function pickOfflineConfigRecord(raw) {
2254
2577
  let resolved;
2255
2578
  try {
2256
- resolved = resolveRemnicConfigRecord5(raw);
2579
+ resolved = resolveRemnicConfigRecord7(raw);
2257
2580
  } catch {
2258
2581
  resolved = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
2259
2582
  }
@@ -2266,7 +2589,7 @@ function pickOfflineConfigRecord(raw) {
2266
2589
  function resolveOfflineImpressionRotation(configPath) {
2267
2590
  let raw;
2268
2591
  try {
2269
- raw = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
2592
+ raw = fs9.existsSync(configPath) ? JSON.parse(fs9.readFileSync(configPath, "utf8")) : {};
2270
2593
  } catch {
2271
2594
  throw new Error(
2272
2595
  `cannot read recall-impression rotation from ${configPath}: config file could not be read as JSON`
@@ -2524,12 +2847,12 @@ function assertBenchModuleFreshForDevelopment() {
2524
2847
  }
2525
2848
 
2526
2849
  // src/cmd-security.ts
2527
- import fs8 from "fs";
2850
+ import fs10 from "fs";
2528
2851
  import {
2529
- Orchestrator as Orchestrator4,
2530
- parseConfig as parseConfig7,
2531
- initLogger as initLogger2,
2532
- resolveRemnicConfigRecord as resolveRemnicConfigRecord6,
2852
+ Orchestrator as Orchestrator5,
2853
+ parseConfig as parseConfig9,
2854
+ initLogger as initLogger4,
2855
+ resolveRemnicConfigRecord as resolveRemnicConfigRecord8,
2533
2856
  runAuditMemoryCliCommand,
2534
2857
  formatAuditMemoryReport
2535
2858
  } from "@remnic/core";
@@ -2542,11 +2865,11 @@ async function cmdSecurity(rest) {
2542
2865
  process.exitCode = 1;
2543
2866
  return;
2544
2867
  }
2545
- initLogger2();
2868
+ initLogger4();
2546
2869
  const configPath = resolveConfigPath();
2547
- const raw = fs8.existsSync(configPath) ? JSON.parse(fs8.readFileSync(configPath, "utf8")) : {};
2548
- const config = parseConfig7(resolveRemnicConfigRecord6(raw));
2549
- const orchestrator = new Orchestrator4(config);
2870
+ const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
2871
+ const config = parseConfig9(resolveRemnicConfigRecord8(raw));
2872
+ const orchestrator = new Orchestrator5(config);
2550
2873
  await orchestrator.initialize();
2551
2874
  try {
2552
2875
  const sinceFlag = rest.indexOf("--since");
@@ -2569,7 +2892,7 @@ async function cmdSecurity(rest) {
2569
2892
  }
2570
2893
 
2571
2894
  // src/daemon-service-candidates.ts
2572
- import fs9 from "fs";
2895
+ import fs11 from "fs";
2573
2896
  import path5 from "path";
2574
2897
  var LAUNCHD_LABEL = "ai.remnic.daemon";
2575
2898
  var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
@@ -2591,7 +2914,7 @@ function systemdUnitPaths(homeDir) {
2591
2914
  function anyFileExists(paths) {
2592
2915
  return paths.some((candidate) => {
2593
2916
  try {
2594
- return fs9.statSync(candidate).isFile();
2917
+ return fs11.statSync(candidate).isFile();
2595
2918
  } catch {
2596
2919
  return false;
2597
2920
  }
@@ -2603,7 +2926,7 @@ function commandNames(command) {
2603
2926
  }
2604
2927
  function isRunnableNodeScript(filePath) {
2605
2928
  try {
2606
- const text = fs9.readFileSync(filePath, "utf8").slice(0, 4096);
2929
+ const text = fs11.readFileSync(filePath, "utf8").slice(0, 4096);
2607
2930
  const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
2608
2931
  if (/^#!.*\bnode\b/.test(firstLine)) return true;
2609
2932
  if (firstLine.startsWith("#!")) return false;
@@ -2616,7 +2939,7 @@ function isRunnableNodeScript(filePath) {
2616
2939
  function resolveShimNodeScript(filePath) {
2617
2940
  let text;
2618
2941
  try {
2619
- text = fs9.readFileSync(filePath, "utf8").slice(0, 16384);
2942
+ text = fs11.readFileSync(filePath, "utf8").slice(0, 16384);
2620
2943
  } catch {
2621
2944
  return void 0;
2622
2945
  }
@@ -2628,8 +2951,8 @@ function resolveShimNodeScript(filePath) {
2628
2951
  const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
2629
2952
  const resolved = path5.isAbsolute(candidate) ? candidate : path5.resolve(basedir, candidate);
2630
2953
  try {
2631
- if (fs9.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
2632
- return fs9.realpathSync(resolved);
2954
+ if (fs11.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
2955
+ return fs11.realpathSync(resolved);
2633
2956
  }
2634
2957
  } catch {
2635
2958
  }
@@ -2637,7 +2960,7 @@ function resolveShimNodeScript(filePath) {
2637
2960
  return void 0;
2638
2961
  }
2639
2962
  function resolveRunnableNodeScript(filePath) {
2640
- const realPath = fs9.realpathSync(filePath);
2963
+ const realPath = fs11.realpathSync(filePath);
2641
2964
  if (isRunnableNodeScript(realPath)) return realPath;
2642
2965
  return resolveShimNodeScript(realPath);
2643
2966
  }
@@ -2647,9 +2970,9 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
2647
2970
  for (const name of commandNames(command)) {
2648
2971
  const candidate = path5.join(dir, name);
2649
2972
  try {
2650
- const stat2 = fs9.statSync(candidate);
2973
+ const stat2 = fs11.statSync(candidate);
2651
2974
  if (!stat2.isFile()) continue;
2652
- if (process.platform !== "win32") fs9.accessSync(candidate, fs9.constants.X_OK);
2975
+ if (process.platform !== "win32") fs11.accessSync(candidate, fs11.constants.X_OK);
2653
2976
  const runnable = resolveRunnableNodeScript(candidate);
2654
2977
  if (runnable) return runnable;
2655
2978
  } catch {
@@ -3049,24 +3372,6 @@ function collectBenchmarks(argv) {
3049
3372
  return benchmarks;
3050
3373
  }
3051
3374
 
3052
- // src/path-utils.ts
3053
- function resolveHomeDir() {
3054
- return process.env.HOME ?? process.env.USERPROFILE ?? "~";
3055
- }
3056
- function expandTilde(p) {
3057
- if (p === "~" || p.startsWith("~/") || p.startsWith("~\\")) {
3058
- return resolveHomeDir() + p.slice(1);
3059
- }
3060
- const home = resolveHomeDir();
3061
- if (p === "$HOME" || p.startsWith("$HOME/") || p.startsWith("$HOME\\")) {
3062
- return home + p.slice(5);
3063
- }
3064
- if (p === "${HOME}" || p.startsWith("${HOME}/") || p.startsWith("${HOME}\\")) {
3065
- return home + p.slice(7);
3066
- }
3067
- return p;
3068
- }
3069
-
3070
3375
  // src/bench-args-research.ts
3071
3376
  import path6 from "path";
3072
3377
  function readPositiveInteger(args, flag) {
@@ -4140,7 +4445,7 @@ function finalizeBenchStatus(filePath) {
4140
4445
  }
4141
4446
 
4142
4447
  // src/bench-fallback.ts
4143
- import fs10 from "fs";
4448
+ import fs12 from "fs";
4144
4449
  import path9 from "path";
4145
4450
  var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
4146
4451
  function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
@@ -4212,7 +4517,7 @@ function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs
4212
4517
  );
4213
4518
  }
4214
4519
  function resolveFallbackBenchResultPath(outputDir) {
4215
- const entries = fs10.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
4520
+ const entries = fs12.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
4216
4521
  if (entries.length === 0) {
4217
4522
  throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
4218
4523
  }
@@ -4220,7 +4525,7 @@ function resolveFallbackBenchResultPath(outputDir) {
4220
4525
  }
4221
4526
 
4222
4527
  // src/openclaw-upgrade-swap.ts
4223
- import fs11 from "fs";
4528
+ import fs13 from "fs";
4224
4529
  import path10 from "path";
4225
4530
  function describeError(error) {
4226
4531
  return error instanceof Error ? error.message : String(error);
@@ -4232,7 +4537,7 @@ function createSiblingTempFilePath(targetPath, label) {
4232
4537
  function resolveAtomicWriteMode(targetPath, explicitMode) {
4233
4538
  if (explicitMode !== void 0) return explicitMode;
4234
4539
  try {
4235
- return fs11.statSync(targetPath).mode & 4095;
4540
+ return fs13.statSync(targetPath).mode & 4095;
4236
4541
  } catch (error) {
4237
4542
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
4238
4543
  return 384;
@@ -4242,8 +4547,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
4242
4547
  }
4243
4548
  function resolveAtomicReplacementPath(targetPath) {
4244
4549
  try {
4245
- if (fs11.lstatSync(targetPath).isSymbolicLink()) {
4246
- return fs11.realpathSync(targetPath);
4550
+ if (fs13.lstatSync(targetPath).isSymbolicLink()) {
4551
+ return fs13.realpathSync(targetPath);
4247
4552
  }
4248
4553
  } catch (error) {
4249
4554
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -4260,7 +4565,7 @@ function createSiblingSwapPath(targetDir, label) {
4260
4565
  function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
4261
4566
  if (!displacedDir) return void 0;
4262
4567
  try {
4263
- fs11.rmSync(displacedDir, { recursive: true, force: true });
4568
+ fs13.rmSync(displacedDir, { recursive: true, force: true });
4264
4569
  return void 0;
4265
4570
  } catch (error) {
4266
4571
  return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
@@ -4268,43 +4573,43 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
4268
4573
  }
4269
4574
  function atomicWriteFileSync(targetPath, data, options = {}) {
4270
4575
  const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
4271
- fs11.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4576
+ fs13.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4272
4577
  const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
4273
4578
  const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
4274
4579
  try {
4275
4580
  if (options.hooks?.writeTempFileSync) {
4276
4581
  options.hooks.writeTempFileSync(tempPath);
4277
4582
  } else {
4278
- fs11.writeFileSync(tempPath, data, { mode });
4583
+ fs13.writeFileSync(tempPath, data, { mode });
4279
4584
  }
4280
- fs11.chmodSync(tempPath, mode);
4281
- const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs11.renameSync;
4585
+ fs13.chmodSync(tempPath, mode);
4586
+ const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs13.renameSync;
4282
4587
  renameTempFileSync(tempPath, resolvedTargetPath);
4283
4588
  } catch (error) {
4284
- fs11.rmSync(tempPath, { force: true });
4589
+ fs13.rmSync(tempPath, { force: true });
4285
4590
  throw error;
4286
4591
  }
4287
4592
  }
4288
4593
  function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
4289
- if (!fs11.existsSync(sourcePath)) return;
4594
+ if (!fs13.existsSync(sourcePath)) return;
4290
4595
  const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
4291
- fs11.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4596
+ fs13.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4292
4597
  const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
4293
- const mode = fs11.statSync(sourcePath).mode & 4095;
4598
+ const mode = fs13.statSync(sourcePath).mode & 4095;
4294
4599
  try {
4295
- const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs11.copyFileSync;
4600
+ const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs13.copyFileSync;
4296
4601
  copyTempFileSync(sourcePath, tempPath);
4297
- fs11.chmodSync(tempPath, mode);
4298
- const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs11.renameSync;
4602
+ fs13.chmodSync(tempPath, mode);
4603
+ const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs13.renameSync;
4299
4604
  renameTempFileSync(tempPath, resolvedTargetPath);
4300
4605
  } catch (error) {
4301
- fs11.rmSync(tempPath, { force: true });
4606
+ fs13.rmSync(tempPath, { force: true });
4302
4607
  throw error;
4303
4608
  }
4304
4609
  }
4305
4610
  function cleanupRollbackDirectory(rollbackDir) {
4306
4611
  if (!rollbackDir) return;
4307
- fs11.rmSync(rollbackDir, { recursive: true, force: true });
4612
+ fs13.rmSync(rollbackDir, { recursive: true, force: true });
4308
4613
  }
4309
4614
  function cleanupRollbackDirectoryBestEffort(rollbackDir) {
4310
4615
  if (!rollbackDir) return void 0;
@@ -4316,20 +4621,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
4316
4621
  }
4317
4622
  }
4318
4623
  function restoreDirectoryFromRollback(targetDir, rollbackDir) {
4319
- if (!fs11.existsSync(rollbackDir)) {
4624
+ if (!fs13.existsSync(rollbackDir)) {
4320
4625
  throw new Error(`Rollback directory is missing: ${rollbackDir}`);
4321
4626
  }
4322
- fs11.mkdirSync(path10.dirname(targetDir), { recursive: true });
4323
- const displacedDir = fs11.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
4627
+ fs13.mkdirSync(path10.dirname(targetDir), { recursive: true });
4628
+ const displacedDir = fs13.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
4324
4629
  if (displacedDir) {
4325
- fs11.renameSync(targetDir, displacedDir);
4630
+ fs13.renameSync(targetDir, displacedDir);
4326
4631
  }
4327
4632
  try {
4328
- fs11.renameSync(rollbackDir, targetDir);
4633
+ fs13.renameSync(rollbackDir, targetDir);
4329
4634
  } catch (restoreError) {
4330
- if (displacedDir && fs11.existsSync(displacedDir)) {
4635
+ if (displacedDir && fs13.existsSync(displacedDir)) {
4331
4636
  try {
4332
- fs11.renameSync(displacedDir, targetDir);
4637
+ fs13.renameSync(displacedDir, targetDir);
4333
4638
  } catch (revertError) {
4334
4639
  throw new AggregateError(
4335
4640
  [restoreError, revertError],
@@ -4345,23 +4650,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
4345
4650
  return cleanupDisplacedDirectoryBestEffort(displacedDir, `restored the previous plugin copy into ${targetDir}`);
4346
4651
  }
4347
4652
  function restoreDirectoryFromBackup(targetDir, backupDir) {
4348
- if (!fs11.existsSync(backupDir)) {
4653
+ if (!fs13.existsSync(backupDir)) {
4349
4654
  throw new Error(`Plugin backup directory is missing: ${backupDir}`);
4350
4655
  }
4351
- fs11.mkdirSync(path10.dirname(targetDir), { recursive: true });
4656
+ fs13.mkdirSync(path10.dirname(targetDir), { recursive: true });
4352
4657
  const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
4353
- const displacedDir = fs11.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
4354
- fs11.cpSync(backupDir, stagedDir, { recursive: true });
4658
+ const displacedDir = fs13.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
4659
+ fs13.cpSync(backupDir, stagedDir, { recursive: true });
4355
4660
  if (displacedDir) {
4356
- fs11.renameSync(targetDir, displacedDir);
4661
+ fs13.renameSync(targetDir, displacedDir);
4357
4662
  }
4358
4663
  try {
4359
- fs11.renameSync(stagedDir, targetDir);
4664
+ fs13.renameSync(stagedDir, targetDir);
4360
4665
  } catch (restoreError) {
4361
- fs11.rmSync(targetDir, { recursive: true, force: true });
4362
- if (displacedDir && fs11.existsSync(displacedDir)) {
4666
+ fs13.rmSync(targetDir, { recursive: true, force: true });
4667
+ if (displacedDir && fs13.existsSync(displacedDir)) {
4363
4668
  try {
4364
- fs11.renameSync(displacedDir, targetDir);
4669
+ fs13.renameSync(displacedDir, targetDir);
4365
4670
  } catch (revertError) {
4366
4671
  throw new AggregateError(
4367
4672
  [restoreError, revertError],
@@ -4369,7 +4674,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
4369
4674
  );
4370
4675
  }
4371
4676
  }
4372
- fs11.rmSync(stagedDir, { recursive: true, force: true });
4677
+ fs13.rmSync(stagedDir, { recursive: true, force: true });
4373
4678
  throw new Error(
4374
4679
  `Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
4375
4680
  { cause: restoreError }
@@ -4394,7 +4699,7 @@ function rollbackOpenclawUpgrade({
4394
4699
  let configRemovalAttempted = false;
4395
4700
  let pluginRestored = false;
4396
4701
  try {
4397
- if (rollbackDir && fs11.existsSync(rollbackDir)) {
4702
+ if (rollbackDir && fs13.existsSync(rollbackDir)) {
4398
4703
  const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
4399
4704
  notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
4400
4705
  if (cleanupWarning) notes.push(cleanupWarning);
@@ -4404,7 +4709,7 @@ function rollbackOpenclawUpgrade({
4404
4709
  rollbackRestoreError = error instanceof Error ? error.message : String(error);
4405
4710
  }
4406
4711
  try {
4407
- if (!pluginRestored && pluginBackupDir && fs11.existsSync(pluginBackupDir)) {
4712
+ if (!pluginRestored && pluginBackupDir && fs13.existsSync(pluginBackupDir)) {
4408
4713
  const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
4409
4714
  if (rollbackRestoreError) {
4410
4715
  notes.push(`Rollback copy restore failed; restored previous plugin from durable backup at ${pluginBackupDir}`);
@@ -4429,12 +4734,12 @@ function rollbackOpenclawUpgrade({
4429
4734
  notes.push("No previous plugin copy was available for automatic restore");
4430
4735
  }
4431
4736
  try {
4432
- if (configBackupPath && fs11.existsSync(configBackupPath)) {
4737
+ if (configBackupPath && fs13.existsSync(configBackupPath)) {
4433
4738
  restoreFileFromBackup(configPath, configBackupPath);
4434
4739
  notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
4435
- } else if (removeConfigIfUnbacked && fs11.existsSync(configPath)) {
4740
+ } else if (removeConfigIfUnbacked && fs13.existsSync(configPath)) {
4436
4741
  configRemovalAttempted = true;
4437
- fs11.rmSync(configPath, { force: true });
4742
+ fs13.rmSync(configPath, { force: true });
4438
4743
  notes.push("Removed OpenClaw config created during the failed upgrade");
4439
4744
  }
4440
4745
  } catch (error) {
@@ -4487,7 +4792,7 @@ Run this manually when you're ready:
4487
4792
 
4488
4793
  // src/openclaw-managed-upgrade-loader.ts
4489
4794
  import { execFileSync } from "child_process";
4490
- import fs12 from "fs";
4795
+ import fs14 from "fs";
4491
4796
  import os from "os";
4492
4797
  import path11 from "path";
4493
4798
  import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
@@ -4563,7 +4868,7 @@ function buildOpenclawManagedUpgradePackageSpec(version = "latest") {
4563
4868
  function readCliAdapterRange() {
4564
4869
  const moduleDir = path11.dirname(fileURLToPath3(import.meta.url));
4565
4870
  const manifestPath = path11.resolve(moduleDir, "../package.json");
4566
- const manifest = JSON.parse(fs12.readFileSync(manifestPath, "utf8"));
4871
+ const manifest = JSON.parse(fs14.readFileSync(manifestPath, "utf8"));
4567
4872
  if (manifest.name !== "@remnic/cli") {
4568
4873
  throw new Error(`Invalid @remnic/cli package manifest at ${manifestPath}.`);
4569
4874
  }
@@ -4607,7 +4912,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
4607
4912
  const adapterMissing = isSpecifierNotFoundError(error, OPENCLAW_PLUGIN_PACKAGE) || isSpecifierNotFoundError(error, MANAGED_UPGRADE_SPECIFIER) || isManagedUpgradeSubpathMissing(error);
4608
4913
  if (!adapterMissing) throw error;
4609
4914
  }
4610
- const temporaryRoot = fs12.mkdtempSync(path11.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
4915
+ const temporaryRoot = fs14.mkdtempSync(path11.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
4611
4916
  try {
4612
4917
  const toolingPackageSpec = `${OPENCLAW_PLUGIN_PACKAGE}@${readCliAdapterRange()}`;
4613
4918
  const installArgs = [
@@ -4622,12 +4927,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
4622
4927
  ];
4623
4928
  (hooks.runNpmInstall ?? runNpmInstall)(installArgs);
4624
4929
  const resolverPath = path11.join(temporaryRoot, "load-managed-upgrade.mjs");
4625
- fs12.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
4930
+ fs14.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
4626
4931
  `, "utf8");
4627
4932
  return await importModule(pathToFileURL2(resolverPath).href);
4628
4933
  } finally {
4629
4934
  try {
4630
- fs12.rmSync(temporaryRoot, { recursive: true, force: true });
4935
+ fs14.rmSync(temporaryRoot, { recursive: true, force: true });
4631
4936
  } catch (error) {
4632
4937
  const detail = error instanceof Error ? error.message : String(error);
4633
4938
  console.warn(`Could not remove temporary managed upgrade project at ${temporaryRoot}: ${detail}`);
@@ -4636,13 +4941,13 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
4636
4941
  }
4637
4942
 
4638
4943
  // src/remote-daemon.ts
4639
- import fs13 from "fs";
4944
+ import fs15 from "fs";
4640
4945
  function readCompatEnv(primary, legacy) {
4641
4946
  return process.env[primary] ?? process.env[legacy];
4642
4947
  }
4643
4948
  function readRemnicConfigRecord(configPath) {
4644
4949
  try {
4645
- const parsed = JSON.parse(fs13.readFileSync(configPath, "utf8"));
4950
+ const parsed = JSON.parse(fs15.readFileSync(configPath, "utf8"));
4646
4951
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
4647
4952
  return parsed;
4648
4953
  }
@@ -4871,7 +5176,7 @@ async function remoteRecallXray(daemon, request) {
4871
5176
  }
4872
5177
 
4873
5178
  // src/daemon-service.ts
4874
- import fs14 from "fs";
5179
+ import fs16 from "fs";
4875
5180
  import path12 from "path";
4876
5181
  import * as childProcess from "child_process";
4877
5182
  import { fileURLToPath as fileURLToPath4 } from "url";
@@ -4883,7 +5188,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
4883
5188
  processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
4884
5189
  }
4885
5190
  function resolveServerBinDetails(options = {}) {
4886
- const existsSync4 = options.existsSync ?? fs14.existsSync;
5191
+ const existsSync4 = options.existsSync ?? fs16.existsSync;
4887
5192
  const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
4888
5193
  const moduleDir = options.moduleDir ?? thisModuleDir;
4889
5194
  const packageResolve = options.packageResolve ?? resolveImportSpecifier;
@@ -4942,8 +5247,8 @@ function resolveServerBin(options = {}) {
4942
5247
  return resolveServerBinDetails(options).path;
4943
5248
  }
4944
5249
  function readVerifiedDaemonPid(options) {
4945
- const readFileSync4 = options.readFileSync ?? fs14.readFileSync;
4946
- const unlinkSync = options.unlinkSync ?? fs14.unlinkSync;
5250
+ const readFileSync4 = options.readFileSync ?? fs16.readFileSync;
5251
+ const unlinkSync = options.unlinkSync ?? fs16.unlinkSync;
4947
5252
  const processKill = options.processKill ?? process.kill;
4948
5253
  const platform = options.platform ?? process.platform;
4949
5254
  const execFileSync4 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
@@ -5043,8 +5348,8 @@ function removePidFileBestEffort(file, unlinkSync) {
5043
5348
  }
5044
5349
  }
5045
5350
  function inspectLaunchdPlist(plistPath, options = {}) {
5046
- const existsSync4 = options.existsSync ?? fs14.existsSync;
5047
- const readFileSync4 = options.readFileSync ?? fs14.readFileSync;
5351
+ const existsSync4 = options.existsSync ?? fs16.existsSync;
5352
+ const readFileSync4 = options.readFileSync ?? fs16.readFileSync;
5048
5353
  if (!existsSync4(plistPath)) {
5049
5354
  return {
5050
5355
  installed: false,
@@ -5168,62 +5473,6 @@ function unescapeXml(input) {
5168
5473
  return input.replaceAll("&quot;", '"').replaceAll("&apos;", "'").replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&amp;", "&");
5169
5474
  }
5170
5475
 
5171
- // src/cli-args.ts
5172
- function resolveFlag(args, flag) {
5173
- const idx = args.indexOf(flag);
5174
- if (idx === -1 || idx + 1 >= args.length) return void 0;
5175
- const value = args[idx + 1];
5176
- return isOptionToken(value) ? void 0 : value;
5177
- }
5178
- function isOptionToken(value) {
5179
- if (!value.startsWith("-")) return false;
5180
- if (/^-\d/.test(value) || /^-\.\d/.test(value)) return false;
5181
- return true;
5182
- }
5183
- function hasFlag(args, flag) {
5184
- return args.indexOf(flag) !== -1;
5185
- }
5186
- var TAXONOMY_RESOLVE_BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--json"]);
5187
- var TAXONOMY_RESOLVE_VALUE_FLAGS = /* @__PURE__ */ new Set(["--category"]);
5188
- function stripResolveFlags(args, booleanFlags = TAXONOMY_RESOLVE_BOOLEAN_FLAGS, valueFlags = TAXONOMY_RESOLVE_VALUE_FLAGS) {
5189
- return parseTaxonomyResolveArgs(args, booleanFlags, valueFlags).textParts;
5190
- }
5191
- function parseTaxonomyResolveArgs(args, booleanFlags = TAXONOMY_RESOLVE_BOOLEAN_FLAGS, valueFlags = TAXONOMY_RESOLVE_VALUE_FLAGS) {
5192
- const textParts = [];
5193
- const values = {};
5194
- const booleans = /* @__PURE__ */ new Set();
5195
- let literalText = false;
5196
- for (let i = 0; i < args.length; i++) {
5197
- const arg = args[i];
5198
- if (literalText) {
5199
- textParts.push(arg);
5200
- continue;
5201
- }
5202
- if (arg === "--") {
5203
- literalText = true;
5204
- continue;
5205
- }
5206
- if (arg.startsWith("--")) {
5207
- if (booleanFlags.has(arg)) {
5208
- booleans.add(arg);
5209
- continue;
5210
- }
5211
- if (valueFlags.has(arg)) {
5212
- const value = args[i + 1];
5213
- if (value === void 0 || value.startsWith("--")) {
5214
- throw new Error(`${arg} requires a value`);
5215
- }
5216
- values[arg] = value;
5217
- i++;
5218
- continue;
5219
- }
5220
- throw new Error(`Unknown flag: ${arg}`);
5221
- }
5222
- textParts.push(arg);
5223
- }
5224
- return { textParts, values, booleans };
5225
- }
5226
-
5227
5476
  // src/parse-connector-config.ts
5228
5477
  function parseConfigAssignment(raw, flag) {
5229
5478
  const eqIdx = raw.indexOf("=");
@@ -5278,7 +5527,7 @@ function stripConfigArgv(args) {
5278
5527
  }
5279
5528
 
5280
5529
  // src/import-dispatch.ts
5281
- import fs15 from "fs";
5530
+ import fs17 from "fs";
5282
5531
  import {
5283
5532
  runImporter,
5284
5533
  validateImportBatchSize,
@@ -5792,7 +6041,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
5792
6041
  let materializedTarget;
5793
6042
  let materializePromise;
5794
6043
  const io = {
5795
- readFile: ioOverrides.readFile ?? (async (p) => fs15.promises.readFile(p, "utf-8")),
6044
+ readFile: ioOverrides.readFile ?? (async (p) => fs17.promises.readFile(p, "utf-8")),
5796
6045
  loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
5797
6046
  runImporter: ioOverrides.runImporter ?? runImporter,
5798
6047
  getWriteTarget: async () => {
@@ -5905,7 +6154,7 @@ async function cmdCapture(rest, io) {
5905
6154
  }
5906
6155
 
5907
6156
  // src/import-lossless-claw-cmd.ts
5908
- import fs16 from "fs";
6157
+ import fs18 from "fs";
5909
6158
  import path14 from "path";
5910
6159
  import {
5911
6160
  applyLcmSchema,
@@ -6017,15 +6266,15 @@ async function loadImportLosslessClawModule() {
6017
6266
 
6018
6267
  // src/import-lossless-claw-cmd.ts
6019
6268
  function assertDirectoryOrAbsent(p, label) {
6020
- if (fs16.existsSync(p) && !fs16.statSync(p).isDirectory()) {
6269
+ if (fs18.existsSync(p) && !fs18.statSync(p).isDirectory()) {
6021
6270
  throw new Error(`${label} is not a directory: ${p}`);
6022
6271
  }
6023
6272
  }
6024
6273
  function assertFile(p, label) {
6025
- if (!fs16.existsSync(p)) {
6274
+ if (!fs18.existsSync(p)) {
6026
6275
  throw new Error(`${label} does not exist: ${p}`);
6027
6276
  }
6028
- if (!fs16.statSync(p).isFile()) {
6277
+ if (!fs18.statSync(p).isFile()) {
6029
6278
  throw new Error(`${label} is not a file: ${p}`);
6030
6279
  }
6031
6280
  }
@@ -6057,7 +6306,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
6057
6306
  try {
6058
6307
  if (parsed.dryRun) {
6059
6308
  const lcmPath = path14.join(memoryDir, "state", "lcm.sqlite");
6060
- if (fs16.existsSync(lcmPath)) {
6309
+ if (fs18.existsSync(lcmPath)) {
6061
6310
  destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
6062
6311
  } else {
6063
6312
  destDb = mod.openInMemoryDestinationDatabase();
@@ -7409,7 +7658,7 @@ async function resolveAllBenchmarks() {
7409
7658
  if (packageBenchmarks) {
7410
7659
  return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
7411
7660
  }
7412
- if (!fs17.existsSync(EVAL_RUNNER_PATH)) {
7661
+ if (!fs19.existsSync(EVAL_RUNNER_PATH)) {
7413
7662
  return [];
7414
7663
  }
7415
7664
  return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
@@ -7457,7 +7706,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
7457
7706
  `Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
7458
7707
  );
7459
7708
  }
7460
- if (!fs17.existsSync(EVAL_RUNNER_PATH)) {
7709
+ if (!fs19.existsSync(EVAL_RUNNER_PATH)) {
7461
7710
  console.error(
7462
7711
  "Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
7463
7712
  );
@@ -7467,7 +7716,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
7467
7716
  path18.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
7468
7717
  path18.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
7469
7718
  ];
7470
- const tsxCmd = tsxCandidates.find((candidate) => fs17.existsSync(candidate)) ?? "tsx";
7719
+ const tsxCmd = tsxCandidates.find((candidate) => fs19.existsSync(candidate)) ?? "tsx";
7471
7720
  const fallbackOutputDir = createFallbackBenchOutputDir(
7472
7721
  parsed.resultsDir ?? resolveBenchOutputDir(),
7473
7722
  benchmarkId,
@@ -7612,9 +7861,9 @@ var PERSONAMEM_COMPLETION_MARKER = path18.join(
7612
7861
  );
7613
7862
  function resolveRealpathWithinDataset(datasetPath, relativePath) {
7614
7863
  try {
7615
- const datasetRoot = fs17.realpathSync(datasetPath);
7864
+ const datasetRoot = fs19.realpathSync(datasetPath);
7616
7865
  const candidatePath = path18.resolve(datasetRoot, relativePath);
7617
- const candidateRealPath = fs17.realpathSync(candidatePath);
7866
+ const candidateRealPath = fs19.realpathSync(candidatePath);
7618
7867
  const relativeToRoot = path18.relative(datasetRoot, candidateRealPath);
7619
7868
  if (relativeToRoot.startsWith("..") || path18.isAbsolute(relativeToRoot)) {
7620
7869
  return null;
@@ -7673,14 +7922,14 @@ function parseCsvRows(raw) {
7673
7922
  function isPersonaMemDatasetComplete(datasetPath) {
7674
7923
  try {
7675
7924
  const completionMarkerPath = path18.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
7676
- if (fs17.statSync(completionMarkerPath).isFile()) {
7925
+ if (fs19.statSync(completionMarkerPath).isFile()) {
7677
7926
  return true;
7678
7927
  }
7679
7928
  } catch {
7680
7929
  }
7681
7930
  const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
7682
7931
  try {
7683
- return fs17.statSync(path18.join(datasetPath, candidate)).isFile();
7932
+ return fs19.statSync(path18.join(datasetPath, candidate)).isFile();
7684
7933
  } catch {
7685
7934
  return false;
7686
7935
  }
@@ -7689,7 +7938,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7689
7938
  return false;
7690
7939
  }
7691
7940
  try {
7692
- const rows = parseCsvRows(fs17.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
7941
+ const rows = parseCsvRows(fs19.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
7693
7942
  if (rows.length < 2) {
7694
7943
  return false;
7695
7944
  }
@@ -7704,7 +7953,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7704
7953
  }
7705
7954
  return historyPaths.every((relativePath) => {
7706
7955
  const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
7707
- return resolvedPath !== null && fs17.statSync(resolvedPath).isFile();
7956
+ return resolvedPath !== null && fs19.statSync(resolvedPath).isFile();
7708
7957
  });
7709
7958
  } catch {
7710
7959
  return false;
@@ -7712,7 +7961,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7712
7961
  }
7713
7962
  function hasDatasetFile(datasetPath, relativePath) {
7714
7963
  try {
7715
- return fs17.statSync(path18.join(datasetPath, relativePath)).isFile();
7964
+ return fs19.statSync(path18.join(datasetPath, relativePath)).isFile();
7716
7965
  } catch {
7717
7966
  return false;
7718
7967
  }
@@ -7732,10 +7981,10 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
7732
7981
  return candidateFilenames.some((filename) => {
7733
7982
  const filePath = path18.join(datasetPath, filename);
7734
7983
  try {
7735
- if (!fs17.statSync(filePath).isFile()) {
7984
+ if (!fs19.statSync(filePath).isFile()) {
7736
7985
  return false;
7737
7986
  }
7738
- const raw = fs17.readFileSync(filePath, "utf8");
7987
+ const raw = fs19.readFileSync(filePath, "utf8");
7739
7988
  return /"source"\s*:\s*"recsys[_-]/i.test(raw);
7740
7989
  } catch {
7741
7990
  return false;
@@ -7751,7 +8000,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
7751
8000
  function isDatasetDownloaded(datasetPath, benchmarkId) {
7752
8001
  let stats;
7753
8002
  try {
7754
- stats = fs17.statSync(datasetPath);
8003
+ stats = fs19.statSync(datasetPath);
7755
8004
  } catch {
7756
8005
  return false;
7757
8006
  }
@@ -7761,7 +8010,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7761
8010
  const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
7762
8011
  if (!marker) {
7763
8012
  try {
7764
- return fs17.readdirSync(datasetPath).length > 0;
8013
+ return fs19.readdirSync(datasetPath).length > 0;
7765
8014
  } catch {
7766
8015
  return false;
7767
8016
  }
@@ -7769,7 +8018,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7769
8018
  if (marker.allOf) {
7770
8019
  const hasAllRequiredFiles = marker.allOf.every((name) => {
7771
8020
  try {
7772
- return fs17.statSync(path18.join(datasetPath, name)).isFile();
8021
+ return fs19.statSync(path18.join(datasetPath, name)).isFile();
7773
8022
  } catch {
7774
8023
  return false;
7775
8024
  }
@@ -7781,7 +8030,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7781
8030
  if (marker.anyOf) {
7782
8031
  const hasMarkerFile = marker.anyOf.some((name) => {
7783
8032
  try {
7784
- return fs17.statSync(path18.join(datasetPath, name)).isFile();
8033
+ return fs19.statSync(path18.join(datasetPath, name)).isFile();
7785
8034
  } catch {
7786
8035
  return false;
7787
8036
  }
@@ -7799,7 +8048,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7799
8048
  }
7800
8049
  if (marker.ext) {
7801
8050
  try {
7802
- return fs17.readdirSync(datasetPath).some(
8051
+ return fs19.readdirSync(datasetPath).some(
7803
8052
  (name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
7804
8053
  );
7805
8054
  } catch {
@@ -7811,7 +8060,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7811
8060
  async function launchBenchUi(resultsDir) {
7812
8061
  const benchUiDir = path18.join(CLI_REPO_ROOT, "packages", "bench-ui");
7813
8062
  const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
7814
- if (!fs17.existsSync(path18.join(benchUiDir, "package.json"))) {
8063
+ if (!fs19.existsSync(path18.join(benchUiDir, "package.json"))) {
7815
8064
  console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
7816
8065
  process.exit(1);
7817
8066
  }
@@ -7849,13 +8098,13 @@ function listDownloadableBenchmarks() {
7849
8098
  }
7850
8099
  function resolveDatasetDownloadScriptPath() {
7851
8100
  const bundled = path18.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
7852
- if (fs17.existsSync(bundled)) {
8101
+ if (fs19.existsSync(bundled)) {
7853
8102
  return bundled;
7854
8103
  }
7855
8104
  return path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
7856
8105
  }
7857
8106
  function isRepoCheckout() {
7858
- return fs17.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs17.existsSync(path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
8107
+ return fs19.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs19.existsSync(path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
7859
8108
  }
7860
8109
  function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
7861
8110
  const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
@@ -8168,8 +8417,8 @@ async function exportBenchPackageResult(parsed) {
8168
8417
  ...reportCardProvenance ? { reportCardProvenance } : {}
8169
8418
  });
8170
8419
  if (parsed.output) {
8171
- fs17.mkdirSync(path18.dirname(parsed.output), { recursive: true });
8172
- fs17.writeFileSync(parsed.output, rendered);
8420
+ fs19.mkdirSync(path18.dirname(parsed.output), { recursive: true });
8421
+ fs19.writeFileSync(parsed.output, rendered);
8173
8422
  console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
8174
8423
  return;
8175
8424
  }
@@ -8214,7 +8463,7 @@ async function manageBenchDatasets(parsed) {
8214
8463
  process.exit(1);
8215
8464
  }
8216
8465
  const scriptPath = resolveDatasetDownloadScriptPath();
8217
- if (!fs17.existsSync(scriptPath)) {
8466
+ if (!fs19.existsSync(scriptPath)) {
8218
8467
  console.error(`ERROR: dataset download script not found: ${scriptPath}`);
8219
8468
  process.exit(1);
8220
8469
  }
@@ -8414,7 +8663,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
8414
8663
  );
8415
8664
  process.exit(1);
8416
8665
  }
8417
- const sourceResultSha256 = createHash4("sha256").update(fs17.readFileSync(latest.path)).digest("hex");
8666
+ const sourceResultSha256 = createHash4("sha256").update(fs19.readFileSync(latest.path)).digest("hex");
8418
8667
  const expandedManifestPath = expandTilde(manifestPath);
8419
8668
  if (!bench.resolveLocalLabJudgeProviderConfig) {
8420
8669
  console.error(
@@ -8829,7 +9078,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
8829
9078
  }
8830
9079
  let decoded;
8831
9080
  try {
8832
- decoded = JSON.parse(fs17.readFileSync(parsed.taskIdsFile, "utf8"));
9081
+ decoded = JSON.parse(fs19.readFileSync(parsed.taskIdsFile, "utf8"));
8833
9082
  } catch (error) {
8834
9083
  throw new Error(
8835
9084
  `Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
@@ -9504,7 +9753,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
9504
9753
  return void 0;
9505
9754
  }
9506
9755
  try {
9507
- return fs17.realpathSync(datasetDir);
9756
+ return fs19.realpathSync(datasetDir);
9508
9757
  } catch {
9509
9758
  return datasetDir;
9510
9759
  }
@@ -9558,13 +9807,13 @@ async function writeBenchReproManifestForPackageRun(args) {
9558
9807
  }
9559
9808
  function loadStandaloneConvergeCommandConfig() {
9560
9809
  const configPath = resolveConfigPath();
9561
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
9562
- return parseConfig8(resolveRemnicConfigRecord7(raw));
9810
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
9811
+ return parseConfig10(resolveRemnicConfigRecord9(raw));
9563
9812
  }
9564
9813
  function parseConvergePluginConfig(value) {
9565
9814
  if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
9566
9815
  if (Object.keys(value).length === 0) return void 0;
9567
- return parseConfig8(resolveRemnicConfigRecord7(value));
9816
+ return parseConfig10(resolveRemnicConfigRecord9(value));
9568
9817
  }
9569
9818
  function loadConvergeCommandConfig() {
9570
9819
  if (readCompatEnv("REMNIC_CONFIG_PATH", "ENGRAM_CONFIG_PATH")) {
@@ -9587,13 +9836,13 @@ function resolveConfigPath(cliPath) {
9587
9836
  path18.join(resolveHomeDir(), ".config", "engram", "config.json")
9588
9837
  ];
9589
9838
  for (const candidate of candidates) {
9590
- if (fs17.existsSync(candidate)) return candidate;
9839
+ if (fs19.existsSync(candidate)) return candidate;
9591
9840
  }
9592
9841
  return path18.join(resolveHomeDir(), ".config", "remnic", "config.json");
9593
9842
  }
9594
9843
  function resolveExistingBenchRemnicConfigPath(cliPath) {
9595
9844
  const configPath = resolveConfigPath(cliPath);
9596
- if (fs17.existsSync(configPath)) {
9845
+ if (fs19.existsSync(configPath)) {
9597
9846
  return configPath;
9598
9847
  }
9599
9848
  if (cliPath) {
@@ -9603,7 +9852,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
9603
9852
  }
9604
9853
  function resolveExistingBenchOpenclawConfigPath(cliPath) {
9605
9854
  const configPath = resolveOpenclawConfigPath(cliPath);
9606
- if (fs17.existsSync(configPath)) {
9855
+ if (fs19.existsSync(configPath)) {
9607
9856
  return configPath;
9608
9857
  }
9609
9858
  if (cliPath) {
@@ -9710,8 +9959,8 @@ function resolveMemoryDir() {
9710
9959
  const envMemoryDir = readCompatEnv("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
9711
9960
  if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
9712
9961
  const configPath = resolveConfigPath();
9713
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
9714
- const remnicCfg = resolveRemnicConfigRecord7(raw);
9962
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
9963
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
9715
9964
  if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
9716
9965
  return normalizeMemoryDirPath(remnicCfg.memoryDir);
9717
9966
  }
@@ -9719,18 +9968,18 @@ function resolveMemoryDir() {
9719
9968
  const standalonePath = path18.join(home, ".remnic", "memory");
9720
9969
  const legacyStandalonePath = path18.join(home, ".engram", "memory");
9721
9970
  const openclawPath = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
9722
- if (fs17.existsSync(standalonePath)) return standalonePath;
9723
- if (fs17.existsSync(legacyStandalonePath)) return legacyStandalonePath;
9971
+ if (fs19.existsSync(standalonePath)) return standalonePath;
9972
+ if (fs19.existsSync(legacyStandalonePath)) return legacyStandalonePath;
9724
9973
  return openclawPath;
9725
9974
  })();
9726
9975
  const manifestPath = getManifestPath();
9727
- if (fs17.existsSync(manifestPath)) {
9976
+ if (fs19.existsSync(manifestPath)) {
9728
9977
  try {
9729
9978
  const active = getActiveSpace();
9730
9979
  if (active?.memoryDir) {
9731
9980
  const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
9732
- if (!fs17.existsSync(activeMemoryDir)) {
9733
- fs17.mkdirSync(activeMemoryDir, { recursive: true });
9981
+ if (!fs19.existsSync(activeMemoryDir)) {
9982
+ fs19.mkdirSync(activeMemoryDir, { recursive: true });
9734
9983
  }
9735
9984
  return activeMemoryDir;
9736
9985
  }
@@ -9779,13 +10028,13 @@ function resolveOpenclawConfigPath(cliPath) {
9779
10028
  const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
9780
10029
  if (envPath) return path18.resolve(expandTilde(envPath));
9781
10030
  for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
9782
- if (fs17.existsSync(candidate)) return candidate;
10031
+ if (fs19.existsSync(candidate)) return candidate;
9783
10032
  }
9784
10033
  return path18.join(resolveOpenclawStateDir(), "openclaw.json");
9785
10034
  }
9786
10035
  function readOpenclawConfig(configPath) {
9787
- if (!fs17.existsSync(configPath)) return {};
9788
- const raw = fs17.readFileSync(configPath, "utf-8");
10036
+ if (!fs19.existsSync(configPath)) return {};
10037
+ const raw = fs19.readFileSync(configPath, "utf-8");
9789
10038
  let parsed;
9790
10039
  try {
9791
10040
  parsed = JSON.parse(raw);
@@ -9887,9 +10136,9 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
9887
10136
  return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
9888
10137
  }
9889
10138
  function backupPathIfPresent(sourcePath, backupPath) {
9890
- if (!fs17.existsSync(sourcePath)) return false;
9891
- fs17.mkdirSync(path18.dirname(backupPath), { recursive: true });
9892
- fs17.cpSync(sourcePath, backupPath, { recursive: true });
10139
+ if (!fs19.existsSync(sourcePath)) return false;
10140
+ fs19.mkdirSync(path18.dirname(backupPath), { recursive: true });
10141
+ fs19.cpSync(sourcePath, backupPath, { recursive: true });
9893
10142
  return true;
9894
10143
  }
9895
10144
  function restartOpenclawGateway() {
@@ -9908,7 +10157,7 @@ function restartOpenclawGateway() {
9908
10157
  }
9909
10158
  function cmdInit() {
9910
10159
  const configPath = path18.join(process.cwd(), "remnic.config.json");
9911
- if (fs17.existsSync(configPath)) {
10160
+ if (fs19.existsSync(configPath)) {
9912
10161
  console.log(`Config already exists: ${configPath}`);
9913
10162
  return;
9914
10163
  }
@@ -9924,7 +10173,7 @@ function cmdInit() {
9924
10173
  authToken: "${REMNIC_AUTH_TOKEN}"
9925
10174
  }
9926
10175
  };
9927
- fs17.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
10176
+ fs19.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
9928
10177
  console.log(`Created ${configPath}`);
9929
10178
  console.log("\nSet these environment variables:");
9930
10179
  console.log(" export OPENAI_API_KEY=sk-...");
@@ -10344,12 +10593,12 @@ async function cmdQuery(queryText, json, explain) {
10344
10593
  printQueryResult(result, json);
10345
10594
  return;
10346
10595
  }
10347
- initLogger3();
10596
+ initLogger5();
10348
10597
  const configPath = resolveConfigPath();
10349
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10350
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10351
- const config = parseConfig8(remnicCfg);
10352
- const orchestrator = new Orchestrator5(config);
10598
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
10599
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
10600
+ const config = parseConfig10(remnicCfg);
10601
+ const orchestrator = new Orchestrator6(config);
10353
10602
  await orchestrator.initialize();
10354
10603
  const service = new EngramAccessService2(orchestrator);
10355
10604
  const recallRequest = buildQueryRecallRequest(queryText);
@@ -10524,12 +10773,12 @@ async function cmdXray(rest) {
10524
10773
  await runXrayCommand(rest, xrayCliIo((request) => remoteRecallXray(remote, request)));
10525
10774
  return;
10526
10775
  }
10527
- initLogger3();
10776
+ initLogger5();
10528
10777
  const configPath = resolveConfigPath();
10529
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10530
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10531
- const config = parseConfig8(remnicCfg);
10532
- const orchestrator = new Orchestrator5(config);
10778
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
10779
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
10780
+ const config = parseConfig10(remnicCfg);
10781
+ const orchestrator = new Orchestrator6(config);
10533
10782
  await orchestrator.initialize();
10534
10783
  await orchestrator.deferredReady;
10535
10784
  const service = new EngramAccessService2(orchestrator);
@@ -10556,36 +10805,45 @@ async function runWhoKnowsCommand(rest, io) {
10556
10805
  });
10557
10806
  io.stdout(renderWhoKnows(result, parsed.json));
10558
10807
  }
10559
- async function cmdWhoKnows(rest) {
10560
- const { topic, options } = extractWhoKnowsRawArgs(rest);
10561
- parseWhoKnowsCliOptions(topic, options);
10562
- if (resolveRemoteDaemon(resolveConfigPath())) {
10563
- throw new Error("who-knows: remote daemon mode is not supported yet; run with a local config");
10564
- }
10565
- initLogger3();
10808
+ async function withLocalService(fn) {
10809
+ initLogger5();
10566
10810
  const configPath = resolveConfigPath();
10567
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10568
- const config = parseConfig8(resolveRemnicConfigRecord7(raw));
10569
- const orchestrator = new Orchestrator5(config);
10811
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
10812
+ const orchestrator = new Orchestrator6(parseConfig10(resolveRemnicConfigRecord9(raw)));
10570
10813
  await orchestrator.initialize();
10571
10814
  await orchestrator.deferredReady;
10572
10815
  const service = new EngramAccessService2(orchestrator);
10573
10816
  try {
10574
- await runWhoKnowsCommand(rest, {
10575
- whoKnows: (request) => service.whoKnows(request),
10576
- stdout: (line) => console.log(line)
10577
- });
10817
+ return await fn(service, orchestrator);
10578
10818
  } finally {
10579
10819
  orchestrator.abortDeferredInit();
10580
10820
  await orchestrator.destroy();
10581
10821
  }
10582
10822
  }
10823
+ async function cmdWhoKnows(rest) {
10824
+ const { topic, options } = extractWhoKnowsRawArgs(rest);
10825
+ parseWhoKnowsCliOptions(topic, options);
10826
+ if (resolveRemoteDaemon(resolveConfigPath())) {
10827
+ throw new Error("who-knows: remote daemon mode is not supported yet; run with a local config");
10828
+ }
10829
+ await withLocalService((service) => runWhoKnowsCommand(rest, {
10830
+ whoKnows: (request) => service.whoKnows(request),
10831
+ stdout: (line) => console.log(line)
10832
+ }));
10833
+ }
10834
+ async function cmdPromotionCandidates(rest) {
10835
+ if (resolveRemoteDaemon(resolveConfigPath())) throw new Error("promotion-candidates: remote daemon mode is not supported yet; run with a local config");
10836
+ await withLocalService((service) => runPromotionCandidatesCommand(rest, {
10837
+ promotionCandidates: (request) => service.promotionCandidates(request),
10838
+ stdout: (line) => console.log(line)
10839
+ }));
10840
+ }
10583
10841
  async function cmdVersions(rest) {
10584
- initLogger3();
10842
+ initLogger5();
10585
10843
  const configPath = resolveConfigPath();
10586
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10587
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10588
- const config = parseConfig8(remnicCfg);
10844
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
10845
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
10846
+ const config = parseConfig10(remnicCfg);
10589
10847
  if (!config.versioningEnabled) {
10590
10848
  console.error("Page versioning is disabled (versioningEnabled = false).");
10591
10849
  process.exit(1);
@@ -10697,11 +10955,11 @@ Options:
10697
10955
  }
10698
10956
  }
10699
10957
  async function cmdEnrich(rest) {
10700
- initLogger3();
10958
+ initLogger5();
10701
10959
  const configPath = resolveConfigPath();
10702
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10703
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10704
- const config = parseConfig8(remnicCfg);
10960
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
10961
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
10962
+ const config = parseConfig10(remnicCfg);
10705
10963
  const subcommand = rest[0];
10706
10964
  if (subcommand === "audit") {
10707
10965
  const memoryDir2 = expandTilde(config.memoryDir);
@@ -10729,7 +10987,7 @@ async function cmdEnrich(rest) {
10729
10987
  pipelineConfig2.providers = [
10730
10988
  { id: "web-search", enabled: true, costTier: "cheap" }
10731
10989
  ];
10732
- const orchestrator2 = new Orchestrator5(config);
10990
+ const orchestrator2 = new Orchestrator6(config);
10733
10991
  await orchestrator2.initialize();
10734
10992
  await orchestrator2.deferredReady;
10735
10993
  const searchBackend2 = orchestrator2.qmd;
@@ -10765,7 +11023,7 @@ Registered providers:`);
10765
11023
  console.error("Usage: remnic enrich <entity-name> | --all | --dry-run | audit | providers");
10766
11024
  process.exit(1);
10767
11025
  }
10768
- const orchestrator = new Orchestrator5(config);
11026
+ const orchestrator = new Orchestrator6(config);
10769
11027
  await orchestrator.initialize();
10770
11028
  await orchestrator.deferredReady;
10771
11029
  const storage = await orchestrator.getStorage(config.defaultNamespace);
@@ -10890,80 +11148,12 @@ Registered providers:`);
10890
11148
  ${totalPersisted} candidate(s) persisted to memory store.`);
10891
11149
  }
10892
11150
  }
10893
- async function cmdProcedural(rest) {
10894
- initLogger3();
10895
- const subcommand = rest[0];
10896
- if (!subcommand || subcommand === "--help" || subcommand === "-h") {
10897
- console.log(`remnic procedural \u2014 Procedural memory operations (issue #567)
10898
-
10899
- Usage:
10900
- remnic procedural stats [--format json|text] [--memory-dir <path>]
10901
-
10902
- Subcommands:
10903
- stats Print counts by status + recent activity + active config.
10904
-
10905
- Shared with:
10906
- GET /engram/v1/procedural/stats
10907
- MCP remnic.procedural_stats (alias engram.procedural_stats)`);
10908
- return;
10909
- }
10910
- if (subcommand !== "stats") {
10911
- console.error(
10912
- `Unknown procedural subcommand "${subcommand}". Run \`remnic procedural --help\` for usage.`
10913
- );
10914
- process.exit(1);
10915
- }
10916
- const args = rest.slice(1);
10917
- const formatPresent = hasFlag(args, "--format");
10918
- const formatRaw = resolveFlag(args, "--format");
10919
- if (formatPresent && (formatRaw === void 0 || formatRaw === null)) {
10920
- console.error(
10921
- "--format requires a value. Use `--format json` or `--format text`."
10922
- );
10923
- process.exit(1);
10924
- }
10925
- const format = (() => {
10926
- if (!formatPresent || formatRaw === void 0 || formatRaw === null) {
10927
- return "text";
10928
- }
10929
- const normalized = String(formatRaw).trim().toLowerCase();
10930
- if (normalized !== "text" && normalized !== "json") {
10931
- console.error(
10932
- `Invalid --format "${formatRaw}". Allowed: text, json.`
10933
- );
10934
- process.exit(1);
10935
- }
10936
- return normalized;
10937
- })();
10938
- const memoryDirPresent = hasFlag(args, "--memory-dir");
10939
- const memoryDirOverride = resolveFlag(args, "--memory-dir");
10940
- if (memoryDirPresent && (memoryDirOverride === void 0 || memoryDirOverride === null)) {
10941
- console.error(
10942
- "--memory-dir requires a path. Omit the flag to use the resolved default."
10943
- );
10944
- process.exit(1);
10945
- }
10946
- const configPath = resolveConfigPath();
10947
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10948
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10949
- const config = parseConfig8(remnicCfg);
10950
- const memoryDir = expandTilde(
10951
- typeof memoryDirOverride === "string" && memoryDirOverride.length > 0 ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
10952
- );
10953
- const storage = new StorageManager2(memoryDir);
10954
- const report = await computeProcedureStats({ storage, config });
10955
- if (format === "json") {
10956
- process.stdout.write(JSON.stringify(report, null, 2) + "\n");
10957
- return;
10958
- }
10959
- process.stdout.write(formatProcedureStatsText(report));
10960
- }
10961
11151
  async function cmdExtensions(action, rest) {
10962
- initLogger3();
11152
+ initLogger5();
10963
11153
  const configPath = resolveConfigPath();
10964
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10965
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10966
- const config = parseConfig8(remnicCfg);
11154
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
11155
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
11156
+ const config = parseConfig10(remnicCfg);
10967
11157
  const root = resolveExtensionsRoot(config);
10968
11158
  const noopLog = { warn: () => {
10969
11159
  }, debug: () => {
@@ -11012,7 +11202,7 @@ Root: ${root}`);
11012
11202
  const extensions = await discoverMemoryExtensions(root, warnLog);
11013
11203
  let entries = [];
11014
11204
  try {
11015
- entries = fs17.readdirSync(root);
11205
+ entries = fs19.readdirSync(root);
11016
11206
  } catch {
11017
11207
  console.log(`Extensions root does not exist: ${root}`);
11018
11208
  process.exitCode = 0;
@@ -11023,7 +11213,7 @@ Root: ${root}`);
11023
11213
  for (const entry of entries) {
11024
11214
  const entryPath = path18.join(root, entry);
11025
11215
  try {
11026
- if (!fs17.statSync(entryPath).isDirectory()) continue;
11216
+ if (!fs19.statSync(entryPath).isDirectory()) continue;
11027
11217
  } catch {
11028
11218
  continue;
11029
11219
  }
@@ -11053,11 +11243,11 @@ Root: ${root}`);
11053
11243
  }
11054
11244
  }
11055
11245
  async function cmdBriefing(rest) {
11056
- initLogger3();
11246
+ initLogger5();
11057
11247
  const configPath = resolveConfigPath();
11058
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
11059
- const remnicCfg = resolveRemnicConfigRecord7(raw);
11060
- const config = parseConfig8(remnicCfg);
11248
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
11249
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
11250
+ const config = parseConfig10(remnicCfg);
11061
11251
  if (!config.briefing.enabled) {
11062
11252
  console.error("Briefing is disabled in config (briefing.enabled = false).");
11063
11253
  process.exit(1);
@@ -11110,7 +11300,7 @@ async function cmdBriefing(rest) {
11110
11300
  process.exit(1);
11111
11301
  }
11112
11302
  const format = effectiveFormatFlag === "json" ? "json" : effectiveFormatFlag === "markdown" ? "markdown" : config.briefing.defaultFormat;
11113
- const orchestrator = new Orchestrator5(config);
11303
+ const orchestrator = new Orchestrator6(config);
11114
11304
  await orchestrator.initialize();
11115
11305
  const storage = await orchestrator.getStorage(config.defaultNamespace);
11116
11306
  const calendarSource = config.briefing.calendarSource ? new FileCalendarSource(config.briefing.calendarSource) : void 0;
@@ -11135,10 +11325,10 @@ async function cmdBriefing(rest) {
11135
11325
  if (save) {
11136
11326
  try {
11137
11327
  const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
11138
- fs17.mkdirSync(saveDir, { recursive: true });
11328
+ fs19.mkdirSync(saveDir, { recursive: true });
11139
11329
  const filename = briefingFilename(new Date(result.window.to), format);
11140
11330
  const filePath = path18.join(saveDir, filename);
11141
- fs17.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
11331
+ fs19.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
11142
11332
  console.error(`Saved briefing: ${filePath}`);
11143
11333
  } catch (err) {
11144
11334
  console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
@@ -11156,7 +11346,7 @@ async function cmdDoctor() {
11156
11346
  detail: `${nodeVersion} (requires >= 22.12.0)`
11157
11347
  });
11158
11348
  const configPath = resolveConfigPath();
11159
- const configExists = fs17.existsSync(configPath);
11349
+ const configExists = fs19.existsSync(configPath);
11160
11350
  checks.push({ name: "Config file", ok: configExists, detail: configPath });
11161
11351
  let standaloneConfig;
11162
11352
  let standaloneConfigError;
@@ -11164,11 +11354,11 @@ async function cmdDoctor() {
11164
11354
  let configuredNs = { invalid: false };
11165
11355
  if (configExists) {
11166
11356
  try {
11167
- const raw = JSON.parse(fs17.readFileSync(configPath, "utf8"));
11168
- const remnicCfg = resolveRemnicConfigRecord7(raw);
11357
+ const raw = JSON.parse(fs19.readFileSync(configPath, "utf8"));
11358
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
11169
11359
  standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
11170
11360
  configuredNs = readConfiguredNamespace(remnicCfg);
11171
- standaloneConfig = parseConfig8(remnicCfg);
11361
+ standaloneConfig = parseConfig10(remnicCfg);
11172
11362
  } catch (err) {
11173
11363
  standaloneConfigError = err instanceof Error ? err.message : String(err);
11174
11364
  }
@@ -11177,10 +11367,10 @@ async function cmdDoctor() {
11177
11367
  try {
11178
11368
  memoryDir = resolveMemoryDir();
11179
11369
  } catch {
11180
- memoryDir = parseConfig8({}).memoryDir;
11370
+ memoryDir = parseConfig10({}).memoryDir;
11181
11371
  }
11182
11372
  try {
11183
- fs17.mkdirSync(memoryDir, { recursive: true });
11373
+ fs19.mkdirSync(memoryDir, { recursive: true });
11184
11374
  checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
11185
11375
  } catch {
11186
11376
  checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
@@ -11209,7 +11399,7 @@ async function cmdDoctor() {
11209
11399
  });
11210
11400
  if (nsPolicyCheck) checks.push(nsPolicyCheck);
11211
11401
  const openclawConfigPath = resolveOpenclawConfigPath();
11212
- const openclawConfigExists = fs17.existsSync(openclawConfigPath);
11402
+ const openclawConfigExists = fs19.existsSync(openclawConfigPath);
11213
11403
  let openclawConfig = {};
11214
11404
  let openclawConfigValid = false;
11215
11405
  let openclawPluginModeConfigured = false;
@@ -11217,7 +11407,7 @@ async function cmdDoctor() {
11217
11407
  let activeOpenclawEntryConfig = null;
11218
11408
  if (openclawConfigExists) {
11219
11409
  try {
11220
- const parsed = JSON.parse(fs17.readFileSync(openclawConfigPath, "utf-8"));
11410
+ const parsed = JSON.parse(fs19.readFileSync(openclawConfigPath, "utf-8"));
11221
11411
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
11222
11412
  openclawConfig = parsed;
11223
11413
  openclawConfigValid = true;
@@ -11297,9 +11487,9 @@ async function cmdDoctor() {
11297
11487
  let memDirOk = false;
11298
11488
  let memDirDetail = `${resolvedMemDir} (not found)`;
11299
11489
  let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
11300
- if (fs17.existsSync(resolvedMemDir)) {
11490
+ if (fs19.existsSync(resolvedMemDir)) {
11301
11491
  try {
11302
- const stat2 = fs17.statSync(resolvedMemDir);
11492
+ const stat2 = fs19.statSync(resolvedMemDir);
11303
11493
  if (stat2.isDirectory()) {
11304
11494
  memDirOk = true;
11305
11495
  memDirDetail = resolvedMemDir;
@@ -11454,12 +11644,12 @@ async function cmdDoctor() {
11454
11644
  }
11455
11645
  function cmdConfig() {
11456
11646
  const configPath = resolveConfigPath();
11457
- if (!fs17.existsSync(configPath)) {
11647
+ if (!fs19.existsSync(configPath)) {
11458
11648
  console.log("No config file found. Run `remnic init` to create one.");
11459
11649
  return;
11460
11650
  }
11461
11651
  console.log(`Config: ${configPath}`);
11462
- const rawConfig = fs17.readFileSync(configPath, "utf8");
11652
+ const rawConfig = fs19.readFileSync(configPath, "utf8");
11463
11653
  const redacted = rawConfig.replace(
11464
11654
  /("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
11465
11655
  "$1[REDACTED]$3"
@@ -11563,13 +11753,13 @@ async function cmdReview(action, rest) {
11563
11753
  console.error("Usage: remnic review <approve|dismiss|flag> <id>");
11564
11754
  process.exit(1);
11565
11755
  }
11566
- const storage = new StorageManager2(memoryDir);
11756
+ const storage = new StorageManager3(memoryDir);
11567
11757
  const configPath = resolveConfigPath();
11568
11758
  let tombstonesConfig = null;
11569
11759
  try {
11570
- const rawCfg = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
11571
- const remnicCfg = resolveRemnicConfigRecord7(rawCfg);
11572
- const config = parseConfig8(remnicCfg);
11760
+ const rawCfg = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
11761
+ const remnicCfg = resolveRemnicConfigRecord9(rawCfg);
11762
+ const config = parseConfig10(remnicCfg);
11573
11763
  tombstonesConfig = {
11574
11764
  enabled: config.tombstonesEnabled,
11575
11765
  semanticMatch: config.tombstonesSemanticMatch,
@@ -12311,7 +12501,7 @@ async function pushOfflineFileContent(args) {
12311
12501
  }
12312
12502
  async function pushOfflineFileContentFromChunkReader(args) {
12313
12503
  const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
12314
- const stat2 = fs17.statSync(filePath);
12504
+ const stat2 = fs19.statSync(filePath);
12315
12505
  if (stat2.mtimeMs !== args.file.mtimeMs) {
12316
12506
  throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
12317
12507
  }
@@ -12802,7 +12992,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
12802
12992
  return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
12803
12993
  }
12804
12994
  async function runOfflineSyncOnce(options) {
12805
- fs17.mkdirSync(options.memoryDir, { recursive: true });
12995
+ fs19.mkdirSync(options.memoryDir, { recursive: true });
12806
12996
  let activeStatePath = options.statePath;
12807
12997
  let priorState = await readOfflineSyncState(activeStatePath);
12808
12998
  let syncNamespace = options.namespace ?? priorState?.namespace;
@@ -13435,7 +13625,7 @@ Environment fallbacks:
13435
13625
  const configPath = resolveConfigPath();
13436
13626
  let config;
13437
13627
  try {
13438
- const rawConfig = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
13628
+ const rawConfig = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
13439
13629
  config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
13440
13630
  } catch {
13441
13631
  throw new Error(
@@ -13450,7 +13640,7 @@ Environment fallbacks:
13450
13640
  const statePath = statePathExplicit ? path18.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
13451
13641
  if (action === "prepare") {
13452
13642
  if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
13453
- fs17.mkdirSync(memoryDir, { recursive: true });
13643
+ fs19.mkdirSync(memoryDir, { recursive: true });
13454
13644
  const remoteSnapshot = await fetchOfflineSnapshot({
13455
13645
  remoteUrl,
13456
13646
  token,
@@ -13549,7 +13739,7 @@ Environment fallbacks:
13549
13739
  return;
13550
13740
  }
13551
13741
  if (action === "status") {
13552
- fs17.mkdirSync(memoryDir, { recursive: true });
13742
+ fs19.mkdirSync(memoryDir, { recursive: true });
13553
13743
  const state = statePath ? await readOfflineSyncState(statePath) : null;
13554
13744
  if (state && remoteUrl && statePath) {
13555
13745
  assertOfflineStateMatches({
@@ -13687,7 +13877,7 @@ function cmdDedup(json) {
13687
13877
  function readInstalledConnectorConfig(configPath, fallback) {
13688
13878
  if (!configPath) return fallback;
13689
13879
  try {
13690
- const parsed = JSON.parse(fs17.readFileSync(configPath, "utf8"));
13880
+ const parsed = JSON.parse(fs19.readFileSync(configPath, "utf8"));
13691
13881
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
13692
13882
  const { token: _token, ...config } = parsed;
13693
13883
  return config;
@@ -13865,7 +14055,7 @@ async function cmdConnectors(action, rest, json) {
13865
14055
  const pub = factory();
13866
14056
  const available = await pub.isHostAvailable();
13867
14057
  const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
13868
- const extensionExists = available && extRoot ? fs17.existsSync(extRoot) : false;
14058
+ const extensionExists = available && extRoot ? fs19.existsSync(extRoot) : false;
13869
14059
  publisherChecks.push({
13870
14060
  name: `Publisher: ${targetHostId}`,
13871
14061
  ok: !available || extensionExists,
@@ -13939,7 +14129,7 @@ async function cmdConnectors(action, rest, json) {
13939
14129
  let connectorsCfg;
13940
14130
  const configPath = resolveConfigPath();
13941
14131
  try {
13942
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
14132
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
13943
14133
  connectorsCfg = parseConfigQuietly(raw).connectors;
13944
14134
  } catch {
13945
14135
  process.stderr.write(
@@ -14013,12 +14203,12 @@ async function cmdConnectors(action, rest, json) {
14013
14203
  process.exitCode = 2;
14014
14204
  return;
14015
14205
  }
14016
- initLogger3();
14206
+ initLogger5();
14017
14207
  const configPath = resolveConfigPath();
14018
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
14019
- const remnicCfg = resolveRemnicConfigRecord7(raw);
14020
- const config = parseConfig8(remnicCfg);
14021
- const orchestrator = new Orchestrator5(config);
14208
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
14209
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
14210
+ const config = parseConfig10(remnicCfg);
14211
+ const orchestrator = new Orchestrator6(config);
14022
14212
  try {
14023
14213
  await orchestrator.initialize();
14024
14214
  await orchestrator.deferredReady;
@@ -14140,9 +14330,9 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
14140
14330
  console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
14141
14331
  process.exit(1);
14142
14332
  }
14143
- const rawConfig = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
14144
- const pluginConfig = resolveRemnicConfigRecord7(rawConfig);
14145
- const config = parseConfig8(pluginConfig);
14333
+ const rawConfig = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
14334
+ const pluginConfig = resolveRemnicConfigRecord9(rawConfig);
14335
+ const config = parseConfig10(pluginConfig);
14146
14336
  if (subAction === "generate") {
14147
14337
  let outputDir;
14148
14338
  try {
@@ -14162,13 +14352,13 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
14162
14352
  } else if (subAction === "validate") {
14163
14353
  const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path18.join(process.cwd(), "marketplace.json");
14164
14354
  const resolved = path18.resolve(targetPath);
14165
- if (!fs17.existsSync(resolved)) {
14355
+ if (!fs19.existsSync(resolved)) {
14166
14356
  console.error(`File not found: ${resolved}`);
14167
14357
  process.exit(1);
14168
14358
  }
14169
14359
  let parsed;
14170
14360
  try {
14171
- parsed = JSON.parse(fs17.readFileSync(resolved, "utf8"));
14361
+ parsed = JSON.parse(fs19.readFileSync(resolved, "utf8"));
14172
14362
  } catch {
14173
14363
  console.error(`Invalid JSON in ${resolved}`);
14174
14364
  process.exit(1);
@@ -14339,12 +14529,14 @@ async function cmdSpace(action, rest, json) {
14339
14529
  }
14340
14530
  const result = await promoteSpace(sourceId, targetId, {
14341
14531
  force: rest.includes("--force"),
14342
- forceOverwrite: rest.includes("--force-overwrite")
14532
+ forceOverwrite: rest.includes("--force-overwrite"),
14533
+ allowUserSubject: rest.includes("--allow-user-subject")
14343
14534
  });
14344
14535
  if (json) {
14345
14536
  console.log(JSON.stringify(result, null, 2));
14346
14537
  } else {
14347
14538
  console.log(`Promoted ${result.memoriesPromoted} memories`);
14539
+ if (result.subjectWarnings && result.subjectWarnings.length > 0) console.log(`Subject-guard warnings: ${result.subjectWarnings.length} (see --json)`);
14348
14540
  if (result.conflicts.length > 0) console.log(`Conflicts: ${result.conflicts.length}`);
14349
14541
  console.log(`Duration: ${result.durationMs}ms`);
14350
14542
  }
@@ -14367,12 +14559,12 @@ async function cmdSpace(action, rest, json) {
14367
14559
  }
14368
14560
  }
14369
14561
  async function cmdLegacyBenchmark(action, rest, json) {
14370
- initLogger3();
14562
+ initLogger5();
14371
14563
  const configPath = resolveConfigPath();
14372
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
14373
- const remnicCfg = resolveRemnicConfigRecord7(raw);
14374
- const config = parseConfig8(remnicCfg);
14375
- const orchestrator = new Orchestrator5(config);
14564
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
14565
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
14566
+ const config = parseConfig10(remnicCfg);
14567
+ const orchestrator = new Orchestrator6(config);
14376
14568
  const service = new EngramAccessService2(orchestrator);
14377
14569
  const { runBenchSuite, loadBaseline, checkRegression } = await loadBenchModule();
14378
14570
  const benchConfig = {
@@ -14774,7 +14966,7 @@ function readPid() {
14774
14966
  function inferPort() {
14775
14967
  try {
14776
14968
  const configPath = resolveConfigPath();
14777
- const raw = JSON.parse(fs17.readFileSync(configPath, "utf8"));
14969
+ const raw = JSON.parse(fs19.readFileSync(configPath, "utf8"));
14778
14970
  return raw.server?.port ?? 4318;
14779
14971
  } catch {
14780
14972
  return 4318;
@@ -14869,13 +15061,13 @@ function daemonInstall() {
14869
15061
  process.exit(1);
14870
15062
  }
14871
15063
  const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
14872
- fs17.mkdirSync(LOGS_DIR, { recursive: true });
15064
+ fs19.mkdirSync(LOGS_DIR, { recursive: true });
14873
15065
  if (isMacOS()) {
14874
15066
  const templatePath = path18.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
14875
- const template = fs17.readFileSync(templatePath, "utf8");
15067
+ const template = fs19.readFileSync(templatePath, "utf8");
14876
15068
  const plist = renderTemplate(template, vars);
14877
- fs17.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
14878
- fs17.writeFileSync(LAUNCHD_PLIST_PATH, plist);
15069
+ fs19.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
15070
+ fs19.writeFileSync(LAUNCHD_PLIST_PATH, plist);
14879
15071
  try {
14880
15072
  launchdLoadPlist(LAUNCHD_PLIST_PATH);
14881
15073
  } catch (err) {
@@ -14892,10 +15084,10 @@ function daemonInstall() {
14892
15084
  console.log(` Logs: ${LOGS_DIR}/daemon.log`);
14893
15085
  } else if (isLinux()) {
14894
15086
  const templatePath = path18.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
14895
- const template = fs17.readFileSync(templatePath, "utf8");
15087
+ const template = fs19.readFileSync(templatePath, "utf8");
14896
15088
  const unit = renderTemplate(template, vars);
14897
- fs17.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
14898
- fs17.writeFileSync(SYSTEMD_UNIT_PATH, unit);
15089
+ fs19.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
15090
+ fs19.writeFileSync(SYSTEMD_UNIT_PATH, unit);
14899
15091
  try {
14900
15092
  childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
14901
15093
  } catch (err) {
@@ -14931,7 +15123,7 @@ function daemonUninstall() {
14931
15123
  } catch {
14932
15124
  }
14933
15125
  try {
14934
- fs17.unlinkSync(plistPath);
15126
+ fs19.unlinkSync(plistPath);
14935
15127
  removed = true;
14936
15128
  console.log(`Removed launchd service: ${plistPath}`);
14937
15129
  } catch {
@@ -14951,7 +15143,7 @@ function daemonUninstall() {
14951
15143
  let removed = false;
14952
15144
  for (const unitPath of SYSTEMD_UNIT_PATHS) {
14953
15145
  try {
14954
- fs17.unlinkSync(unitPath);
15146
+ fs19.unlinkSync(unitPath);
14955
15147
  removed = true;
14956
15148
  console.log(`Removed systemd service: ${unitPath}`);
14957
15149
  } catch {
@@ -15018,13 +15210,13 @@ async function daemonStatus() {
15018
15210
  console.log(` Port: ${port}`);
15019
15211
  console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
15020
15212
  console.log(` Platform: ${process.platform}`);
15021
- console.log(` PID file: ${fs17.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
15022
- console.log(` Log file: ${fs17.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
15213
+ console.log(` PID file: ${fs19.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
15214
+ console.log(` Log file: ${fs19.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
15023
15215
  try {
15024
15216
  const configPath = resolveConfigPath();
15025
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
15026
- const remnicCfg = resolveRemnicConfigRecord7(raw);
15027
- const config = parseConfig8(remnicCfg);
15217
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
15218
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
15219
+ const config = parseConfig10(remnicCfg);
15028
15220
  const extRoot = resolveExtensionsRoot(config);
15029
15221
  const noopLog = { warn: () => {
15030
15222
  }, debug: () => {
@@ -15063,9 +15255,9 @@ function daemonStart() {
15063
15255
  return;
15064
15256
  }
15065
15257
  }
15066
- fs17.mkdirSync(PID_DIR, { recursive: true });
15067
- fs17.mkdirSync(LOGS_DIR, { recursive: true });
15068
- const logStream = fs17.openSync(LOG_FILE, "a");
15258
+ fs19.mkdirSync(PID_DIR, { recursive: true });
15259
+ fs19.mkdirSync(LOGS_DIR, { recursive: true });
15260
+ const logStream = fs19.openSync(LOG_FILE, "a");
15069
15261
  const serverBin = resolveServerBin();
15070
15262
  const isSource = serverBin.endsWith(".ts");
15071
15263
  let cmd;
@@ -15087,7 +15279,7 @@ function daemonStart() {
15087
15279
  }
15088
15280
  });
15089
15281
  child.unref();
15090
- fs17.writeFileSync(PID_FILE, String(child.pid));
15282
+ fs19.writeFileSync(PID_FILE, String(child.pid));
15091
15283
  console.log(`Started remnic server (pid ${child.pid})`);
15092
15284
  console.log(` Log: ${LOG_FILE}`);
15093
15285
  }
@@ -15121,11 +15313,11 @@ function daemonStop() {
15121
15313
  console.log("Process not found (cleaning up PID file)");
15122
15314
  }
15123
15315
  try {
15124
- fs17.unlinkSync(PID_FILE);
15316
+ fs19.unlinkSync(PID_FILE);
15125
15317
  } catch {
15126
15318
  }
15127
15319
  try {
15128
- fs17.unlinkSync(LEGACY_PID_FILE);
15320
+ fs19.unlinkSync(LEGACY_PID_FILE);
15129
15321
  } catch {
15130
15322
  }
15131
15323
  }
@@ -15251,11 +15443,11 @@ async function promptYesNo(question, defaultYes = true) {
15251
15443
  });
15252
15444
  }
15253
15445
  async function cmdBinary(rest) {
15254
- initLogger3();
15446
+ initLogger5();
15255
15447
  const configPath = resolveConfigPath();
15256
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
15257
- const remnicCfg = resolveRemnicConfigRecord7(raw);
15258
- const config = parseConfig8(remnicCfg);
15448
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
15449
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
15450
+ const config = parseConfig10(remnicCfg);
15259
15451
  const memoryDir = resolveMemoryDir();
15260
15452
  const blConfig = {
15261
15453
  enabled: config.binaryLifecycleEnabled,
@@ -15444,7 +15636,7 @@ async function cmdOpenclawInstall(opts) {
15444
15636
  } else if (slotIsActiveLegacy) {
15445
15637
  changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
15446
15638
  }
15447
- if (!fs17.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
15639
+ if (!fs19.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
15448
15640
  if (hasLegacy && migrateLegacy) {
15449
15641
  changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
15450
15642
  }
@@ -15464,8 +15656,8 @@ async function cmdOpenclawInstall(opts) {
15464
15656
  Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
15465
15657
  return;
15466
15658
  }
15467
- if (fs17.existsSync(memoryDir)) {
15468
- const st = fs17.statSync(memoryDir);
15659
+ if (fs19.existsSync(memoryDir)) {
15660
+ const st = fs19.statSync(memoryDir);
15469
15661
  if (!st.isDirectory()) {
15470
15662
  throw new Error(
15471
15663
  `Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
@@ -15473,12 +15665,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
15473
15665
  );
15474
15666
  }
15475
15667
  } else {
15476
- fs17.mkdirSync(memoryDir, { recursive: true });
15668
+ fs19.mkdirSync(memoryDir, { recursive: true });
15477
15669
  console.log(`Created memory directory: ${memoryDir}`);
15478
15670
  }
15479
15671
  const configDir = path18.dirname(configPath);
15480
- if (!fs17.existsSync(configDir)) {
15481
- fs17.mkdirSync(configDir, { recursive: true });
15672
+ if (!fs19.existsSync(configDir)) {
15673
+ fs19.mkdirSync(configDir, { recursive: true });
15482
15674
  }
15483
15675
  atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
15484
15676
  console.log("\nDone! Summary of changes:");
@@ -15507,7 +15699,7 @@ async function cmdOpenclawUpgrade(opts) {
15507
15699
  const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
15508
15700
  const fallbackMemoryDir = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
15509
15701
  const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
15510
- const configExistedBefore = fs17.existsSync(configPath);
15702
+ const configExistedBefore = fs19.existsSync(configPath);
15511
15703
  const existingConfig = readOpenclawConfig(configPath);
15512
15704
  const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
15513
15705
  const preservedMemoryDir = opts.memoryDir ? path18.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
@@ -15732,15 +15924,15 @@ async function cmdOpenclawMigrateEngram(opts) {
15732
15924
  }
15733
15925
  function createOpenclawUpgradeBackupDir() {
15734
15926
  const backupsRoot = path18.join(resolveOpenclawStateDir(), "backups");
15735
- fs17.mkdirSync(backupsRoot, { recursive: true });
15736
- return fs17.mkdtempSync(path18.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
15927
+ fs19.mkdirSync(backupsRoot, { recursive: true });
15928
+ return fs19.mkdtempSync(path18.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
15737
15929
  }
15738
15930
  async function cmdTaxonomy(rest) {
15739
- initLogger3();
15931
+ initLogger5();
15740
15932
  const configPath = resolveConfigPath();
15741
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
15742
- const remnicCfg = resolveRemnicConfigRecord7(raw);
15743
- const config = parseConfig8(remnicCfg);
15933
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
15934
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
15935
+ const config = parseConfig10(remnicCfg);
15744
15936
  if (!config.taxonomyEnabled) {
15745
15937
  console.error(
15746
15938
  "Taxonomy is disabled in config (taxonomyEnabled = false). Enable it to use taxonomy commands."
@@ -15776,8 +15968,8 @@ async function cmdTaxonomy(rest) {
15776
15968
  console.log(doc);
15777
15969
  if (config.taxonomyAutoGenResolver) {
15778
15970
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15779
- fs17.mkdirSync(path18.dirname(resolverPath), { recursive: true });
15780
- fs17.writeFileSync(resolverPath, doc);
15971
+ fs19.mkdirSync(path18.dirname(resolverPath), { recursive: true });
15972
+ fs19.writeFileSync(resolverPath, doc);
15781
15973
  console.error(`Written: ${resolverPath}`);
15782
15974
  }
15783
15975
  break;
@@ -15823,7 +16015,7 @@ async function cmdTaxonomy(rest) {
15823
16015
  if (config.taxonomyAutoGenResolver) {
15824
16016
  const doc = generateResolverDocument(taxonomy);
15825
16017
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15826
- fs17.writeFileSync(resolverPath, doc);
16018
+ fs19.writeFileSync(resolverPath, doc);
15827
16019
  console.error(`Regenerated: ${resolverPath}`);
15828
16020
  }
15829
16021
  break;
@@ -15854,7 +16046,7 @@ async function cmdTaxonomy(rest) {
15854
16046
  if (config.taxonomyAutoGenResolver) {
15855
16047
  const doc = generateResolverDocument(taxonomy);
15856
16048
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15857
- fs17.writeFileSync(resolverPath, doc);
16049
+ fs19.writeFileSync(resolverPath, doc);
15858
16050
  console.error(`Regenerated: ${resolverPath}`);
15859
16051
  }
15860
16052
  break;
@@ -16045,12 +16237,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
16045
16237
  `Unknown training-export format "${args.format}". ${validList}`
16046
16238
  );
16047
16239
  }
16048
- if (!fs17.existsSync(args.memoryDir)) {
16240
+ if (!fs19.existsSync(args.memoryDir)) {
16049
16241
  throw new Error(
16050
16242
  `--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
16051
16243
  );
16052
16244
  }
16053
- if (!fs17.statSync(args.memoryDir).isDirectory()) {
16245
+ if (!fs19.statSync(args.memoryDir).isDirectory()) {
16054
16246
  throw new Error(
16055
16247
  `--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
16056
16248
  );
@@ -16136,10 +16328,10 @@ async function runTrainingExport(args, stdout = process.stdout) {
16136
16328
  }
16137
16329
  const formatted = adapter.formatRecords(records);
16138
16330
  const outDir = path18.dirname(args.output);
16139
- fs17.mkdirSync(outDir, { recursive: true });
16331
+ fs19.mkdirSync(outDir, { recursive: true });
16140
16332
  const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
16141
- fs17.writeFileSync(tmpPath, formatted, "utf-8");
16142
- fs17.renameSync(tmpPath, args.output);
16333
+ fs19.writeFileSync(tmpPath, formatted, "utf-8");
16334
+ fs19.renameSync(tmpPath, args.output);
16143
16335
  stdout.write(
16144
16336
  `Exported ${records.length} records to ${args.output} (${adapter.name} format)
16145
16337
  `
@@ -16191,6 +16383,9 @@ async function main(argv = process.argv.slice(2)) {
16191
16383
  case "who-knows":
16192
16384
  await cmdWhoKnows(rest);
16193
16385
  break;
16386
+ case "promotion-candidates":
16387
+ await cmdPromotionCandidates(rest);
16388
+ break;
16194
16389
  case "security":
16195
16390
  await cmdSecurity(rest);
16196
16391
  break;
@@ -16314,7 +16509,7 @@ async function main(argv = process.argv.slice(2)) {
16314
16509
  }
16315
16510
  }, 500);
16316
16511
  };
16317
- fs17.watch(memoryDir, { recursive: true }, (_event, filename) => {
16512
+ fs19.watch(memoryDir, { recursive: true }, (_event, filename) => {
16318
16513
  if (filename && filename.startsWith(".")) return;
16319
16514
  rebuild();
16320
16515
  });
@@ -16322,12 +16517,12 @@ async function main(argv = process.argv.slice(2)) {
16322
16517
  });
16323
16518
  } else if (subAction === "validate") {
16324
16519
  const treeDir = outputDir;
16325
- if (!fs17.existsSync(treeDir)) {
16520
+ if (!fs19.existsSync(treeDir)) {
16326
16521
  console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
16327
16522
  process.exit(1);
16328
16523
  }
16329
16524
  const indexPath = path18.join(treeDir, "INDEX.md");
16330
- if (!fs17.existsSync(indexPath)) {
16525
+ if (!fs19.existsSync(indexPath)) {
16331
16526
  console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
16332
16527
  process.exit(1);
16333
16528
  }
@@ -16449,7 +16644,11 @@ Options:
16449
16644
  break;
16450
16645
  }
16451
16646
  case "procedural": {
16452
- await cmdProcedural(rest);
16647
+ await runProceduralBinaryCommand(rest);
16648
+ break;
16649
+ }
16650
+ case "drift": {
16651
+ await runDriftBinaryCommand(rest);
16453
16652
  break;
16454
16653
  }
16455
16654
  case "extensions": {
@@ -16509,10 +16708,10 @@ Other:
16509
16708
  let wearablesService;
16510
16709
  try {
16511
16710
  const configPath = resolveConfigPath();
16512
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
16513
- const remnicCfg = resolveRemnicConfigRecord7(raw);
16514
- const config = parseConfig8(remnicCfg);
16515
- wearablesOrchestrator = new Orchestrator5(config);
16711
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
16712
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
16713
+ const config = parseConfig10(remnicCfg);
16714
+ wearablesOrchestrator = new Orchestrator6(config);
16516
16715
  await wearablesOrchestrator.initialize();
16517
16716
  await wearablesOrchestrator.deferredReady;
16518
16717
  wearablesService = wearablesOrchestrator.getWearablesService();
@@ -16567,10 +16766,10 @@ Other:
16567
16766
  const targetFactory = async () => {
16568
16767
  if (!orchestratorSingleton) {
16569
16768
  const configPath = resolveConfigPath();
16570
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
16571
- const remnicCfg = resolveRemnicConfigRecord7(raw);
16572
- const config = parseConfig8(remnicCfg);
16573
- orchestratorSingleton = new Orchestrator5(config);
16769
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
16770
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
16771
+ const config = parseConfig10(remnicCfg);
16772
+ orchestratorSingleton = new Orchestrator6(config);
16574
16773
  await orchestratorSingleton.initialize();
16575
16774
  await orchestratorSingleton.deferredReady;
16576
16775
  }
@@ -16821,6 +17020,17 @@ Usage:
16821
17020
  Print procedural memory stats (counts + recency + config). Mirrors
16822
17021
  GET /engram/v1/procedural/stats and remnic.procedural_stats MCP tool
16823
17022
  (issue #567).
17023
+ remnic procedural maintain [--apply] [--format json|text] [--memory-dir <path>]
17024
+ Run procedure library-health maintenance (issue #2370): shadow report of
17025
+ merge / repair-flag / retire proposals from outcome telemetry; --apply
17026
+ executes them (requires procedural.maintenance.enabled). Mirrors the
17027
+ remnic.procedure_library_maintenance MCP tool.
17028
+ remnic drift scan [--apply] [--namespace <ns>] [--format json|text] [--memory-dir <path>]
17029
+ Run preference drift detection (issue #2371): classify aging preference
17030
+ memories as corroborated / stale / drifted from recent evidence; --apply
17031
+ stamps lastCorroborated / driftState and opens a review item per drifted
17032
+ preference (requires driftDetection.enabled). Mirrors the
17033
+ remnic.preference_drift_scan MCP tool.
16824
17034
  remnic training:export --format <name> --output <path> [options]
16825
17035
  Export memories as a fine-tuning dataset (issue #459). Run
16826
17036
  'remnic training:export --help' for the full option list.