@remnic/cli 9.65.2 → 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 +428 -288
  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 fs18 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 parseConfig9,
30
+ parseConfig as parseConfig10,
31
31
  isOpenaiApiKeyDisabled,
32
32
  resolveEnvVars,
33
- resolveRemnicConfigRecord as resolveRemnicConfigRecord8,
34
- Orchestrator as Orchestrator5,
33
+ resolveRemnicConfigRecord as resolveRemnicConfigRecord9,
34
+ Orchestrator as Orchestrator6,
35
35
  EngramAccessService as EngramAccessService2,
36
- initLogger as initLogger4,
36
+ initLogger as initLogger5,
37
37
  onboard,
38
38
  curate,
39
39
  listReviewItems,
@@ -452,6 +452,136 @@ function formatProcedureMaintenanceText(report) {
452
452
  return lines.join("\n") + "\n";
453
453
  }
454
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
+
455
585
  // src/optional-module-loader.ts
456
586
  function isSpecifierNotFoundError(err, specifier) {
457
587
  if (!err || typeof err !== "object") {
@@ -502,13 +632,13 @@ async function loadWecloneExportModule() {
502
632
  }
503
633
 
504
634
  // src/converge.ts
505
- import * as fs6 from "fs";
635
+ import * as fs7 from "fs";
506
636
  import { createHash as createHash3 } from "crypto";
507
637
  import * as path2 from "path";
508
638
  import {
509
639
  CONVERGE_CONFLICT_POLICIES,
510
640
  DEFAULT_CONVERGE_CONFLICT_POLICY,
511
- parseConfig as parseConfig5,
641
+ parseConfig as parseConfig6,
512
642
  buildOfflineSyncSnapshotFromBase,
513
643
  applyOfflineSyncFileContentChunk,
514
644
  isInternalRemnicStatePath as isInternalRemnicStatePath3,
@@ -534,7 +664,7 @@ import {
534
664
 
535
665
  // src/offline-storage-io.ts
536
666
  import { createDecipheriv, createHash } from "crypto";
537
- import fs5 from "fs";
667
+ import fs6 from "fs";
538
668
  import { lstat, mkdtemp, readdir, rm } from "fs/promises";
539
669
  import path from "path";
540
670
  import {
@@ -696,7 +826,7 @@ async function* readOfflineSyncFileChunks(options) {
696
826
  });
697
827
  }
698
828
  async function readFilePrefix(filePath, length) {
699
- const handle = await fs5.promises.open(filePath, "r");
829
+ const handle = await fs6.promises.open(filePath, "r");
700
830
  try {
701
831
  const out = Buffer.alloc(length);
702
832
  const { bytesRead } = await handle.read(out, 0, length, 0);
@@ -706,7 +836,7 @@ async function readFilePrefix(filePath, length) {
706
836
  }
707
837
  }
708
838
  async function* readPlainOfflineFileChunks(filePath, chunkSize) {
709
- const stream = fs5.createReadStream(filePath, { highWaterMark: chunkSize });
839
+ const stream = fs6.createReadStream(filePath, { highWaterMark: chunkSize });
710
840
  for await (const chunk of stream) {
711
841
  yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
712
842
  }
@@ -743,9 +873,9 @@ async function* readEncryptedOfflineFileChunks(options) {
743
873
  });
744
874
  decipher.setAuthTag(authTag);
745
875
  decipher.setAAD(Buffer.concat([secureStoreEnvelopeHeaderAad(salt), aad]));
746
- const output = fs5.createWriteStream(tempPath, { mode: 384 });
876
+ const output = fs6.createWriteStream(tempPath, { mode: 384 });
747
877
  try {
748
- const stream = fs5.createReadStream(options.filePath, {
878
+ const stream = fs6.createReadStream(options.filePath, {
749
879
  start: MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE,
750
880
  highWaterMark: options.chunkSize
751
881
  });
@@ -1355,7 +1485,7 @@ async function readLocalTombstoneEvidence(rootDir) {
1355
1485
  for (const relativePath of TOMBSTONE_PATHS) {
1356
1486
  let content;
1357
1487
  try {
1358
- content = await fs6.promises.readFile(path2.join(rootDir, relativePath), "utf-8");
1488
+ content = await fs7.promises.readFile(path2.join(rootDir, relativePath), "utf-8");
1359
1489
  } catch (error) {
1360
1490
  if (error.code === "ENOENT") continue;
1361
1491
  throw error;
@@ -1370,7 +1500,7 @@ async function discoverCursorNamespaces(memoryDir, peerUrl) {
1370
1500
  const cursorDir = path2.join(path2.resolve(memoryDir), ".remnic", "state", "converge-cursors");
1371
1501
  let entries;
1372
1502
  try {
1373
- entries = await fs6.promises.readdir(cursorDir, { withFileTypes: true });
1503
+ entries = await fs7.promises.readdir(cursorDir, { withFileTypes: true });
1374
1504
  } catch (error) {
1375
1505
  if (error.code === "ENOENT") return [];
1376
1506
  throw error;
@@ -1446,7 +1576,7 @@ async function computeConvergePlan(options = {}) {
1446
1576
  let config = options.config;
1447
1577
  if (!config) {
1448
1578
  try {
1449
- config = parseConfig5({});
1579
+ config = parseConfig6({});
1450
1580
  } catch {
1451
1581
  }
1452
1582
  }
@@ -1697,7 +1827,7 @@ async function executeConvergeApply(options = {}) {
1697
1827
  let config = options.config;
1698
1828
  if (!config) {
1699
1829
  try {
1700
- config = parseConfig5({});
1830
+ config = parseConfig6({});
1701
1831
  } catch {
1702
1832
  }
1703
1833
  }
@@ -1860,7 +1990,7 @@ async function executeConvergeApply(options = {}) {
1860
1990
  if (current.sha256 !== entry.localSha256) {
1861
1991
  throw new Error(`local file changed during push: ${localPath}`);
1862
1992
  }
1863
- const stat2 = await fs6.promises.stat(filePath);
1993
+ const stat2 = await fs7.promises.stat(filePath);
1864
1994
  let chunks;
1865
1995
  let chunkOffset = 0;
1866
1996
  const resetChunks = async () => {
@@ -2137,7 +2267,7 @@ function formatConvergeApplyReport(result) {
2137
2267
  lines.push(formatConvergeReport(result.plan));
2138
2268
  return lines.join("\n");
2139
2269
  }
2140
- async function cmdConverge(action, rest, json, config = parseConfig5({})) {
2270
+ async function cmdConverge(action, rest, json, config = parseConfig6({})) {
2141
2271
  if (action === "help" || action === "--help" || action === "-h" || rest.includes("--help") || rest.includes("-h")) {
2142
2272
  console.log(`Usage: remnic converge <plan|apply> [options]
2143
2273
 
@@ -2343,8 +2473,8 @@ function renderReplayResult(result, targetNamespace, format) {
2343
2473
  }
2344
2474
 
2345
2475
  // src/quarantine-replay.ts
2346
- import * as fs7 from "fs";
2347
- import { EngramAccessService, Orchestrator as Orchestrator3, initLogger as initLogger2, parseConfig as parseConfig6, resolveRemnicConfigRecord as resolveRemnicConfigRecord5 } 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";
2348
2478
  import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
2349
2479
  function valueFlag(args, flag) {
2350
2480
  const occurrences = args.filter((a) => a === flag).length;
@@ -2388,13 +2518,13 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
2388
2518
  process.exitCode = 2;
2389
2519
  return;
2390
2520
  }
2391
- initLogger2();
2521
+ initLogger3();
2392
2522
  let orchestrator;
2393
2523
  try {
2394
2524
  const configPath = resolveConfigPath2();
2395
- const raw = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
2396
- const config = parseConfig6(resolveRemnicConfigRecord5(raw));
2397
- 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);
2398
2528
  await orchestrator.initialize();
2399
2529
  await orchestrator.deferredReady;
2400
2530
  const service = new EngramAccessService(orchestrator);
@@ -2424,15 +2554,15 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
2424
2554
  }
2425
2555
 
2426
2556
  // src/offline-impression-rotation.ts
2427
- import fs8 from "fs";
2428
- import { parseConfig as parseConfig7, resolveRemnicConfigRecord as resolveRemnicConfigRecord6, drainPendingImpressionsForOfflineSync } from "@remnic/core";
2557
+ import fs9 from "fs";
2558
+ import { parseConfig as parseConfig8, resolveRemnicConfigRecord as resolveRemnicConfigRecord7, drainPendingImpressionsForOfflineSync } from "@remnic/core";
2429
2559
  import { LastRecallStore } from "@remnic/core/recall-state";
2430
2560
  function parseConfigQuietly(raw) {
2431
2561
  const originalWarn = console.warn;
2432
2562
  console.warn = () => {
2433
2563
  };
2434
2564
  try {
2435
- return parseConfig7(resolveRemnicConfigRecord6(raw));
2565
+ return parseConfig8(resolveRemnicConfigRecord7(raw));
2436
2566
  } finally {
2437
2567
  console.warn = originalWarn;
2438
2568
  }
@@ -2446,7 +2576,7 @@ var OFFLINE_CONFIG_KEYS = [
2446
2576
  function pickOfflineConfigRecord(raw) {
2447
2577
  let resolved;
2448
2578
  try {
2449
- resolved = resolveRemnicConfigRecord6(raw);
2579
+ resolved = resolveRemnicConfigRecord7(raw);
2450
2580
  } catch {
2451
2581
  resolved = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
2452
2582
  }
@@ -2459,7 +2589,7 @@ function pickOfflineConfigRecord(raw) {
2459
2589
  function resolveOfflineImpressionRotation(configPath) {
2460
2590
  let raw;
2461
2591
  try {
2462
- raw = fs8.existsSync(configPath) ? JSON.parse(fs8.readFileSync(configPath, "utf8")) : {};
2592
+ raw = fs9.existsSync(configPath) ? JSON.parse(fs9.readFileSync(configPath, "utf8")) : {};
2463
2593
  } catch {
2464
2594
  throw new Error(
2465
2595
  `cannot read recall-impression rotation from ${configPath}: config file could not be read as JSON`
@@ -2717,12 +2847,12 @@ function assertBenchModuleFreshForDevelopment() {
2717
2847
  }
2718
2848
 
2719
2849
  // src/cmd-security.ts
2720
- import fs9 from "fs";
2850
+ import fs10 from "fs";
2721
2851
  import {
2722
- Orchestrator as Orchestrator4,
2723
- parseConfig as parseConfig8,
2724
- initLogger as initLogger3,
2725
- resolveRemnicConfigRecord as resolveRemnicConfigRecord7,
2852
+ Orchestrator as Orchestrator5,
2853
+ parseConfig as parseConfig9,
2854
+ initLogger as initLogger4,
2855
+ resolveRemnicConfigRecord as resolveRemnicConfigRecord8,
2726
2856
  runAuditMemoryCliCommand,
2727
2857
  formatAuditMemoryReport
2728
2858
  } from "@remnic/core";
@@ -2735,11 +2865,11 @@ async function cmdSecurity(rest) {
2735
2865
  process.exitCode = 1;
2736
2866
  return;
2737
2867
  }
2738
- initLogger3();
2868
+ initLogger4();
2739
2869
  const configPath = resolveConfigPath();
2740
- const raw = fs9.existsSync(configPath) ? JSON.parse(fs9.readFileSync(configPath, "utf8")) : {};
2741
- const config = parseConfig8(resolveRemnicConfigRecord7(raw));
2742
- 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);
2743
2873
  await orchestrator.initialize();
2744
2874
  try {
2745
2875
  const sinceFlag = rest.indexOf("--since");
@@ -2762,7 +2892,7 @@ async function cmdSecurity(rest) {
2762
2892
  }
2763
2893
 
2764
2894
  // src/daemon-service-candidates.ts
2765
- import fs10 from "fs";
2895
+ import fs11 from "fs";
2766
2896
  import path5 from "path";
2767
2897
  var LAUNCHD_LABEL = "ai.remnic.daemon";
2768
2898
  var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
@@ -2784,7 +2914,7 @@ function systemdUnitPaths(homeDir) {
2784
2914
  function anyFileExists(paths) {
2785
2915
  return paths.some((candidate) => {
2786
2916
  try {
2787
- return fs10.statSync(candidate).isFile();
2917
+ return fs11.statSync(candidate).isFile();
2788
2918
  } catch {
2789
2919
  return false;
2790
2920
  }
@@ -2796,7 +2926,7 @@ function commandNames(command) {
2796
2926
  }
2797
2927
  function isRunnableNodeScript(filePath) {
2798
2928
  try {
2799
- const text = fs10.readFileSync(filePath, "utf8").slice(0, 4096);
2929
+ const text = fs11.readFileSync(filePath, "utf8").slice(0, 4096);
2800
2930
  const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
2801
2931
  if (/^#!.*\bnode\b/.test(firstLine)) return true;
2802
2932
  if (firstLine.startsWith("#!")) return false;
@@ -2809,7 +2939,7 @@ function isRunnableNodeScript(filePath) {
2809
2939
  function resolveShimNodeScript(filePath) {
2810
2940
  let text;
2811
2941
  try {
2812
- text = fs10.readFileSync(filePath, "utf8").slice(0, 16384);
2942
+ text = fs11.readFileSync(filePath, "utf8").slice(0, 16384);
2813
2943
  } catch {
2814
2944
  return void 0;
2815
2945
  }
@@ -2821,8 +2951,8 @@ function resolveShimNodeScript(filePath) {
2821
2951
  const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
2822
2952
  const resolved = path5.isAbsolute(candidate) ? candidate : path5.resolve(basedir, candidate);
2823
2953
  try {
2824
- if (fs10.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
2825
- return fs10.realpathSync(resolved);
2954
+ if (fs11.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
2955
+ return fs11.realpathSync(resolved);
2826
2956
  }
2827
2957
  } catch {
2828
2958
  }
@@ -2830,7 +2960,7 @@ function resolveShimNodeScript(filePath) {
2830
2960
  return void 0;
2831
2961
  }
2832
2962
  function resolveRunnableNodeScript(filePath) {
2833
- const realPath = fs10.realpathSync(filePath);
2963
+ const realPath = fs11.realpathSync(filePath);
2834
2964
  if (isRunnableNodeScript(realPath)) return realPath;
2835
2965
  return resolveShimNodeScript(realPath);
2836
2966
  }
@@ -2840,9 +2970,9 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
2840
2970
  for (const name of commandNames(command)) {
2841
2971
  const candidate = path5.join(dir, name);
2842
2972
  try {
2843
- const stat2 = fs10.statSync(candidate);
2973
+ const stat2 = fs11.statSync(candidate);
2844
2974
  if (!stat2.isFile()) continue;
2845
- if (process.platform !== "win32") fs10.accessSync(candidate, fs10.constants.X_OK);
2975
+ if (process.platform !== "win32") fs11.accessSync(candidate, fs11.constants.X_OK);
2846
2976
  const runnable = resolveRunnableNodeScript(candidate);
2847
2977
  if (runnable) return runnable;
2848
2978
  } catch {
@@ -4315,7 +4445,7 @@ function finalizeBenchStatus(filePath) {
4315
4445
  }
4316
4446
 
4317
4447
  // src/bench-fallback.ts
4318
- import fs11 from "fs";
4448
+ import fs12 from "fs";
4319
4449
  import path9 from "path";
4320
4450
  var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
4321
4451
  function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
@@ -4387,7 +4517,7 @@ function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs
4387
4517
  );
4388
4518
  }
4389
4519
  function resolveFallbackBenchResultPath(outputDir) {
4390
- const entries = fs11.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();
4391
4521
  if (entries.length === 0) {
4392
4522
  throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
4393
4523
  }
@@ -4395,7 +4525,7 @@ function resolveFallbackBenchResultPath(outputDir) {
4395
4525
  }
4396
4526
 
4397
4527
  // src/openclaw-upgrade-swap.ts
4398
- import fs12 from "fs";
4528
+ import fs13 from "fs";
4399
4529
  import path10 from "path";
4400
4530
  function describeError(error) {
4401
4531
  return error instanceof Error ? error.message : String(error);
@@ -4407,7 +4537,7 @@ function createSiblingTempFilePath(targetPath, label) {
4407
4537
  function resolveAtomicWriteMode(targetPath, explicitMode) {
4408
4538
  if (explicitMode !== void 0) return explicitMode;
4409
4539
  try {
4410
- return fs12.statSync(targetPath).mode & 4095;
4540
+ return fs13.statSync(targetPath).mode & 4095;
4411
4541
  } catch (error) {
4412
4542
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
4413
4543
  return 384;
@@ -4417,8 +4547,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
4417
4547
  }
4418
4548
  function resolveAtomicReplacementPath(targetPath) {
4419
4549
  try {
4420
- if (fs12.lstatSync(targetPath).isSymbolicLink()) {
4421
- return fs12.realpathSync(targetPath);
4550
+ if (fs13.lstatSync(targetPath).isSymbolicLink()) {
4551
+ return fs13.realpathSync(targetPath);
4422
4552
  }
4423
4553
  } catch (error) {
4424
4554
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -4435,7 +4565,7 @@ function createSiblingSwapPath(targetDir, label) {
4435
4565
  function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
4436
4566
  if (!displacedDir) return void 0;
4437
4567
  try {
4438
- fs12.rmSync(displacedDir, { recursive: true, force: true });
4568
+ fs13.rmSync(displacedDir, { recursive: true, force: true });
4439
4569
  return void 0;
4440
4570
  } catch (error) {
4441
4571
  return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
@@ -4443,43 +4573,43 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
4443
4573
  }
4444
4574
  function atomicWriteFileSync(targetPath, data, options = {}) {
4445
4575
  const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
4446
- fs12.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4576
+ fs13.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4447
4577
  const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
4448
4578
  const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
4449
4579
  try {
4450
4580
  if (options.hooks?.writeTempFileSync) {
4451
4581
  options.hooks.writeTempFileSync(tempPath);
4452
4582
  } else {
4453
- fs12.writeFileSync(tempPath, data, { mode });
4583
+ fs13.writeFileSync(tempPath, data, { mode });
4454
4584
  }
4455
- fs12.chmodSync(tempPath, mode);
4456
- const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs12.renameSync;
4585
+ fs13.chmodSync(tempPath, mode);
4586
+ const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs13.renameSync;
4457
4587
  renameTempFileSync(tempPath, resolvedTargetPath);
4458
4588
  } catch (error) {
4459
- fs12.rmSync(tempPath, { force: true });
4589
+ fs13.rmSync(tempPath, { force: true });
4460
4590
  throw error;
4461
4591
  }
4462
4592
  }
4463
4593
  function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
4464
- if (!fs12.existsSync(sourcePath)) return;
4594
+ if (!fs13.existsSync(sourcePath)) return;
4465
4595
  const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
4466
- fs12.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4596
+ fs13.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4467
4597
  const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
4468
- const mode = fs12.statSync(sourcePath).mode & 4095;
4598
+ const mode = fs13.statSync(sourcePath).mode & 4095;
4469
4599
  try {
4470
- const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs12.copyFileSync;
4600
+ const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs13.copyFileSync;
4471
4601
  copyTempFileSync(sourcePath, tempPath);
4472
- fs12.chmodSync(tempPath, mode);
4473
- const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs12.renameSync;
4602
+ fs13.chmodSync(tempPath, mode);
4603
+ const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs13.renameSync;
4474
4604
  renameTempFileSync(tempPath, resolvedTargetPath);
4475
4605
  } catch (error) {
4476
- fs12.rmSync(tempPath, { force: true });
4606
+ fs13.rmSync(tempPath, { force: true });
4477
4607
  throw error;
4478
4608
  }
4479
4609
  }
4480
4610
  function cleanupRollbackDirectory(rollbackDir) {
4481
4611
  if (!rollbackDir) return;
4482
- fs12.rmSync(rollbackDir, { recursive: true, force: true });
4612
+ fs13.rmSync(rollbackDir, { recursive: true, force: true });
4483
4613
  }
4484
4614
  function cleanupRollbackDirectoryBestEffort(rollbackDir) {
4485
4615
  if (!rollbackDir) return void 0;
@@ -4491,20 +4621,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
4491
4621
  }
4492
4622
  }
4493
4623
  function restoreDirectoryFromRollback(targetDir, rollbackDir) {
4494
- if (!fs12.existsSync(rollbackDir)) {
4624
+ if (!fs13.existsSync(rollbackDir)) {
4495
4625
  throw new Error(`Rollback directory is missing: ${rollbackDir}`);
4496
4626
  }
4497
- fs12.mkdirSync(path10.dirname(targetDir), { recursive: true });
4498
- const displacedDir = fs12.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;
4499
4629
  if (displacedDir) {
4500
- fs12.renameSync(targetDir, displacedDir);
4630
+ fs13.renameSync(targetDir, displacedDir);
4501
4631
  }
4502
4632
  try {
4503
- fs12.renameSync(rollbackDir, targetDir);
4633
+ fs13.renameSync(rollbackDir, targetDir);
4504
4634
  } catch (restoreError) {
4505
- if (displacedDir && fs12.existsSync(displacedDir)) {
4635
+ if (displacedDir && fs13.existsSync(displacedDir)) {
4506
4636
  try {
4507
- fs12.renameSync(displacedDir, targetDir);
4637
+ fs13.renameSync(displacedDir, targetDir);
4508
4638
  } catch (revertError) {
4509
4639
  throw new AggregateError(
4510
4640
  [restoreError, revertError],
@@ -4520,23 +4650,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
4520
4650
  return cleanupDisplacedDirectoryBestEffort(displacedDir, `restored the previous plugin copy into ${targetDir}`);
4521
4651
  }
4522
4652
  function restoreDirectoryFromBackup(targetDir, backupDir) {
4523
- if (!fs12.existsSync(backupDir)) {
4653
+ if (!fs13.existsSync(backupDir)) {
4524
4654
  throw new Error(`Plugin backup directory is missing: ${backupDir}`);
4525
4655
  }
4526
- fs12.mkdirSync(path10.dirname(targetDir), { recursive: true });
4656
+ fs13.mkdirSync(path10.dirname(targetDir), { recursive: true });
4527
4657
  const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
4528
- const displacedDir = fs12.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
4529
- fs12.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 });
4530
4660
  if (displacedDir) {
4531
- fs12.renameSync(targetDir, displacedDir);
4661
+ fs13.renameSync(targetDir, displacedDir);
4532
4662
  }
4533
4663
  try {
4534
- fs12.renameSync(stagedDir, targetDir);
4664
+ fs13.renameSync(stagedDir, targetDir);
4535
4665
  } catch (restoreError) {
4536
- fs12.rmSync(targetDir, { recursive: true, force: true });
4537
- if (displacedDir && fs12.existsSync(displacedDir)) {
4666
+ fs13.rmSync(targetDir, { recursive: true, force: true });
4667
+ if (displacedDir && fs13.existsSync(displacedDir)) {
4538
4668
  try {
4539
- fs12.renameSync(displacedDir, targetDir);
4669
+ fs13.renameSync(displacedDir, targetDir);
4540
4670
  } catch (revertError) {
4541
4671
  throw new AggregateError(
4542
4672
  [restoreError, revertError],
@@ -4544,7 +4674,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
4544
4674
  );
4545
4675
  }
4546
4676
  }
4547
- fs12.rmSync(stagedDir, { recursive: true, force: true });
4677
+ fs13.rmSync(stagedDir, { recursive: true, force: true });
4548
4678
  throw new Error(
4549
4679
  `Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
4550
4680
  { cause: restoreError }
@@ -4569,7 +4699,7 @@ function rollbackOpenclawUpgrade({
4569
4699
  let configRemovalAttempted = false;
4570
4700
  let pluginRestored = false;
4571
4701
  try {
4572
- if (rollbackDir && fs12.existsSync(rollbackDir)) {
4702
+ if (rollbackDir && fs13.existsSync(rollbackDir)) {
4573
4703
  const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
4574
4704
  notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
4575
4705
  if (cleanupWarning) notes.push(cleanupWarning);
@@ -4579,7 +4709,7 @@ function rollbackOpenclawUpgrade({
4579
4709
  rollbackRestoreError = error instanceof Error ? error.message : String(error);
4580
4710
  }
4581
4711
  try {
4582
- if (!pluginRestored && pluginBackupDir && fs12.existsSync(pluginBackupDir)) {
4712
+ if (!pluginRestored && pluginBackupDir && fs13.existsSync(pluginBackupDir)) {
4583
4713
  const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
4584
4714
  if (rollbackRestoreError) {
4585
4715
  notes.push(`Rollback copy restore failed; restored previous plugin from durable backup at ${pluginBackupDir}`);
@@ -4604,12 +4734,12 @@ function rollbackOpenclawUpgrade({
4604
4734
  notes.push("No previous plugin copy was available for automatic restore");
4605
4735
  }
4606
4736
  try {
4607
- if (configBackupPath && fs12.existsSync(configBackupPath)) {
4737
+ if (configBackupPath && fs13.existsSync(configBackupPath)) {
4608
4738
  restoreFileFromBackup(configPath, configBackupPath);
4609
4739
  notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
4610
- } else if (removeConfigIfUnbacked && fs12.existsSync(configPath)) {
4740
+ } else if (removeConfigIfUnbacked && fs13.existsSync(configPath)) {
4611
4741
  configRemovalAttempted = true;
4612
- fs12.rmSync(configPath, { force: true });
4742
+ fs13.rmSync(configPath, { force: true });
4613
4743
  notes.push("Removed OpenClaw config created during the failed upgrade");
4614
4744
  }
4615
4745
  } catch (error) {
@@ -4662,7 +4792,7 @@ Run this manually when you're ready:
4662
4792
 
4663
4793
  // src/openclaw-managed-upgrade-loader.ts
4664
4794
  import { execFileSync } from "child_process";
4665
- import fs13 from "fs";
4795
+ import fs14 from "fs";
4666
4796
  import os from "os";
4667
4797
  import path11 from "path";
4668
4798
  import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
@@ -4738,7 +4868,7 @@ function buildOpenclawManagedUpgradePackageSpec(version = "latest") {
4738
4868
  function readCliAdapterRange() {
4739
4869
  const moduleDir = path11.dirname(fileURLToPath3(import.meta.url));
4740
4870
  const manifestPath = path11.resolve(moduleDir, "../package.json");
4741
- const manifest = JSON.parse(fs13.readFileSync(manifestPath, "utf8"));
4871
+ const manifest = JSON.parse(fs14.readFileSync(manifestPath, "utf8"));
4742
4872
  if (manifest.name !== "@remnic/cli") {
4743
4873
  throw new Error(`Invalid @remnic/cli package manifest at ${manifestPath}.`);
4744
4874
  }
@@ -4782,7 +4912,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
4782
4912
  const adapterMissing = isSpecifierNotFoundError(error, OPENCLAW_PLUGIN_PACKAGE) || isSpecifierNotFoundError(error, MANAGED_UPGRADE_SPECIFIER) || isManagedUpgradeSubpathMissing(error);
4783
4913
  if (!adapterMissing) throw error;
4784
4914
  }
4785
- const temporaryRoot = fs13.mkdtempSync(path11.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
4915
+ const temporaryRoot = fs14.mkdtempSync(path11.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
4786
4916
  try {
4787
4917
  const toolingPackageSpec = `${OPENCLAW_PLUGIN_PACKAGE}@${readCliAdapterRange()}`;
4788
4918
  const installArgs = [
@@ -4797,12 +4927,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
4797
4927
  ];
4798
4928
  (hooks.runNpmInstall ?? runNpmInstall)(installArgs);
4799
4929
  const resolverPath = path11.join(temporaryRoot, "load-managed-upgrade.mjs");
4800
- fs13.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
4930
+ fs14.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
4801
4931
  `, "utf8");
4802
4932
  return await importModule(pathToFileURL2(resolverPath).href);
4803
4933
  } finally {
4804
4934
  try {
4805
- fs13.rmSync(temporaryRoot, { recursive: true, force: true });
4935
+ fs14.rmSync(temporaryRoot, { recursive: true, force: true });
4806
4936
  } catch (error) {
4807
4937
  const detail = error instanceof Error ? error.message : String(error);
4808
4938
  console.warn(`Could not remove temporary managed upgrade project at ${temporaryRoot}: ${detail}`);
@@ -4811,13 +4941,13 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
4811
4941
  }
4812
4942
 
4813
4943
  // src/remote-daemon.ts
4814
- import fs14 from "fs";
4944
+ import fs15 from "fs";
4815
4945
  function readCompatEnv(primary, legacy) {
4816
4946
  return process.env[primary] ?? process.env[legacy];
4817
4947
  }
4818
4948
  function readRemnicConfigRecord(configPath) {
4819
4949
  try {
4820
- const parsed = JSON.parse(fs14.readFileSync(configPath, "utf8"));
4950
+ const parsed = JSON.parse(fs15.readFileSync(configPath, "utf8"));
4821
4951
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
4822
4952
  return parsed;
4823
4953
  }
@@ -5046,7 +5176,7 @@ async function remoteRecallXray(daemon, request) {
5046
5176
  }
5047
5177
 
5048
5178
  // src/daemon-service.ts
5049
- import fs15 from "fs";
5179
+ import fs16 from "fs";
5050
5180
  import path12 from "path";
5051
5181
  import * as childProcess from "child_process";
5052
5182
  import { fileURLToPath as fileURLToPath4 } from "url";
@@ -5058,7 +5188,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
5058
5188
  processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
5059
5189
  }
5060
5190
  function resolveServerBinDetails(options = {}) {
5061
- const existsSync4 = options.existsSync ?? fs15.existsSync;
5191
+ const existsSync4 = options.existsSync ?? fs16.existsSync;
5062
5192
  const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
5063
5193
  const moduleDir = options.moduleDir ?? thisModuleDir;
5064
5194
  const packageResolve = options.packageResolve ?? resolveImportSpecifier;
@@ -5117,8 +5247,8 @@ function resolveServerBin(options = {}) {
5117
5247
  return resolveServerBinDetails(options).path;
5118
5248
  }
5119
5249
  function readVerifiedDaemonPid(options) {
5120
- const readFileSync4 = options.readFileSync ?? fs15.readFileSync;
5121
- const unlinkSync = options.unlinkSync ?? fs15.unlinkSync;
5250
+ const readFileSync4 = options.readFileSync ?? fs16.readFileSync;
5251
+ const unlinkSync = options.unlinkSync ?? fs16.unlinkSync;
5122
5252
  const processKill = options.processKill ?? process.kill;
5123
5253
  const platform = options.platform ?? process.platform;
5124
5254
  const execFileSync4 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
@@ -5218,8 +5348,8 @@ function removePidFileBestEffort(file, unlinkSync) {
5218
5348
  }
5219
5349
  }
5220
5350
  function inspectLaunchdPlist(plistPath, options = {}) {
5221
- const existsSync4 = options.existsSync ?? fs15.existsSync;
5222
- const readFileSync4 = options.readFileSync ?? fs15.readFileSync;
5351
+ const existsSync4 = options.existsSync ?? fs16.existsSync;
5352
+ const readFileSync4 = options.readFileSync ?? fs16.readFileSync;
5223
5353
  if (!existsSync4(plistPath)) {
5224
5354
  return {
5225
5355
  installed: false,
@@ -5397,7 +5527,7 @@ function stripConfigArgv(args) {
5397
5527
  }
5398
5528
 
5399
5529
  // src/import-dispatch.ts
5400
- import fs16 from "fs";
5530
+ import fs17 from "fs";
5401
5531
  import {
5402
5532
  runImporter,
5403
5533
  validateImportBatchSize,
@@ -5911,7 +6041,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
5911
6041
  let materializedTarget;
5912
6042
  let materializePromise;
5913
6043
  const io = {
5914
- readFile: ioOverrides.readFile ?? (async (p) => fs16.promises.readFile(p, "utf-8")),
6044
+ readFile: ioOverrides.readFile ?? (async (p) => fs17.promises.readFile(p, "utf-8")),
5915
6045
  loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
5916
6046
  runImporter: ioOverrides.runImporter ?? runImporter,
5917
6047
  getWriteTarget: async () => {
@@ -6024,7 +6154,7 @@ async function cmdCapture(rest, io) {
6024
6154
  }
6025
6155
 
6026
6156
  // src/import-lossless-claw-cmd.ts
6027
- import fs17 from "fs";
6157
+ import fs18 from "fs";
6028
6158
  import path14 from "path";
6029
6159
  import {
6030
6160
  applyLcmSchema,
@@ -6136,15 +6266,15 @@ async function loadImportLosslessClawModule() {
6136
6266
 
6137
6267
  // src/import-lossless-claw-cmd.ts
6138
6268
  function assertDirectoryOrAbsent(p, label) {
6139
- if (fs17.existsSync(p) && !fs17.statSync(p).isDirectory()) {
6269
+ if (fs18.existsSync(p) && !fs18.statSync(p).isDirectory()) {
6140
6270
  throw new Error(`${label} is not a directory: ${p}`);
6141
6271
  }
6142
6272
  }
6143
6273
  function assertFile(p, label) {
6144
- if (!fs17.existsSync(p)) {
6274
+ if (!fs18.existsSync(p)) {
6145
6275
  throw new Error(`${label} does not exist: ${p}`);
6146
6276
  }
6147
- if (!fs17.statSync(p).isFile()) {
6277
+ if (!fs18.statSync(p).isFile()) {
6148
6278
  throw new Error(`${label} is not a file: ${p}`);
6149
6279
  }
6150
6280
  }
@@ -6176,7 +6306,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
6176
6306
  try {
6177
6307
  if (parsed.dryRun) {
6178
6308
  const lcmPath = path14.join(memoryDir, "state", "lcm.sqlite");
6179
- if (fs17.existsSync(lcmPath)) {
6309
+ if (fs18.existsSync(lcmPath)) {
6180
6310
  destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
6181
6311
  } else {
6182
6312
  destDb = mod.openInMemoryDestinationDatabase();
@@ -7528,7 +7658,7 @@ async function resolveAllBenchmarks() {
7528
7658
  if (packageBenchmarks) {
7529
7659
  return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
7530
7660
  }
7531
- if (!fs18.existsSync(EVAL_RUNNER_PATH)) {
7661
+ if (!fs19.existsSync(EVAL_RUNNER_PATH)) {
7532
7662
  return [];
7533
7663
  }
7534
7664
  return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
@@ -7576,7 +7706,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
7576
7706
  `Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
7577
7707
  );
7578
7708
  }
7579
- if (!fs18.existsSync(EVAL_RUNNER_PATH)) {
7709
+ if (!fs19.existsSync(EVAL_RUNNER_PATH)) {
7580
7710
  console.error(
7581
7711
  "Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
7582
7712
  );
@@ -7586,7 +7716,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
7586
7716
  path18.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
7587
7717
  path18.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
7588
7718
  ];
7589
- const tsxCmd = tsxCandidates.find((candidate) => fs18.existsSync(candidate)) ?? "tsx";
7719
+ const tsxCmd = tsxCandidates.find((candidate) => fs19.existsSync(candidate)) ?? "tsx";
7590
7720
  const fallbackOutputDir = createFallbackBenchOutputDir(
7591
7721
  parsed.resultsDir ?? resolveBenchOutputDir(),
7592
7722
  benchmarkId,
@@ -7731,9 +7861,9 @@ var PERSONAMEM_COMPLETION_MARKER = path18.join(
7731
7861
  );
7732
7862
  function resolveRealpathWithinDataset(datasetPath, relativePath) {
7733
7863
  try {
7734
- const datasetRoot = fs18.realpathSync(datasetPath);
7864
+ const datasetRoot = fs19.realpathSync(datasetPath);
7735
7865
  const candidatePath = path18.resolve(datasetRoot, relativePath);
7736
- const candidateRealPath = fs18.realpathSync(candidatePath);
7866
+ const candidateRealPath = fs19.realpathSync(candidatePath);
7737
7867
  const relativeToRoot = path18.relative(datasetRoot, candidateRealPath);
7738
7868
  if (relativeToRoot.startsWith("..") || path18.isAbsolute(relativeToRoot)) {
7739
7869
  return null;
@@ -7792,14 +7922,14 @@ function parseCsvRows(raw) {
7792
7922
  function isPersonaMemDatasetComplete(datasetPath) {
7793
7923
  try {
7794
7924
  const completionMarkerPath = path18.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
7795
- if (fs18.statSync(completionMarkerPath).isFile()) {
7925
+ if (fs19.statSync(completionMarkerPath).isFile()) {
7796
7926
  return true;
7797
7927
  }
7798
7928
  } catch {
7799
7929
  }
7800
7930
  const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
7801
7931
  try {
7802
- return fs18.statSync(path18.join(datasetPath, candidate)).isFile();
7932
+ return fs19.statSync(path18.join(datasetPath, candidate)).isFile();
7803
7933
  } catch {
7804
7934
  return false;
7805
7935
  }
@@ -7808,7 +7938,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7808
7938
  return false;
7809
7939
  }
7810
7940
  try {
7811
- const rows = parseCsvRows(fs18.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
7941
+ const rows = parseCsvRows(fs19.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
7812
7942
  if (rows.length < 2) {
7813
7943
  return false;
7814
7944
  }
@@ -7823,7 +7953,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7823
7953
  }
7824
7954
  return historyPaths.every((relativePath) => {
7825
7955
  const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
7826
- return resolvedPath !== null && fs18.statSync(resolvedPath).isFile();
7956
+ return resolvedPath !== null && fs19.statSync(resolvedPath).isFile();
7827
7957
  });
7828
7958
  } catch {
7829
7959
  return false;
@@ -7831,7 +7961,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7831
7961
  }
7832
7962
  function hasDatasetFile(datasetPath, relativePath) {
7833
7963
  try {
7834
- return fs18.statSync(path18.join(datasetPath, relativePath)).isFile();
7964
+ return fs19.statSync(path18.join(datasetPath, relativePath)).isFile();
7835
7965
  } catch {
7836
7966
  return false;
7837
7967
  }
@@ -7851,10 +7981,10 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
7851
7981
  return candidateFilenames.some((filename) => {
7852
7982
  const filePath = path18.join(datasetPath, filename);
7853
7983
  try {
7854
- if (!fs18.statSync(filePath).isFile()) {
7984
+ if (!fs19.statSync(filePath).isFile()) {
7855
7985
  return false;
7856
7986
  }
7857
- const raw = fs18.readFileSync(filePath, "utf8");
7987
+ const raw = fs19.readFileSync(filePath, "utf8");
7858
7988
  return /"source"\s*:\s*"recsys[_-]/i.test(raw);
7859
7989
  } catch {
7860
7990
  return false;
@@ -7870,7 +8000,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
7870
8000
  function isDatasetDownloaded(datasetPath, benchmarkId) {
7871
8001
  let stats;
7872
8002
  try {
7873
- stats = fs18.statSync(datasetPath);
8003
+ stats = fs19.statSync(datasetPath);
7874
8004
  } catch {
7875
8005
  return false;
7876
8006
  }
@@ -7880,7 +8010,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7880
8010
  const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
7881
8011
  if (!marker) {
7882
8012
  try {
7883
- return fs18.readdirSync(datasetPath).length > 0;
8013
+ return fs19.readdirSync(datasetPath).length > 0;
7884
8014
  } catch {
7885
8015
  return false;
7886
8016
  }
@@ -7888,7 +8018,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7888
8018
  if (marker.allOf) {
7889
8019
  const hasAllRequiredFiles = marker.allOf.every((name) => {
7890
8020
  try {
7891
- return fs18.statSync(path18.join(datasetPath, name)).isFile();
8021
+ return fs19.statSync(path18.join(datasetPath, name)).isFile();
7892
8022
  } catch {
7893
8023
  return false;
7894
8024
  }
@@ -7900,7 +8030,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7900
8030
  if (marker.anyOf) {
7901
8031
  const hasMarkerFile = marker.anyOf.some((name) => {
7902
8032
  try {
7903
- return fs18.statSync(path18.join(datasetPath, name)).isFile();
8033
+ return fs19.statSync(path18.join(datasetPath, name)).isFile();
7904
8034
  } catch {
7905
8035
  return false;
7906
8036
  }
@@ -7918,7 +8048,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7918
8048
  }
7919
8049
  if (marker.ext) {
7920
8050
  try {
7921
- return fs18.readdirSync(datasetPath).some(
8051
+ return fs19.readdirSync(datasetPath).some(
7922
8052
  (name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
7923
8053
  );
7924
8054
  } catch {
@@ -7930,7 +8060,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7930
8060
  async function launchBenchUi(resultsDir) {
7931
8061
  const benchUiDir = path18.join(CLI_REPO_ROOT, "packages", "bench-ui");
7932
8062
  const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
7933
- if (!fs18.existsSync(path18.join(benchUiDir, "package.json"))) {
8063
+ if (!fs19.existsSync(path18.join(benchUiDir, "package.json"))) {
7934
8064
  console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
7935
8065
  process.exit(1);
7936
8066
  }
@@ -7968,13 +8098,13 @@ function listDownloadableBenchmarks() {
7968
8098
  }
7969
8099
  function resolveDatasetDownloadScriptPath() {
7970
8100
  const bundled = path18.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
7971
- if (fs18.existsSync(bundled)) {
8101
+ if (fs19.existsSync(bundled)) {
7972
8102
  return bundled;
7973
8103
  }
7974
8104
  return path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
7975
8105
  }
7976
8106
  function isRepoCheckout() {
7977
- return fs18.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs18.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"));
7978
8108
  }
7979
8109
  function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
7980
8110
  const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
@@ -8287,8 +8417,8 @@ async function exportBenchPackageResult(parsed) {
8287
8417
  ...reportCardProvenance ? { reportCardProvenance } : {}
8288
8418
  });
8289
8419
  if (parsed.output) {
8290
- fs18.mkdirSync(path18.dirname(parsed.output), { recursive: true });
8291
- fs18.writeFileSync(parsed.output, rendered);
8420
+ fs19.mkdirSync(path18.dirname(parsed.output), { recursive: true });
8421
+ fs19.writeFileSync(parsed.output, rendered);
8292
8422
  console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
8293
8423
  return;
8294
8424
  }
@@ -8333,7 +8463,7 @@ async function manageBenchDatasets(parsed) {
8333
8463
  process.exit(1);
8334
8464
  }
8335
8465
  const scriptPath = resolveDatasetDownloadScriptPath();
8336
- if (!fs18.existsSync(scriptPath)) {
8466
+ if (!fs19.existsSync(scriptPath)) {
8337
8467
  console.error(`ERROR: dataset download script not found: ${scriptPath}`);
8338
8468
  process.exit(1);
8339
8469
  }
@@ -8533,7 +8663,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
8533
8663
  );
8534
8664
  process.exit(1);
8535
8665
  }
8536
- const sourceResultSha256 = createHash4("sha256").update(fs18.readFileSync(latest.path)).digest("hex");
8666
+ const sourceResultSha256 = createHash4("sha256").update(fs19.readFileSync(latest.path)).digest("hex");
8537
8667
  const expandedManifestPath = expandTilde(manifestPath);
8538
8668
  if (!bench.resolveLocalLabJudgeProviderConfig) {
8539
8669
  console.error(
@@ -8948,7 +9078,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
8948
9078
  }
8949
9079
  let decoded;
8950
9080
  try {
8951
- decoded = JSON.parse(fs18.readFileSync(parsed.taskIdsFile, "utf8"));
9081
+ decoded = JSON.parse(fs19.readFileSync(parsed.taskIdsFile, "utf8"));
8952
9082
  } catch (error) {
8953
9083
  throw new Error(
8954
9084
  `Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
@@ -9623,7 +9753,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
9623
9753
  return void 0;
9624
9754
  }
9625
9755
  try {
9626
- return fs18.realpathSync(datasetDir);
9756
+ return fs19.realpathSync(datasetDir);
9627
9757
  } catch {
9628
9758
  return datasetDir;
9629
9759
  }
@@ -9677,13 +9807,13 @@ async function writeBenchReproManifestForPackageRun(args) {
9677
9807
  }
9678
9808
  function loadStandaloneConvergeCommandConfig() {
9679
9809
  const configPath = resolveConfigPath();
9680
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
9681
- return parseConfig9(resolveRemnicConfigRecord8(raw));
9810
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
9811
+ return parseConfig10(resolveRemnicConfigRecord9(raw));
9682
9812
  }
9683
9813
  function parseConvergePluginConfig(value) {
9684
9814
  if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
9685
9815
  if (Object.keys(value).length === 0) return void 0;
9686
- return parseConfig9(resolveRemnicConfigRecord8(value));
9816
+ return parseConfig10(resolveRemnicConfigRecord9(value));
9687
9817
  }
9688
9818
  function loadConvergeCommandConfig() {
9689
9819
  if (readCompatEnv("REMNIC_CONFIG_PATH", "ENGRAM_CONFIG_PATH")) {
@@ -9706,13 +9836,13 @@ function resolveConfigPath(cliPath) {
9706
9836
  path18.join(resolveHomeDir(), ".config", "engram", "config.json")
9707
9837
  ];
9708
9838
  for (const candidate of candidates) {
9709
- if (fs18.existsSync(candidate)) return candidate;
9839
+ if (fs19.existsSync(candidate)) return candidate;
9710
9840
  }
9711
9841
  return path18.join(resolveHomeDir(), ".config", "remnic", "config.json");
9712
9842
  }
9713
9843
  function resolveExistingBenchRemnicConfigPath(cliPath) {
9714
9844
  const configPath = resolveConfigPath(cliPath);
9715
- if (fs18.existsSync(configPath)) {
9845
+ if (fs19.existsSync(configPath)) {
9716
9846
  return configPath;
9717
9847
  }
9718
9848
  if (cliPath) {
@@ -9722,7 +9852,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
9722
9852
  }
9723
9853
  function resolveExistingBenchOpenclawConfigPath(cliPath) {
9724
9854
  const configPath = resolveOpenclawConfigPath(cliPath);
9725
- if (fs18.existsSync(configPath)) {
9855
+ if (fs19.existsSync(configPath)) {
9726
9856
  return configPath;
9727
9857
  }
9728
9858
  if (cliPath) {
@@ -9829,8 +9959,8 @@ function resolveMemoryDir() {
9829
9959
  const envMemoryDir = readCompatEnv("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
9830
9960
  if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
9831
9961
  const configPath = resolveConfigPath();
9832
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
9833
- const remnicCfg = resolveRemnicConfigRecord8(raw);
9962
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
9963
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
9834
9964
  if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
9835
9965
  return normalizeMemoryDirPath(remnicCfg.memoryDir);
9836
9966
  }
@@ -9838,18 +9968,18 @@ function resolveMemoryDir() {
9838
9968
  const standalonePath = path18.join(home, ".remnic", "memory");
9839
9969
  const legacyStandalonePath = path18.join(home, ".engram", "memory");
9840
9970
  const openclawPath = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
9841
- if (fs18.existsSync(standalonePath)) return standalonePath;
9842
- if (fs18.existsSync(legacyStandalonePath)) return legacyStandalonePath;
9971
+ if (fs19.existsSync(standalonePath)) return standalonePath;
9972
+ if (fs19.existsSync(legacyStandalonePath)) return legacyStandalonePath;
9843
9973
  return openclawPath;
9844
9974
  })();
9845
9975
  const manifestPath = getManifestPath();
9846
- if (fs18.existsSync(manifestPath)) {
9976
+ if (fs19.existsSync(manifestPath)) {
9847
9977
  try {
9848
9978
  const active = getActiveSpace();
9849
9979
  if (active?.memoryDir) {
9850
9980
  const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
9851
- if (!fs18.existsSync(activeMemoryDir)) {
9852
- fs18.mkdirSync(activeMemoryDir, { recursive: true });
9981
+ if (!fs19.existsSync(activeMemoryDir)) {
9982
+ fs19.mkdirSync(activeMemoryDir, { recursive: true });
9853
9983
  }
9854
9984
  return activeMemoryDir;
9855
9985
  }
@@ -9898,13 +10028,13 @@ function resolveOpenclawConfigPath(cliPath) {
9898
10028
  const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
9899
10029
  if (envPath) return path18.resolve(expandTilde(envPath));
9900
10030
  for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
9901
- if (fs18.existsSync(candidate)) return candidate;
10031
+ if (fs19.existsSync(candidate)) return candidate;
9902
10032
  }
9903
10033
  return path18.join(resolveOpenclawStateDir(), "openclaw.json");
9904
10034
  }
9905
10035
  function readOpenclawConfig(configPath) {
9906
- if (!fs18.existsSync(configPath)) return {};
9907
- const raw = fs18.readFileSync(configPath, "utf-8");
10036
+ if (!fs19.existsSync(configPath)) return {};
10037
+ const raw = fs19.readFileSync(configPath, "utf-8");
9908
10038
  let parsed;
9909
10039
  try {
9910
10040
  parsed = JSON.parse(raw);
@@ -10006,9 +10136,9 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
10006
10136
  return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
10007
10137
  }
10008
10138
  function backupPathIfPresent(sourcePath, backupPath) {
10009
- if (!fs18.existsSync(sourcePath)) return false;
10010
- fs18.mkdirSync(path18.dirname(backupPath), { recursive: true });
10011
- fs18.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 });
10012
10142
  return true;
10013
10143
  }
10014
10144
  function restartOpenclawGateway() {
@@ -10027,7 +10157,7 @@ function restartOpenclawGateway() {
10027
10157
  }
10028
10158
  function cmdInit() {
10029
10159
  const configPath = path18.join(process.cwd(), "remnic.config.json");
10030
- if (fs18.existsSync(configPath)) {
10160
+ if (fs19.existsSync(configPath)) {
10031
10161
  console.log(`Config already exists: ${configPath}`);
10032
10162
  return;
10033
10163
  }
@@ -10043,7 +10173,7 @@ function cmdInit() {
10043
10173
  authToken: "${REMNIC_AUTH_TOKEN}"
10044
10174
  }
10045
10175
  };
10046
- fs18.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
10176
+ fs19.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
10047
10177
  console.log(`Created ${configPath}`);
10048
10178
  console.log("\nSet these environment variables:");
10049
10179
  console.log(" export OPENAI_API_KEY=sk-...");
@@ -10463,12 +10593,12 @@ async function cmdQuery(queryText, json, explain) {
10463
10593
  printQueryResult(result, json);
10464
10594
  return;
10465
10595
  }
10466
- initLogger4();
10596
+ initLogger5();
10467
10597
  const configPath = resolveConfigPath();
10468
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
10469
- const remnicCfg = resolveRemnicConfigRecord8(raw);
10470
- const config = parseConfig9(remnicCfg);
10471
- 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);
10472
10602
  await orchestrator.initialize();
10473
10603
  const service = new EngramAccessService2(orchestrator);
10474
10604
  const recallRequest = buildQueryRecallRequest(queryText);
@@ -10643,12 +10773,12 @@ async function cmdXray(rest) {
10643
10773
  await runXrayCommand(rest, xrayCliIo((request) => remoteRecallXray(remote, request)));
10644
10774
  return;
10645
10775
  }
10646
- initLogger4();
10776
+ initLogger5();
10647
10777
  const configPath = resolveConfigPath();
10648
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
10649
- const remnicCfg = resolveRemnicConfigRecord8(raw);
10650
- const config = parseConfig9(remnicCfg);
10651
- 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);
10652
10782
  await orchestrator.initialize();
10653
10783
  await orchestrator.deferredReady;
10654
10784
  const service = new EngramAccessService2(orchestrator);
@@ -10676,10 +10806,10 @@ async function runWhoKnowsCommand(rest, io) {
10676
10806
  io.stdout(renderWhoKnows(result, parsed.json));
10677
10807
  }
10678
10808
  async function withLocalService(fn) {
10679
- initLogger4();
10809
+ initLogger5();
10680
10810
  const configPath = resolveConfigPath();
10681
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
10682
- const orchestrator = new Orchestrator5(parseConfig9(resolveRemnicConfigRecord8(raw)));
10811
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
10812
+ const orchestrator = new Orchestrator6(parseConfig10(resolveRemnicConfigRecord9(raw)));
10683
10813
  await orchestrator.initialize();
10684
10814
  await orchestrator.deferredReady;
10685
10815
  const service = new EngramAccessService2(orchestrator);
@@ -10709,11 +10839,11 @@ async function cmdPromotionCandidates(rest) {
10709
10839
  }));
10710
10840
  }
10711
10841
  async function cmdVersions(rest) {
10712
- initLogger4();
10842
+ initLogger5();
10713
10843
  const configPath = resolveConfigPath();
10714
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
10715
- const remnicCfg = resolveRemnicConfigRecord8(raw);
10716
- const config = parseConfig9(remnicCfg);
10844
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
10845
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
10846
+ const config = parseConfig10(remnicCfg);
10717
10847
  if (!config.versioningEnabled) {
10718
10848
  console.error("Page versioning is disabled (versioningEnabled = false).");
10719
10849
  process.exit(1);
@@ -10825,11 +10955,11 @@ Options:
10825
10955
  }
10826
10956
  }
10827
10957
  async function cmdEnrich(rest) {
10828
- initLogger4();
10958
+ initLogger5();
10829
10959
  const configPath = resolveConfigPath();
10830
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
10831
- const remnicCfg = resolveRemnicConfigRecord8(raw);
10832
- const config = parseConfig9(remnicCfg);
10960
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
10961
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
10962
+ const config = parseConfig10(remnicCfg);
10833
10963
  const subcommand = rest[0];
10834
10964
  if (subcommand === "audit") {
10835
10965
  const memoryDir2 = expandTilde(config.memoryDir);
@@ -10857,7 +10987,7 @@ async function cmdEnrich(rest) {
10857
10987
  pipelineConfig2.providers = [
10858
10988
  { id: "web-search", enabled: true, costTier: "cheap" }
10859
10989
  ];
10860
- const orchestrator2 = new Orchestrator5(config);
10990
+ const orchestrator2 = new Orchestrator6(config);
10861
10991
  await orchestrator2.initialize();
10862
10992
  await orchestrator2.deferredReady;
10863
10993
  const searchBackend2 = orchestrator2.qmd;
@@ -10893,7 +11023,7 @@ Registered providers:`);
10893
11023
  console.error("Usage: remnic enrich <entity-name> | --all | --dry-run | audit | providers");
10894
11024
  process.exit(1);
10895
11025
  }
10896
- const orchestrator = new Orchestrator5(config);
11026
+ const orchestrator = new Orchestrator6(config);
10897
11027
  await orchestrator.initialize();
10898
11028
  await orchestrator.deferredReady;
10899
11029
  const storage = await orchestrator.getStorage(config.defaultNamespace);
@@ -11019,11 +11149,11 @@ Registered providers:`);
11019
11149
  }
11020
11150
  }
11021
11151
  async function cmdExtensions(action, rest) {
11022
- initLogger4();
11152
+ initLogger5();
11023
11153
  const configPath = resolveConfigPath();
11024
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
11025
- const remnicCfg = resolveRemnicConfigRecord8(raw);
11026
- const config = parseConfig9(remnicCfg);
11154
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
11155
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
11156
+ const config = parseConfig10(remnicCfg);
11027
11157
  const root = resolveExtensionsRoot(config);
11028
11158
  const noopLog = { warn: () => {
11029
11159
  }, debug: () => {
@@ -11072,7 +11202,7 @@ Root: ${root}`);
11072
11202
  const extensions = await discoverMemoryExtensions(root, warnLog);
11073
11203
  let entries = [];
11074
11204
  try {
11075
- entries = fs18.readdirSync(root);
11205
+ entries = fs19.readdirSync(root);
11076
11206
  } catch {
11077
11207
  console.log(`Extensions root does not exist: ${root}`);
11078
11208
  process.exitCode = 0;
@@ -11083,7 +11213,7 @@ Root: ${root}`);
11083
11213
  for (const entry of entries) {
11084
11214
  const entryPath = path18.join(root, entry);
11085
11215
  try {
11086
- if (!fs18.statSync(entryPath).isDirectory()) continue;
11216
+ if (!fs19.statSync(entryPath).isDirectory()) continue;
11087
11217
  } catch {
11088
11218
  continue;
11089
11219
  }
@@ -11113,11 +11243,11 @@ Root: ${root}`);
11113
11243
  }
11114
11244
  }
11115
11245
  async function cmdBriefing(rest) {
11116
- initLogger4();
11246
+ initLogger5();
11117
11247
  const configPath = resolveConfigPath();
11118
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
11119
- const remnicCfg = resolveRemnicConfigRecord8(raw);
11120
- const config = parseConfig9(remnicCfg);
11248
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
11249
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
11250
+ const config = parseConfig10(remnicCfg);
11121
11251
  if (!config.briefing.enabled) {
11122
11252
  console.error("Briefing is disabled in config (briefing.enabled = false).");
11123
11253
  process.exit(1);
@@ -11170,7 +11300,7 @@ async function cmdBriefing(rest) {
11170
11300
  process.exit(1);
11171
11301
  }
11172
11302
  const format = effectiveFormatFlag === "json" ? "json" : effectiveFormatFlag === "markdown" ? "markdown" : config.briefing.defaultFormat;
11173
- const orchestrator = new Orchestrator5(config);
11303
+ const orchestrator = new Orchestrator6(config);
11174
11304
  await orchestrator.initialize();
11175
11305
  const storage = await orchestrator.getStorage(config.defaultNamespace);
11176
11306
  const calendarSource = config.briefing.calendarSource ? new FileCalendarSource(config.briefing.calendarSource) : void 0;
@@ -11195,10 +11325,10 @@ async function cmdBriefing(rest) {
11195
11325
  if (save) {
11196
11326
  try {
11197
11327
  const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
11198
- fs18.mkdirSync(saveDir, { recursive: true });
11328
+ fs19.mkdirSync(saveDir, { recursive: true });
11199
11329
  const filename = briefingFilename(new Date(result.window.to), format);
11200
11330
  const filePath = path18.join(saveDir, filename);
11201
- fs18.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
11331
+ fs19.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
11202
11332
  console.error(`Saved briefing: ${filePath}`);
11203
11333
  } catch (err) {
11204
11334
  console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
@@ -11216,7 +11346,7 @@ async function cmdDoctor() {
11216
11346
  detail: `${nodeVersion} (requires >= 22.12.0)`
11217
11347
  });
11218
11348
  const configPath = resolveConfigPath();
11219
- const configExists = fs18.existsSync(configPath);
11349
+ const configExists = fs19.existsSync(configPath);
11220
11350
  checks.push({ name: "Config file", ok: configExists, detail: configPath });
11221
11351
  let standaloneConfig;
11222
11352
  let standaloneConfigError;
@@ -11224,11 +11354,11 @@ async function cmdDoctor() {
11224
11354
  let configuredNs = { invalid: false };
11225
11355
  if (configExists) {
11226
11356
  try {
11227
- const raw = JSON.parse(fs18.readFileSync(configPath, "utf8"));
11228
- const remnicCfg = resolveRemnicConfigRecord8(raw);
11357
+ const raw = JSON.parse(fs19.readFileSync(configPath, "utf8"));
11358
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
11229
11359
  standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
11230
11360
  configuredNs = readConfiguredNamespace(remnicCfg);
11231
- standaloneConfig = parseConfig9(remnicCfg);
11361
+ standaloneConfig = parseConfig10(remnicCfg);
11232
11362
  } catch (err) {
11233
11363
  standaloneConfigError = err instanceof Error ? err.message : String(err);
11234
11364
  }
@@ -11237,10 +11367,10 @@ async function cmdDoctor() {
11237
11367
  try {
11238
11368
  memoryDir = resolveMemoryDir();
11239
11369
  } catch {
11240
- memoryDir = parseConfig9({}).memoryDir;
11370
+ memoryDir = parseConfig10({}).memoryDir;
11241
11371
  }
11242
11372
  try {
11243
- fs18.mkdirSync(memoryDir, { recursive: true });
11373
+ fs19.mkdirSync(memoryDir, { recursive: true });
11244
11374
  checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
11245
11375
  } catch {
11246
11376
  checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
@@ -11269,7 +11399,7 @@ async function cmdDoctor() {
11269
11399
  });
11270
11400
  if (nsPolicyCheck) checks.push(nsPolicyCheck);
11271
11401
  const openclawConfigPath = resolveOpenclawConfigPath();
11272
- const openclawConfigExists = fs18.existsSync(openclawConfigPath);
11402
+ const openclawConfigExists = fs19.existsSync(openclawConfigPath);
11273
11403
  let openclawConfig = {};
11274
11404
  let openclawConfigValid = false;
11275
11405
  let openclawPluginModeConfigured = false;
@@ -11277,7 +11407,7 @@ async function cmdDoctor() {
11277
11407
  let activeOpenclawEntryConfig = null;
11278
11408
  if (openclawConfigExists) {
11279
11409
  try {
11280
- const parsed = JSON.parse(fs18.readFileSync(openclawConfigPath, "utf-8"));
11410
+ const parsed = JSON.parse(fs19.readFileSync(openclawConfigPath, "utf-8"));
11281
11411
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
11282
11412
  openclawConfig = parsed;
11283
11413
  openclawConfigValid = true;
@@ -11357,9 +11487,9 @@ async function cmdDoctor() {
11357
11487
  let memDirOk = false;
11358
11488
  let memDirDetail = `${resolvedMemDir} (not found)`;
11359
11489
  let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
11360
- if (fs18.existsSync(resolvedMemDir)) {
11490
+ if (fs19.existsSync(resolvedMemDir)) {
11361
11491
  try {
11362
- const stat2 = fs18.statSync(resolvedMemDir);
11492
+ const stat2 = fs19.statSync(resolvedMemDir);
11363
11493
  if (stat2.isDirectory()) {
11364
11494
  memDirOk = true;
11365
11495
  memDirDetail = resolvedMemDir;
@@ -11514,12 +11644,12 @@ async function cmdDoctor() {
11514
11644
  }
11515
11645
  function cmdConfig() {
11516
11646
  const configPath = resolveConfigPath();
11517
- if (!fs18.existsSync(configPath)) {
11647
+ if (!fs19.existsSync(configPath)) {
11518
11648
  console.log("No config file found. Run `remnic init` to create one.");
11519
11649
  return;
11520
11650
  }
11521
11651
  console.log(`Config: ${configPath}`);
11522
- const rawConfig = fs18.readFileSync(configPath, "utf8");
11652
+ const rawConfig = fs19.readFileSync(configPath, "utf8");
11523
11653
  const redacted = rawConfig.replace(
11524
11654
  /("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
11525
11655
  "$1[REDACTED]$3"
@@ -11627,9 +11757,9 @@ async function cmdReview(action, rest) {
11627
11757
  const configPath = resolveConfigPath();
11628
11758
  let tombstonesConfig = null;
11629
11759
  try {
11630
- const rawCfg = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
11631
- const remnicCfg = resolveRemnicConfigRecord8(rawCfg);
11632
- const config = parseConfig9(remnicCfg);
11760
+ const rawCfg = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
11761
+ const remnicCfg = resolveRemnicConfigRecord9(rawCfg);
11762
+ const config = parseConfig10(remnicCfg);
11633
11763
  tombstonesConfig = {
11634
11764
  enabled: config.tombstonesEnabled,
11635
11765
  semanticMatch: config.tombstonesSemanticMatch,
@@ -12371,7 +12501,7 @@ async function pushOfflineFileContent(args) {
12371
12501
  }
12372
12502
  async function pushOfflineFileContentFromChunkReader(args) {
12373
12503
  const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
12374
- const stat2 = fs18.statSync(filePath);
12504
+ const stat2 = fs19.statSync(filePath);
12375
12505
  if (stat2.mtimeMs !== args.file.mtimeMs) {
12376
12506
  throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
12377
12507
  }
@@ -12862,7 +12992,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
12862
12992
  return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
12863
12993
  }
12864
12994
  async function runOfflineSyncOnce(options) {
12865
- fs18.mkdirSync(options.memoryDir, { recursive: true });
12995
+ fs19.mkdirSync(options.memoryDir, { recursive: true });
12866
12996
  let activeStatePath = options.statePath;
12867
12997
  let priorState = await readOfflineSyncState(activeStatePath);
12868
12998
  let syncNamespace = options.namespace ?? priorState?.namespace;
@@ -13495,7 +13625,7 @@ Environment fallbacks:
13495
13625
  const configPath = resolveConfigPath();
13496
13626
  let config;
13497
13627
  try {
13498
- const rawConfig = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
13628
+ const rawConfig = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
13499
13629
  config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
13500
13630
  } catch {
13501
13631
  throw new Error(
@@ -13510,7 +13640,7 @@ Environment fallbacks:
13510
13640
  const statePath = statePathExplicit ? path18.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
13511
13641
  if (action === "prepare") {
13512
13642
  if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
13513
- fs18.mkdirSync(memoryDir, { recursive: true });
13643
+ fs19.mkdirSync(memoryDir, { recursive: true });
13514
13644
  const remoteSnapshot = await fetchOfflineSnapshot({
13515
13645
  remoteUrl,
13516
13646
  token,
@@ -13609,7 +13739,7 @@ Environment fallbacks:
13609
13739
  return;
13610
13740
  }
13611
13741
  if (action === "status") {
13612
- fs18.mkdirSync(memoryDir, { recursive: true });
13742
+ fs19.mkdirSync(memoryDir, { recursive: true });
13613
13743
  const state = statePath ? await readOfflineSyncState(statePath) : null;
13614
13744
  if (state && remoteUrl && statePath) {
13615
13745
  assertOfflineStateMatches({
@@ -13747,7 +13877,7 @@ function cmdDedup(json) {
13747
13877
  function readInstalledConnectorConfig(configPath, fallback) {
13748
13878
  if (!configPath) return fallback;
13749
13879
  try {
13750
- const parsed = JSON.parse(fs18.readFileSync(configPath, "utf8"));
13880
+ const parsed = JSON.parse(fs19.readFileSync(configPath, "utf8"));
13751
13881
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
13752
13882
  const { token: _token, ...config } = parsed;
13753
13883
  return config;
@@ -13925,7 +14055,7 @@ async function cmdConnectors(action, rest, json) {
13925
14055
  const pub = factory();
13926
14056
  const available = await pub.isHostAvailable();
13927
14057
  const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
13928
- const extensionExists = available && extRoot ? fs18.existsSync(extRoot) : false;
14058
+ const extensionExists = available && extRoot ? fs19.existsSync(extRoot) : false;
13929
14059
  publisherChecks.push({
13930
14060
  name: `Publisher: ${targetHostId}`,
13931
14061
  ok: !available || extensionExists,
@@ -13999,7 +14129,7 @@ async function cmdConnectors(action, rest, json) {
13999
14129
  let connectorsCfg;
14000
14130
  const configPath = resolveConfigPath();
14001
14131
  try {
14002
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
14132
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
14003
14133
  connectorsCfg = parseConfigQuietly(raw).connectors;
14004
14134
  } catch {
14005
14135
  process.stderr.write(
@@ -14073,12 +14203,12 @@ async function cmdConnectors(action, rest, json) {
14073
14203
  process.exitCode = 2;
14074
14204
  return;
14075
14205
  }
14076
- initLogger4();
14206
+ initLogger5();
14077
14207
  const configPath = resolveConfigPath();
14078
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
14079
- const remnicCfg = resolveRemnicConfigRecord8(raw);
14080
- const config = parseConfig9(remnicCfg);
14081
- 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);
14082
14212
  try {
14083
14213
  await orchestrator.initialize();
14084
14214
  await orchestrator.deferredReady;
@@ -14200,9 +14330,9 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
14200
14330
  console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
14201
14331
  process.exit(1);
14202
14332
  }
14203
- const rawConfig = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
14204
- const pluginConfig = resolveRemnicConfigRecord8(rawConfig);
14205
- const config = parseConfig9(pluginConfig);
14333
+ const rawConfig = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
14334
+ const pluginConfig = resolveRemnicConfigRecord9(rawConfig);
14335
+ const config = parseConfig10(pluginConfig);
14206
14336
  if (subAction === "generate") {
14207
14337
  let outputDir;
14208
14338
  try {
@@ -14222,13 +14352,13 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
14222
14352
  } else if (subAction === "validate") {
14223
14353
  const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path18.join(process.cwd(), "marketplace.json");
14224
14354
  const resolved = path18.resolve(targetPath);
14225
- if (!fs18.existsSync(resolved)) {
14355
+ if (!fs19.existsSync(resolved)) {
14226
14356
  console.error(`File not found: ${resolved}`);
14227
14357
  process.exit(1);
14228
14358
  }
14229
14359
  let parsed;
14230
14360
  try {
14231
- parsed = JSON.parse(fs18.readFileSync(resolved, "utf8"));
14361
+ parsed = JSON.parse(fs19.readFileSync(resolved, "utf8"));
14232
14362
  } catch {
14233
14363
  console.error(`Invalid JSON in ${resolved}`);
14234
14364
  process.exit(1);
@@ -14429,12 +14559,12 @@ async function cmdSpace(action, rest, json) {
14429
14559
  }
14430
14560
  }
14431
14561
  async function cmdLegacyBenchmark(action, rest, json) {
14432
- initLogger4();
14562
+ initLogger5();
14433
14563
  const configPath = resolveConfigPath();
14434
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
14435
- const remnicCfg = resolveRemnicConfigRecord8(raw);
14436
- const config = parseConfig9(remnicCfg);
14437
- 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);
14438
14568
  const service = new EngramAccessService2(orchestrator);
14439
14569
  const { runBenchSuite, loadBaseline, checkRegression } = await loadBenchModule();
14440
14570
  const benchConfig = {
@@ -14836,7 +14966,7 @@ function readPid() {
14836
14966
  function inferPort() {
14837
14967
  try {
14838
14968
  const configPath = resolveConfigPath();
14839
- const raw = JSON.parse(fs18.readFileSync(configPath, "utf8"));
14969
+ const raw = JSON.parse(fs19.readFileSync(configPath, "utf8"));
14840
14970
  return raw.server?.port ?? 4318;
14841
14971
  } catch {
14842
14972
  return 4318;
@@ -14931,13 +15061,13 @@ function daemonInstall() {
14931
15061
  process.exit(1);
14932
15062
  }
14933
15063
  const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
14934
- fs18.mkdirSync(LOGS_DIR, { recursive: true });
15064
+ fs19.mkdirSync(LOGS_DIR, { recursive: true });
14935
15065
  if (isMacOS()) {
14936
15066
  const templatePath = path18.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
14937
- const template = fs18.readFileSync(templatePath, "utf8");
15067
+ const template = fs19.readFileSync(templatePath, "utf8");
14938
15068
  const plist = renderTemplate(template, vars);
14939
- fs18.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
14940
- fs18.writeFileSync(LAUNCHD_PLIST_PATH, plist);
15069
+ fs19.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
15070
+ fs19.writeFileSync(LAUNCHD_PLIST_PATH, plist);
14941
15071
  try {
14942
15072
  launchdLoadPlist(LAUNCHD_PLIST_PATH);
14943
15073
  } catch (err) {
@@ -14954,10 +15084,10 @@ function daemonInstall() {
14954
15084
  console.log(` Logs: ${LOGS_DIR}/daemon.log`);
14955
15085
  } else if (isLinux()) {
14956
15086
  const templatePath = path18.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
14957
- const template = fs18.readFileSync(templatePath, "utf8");
15087
+ const template = fs19.readFileSync(templatePath, "utf8");
14958
15088
  const unit = renderTemplate(template, vars);
14959
- fs18.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
14960
- fs18.writeFileSync(SYSTEMD_UNIT_PATH, unit);
15089
+ fs19.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
15090
+ fs19.writeFileSync(SYSTEMD_UNIT_PATH, unit);
14961
15091
  try {
14962
15092
  childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
14963
15093
  } catch (err) {
@@ -14993,7 +15123,7 @@ function daemonUninstall() {
14993
15123
  } catch {
14994
15124
  }
14995
15125
  try {
14996
- fs18.unlinkSync(plistPath);
15126
+ fs19.unlinkSync(plistPath);
14997
15127
  removed = true;
14998
15128
  console.log(`Removed launchd service: ${plistPath}`);
14999
15129
  } catch {
@@ -15013,7 +15143,7 @@ function daemonUninstall() {
15013
15143
  let removed = false;
15014
15144
  for (const unitPath of SYSTEMD_UNIT_PATHS) {
15015
15145
  try {
15016
- fs18.unlinkSync(unitPath);
15146
+ fs19.unlinkSync(unitPath);
15017
15147
  removed = true;
15018
15148
  console.log(`Removed systemd service: ${unitPath}`);
15019
15149
  } catch {
@@ -15080,13 +15210,13 @@ async function daemonStatus() {
15080
15210
  console.log(` Port: ${port}`);
15081
15211
  console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
15082
15212
  console.log(` Platform: ${process.platform}`);
15083
- console.log(` PID file: ${fs18.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
15084
- console.log(` Log file: ${fs18.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}`);
15085
15215
  try {
15086
15216
  const configPath = resolveConfigPath();
15087
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
15088
- const remnicCfg = resolveRemnicConfigRecord8(raw);
15089
- const config = parseConfig9(remnicCfg);
15217
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
15218
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
15219
+ const config = parseConfig10(remnicCfg);
15090
15220
  const extRoot = resolveExtensionsRoot(config);
15091
15221
  const noopLog = { warn: () => {
15092
15222
  }, debug: () => {
@@ -15125,9 +15255,9 @@ function daemonStart() {
15125
15255
  return;
15126
15256
  }
15127
15257
  }
15128
- fs18.mkdirSync(PID_DIR, { recursive: true });
15129
- fs18.mkdirSync(LOGS_DIR, { recursive: true });
15130
- const logStream = fs18.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");
15131
15261
  const serverBin = resolveServerBin();
15132
15262
  const isSource = serverBin.endsWith(".ts");
15133
15263
  let cmd;
@@ -15149,7 +15279,7 @@ function daemonStart() {
15149
15279
  }
15150
15280
  });
15151
15281
  child.unref();
15152
- fs18.writeFileSync(PID_FILE, String(child.pid));
15282
+ fs19.writeFileSync(PID_FILE, String(child.pid));
15153
15283
  console.log(`Started remnic server (pid ${child.pid})`);
15154
15284
  console.log(` Log: ${LOG_FILE}`);
15155
15285
  }
@@ -15183,11 +15313,11 @@ function daemonStop() {
15183
15313
  console.log("Process not found (cleaning up PID file)");
15184
15314
  }
15185
15315
  try {
15186
- fs18.unlinkSync(PID_FILE);
15316
+ fs19.unlinkSync(PID_FILE);
15187
15317
  } catch {
15188
15318
  }
15189
15319
  try {
15190
- fs18.unlinkSync(LEGACY_PID_FILE);
15320
+ fs19.unlinkSync(LEGACY_PID_FILE);
15191
15321
  } catch {
15192
15322
  }
15193
15323
  }
@@ -15313,11 +15443,11 @@ async function promptYesNo(question, defaultYes = true) {
15313
15443
  });
15314
15444
  }
15315
15445
  async function cmdBinary(rest) {
15316
- initLogger4();
15446
+ initLogger5();
15317
15447
  const configPath = resolveConfigPath();
15318
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
15319
- const remnicCfg = resolveRemnicConfigRecord8(raw);
15320
- const config = parseConfig9(remnicCfg);
15448
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
15449
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
15450
+ const config = parseConfig10(remnicCfg);
15321
15451
  const memoryDir = resolveMemoryDir();
15322
15452
  const blConfig = {
15323
15453
  enabled: config.binaryLifecycleEnabled,
@@ -15506,7 +15636,7 @@ async function cmdOpenclawInstall(opts) {
15506
15636
  } else if (slotIsActiveLegacy) {
15507
15637
  changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
15508
15638
  }
15509
- if (!fs18.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
15639
+ if (!fs19.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
15510
15640
  if (hasLegacy && migrateLegacy) {
15511
15641
  changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
15512
15642
  }
@@ -15526,8 +15656,8 @@ async function cmdOpenclawInstall(opts) {
15526
15656
  Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
15527
15657
  return;
15528
15658
  }
15529
- if (fs18.existsSync(memoryDir)) {
15530
- const st = fs18.statSync(memoryDir);
15659
+ if (fs19.existsSync(memoryDir)) {
15660
+ const st = fs19.statSync(memoryDir);
15531
15661
  if (!st.isDirectory()) {
15532
15662
  throw new Error(
15533
15663
  `Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
@@ -15535,12 +15665,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
15535
15665
  );
15536
15666
  }
15537
15667
  } else {
15538
- fs18.mkdirSync(memoryDir, { recursive: true });
15668
+ fs19.mkdirSync(memoryDir, { recursive: true });
15539
15669
  console.log(`Created memory directory: ${memoryDir}`);
15540
15670
  }
15541
15671
  const configDir = path18.dirname(configPath);
15542
- if (!fs18.existsSync(configDir)) {
15543
- fs18.mkdirSync(configDir, { recursive: true });
15672
+ if (!fs19.existsSync(configDir)) {
15673
+ fs19.mkdirSync(configDir, { recursive: true });
15544
15674
  }
15545
15675
  atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
15546
15676
  console.log("\nDone! Summary of changes:");
@@ -15569,7 +15699,7 @@ async function cmdOpenclawUpgrade(opts) {
15569
15699
  const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
15570
15700
  const fallbackMemoryDir = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
15571
15701
  const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
15572
- const configExistedBefore = fs18.existsSync(configPath);
15702
+ const configExistedBefore = fs19.existsSync(configPath);
15573
15703
  const existingConfig = readOpenclawConfig(configPath);
15574
15704
  const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
15575
15705
  const preservedMemoryDir = opts.memoryDir ? path18.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
@@ -15794,15 +15924,15 @@ async function cmdOpenclawMigrateEngram(opts) {
15794
15924
  }
15795
15925
  function createOpenclawUpgradeBackupDir() {
15796
15926
  const backupsRoot = path18.join(resolveOpenclawStateDir(), "backups");
15797
- fs18.mkdirSync(backupsRoot, { recursive: true });
15798
- return fs18.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()}-`));
15799
15929
  }
15800
15930
  async function cmdTaxonomy(rest) {
15801
- initLogger4();
15931
+ initLogger5();
15802
15932
  const configPath = resolveConfigPath();
15803
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
15804
- const remnicCfg = resolveRemnicConfigRecord8(raw);
15805
- const config = parseConfig9(remnicCfg);
15933
+ const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
15934
+ const remnicCfg = resolveRemnicConfigRecord9(raw);
15935
+ const config = parseConfig10(remnicCfg);
15806
15936
  if (!config.taxonomyEnabled) {
15807
15937
  console.error(
15808
15938
  "Taxonomy is disabled in config (taxonomyEnabled = false). Enable it to use taxonomy commands."
@@ -15838,8 +15968,8 @@ async function cmdTaxonomy(rest) {
15838
15968
  console.log(doc);
15839
15969
  if (config.taxonomyAutoGenResolver) {
15840
15970
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15841
- fs18.mkdirSync(path18.dirname(resolverPath), { recursive: true });
15842
- fs18.writeFileSync(resolverPath, doc);
15971
+ fs19.mkdirSync(path18.dirname(resolverPath), { recursive: true });
15972
+ fs19.writeFileSync(resolverPath, doc);
15843
15973
  console.error(`Written: ${resolverPath}`);
15844
15974
  }
15845
15975
  break;
@@ -15885,7 +16015,7 @@ async function cmdTaxonomy(rest) {
15885
16015
  if (config.taxonomyAutoGenResolver) {
15886
16016
  const doc = generateResolverDocument(taxonomy);
15887
16017
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15888
- fs18.writeFileSync(resolverPath, doc);
16018
+ fs19.writeFileSync(resolverPath, doc);
15889
16019
  console.error(`Regenerated: ${resolverPath}`);
15890
16020
  }
15891
16021
  break;
@@ -15916,7 +16046,7 @@ async function cmdTaxonomy(rest) {
15916
16046
  if (config.taxonomyAutoGenResolver) {
15917
16047
  const doc = generateResolverDocument(taxonomy);
15918
16048
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15919
- fs18.writeFileSync(resolverPath, doc);
16049
+ fs19.writeFileSync(resolverPath, doc);
15920
16050
  console.error(`Regenerated: ${resolverPath}`);
15921
16051
  }
15922
16052
  break;
@@ -16107,12 +16237,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
16107
16237
  `Unknown training-export format "${args.format}". ${validList}`
16108
16238
  );
16109
16239
  }
16110
- if (!fs18.existsSync(args.memoryDir)) {
16240
+ if (!fs19.existsSync(args.memoryDir)) {
16111
16241
  throw new Error(
16112
16242
  `--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
16113
16243
  );
16114
16244
  }
16115
- if (!fs18.statSync(args.memoryDir).isDirectory()) {
16245
+ if (!fs19.statSync(args.memoryDir).isDirectory()) {
16116
16246
  throw new Error(
16117
16247
  `--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
16118
16248
  );
@@ -16198,10 +16328,10 @@ async function runTrainingExport(args, stdout = process.stdout) {
16198
16328
  }
16199
16329
  const formatted = adapter.formatRecords(records);
16200
16330
  const outDir = path18.dirname(args.output);
16201
- fs18.mkdirSync(outDir, { recursive: true });
16331
+ fs19.mkdirSync(outDir, { recursive: true });
16202
16332
  const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
16203
- fs18.writeFileSync(tmpPath, formatted, "utf-8");
16204
- fs18.renameSync(tmpPath, args.output);
16333
+ fs19.writeFileSync(tmpPath, formatted, "utf-8");
16334
+ fs19.renameSync(tmpPath, args.output);
16205
16335
  stdout.write(
16206
16336
  `Exported ${records.length} records to ${args.output} (${adapter.name} format)
16207
16337
  `
@@ -16379,7 +16509,7 @@ async function main(argv = process.argv.slice(2)) {
16379
16509
  }
16380
16510
  }, 500);
16381
16511
  };
16382
- fs18.watch(memoryDir, { recursive: true }, (_event, filename) => {
16512
+ fs19.watch(memoryDir, { recursive: true }, (_event, filename) => {
16383
16513
  if (filename && filename.startsWith(".")) return;
16384
16514
  rebuild();
16385
16515
  });
@@ -16387,12 +16517,12 @@ async function main(argv = process.argv.slice(2)) {
16387
16517
  });
16388
16518
  } else if (subAction === "validate") {
16389
16519
  const treeDir = outputDir;
16390
- if (!fs18.existsSync(treeDir)) {
16520
+ if (!fs19.existsSync(treeDir)) {
16391
16521
  console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
16392
16522
  process.exit(1);
16393
16523
  }
16394
16524
  const indexPath = path18.join(treeDir, "INDEX.md");
16395
- if (!fs18.existsSync(indexPath)) {
16525
+ if (!fs19.existsSync(indexPath)) {
16396
16526
  console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
16397
16527
  process.exit(1);
16398
16528
  }
@@ -16517,6 +16647,10 @@ Options:
16517
16647
  await runProceduralBinaryCommand(rest);
16518
16648
  break;
16519
16649
  }
16650
+ case "drift": {
16651
+ await runDriftBinaryCommand(rest);
16652
+ break;
16653
+ }
16520
16654
  case "extensions": {
16521
16655
  const action = rest[0] ?? "help";
16522
16656
  await cmdExtensions(action, rest.slice(1));
@@ -16574,10 +16708,10 @@ Other:
16574
16708
  let wearablesService;
16575
16709
  try {
16576
16710
  const configPath = resolveConfigPath();
16577
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
16578
- const remnicCfg = resolveRemnicConfigRecord8(raw);
16579
- const config = parseConfig9(remnicCfg);
16580
- 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);
16581
16715
  await wearablesOrchestrator.initialize();
16582
16716
  await wearablesOrchestrator.deferredReady;
16583
16717
  wearablesService = wearablesOrchestrator.getWearablesService();
@@ -16632,10 +16766,10 @@ Other:
16632
16766
  const targetFactory = async () => {
16633
16767
  if (!orchestratorSingleton) {
16634
16768
  const configPath = resolveConfigPath();
16635
- const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
16636
- const remnicCfg = resolveRemnicConfigRecord8(raw);
16637
- const config = parseConfig9(remnicCfg);
16638
- 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);
16639
16773
  await orchestratorSingleton.initialize();
16640
16774
  await orchestratorSingleton.deferredReady;
16641
16775
  }
@@ -16891,6 +17025,12 @@ Usage:
16891
17025
  merge / repair-flag / retire proposals from outcome telemetry; --apply
16892
17026
  executes them (requires procedural.maintenance.enabled). Mirrors the
16893
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.
16894
17034
  remnic training:export --format <name> --output <path> [options]
16895
17035
  Export memories as a fine-tuning dataset (issue #459). Run
16896
17036
  'remnic training:export --help' for the full option list.