@remnic/cli 9.65.1 → 9.65.2

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 +507 -437
  2. package/package.json +31 -31
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ async function persistEnrichmentCandidate(storage, entityName, candidate) {
18
18
  }
19
19
 
20
20
  // src/index.ts
21
- import fs17 from "fs";
21
+ import fs18 from "fs";
22
22
  import os3 from "os";
23
23
  import path18 from "path";
24
24
  import { createHash as createHash4 } from "crypto";
@@ -27,13 +27,13 @@ import * as childProcess2 from "child_process";
27
27
  import { fileURLToPath as fileURLToPath5 } from "url";
28
28
  import { gzipSync } from "zlib";
29
29
  import {
30
- parseConfig as parseConfig8,
30
+ parseConfig as parseConfig9,
31
31
  isOpenaiApiKeyDisabled,
32
32
  resolveEnvVars,
33
- resolveRemnicConfigRecord as resolveRemnicConfigRecord7,
33
+ resolveRemnicConfigRecord as resolveRemnicConfigRecord8,
34
34
  Orchestrator as Orchestrator5,
35
35
  EngramAccessService as EngramAccessService2,
36
- initLogger as initLogger3,
36
+ initLogger as initLogger4,
37
37
  onboard,
38
38
  curate,
39
39
  listReviewItems,
@@ -105,9 +105,7 @@ import {
105
105
  discoverMemoryExtensions,
106
106
  resolveExtensionsRoot,
107
107
  coerceInstallExtension,
108
- StorageManager as StorageManager2,
109
- computeProcedureStats,
110
- formatProcedureStatsText,
108
+ StorageManager as StorageManager3,
111
109
  parseXrayCliOptions,
112
110
  renderXray,
113
111
  extractWhoKnowsRawArgs,
@@ -119,6 +117,7 @@ import {
119
117
  OFFLINE_SYNC_SNAPSHOT_BASE_MAX_BODY_BYTES,
120
118
  applyOfflineSyncFileContentChunk as applyOfflineSyncFileContentChunk2,
121
119
  applyOfflineSyncSnapshot,
120
+ runPromotionCandidatesCommand,
122
121
  buildOfflineSyncChangesetFromSnapshot,
123
122
  drainPendingLifecycleForOfflineSync,
124
123
  compileOfflineSyncExcludeGlobs,
@@ -259,6 +258,200 @@ async function runExternalWikiBinaryCommand(rest) {
259
258
  }
260
259
  }
261
260
 
261
+ // src/commands/procedural.ts
262
+ import fs4 from "fs";
263
+ import {
264
+ StorageManager,
265
+ computeProcedureStats,
266
+ formatProcedureStatsText,
267
+ initLogger,
268
+ parseConfig as parseConfig4,
269
+ resolveRemnicConfigRecord as resolveRemnicConfigRecord4,
270
+ runProcedureLibraryMaintenance
271
+ } from "@remnic/core";
272
+
273
+ // src/cli-args.ts
274
+ function resolveFlag(args, flag) {
275
+ const idx = args.indexOf(flag);
276
+ if (idx === -1 || idx + 1 >= args.length) return void 0;
277
+ const value = args[idx + 1];
278
+ return isOptionToken(value) ? void 0 : value;
279
+ }
280
+ function isOptionToken(value) {
281
+ if (!value.startsWith("-")) return false;
282
+ if (/^-\d/.test(value) || /^-\.\d/.test(value)) return false;
283
+ return true;
284
+ }
285
+ function hasFlag(args, flag) {
286
+ return args.indexOf(flag) !== -1;
287
+ }
288
+ var TAXONOMY_RESOLVE_BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--json"]);
289
+ var TAXONOMY_RESOLVE_VALUE_FLAGS = /* @__PURE__ */ new Set(["--category"]);
290
+ function stripResolveFlags(args, booleanFlags = TAXONOMY_RESOLVE_BOOLEAN_FLAGS, valueFlags = TAXONOMY_RESOLVE_VALUE_FLAGS) {
291
+ return parseTaxonomyResolveArgs(args, booleanFlags, valueFlags).textParts;
292
+ }
293
+ function parseTaxonomyResolveArgs(args, booleanFlags = TAXONOMY_RESOLVE_BOOLEAN_FLAGS, valueFlags = TAXONOMY_RESOLVE_VALUE_FLAGS) {
294
+ const textParts = [];
295
+ const values = {};
296
+ const booleans = /* @__PURE__ */ new Set();
297
+ let literalText = false;
298
+ for (let i = 0; i < args.length; i++) {
299
+ const arg = args[i];
300
+ if (literalText) {
301
+ textParts.push(arg);
302
+ continue;
303
+ }
304
+ if (arg === "--") {
305
+ literalText = true;
306
+ continue;
307
+ }
308
+ if (arg.startsWith("--")) {
309
+ if (booleanFlags.has(arg)) {
310
+ booleans.add(arg);
311
+ continue;
312
+ }
313
+ if (valueFlags.has(arg)) {
314
+ const value = args[i + 1];
315
+ if (value === void 0 || value.startsWith("--")) {
316
+ throw new Error(`${arg} requires a value`);
317
+ }
318
+ values[arg] = value;
319
+ i++;
320
+ continue;
321
+ }
322
+ throw new Error(`Unknown flag: ${arg}`);
323
+ }
324
+ textParts.push(arg);
325
+ }
326
+ return { textParts, values, booleans };
327
+ }
328
+
329
+ // src/path-utils.ts
330
+ function resolveHomeDir() {
331
+ return process.env.HOME ?? process.env.USERPROFILE ?? "~";
332
+ }
333
+ function expandTilde(p) {
334
+ if (p === "~" || p.startsWith("~/") || p.startsWith("~\\")) {
335
+ return resolveHomeDir() + p.slice(1);
336
+ }
337
+ const home = resolveHomeDir();
338
+ if (p === "$HOME" || p.startsWith("$HOME/") || p.startsWith("$HOME\\")) {
339
+ return home + p.slice(5);
340
+ }
341
+ if (p === "${HOME}" || p.startsWith("${HOME}/") || p.startsWith("${HOME}\\")) {
342
+ return home + p.slice(7);
343
+ }
344
+ return p;
345
+ }
346
+
347
+ // src/commands/procedural.ts
348
+ async function runProceduralBinaryCommand(rest) {
349
+ initLogger();
350
+ const subcommand = rest[0];
351
+ if (!subcommand || subcommand === "--help" || subcommand === "-h") {
352
+ console.log(`remnic procedural \u2014 Procedural memory operations (issue #567)
353
+
354
+ Usage:
355
+ remnic procedural stats [--format json|text] [--memory-dir <path>]
356
+ remnic procedural maintain [--apply] [--format json|text] [--memory-dir <path>]
357
+
358
+ Subcommands:
359
+ stats Print counts by status + recent activity + active config.
360
+ maintain Run library-health maintenance (issue #2370): shadow
361
+ report of merge / repair-flag / retire proposals.
362
+ --apply executes them (requires
363
+ procedural.maintenance.enabled in config).
364
+
365
+ Shared with:
366
+ GET /engram/v1/procedural/stats
367
+ MCP remnic.procedural_stats (alias engram.procedural_stats)
368
+ MCP remnic.procedure_library_maintenance (alias engram.procedure_library_maintenance)`);
369
+ return;
370
+ }
371
+ if (subcommand !== "stats" && subcommand !== "maintain") {
372
+ console.error(
373
+ `Unknown procedural subcommand "${subcommand}". Run \`remnic procedural --help\` for usage.`
374
+ );
375
+ process.exit(1);
376
+ }
377
+ const args = rest.slice(1);
378
+ const formatPresent = hasFlag(args, "--format");
379
+ const formatRaw = resolveFlag(args, "--format");
380
+ if (formatPresent && (formatRaw === void 0 || formatRaw === null)) {
381
+ console.error("--format requires a value. Use `--format json` or `--format text`.");
382
+ process.exit(1);
383
+ }
384
+ const format = (() => {
385
+ if (!formatPresent || formatRaw === void 0 || formatRaw === null) return "text";
386
+ const normalized = String(formatRaw).trim().toLowerCase();
387
+ if (normalized !== "text" && normalized !== "json") {
388
+ console.error(`Invalid --format "${formatRaw}". Allowed: text, json.`);
389
+ process.exit(1);
390
+ }
391
+ return normalized;
392
+ })();
393
+ const memoryDirPresent = hasFlag(args, "--memory-dir");
394
+ const memoryDirOverride = resolveFlag(args, "--memory-dir");
395
+ if (memoryDirPresent && (memoryDirOverride === void 0 || memoryDirOverride === null)) {
396
+ console.error("--memory-dir requires a path. Omit the flag to use the resolved default.");
397
+ process.exit(1);
398
+ }
399
+ const configPath = resolveConfigPath();
400
+ const raw = fs4.existsSync(configPath) ? JSON.parse(fs4.readFileSync(configPath, "utf8")) : {};
401
+ const config = parseConfig4(resolveRemnicConfigRecord4(raw));
402
+ const memoryDir = expandTilde(
403
+ typeof memoryDirOverride === "string" && memoryDirOverride.length > 0 ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
404
+ );
405
+ const storage = new StorageManager(memoryDir);
406
+ if (subcommand === "maintain") {
407
+ const report2 = await runProcedureLibraryMaintenance({
408
+ memoryDir,
409
+ storage,
410
+ config,
411
+ apply: hasFlag(args, "--apply")
412
+ });
413
+ if (format === "json") {
414
+ process.stdout.write(JSON.stringify(report2, null, 2) + "\n");
415
+ return;
416
+ }
417
+ process.stdout.write(formatProcedureMaintenanceText(report2));
418
+ return;
419
+ }
420
+ const report = await computeProcedureStats({ storage, config });
421
+ if (format === "json") {
422
+ process.stdout.write(JSON.stringify(report, null, 2) + "\n");
423
+ return;
424
+ }
425
+ process.stdout.write(formatProcedureStatsText(report));
426
+ }
427
+ function formatProcedureMaintenanceText(report) {
428
+ const lines = [
429
+ `Procedure library maintenance (schema v${report.schemaVersion}, ${report.mode})`,
430
+ ` generated: ${report.generatedAt}`,
431
+ ` scanned: ${report.scannedProcedures}`
432
+ ];
433
+ if (report.skippedReason) {
434
+ lines.push(` skipped: ${report.skippedReason}`);
435
+ }
436
+ lines.push(` proposed: ${report.proposed.length}`);
437
+ lines.push(` applied: ${report.appliedCount}`);
438
+ for (const action of report.proposed) {
439
+ lines.push("");
440
+ lines.push(` [${action.action}] ${action.reasonCode}`);
441
+ lines.push(` ids: ${action.memoryIds.join(", ")}`);
442
+ if (action.canonicalId) {
443
+ lines.push(` canonical: ${action.canonicalId}`);
444
+ }
445
+ lines.push(` reason: ${action.reason}`);
446
+ for (const ev of action.evidence) {
447
+ lines.push(
448
+ ` ${ev.memoryId}: mw_success=${ev.mwSuccess} mw_fail=${ev.mwFail} lastAccessed=${ev.lastAccessed ?? "(none)"}`
449
+ );
450
+ }
451
+ }
452
+ return lines.join("\n") + "\n";
453
+ }
454
+
262
455
  // src/optional-module-loader.ts
263
456
  function isSpecifierNotFoundError(err, specifier) {
264
457
  if (!err || typeof err !== "object") {
@@ -309,13 +502,13 @@ async function loadWecloneExportModule() {
309
502
  }
310
503
 
311
504
  // src/converge.ts
312
- import * as fs5 from "fs";
505
+ import * as fs6 from "fs";
313
506
  import { createHash as createHash3 } from "crypto";
314
507
  import * as path2 from "path";
315
508
  import {
316
509
  CONVERGE_CONFLICT_POLICIES,
317
510
  DEFAULT_CONVERGE_CONFLICT_POLICY,
318
- parseConfig as parseConfig4,
511
+ parseConfig as parseConfig5,
319
512
  buildOfflineSyncSnapshotFromBase,
320
513
  applyOfflineSyncFileContentChunk,
321
514
  isInternalRemnicStatePath as isInternalRemnicStatePath3,
@@ -341,12 +534,12 @@ import {
341
534
 
342
535
  // src/offline-storage-io.ts
343
536
  import { createDecipheriv, createHash } from "crypto";
344
- import fs4 from "fs";
537
+ import fs5 from "fs";
345
538
  import { lstat, mkdtemp, readdir, rm } from "fs/promises";
346
539
  import path from "path";
347
540
  import {
348
541
  OFFLINE_SYNC_FILE_CONTENT_TRANSFER_CHUNK_BYTES,
349
- StorageManager,
542
+ StorageManager as StorageManager2,
350
543
  createSupportPassportPrivateFileExclusion
351
544
  } from "@remnic/core";
352
545
  import { OFFLINE_DECRYPT_STAGING_DIR_PREFIX } from "@remnic/core/offline-sync-exclude-globs";
@@ -391,7 +584,7 @@ async function filterOfflineSyncBaseFiles(memoryDir, files, excludeFile) {
391
584
  return files.filter((_file, index) => excluded[index] === false);
392
585
  }
393
586
  async function createConfiguredOfflineStorage(memoryDir, secureStoreEncryptOnWrite = true) {
394
- const storage = new StorageManager(memoryDir);
587
+ const storage = new StorageManager2(memoryDir);
395
588
  const header = await readHeader(memoryDir);
396
589
  let secureStoreKey = null;
397
590
  let secureStoreRequired = false;
@@ -416,7 +609,7 @@ async function createOfflineStorageForPath(memoryDir, filePath, configured, secu
416
609
  if (storageRoot !== memoryRoot && !storageRoot.startsWith(`${memoryRoot}${path.sep}`)) {
417
610
  throw new Error(`lifecycle ledger path is outside the offline memory directory: ${filePath}`);
418
611
  }
419
- const storage = new StorageManager(storageRoot);
612
+ const storage = new StorageManager2(storageRoot);
420
613
  if (configured.secureStoreRequired) {
421
614
  storage.setSecureStoreRequired(true);
422
615
  }
@@ -503,7 +696,7 @@ async function* readOfflineSyncFileChunks(options) {
503
696
  });
504
697
  }
505
698
  async function readFilePrefix(filePath, length) {
506
- const handle = await fs4.promises.open(filePath, "r");
699
+ const handle = await fs5.promises.open(filePath, "r");
507
700
  try {
508
701
  const out = Buffer.alloc(length);
509
702
  const { bytesRead } = await handle.read(out, 0, length, 0);
@@ -513,7 +706,7 @@ async function readFilePrefix(filePath, length) {
513
706
  }
514
707
  }
515
708
  async function* readPlainOfflineFileChunks(filePath, chunkSize) {
516
- const stream = fs4.createReadStream(filePath, { highWaterMark: chunkSize });
709
+ const stream = fs5.createReadStream(filePath, { highWaterMark: chunkSize });
517
710
  for await (const chunk of stream) {
518
711
  yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
519
712
  }
@@ -550,9 +743,9 @@ async function* readEncryptedOfflineFileChunks(options) {
550
743
  });
551
744
  decipher.setAuthTag(authTag);
552
745
  decipher.setAAD(Buffer.concat([secureStoreEnvelopeHeaderAad(salt), aad]));
553
- const output = fs4.createWriteStream(tempPath, { mode: 384 });
746
+ const output = fs5.createWriteStream(tempPath, { mode: 384 });
554
747
  try {
555
- const stream = fs4.createReadStream(options.filePath, {
748
+ const stream = fs5.createReadStream(options.filePath, {
556
749
  start: MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE,
557
750
  highWaterMark: options.chunkSize
558
751
  });
@@ -1162,7 +1355,7 @@ async function readLocalTombstoneEvidence(rootDir) {
1162
1355
  for (const relativePath of TOMBSTONE_PATHS) {
1163
1356
  let content;
1164
1357
  try {
1165
- content = await fs5.promises.readFile(path2.join(rootDir, relativePath), "utf-8");
1358
+ content = await fs6.promises.readFile(path2.join(rootDir, relativePath), "utf-8");
1166
1359
  } catch (error) {
1167
1360
  if (error.code === "ENOENT") continue;
1168
1361
  throw error;
@@ -1177,7 +1370,7 @@ async function discoverCursorNamespaces(memoryDir, peerUrl) {
1177
1370
  const cursorDir = path2.join(path2.resolve(memoryDir), ".remnic", "state", "converge-cursors");
1178
1371
  let entries;
1179
1372
  try {
1180
- entries = await fs5.promises.readdir(cursorDir, { withFileTypes: true });
1373
+ entries = await fs6.promises.readdir(cursorDir, { withFileTypes: true });
1181
1374
  } catch (error) {
1182
1375
  if (error.code === "ENOENT") return [];
1183
1376
  throw error;
@@ -1253,7 +1446,7 @@ async function computeConvergePlan(options = {}) {
1253
1446
  let config = options.config;
1254
1447
  if (!config) {
1255
1448
  try {
1256
- config = parseConfig4({});
1449
+ config = parseConfig5({});
1257
1450
  } catch {
1258
1451
  }
1259
1452
  }
@@ -1504,7 +1697,7 @@ async function executeConvergeApply(options = {}) {
1504
1697
  let config = options.config;
1505
1698
  if (!config) {
1506
1699
  try {
1507
- config = parseConfig4({});
1700
+ config = parseConfig5({});
1508
1701
  } catch {
1509
1702
  }
1510
1703
  }
@@ -1667,7 +1860,7 @@ async function executeConvergeApply(options = {}) {
1667
1860
  if (current.sha256 !== entry.localSha256) {
1668
1861
  throw new Error(`local file changed during push: ${localPath}`);
1669
1862
  }
1670
- const stat2 = await fs5.promises.stat(filePath);
1863
+ const stat2 = await fs6.promises.stat(filePath);
1671
1864
  let chunks;
1672
1865
  let chunkOffset = 0;
1673
1866
  const resetChunks = async () => {
@@ -1944,7 +2137,7 @@ function formatConvergeApplyReport(result) {
1944
2137
  lines.push(formatConvergeReport(result.plan));
1945
2138
  return lines.join("\n");
1946
2139
  }
1947
- async function cmdConverge(action, rest, json, config = parseConfig4({})) {
2140
+ async function cmdConverge(action, rest, json, config = parseConfig5({})) {
1948
2141
  if (action === "help" || action === "--help" || action === "-h" || rest.includes("--help") || rest.includes("-h")) {
1949
2142
  console.log(`Usage: remnic converge <plan|apply> [options]
1950
2143
 
@@ -2150,8 +2343,8 @@ function renderReplayResult(result, targetNamespace, format) {
2150
2343
  }
2151
2344
 
2152
2345
  // src/quarantine-replay.ts
2153
- import * as fs6 from "fs";
2154
- import { EngramAccessService, Orchestrator as Orchestrator3, initLogger, parseConfig as parseConfig5, resolveRemnicConfigRecord as resolveRemnicConfigRecord4 } from "@remnic/core";
2346
+ import * as fs7 from "fs";
2347
+ import { EngramAccessService, Orchestrator as Orchestrator3, initLogger as initLogger2, parseConfig as parseConfig6, resolveRemnicConfigRecord as resolveRemnicConfigRecord5 } from "@remnic/core";
2155
2348
  import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
2156
2349
  function valueFlag(args, flag) {
2157
2350
  const occurrences = args.filter((a) => a === flag).length;
@@ -2195,12 +2388,12 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
2195
2388
  process.exitCode = 2;
2196
2389
  return;
2197
2390
  }
2198
- initLogger();
2391
+ initLogger2();
2199
2392
  let orchestrator;
2200
2393
  try {
2201
2394
  const configPath = resolveConfigPath2();
2202
- const raw = fs6.existsSync(configPath) ? JSON.parse(fs6.readFileSync(configPath, "utf8")) : {};
2203
- const config = parseConfig5(resolveRemnicConfigRecord4(raw));
2395
+ const raw = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
2396
+ const config = parseConfig6(resolveRemnicConfigRecord5(raw));
2204
2397
  orchestrator = new Orchestrator3(config);
2205
2398
  await orchestrator.initialize();
2206
2399
  await orchestrator.deferredReady;
@@ -2231,15 +2424,15 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
2231
2424
  }
2232
2425
 
2233
2426
  // src/offline-impression-rotation.ts
2234
- import fs7 from "fs";
2235
- import { parseConfig as parseConfig6, resolveRemnicConfigRecord as resolveRemnicConfigRecord5, drainPendingImpressionsForOfflineSync } from "@remnic/core";
2427
+ import fs8 from "fs";
2428
+ import { parseConfig as parseConfig7, resolveRemnicConfigRecord as resolveRemnicConfigRecord6, drainPendingImpressionsForOfflineSync } from "@remnic/core";
2236
2429
  import { LastRecallStore } from "@remnic/core/recall-state";
2237
2430
  function parseConfigQuietly(raw) {
2238
2431
  const originalWarn = console.warn;
2239
2432
  console.warn = () => {
2240
2433
  };
2241
2434
  try {
2242
- return parseConfig6(resolveRemnicConfigRecord5(raw));
2435
+ return parseConfig7(resolveRemnicConfigRecord6(raw));
2243
2436
  } finally {
2244
2437
  console.warn = originalWarn;
2245
2438
  }
@@ -2253,7 +2446,7 @@ var OFFLINE_CONFIG_KEYS = [
2253
2446
  function pickOfflineConfigRecord(raw) {
2254
2447
  let resolved;
2255
2448
  try {
2256
- resolved = resolveRemnicConfigRecord5(raw);
2449
+ resolved = resolveRemnicConfigRecord6(raw);
2257
2450
  } catch {
2258
2451
  resolved = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
2259
2452
  }
@@ -2266,7 +2459,7 @@ function pickOfflineConfigRecord(raw) {
2266
2459
  function resolveOfflineImpressionRotation(configPath) {
2267
2460
  let raw;
2268
2461
  try {
2269
- raw = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
2462
+ raw = fs8.existsSync(configPath) ? JSON.parse(fs8.readFileSync(configPath, "utf8")) : {};
2270
2463
  } catch {
2271
2464
  throw new Error(
2272
2465
  `cannot read recall-impression rotation from ${configPath}: config file could not be read as JSON`
@@ -2524,12 +2717,12 @@ function assertBenchModuleFreshForDevelopment() {
2524
2717
  }
2525
2718
 
2526
2719
  // src/cmd-security.ts
2527
- import fs8 from "fs";
2720
+ import fs9 from "fs";
2528
2721
  import {
2529
2722
  Orchestrator as Orchestrator4,
2530
- parseConfig as parseConfig7,
2531
- initLogger as initLogger2,
2532
- resolveRemnicConfigRecord as resolveRemnicConfigRecord6,
2723
+ parseConfig as parseConfig8,
2724
+ initLogger as initLogger3,
2725
+ resolveRemnicConfigRecord as resolveRemnicConfigRecord7,
2533
2726
  runAuditMemoryCliCommand,
2534
2727
  formatAuditMemoryReport
2535
2728
  } from "@remnic/core";
@@ -2542,10 +2735,10 @@ async function cmdSecurity(rest) {
2542
2735
  process.exitCode = 1;
2543
2736
  return;
2544
2737
  }
2545
- initLogger2();
2738
+ initLogger3();
2546
2739
  const configPath = resolveConfigPath();
2547
- const raw = fs8.existsSync(configPath) ? JSON.parse(fs8.readFileSync(configPath, "utf8")) : {};
2548
- const config = parseConfig7(resolveRemnicConfigRecord6(raw));
2740
+ const raw = fs9.existsSync(configPath) ? JSON.parse(fs9.readFileSync(configPath, "utf8")) : {};
2741
+ const config = parseConfig8(resolveRemnicConfigRecord7(raw));
2549
2742
  const orchestrator = new Orchestrator4(config);
2550
2743
  await orchestrator.initialize();
2551
2744
  try {
@@ -2569,7 +2762,7 @@ async function cmdSecurity(rest) {
2569
2762
  }
2570
2763
 
2571
2764
  // src/daemon-service-candidates.ts
2572
- import fs9 from "fs";
2765
+ import fs10 from "fs";
2573
2766
  import path5 from "path";
2574
2767
  var LAUNCHD_LABEL = "ai.remnic.daemon";
2575
2768
  var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
@@ -2591,7 +2784,7 @@ function systemdUnitPaths(homeDir) {
2591
2784
  function anyFileExists(paths) {
2592
2785
  return paths.some((candidate) => {
2593
2786
  try {
2594
- return fs9.statSync(candidate).isFile();
2787
+ return fs10.statSync(candidate).isFile();
2595
2788
  } catch {
2596
2789
  return false;
2597
2790
  }
@@ -2603,7 +2796,7 @@ function commandNames(command) {
2603
2796
  }
2604
2797
  function isRunnableNodeScript(filePath) {
2605
2798
  try {
2606
- const text = fs9.readFileSync(filePath, "utf8").slice(0, 4096);
2799
+ const text = fs10.readFileSync(filePath, "utf8").slice(0, 4096);
2607
2800
  const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
2608
2801
  if (/^#!.*\bnode\b/.test(firstLine)) return true;
2609
2802
  if (firstLine.startsWith("#!")) return false;
@@ -2616,7 +2809,7 @@ function isRunnableNodeScript(filePath) {
2616
2809
  function resolveShimNodeScript(filePath) {
2617
2810
  let text;
2618
2811
  try {
2619
- text = fs9.readFileSync(filePath, "utf8").slice(0, 16384);
2812
+ text = fs10.readFileSync(filePath, "utf8").slice(0, 16384);
2620
2813
  } catch {
2621
2814
  return void 0;
2622
2815
  }
@@ -2628,8 +2821,8 @@ function resolveShimNodeScript(filePath) {
2628
2821
  const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
2629
2822
  const resolved = path5.isAbsolute(candidate) ? candidate : path5.resolve(basedir, candidate);
2630
2823
  try {
2631
- if (fs9.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
2632
- return fs9.realpathSync(resolved);
2824
+ if (fs10.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
2825
+ return fs10.realpathSync(resolved);
2633
2826
  }
2634
2827
  } catch {
2635
2828
  }
@@ -2637,7 +2830,7 @@ function resolveShimNodeScript(filePath) {
2637
2830
  return void 0;
2638
2831
  }
2639
2832
  function resolveRunnableNodeScript(filePath) {
2640
- const realPath = fs9.realpathSync(filePath);
2833
+ const realPath = fs10.realpathSync(filePath);
2641
2834
  if (isRunnableNodeScript(realPath)) return realPath;
2642
2835
  return resolveShimNodeScript(realPath);
2643
2836
  }
@@ -2647,9 +2840,9 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
2647
2840
  for (const name of commandNames(command)) {
2648
2841
  const candidate = path5.join(dir, name);
2649
2842
  try {
2650
- const stat2 = fs9.statSync(candidate);
2843
+ const stat2 = fs10.statSync(candidate);
2651
2844
  if (!stat2.isFile()) continue;
2652
- if (process.platform !== "win32") fs9.accessSync(candidate, fs9.constants.X_OK);
2845
+ if (process.platform !== "win32") fs10.accessSync(candidate, fs10.constants.X_OK);
2653
2846
  const runnable = resolveRunnableNodeScript(candidate);
2654
2847
  if (runnable) return runnable;
2655
2848
  } catch {
@@ -3049,24 +3242,6 @@ function collectBenchmarks(argv) {
3049
3242
  return benchmarks;
3050
3243
  }
3051
3244
 
3052
- // src/path-utils.ts
3053
- function resolveHomeDir() {
3054
- return process.env.HOME ?? process.env.USERPROFILE ?? "~";
3055
- }
3056
- function expandTilde(p) {
3057
- if (p === "~" || p.startsWith("~/") || p.startsWith("~\\")) {
3058
- return resolveHomeDir() + p.slice(1);
3059
- }
3060
- const home = resolveHomeDir();
3061
- if (p === "$HOME" || p.startsWith("$HOME/") || p.startsWith("$HOME\\")) {
3062
- return home + p.slice(5);
3063
- }
3064
- if (p === "${HOME}" || p.startsWith("${HOME}/") || p.startsWith("${HOME}\\")) {
3065
- return home + p.slice(7);
3066
- }
3067
- return p;
3068
- }
3069
-
3070
3245
  // src/bench-args-research.ts
3071
3246
  import path6 from "path";
3072
3247
  function readPositiveInteger(args, flag) {
@@ -4140,7 +4315,7 @@ function finalizeBenchStatus(filePath) {
4140
4315
  }
4141
4316
 
4142
4317
  // src/bench-fallback.ts
4143
- import fs10 from "fs";
4318
+ import fs11 from "fs";
4144
4319
  import path9 from "path";
4145
4320
  var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
4146
4321
  function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
@@ -4212,7 +4387,7 @@ function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs
4212
4387
  );
4213
4388
  }
4214
4389
  function resolveFallbackBenchResultPath(outputDir) {
4215
- const entries = fs10.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
4390
+ const entries = fs11.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
4216
4391
  if (entries.length === 0) {
4217
4392
  throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
4218
4393
  }
@@ -4220,7 +4395,7 @@ function resolveFallbackBenchResultPath(outputDir) {
4220
4395
  }
4221
4396
 
4222
4397
  // src/openclaw-upgrade-swap.ts
4223
- import fs11 from "fs";
4398
+ import fs12 from "fs";
4224
4399
  import path10 from "path";
4225
4400
  function describeError(error) {
4226
4401
  return error instanceof Error ? error.message : String(error);
@@ -4232,7 +4407,7 @@ function createSiblingTempFilePath(targetPath, label) {
4232
4407
  function resolveAtomicWriteMode(targetPath, explicitMode) {
4233
4408
  if (explicitMode !== void 0) return explicitMode;
4234
4409
  try {
4235
- return fs11.statSync(targetPath).mode & 4095;
4410
+ return fs12.statSync(targetPath).mode & 4095;
4236
4411
  } catch (error) {
4237
4412
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
4238
4413
  return 384;
@@ -4242,8 +4417,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
4242
4417
  }
4243
4418
  function resolveAtomicReplacementPath(targetPath) {
4244
4419
  try {
4245
- if (fs11.lstatSync(targetPath).isSymbolicLink()) {
4246
- return fs11.realpathSync(targetPath);
4420
+ if (fs12.lstatSync(targetPath).isSymbolicLink()) {
4421
+ return fs12.realpathSync(targetPath);
4247
4422
  }
4248
4423
  } catch (error) {
4249
4424
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -4260,7 +4435,7 @@ function createSiblingSwapPath(targetDir, label) {
4260
4435
  function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
4261
4436
  if (!displacedDir) return void 0;
4262
4437
  try {
4263
- fs11.rmSync(displacedDir, { recursive: true, force: true });
4438
+ fs12.rmSync(displacedDir, { recursive: true, force: true });
4264
4439
  return void 0;
4265
4440
  } catch (error) {
4266
4441
  return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
@@ -4268,43 +4443,43 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
4268
4443
  }
4269
4444
  function atomicWriteFileSync(targetPath, data, options = {}) {
4270
4445
  const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
4271
- fs11.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4446
+ fs12.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4272
4447
  const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
4273
4448
  const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
4274
4449
  try {
4275
4450
  if (options.hooks?.writeTempFileSync) {
4276
4451
  options.hooks.writeTempFileSync(tempPath);
4277
4452
  } else {
4278
- fs11.writeFileSync(tempPath, data, { mode });
4453
+ fs12.writeFileSync(tempPath, data, { mode });
4279
4454
  }
4280
- fs11.chmodSync(tempPath, mode);
4281
- const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs11.renameSync;
4455
+ fs12.chmodSync(tempPath, mode);
4456
+ const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs12.renameSync;
4282
4457
  renameTempFileSync(tempPath, resolvedTargetPath);
4283
4458
  } catch (error) {
4284
- fs11.rmSync(tempPath, { force: true });
4459
+ fs12.rmSync(tempPath, { force: true });
4285
4460
  throw error;
4286
4461
  }
4287
4462
  }
4288
4463
  function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
4289
- if (!fs11.existsSync(sourcePath)) return;
4464
+ if (!fs12.existsSync(sourcePath)) return;
4290
4465
  const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
4291
- fs11.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4466
+ fs12.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
4292
4467
  const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
4293
- const mode = fs11.statSync(sourcePath).mode & 4095;
4468
+ const mode = fs12.statSync(sourcePath).mode & 4095;
4294
4469
  try {
4295
- const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs11.copyFileSync;
4470
+ const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs12.copyFileSync;
4296
4471
  copyTempFileSync(sourcePath, tempPath);
4297
- fs11.chmodSync(tempPath, mode);
4298
- const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs11.renameSync;
4472
+ fs12.chmodSync(tempPath, mode);
4473
+ const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs12.renameSync;
4299
4474
  renameTempFileSync(tempPath, resolvedTargetPath);
4300
4475
  } catch (error) {
4301
- fs11.rmSync(tempPath, { force: true });
4476
+ fs12.rmSync(tempPath, { force: true });
4302
4477
  throw error;
4303
4478
  }
4304
4479
  }
4305
4480
  function cleanupRollbackDirectory(rollbackDir) {
4306
4481
  if (!rollbackDir) return;
4307
- fs11.rmSync(rollbackDir, { recursive: true, force: true });
4482
+ fs12.rmSync(rollbackDir, { recursive: true, force: true });
4308
4483
  }
4309
4484
  function cleanupRollbackDirectoryBestEffort(rollbackDir) {
4310
4485
  if (!rollbackDir) return void 0;
@@ -4316,20 +4491,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
4316
4491
  }
4317
4492
  }
4318
4493
  function restoreDirectoryFromRollback(targetDir, rollbackDir) {
4319
- if (!fs11.existsSync(rollbackDir)) {
4494
+ if (!fs12.existsSync(rollbackDir)) {
4320
4495
  throw new Error(`Rollback directory is missing: ${rollbackDir}`);
4321
4496
  }
4322
- fs11.mkdirSync(path10.dirname(targetDir), { recursive: true });
4323
- const displacedDir = fs11.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
4497
+ fs12.mkdirSync(path10.dirname(targetDir), { recursive: true });
4498
+ const displacedDir = fs12.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
4324
4499
  if (displacedDir) {
4325
- fs11.renameSync(targetDir, displacedDir);
4500
+ fs12.renameSync(targetDir, displacedDir);
4326
4501
  }
4327
4502
  try {
4328
- fs11.renameSync(rollbackDir, targetDir);
4503
+ fs12.renameSync(rollbackDir, targetDir);
4329
4504
  } catch (restoreError) {
4330
- if (displacedDir && fs11.existsSync(displacedDir)) {
4505
+ if (displacedDir && fs12.existsSync(displacedDir)) {
4331
4506
  try {
4332
- fs11.renameSync(displacedDir, targetDir);
4507
+ fs12.renameSync(displacedDir, targetDir);
4333
4508
  } catch (revertError) {
4334
4509
  throw new AggregateError(
4335
4510
  [restoreError, revertError],
@@ -4345,23 +4520,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
4345
4520
  return cleanupDisplacedDirectoryBestEffort(displacedDir, `restored the previous plugin copy into ${targetDir}`);
4346
4521
  }
4347
4522
  function restoreDirectoryFromBackup(targetDir, backupDir) {
4348
- if (!fs11.existsSync(backupDir)) {
4523
+ if (!fs12.existsSync(backupDir)) {
4349
4524
  throw new Error(`Plugin backup directory is missing: ${backupDir}`);
4350
4525
  }
4351
- fs11.mkdirSync(path10.dirname(targetDir), { recursive: true });
4526
+ fs12.mkdirSync(path10.dirname(targetDir), { recursive: true });
4352
4527
  const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
4353
- const displacedDir = fs11.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
4354
- fs11.cpSync(backupDir, stagedDir, { recursive: true });
4528
+ const displacedDir = fs12.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
4529
+ fs12.cpSync(backupDir, stagedDir, { recursive: true });
4355
4530
  if (displacedDir) {
4356
- fs11.renameSync(targetDir, displacedDir);
4531
+ fs12.renameSync(targetDir, displacedDir);
4357
4532
  }
4358
4533
  try {
4359
- fs11.renameSync(stagedDir, targetDir);
4534
+ fs12.renameSync(stagedDir, targetDir);
4360
4535
  } catch (restoreError) {
4361
- fs11.rmSync(targetDir, { recursive: true, force: true });
4362
- if (displacedDir && fs11.existsSync(displacedDir)) {
4536
+ fs12.rmSync(targetDir, { recursive: true, force: true });
4537
+ if (displacedDir && fs12.existsSync(displacedDir)) {
4363
4538
  try {
4364
- fs11.renameSync(displacedDir, targetDir);
4539
+ fs12.renameSync(displacedDir, targetDir);
4365
4540
  } catch (revertError) {
4366
4541
  throw new AggregateError(
4367
4542
  [restoreError, revertError],
@@ -4369,7 +4544,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
4369
4544
  );
4370
4545
  }
4371
4546
  }
4372
- fs11.rmSync(stagedDir, { recursive: true, force: true });
4547
+ fs12.rmSync(stagedDir, { recursive: true, force: true });
4373
4548
  throw new Error(
4374
4549
  `Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
4375
4550
  { cause: restoreError }
@@ -4394,7 +4569,7 @@ function rollbackOpenclawUpgrade({
4394
4569
  let configRemovalAttempted = false;
4395
4570
  let pluginRestored = false;
4396
4571
  try {
4397
- if (rollbackDir && fs11.existsSync(rollbackDir)) {
4572
+ if (rollbackDir && fs12.existsSync(rollbackDir)) {
4398
4573
  const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
4399
4574
  notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
4400
4575
  if (cleanupWarning) notes.push(cleanupWarning);
@@ -4404,7 +4579,7 @@ function rollbackOpenclawUpgrade({
4404
4579
  rollbackRestoreError = error instanceof Error ? error.message : String(error);
4405
4580
  }
4406
4581
  try {
4407
- if (!pluginRestored && pluginBackupDir && fs11.existsSync(pluginBackupDir)) {
4582
+ if (!pluginRestored && pluginBackupDir && fs12.existsSync(pluginBackupDir)) {
4408
4583
  const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
4409
4584
  if (rollbackRestoreError) {
4410
4585
  notes.push(`Rollback copy restore failed; restored previous plugin from durable backup at ${pluginBackupDir}`);
@@ -4429,12 +4604,12 @@ function rollbackOpenclawUpgrade({
4429
4604
  notes.push("No previous plugin copy was available for automatic restore");
4430
4605
  }
4431
4606
  try {
4432
- if (configBackupPath && fs11.existsSync(configBackupPath)) {
4607
+ if (configBackupPath && fs12.existsSync(configBackupPath)) {
4433
4608
  restoreFileFromBackup(configPath, configBackupPath);
4434
4609
  notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
4435
- } else if (removeConfigIfUnbacked && fs11.existsSync(configPath)) {
4610
+ } else if (removeConfigIfUnbacked && fs12.existsSync(configPath)) {
4436
4611
  configRemovalAttempted = true;
4437
- fs11.rmSync(configPath, { force: true });
4612
+ fs12.rmSync(configPath, { force: true });
4438
4613
  notes.push("Removed OpenClaw config created during the failed upgrade");
4439
4614
  }
4440
4615
  } catch (error) {
@@ -4487,7 +4662,7 @@ Run this manually when you're ready:
4487
4662
 
4488
4663
  // src/openclaw-managed-upgrade-loader.ts
4489
4664
  import { execFileSync } from "child_process";
4490
- import fs12 from "fs";
4665
+ import fs13 from "fs";
4491
4666
  import os from "os";
4492
4667
  import path11 from "path";
4493
4668
  import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
@@ -4563,7 +4738,7 @@ function buildOpenclawManagedUpgradePackageSpec(version = "latest") {
4563
4738
  function readCliAdapterRange() {
4564
4739
  const moduleDir = path11.dirname(fileURLToPath3(import.meta.url));
4565
4740
  const manifestPath = path11.resolve(moduleDir, "../package.json");
4566
- const manifest = JSON.parse(fs12.readFileSync(manifestPath, "utf8"));
4741
+ const manifest = JSON.parse(fs13.readFileSync(manifestPath, "utf8"));
4567
4742
  if (manifest.name !== "@remnic/cli") {
4568
4743
  throw new Error(`Invalid @remnic/cli package manifest at ${manifestPath}.`);
4569
4744
  }
@@ -4607,7 +4782,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
4607
4782
  const adapterMissing = isSpecifierNotFoundError(error, OPENCLAW_PLUGIN_PACKAGE) || isSpecifierNotFoundError(error, MANAGED_UPGRADE_SPECIFIER) || isManagedUpgradeSubpathMissing(error);
4608
4783
  if (!adapterMissing) throw error;
4609
4784
  }
4610
- const temporaryRoot = fs12.mkdtempSync(path11.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
4785
+ const temporaryRoot = fs13.mkdtempSync(path11.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
4611
4786
  try {
4612
4787
  const toolingPackageSpec = `${OPENCLAW_PLUGIN_PACKAGE}@${readCliAdapterRange()}`;
4613
4788
  const installArgs = [
@@ -4622,12 +4797,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
4622
4797
  ];
4623
4798
  (hooks.runNpmInstall ?? runNpmInstall)(installArgs);
4624
4799
  const resolverPath = path11.join(temporaryRoot, "load-managed-upgrade.mjs");
4625
- fs12.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
4800
+ fs13.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
4626
4801
  `, "utf8");
4627
4802
  return await importModule(pathToFileURL2(resolverPath).href);
4628
4803
  } finally {
4629
4804
  try {
4630
- fs12.rmSync(temporaryRoot, { recursive: true, force: true });
4805
+ fs13.rmSync(temporaryRoot, { recursive: true, force: true });
4631
4806
  } catch (error) {
4632
4807
  const detail = error instanceof Error ? error.message : String(error);
4633
4808
  console.warn(`Could not remove temporary managed upgrade project at ${temporaryRoot}: ${detail}`);
@@ -4636,13 +4811,13 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
4636
4811
  }
4637
4812
 
4638
4813
  // src/remote-daemon.ts
4639
- import fs13 from "fs";
4814
+ import fs14 from "fs";
4640
4815
  function readCompatEnv(primary, legacy) {
4641
4816
  return process.env[primary] ?? process.env[legacy];
4642
4817
  }
4643
4818
  function readRemnicConfigRecord(configPath) {
4644
4819
  try {
4645
- const parsed = JSON.parse(fs13.readFileSync(configPath, "utf8"));
4820
+ const parsed = JSON.parse(fs14.readFileSync(configPath, "utf8"));
4646
4821
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
4647
4822
  return parsed;
4648
4823
  }
@@ -4871,7 +5046,7 @@ async function remoteRecallXray(daemon, request) {
4871
5046
  }
4872
5047
 
4873
5048
  // src/daemon-service.ts
4874
- import fs14 from "fs";
5049
+ import fs15 from "fs";
4875
5050
  import path12 from "path";
4876
5051
  import * as childProcess from "child_process";
4877
5052
  import { fileURLToPath as fileURLToPath4 } from "url";
@@ -4883,7 +5058,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
4883
5058
  processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
4884
5059
  }
4885
5060
  function resolveServerBinDetails(options = {}) {
4886
- const existsSync4 = options.existsSync ?? fs14.existsSync;
5061
+ const existsSync4 = options.existsSync ?? fs15.existsSync;
4887
5062
  const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
4888
5063
  const moduleDir = options.moduleDir ?? thisModuleDir;
4889
5064
  const packageResolve = options.packageResolve ?? resolveImportSpecifier;
@@ -4942,8 +5117,8 @@ function resolveServerBin(options = {}) {
4942
5117
  return resolveServerBinDetails(options).path;
4943
5118
  }
4944
5119
  function readVerifiedDaemonPid(options) {
4945
- const readFileSync4 = options.readFileSync ?? fs14.readFileSync;
4946
- const unlinkSync = options.unlinkSync ?? fs14.unlinkSync;
5120
+ const readFileSync4 = options.readFileSync ?? fs15.readFileSync;
5121
+ const unlinkSync = options.unlinkSync ?? fs15.unlinkSync;
4947
5122
  const processKill = options.processKill ?? process.kill;
4948
5123
  const platform = options.platform ?? process.platform;
4949
5124
  const execFileSync4 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
@@ -5043,8 +5218,8 @@ function removePidFileBestEffort(file, unlinkSync) {
5043
5218
  }
5044
5219
  }
5045
5220
  function inspectLaunchdPlist(plistPath, options = {}) {
5046
- const existsSync4 = options.existsSync ?? fs14.existsSync;
5047
- const readFileSync4 = options.readFileSync ?? fs14.readFileSync;
5221
+ const existsSync4 = options.existsSync ?? fs15.existsSync;
5222
+ const readFileSync4 = options.readFileSync ?? fs15.readFileSync;
5048
5223
  if (!existsSync4(plistPath)) {
5049
5224
  return {
5050
5225
  installed: false,
@@ -5168,62 +5343,6 @@ function unescapeXml(input) {
5168
5343
  return input.replaceAll("&quot;", '"').replaceAll("&apos;", "'").replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&amp;", "&");
5169
5344
  }
5170
5345
 
5171
- // src/cli-args.ts
5172
- function resolveFlag(args, flag) {
5173
- const idx = args.indexOf(flag);
5174
- if (idx === -1 || idx + 1 >= args.length) return void 0;
5175
- const value = args[idx + 1];
5176
- return isOptionToken(value) ? void 0 : value;
5177
- }
5178
- function isOptionToken(value) {
5179
- if (!value.startsWith("-")) return false;
5180
- if (/^-\d/.test(value) || /^-\.\d/.test(value)) return false;
5181
- return true;
5182
- }
5183
- function hasFlag(args, flag) {
5184
- return args.indexOf(flag) !== -1;
5185
- }
5186
- var TAXONOMY_RESOLVE_BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--json"]);
5187
- var TAXONOMY_RESOLVE_VALUE_FLAGS = /* @__PURE__ */ new Set(["--category"]);
5188
- function stripResolveFlags(args, booleanFlags = TAXONOMY_RESOLVE_BOOLEAN_FLAGS, valueFlags = TAXONOMY_RESOLVE_VALUE_FLAGS) {
5189
- return parseTaxonomyResolveArgs(args, booleanFlags, valueFlags).textParts;
5190
- }
5191
- function parseTaxonomyResolveArgs(args, booleanFlags = TAXONOMY_RESOLVE_BOOLEAN_FLAGS, valueFlags = TAXONOMY_RESOLVE_VALUE_FLAGS) {
5192
- const textParts = [];
5193
- const values = {};
5194
- const booleans = /* @__PURE__ */ new Set();
5195
- let literalText = false;
5196
- for (let i = 0; i < args.length; i++) {
5197
- const arg = args[i];
5198
- if (literalText) {
5199
- textParts.push(arg);
5200
- continue;
5201
- }
5202
- if (arg === "--") {
5203
- literalText = true;
5204
- continue;
5205
- }
5206
- if (arg.startsWith("--")) {
5207
- if (booleanFlags.has(arg)) {
5208
- booleans.add(arg);
5209
- continue;
5210
- }
5211
- if (valueFlags.has(arg)) {
5212
- const value = args[i + 1];
5213
- if (value === void 0 || value.startsWith("--")) {
5214
- throw new Error(`${arg} requires a value`);
5215
- }
5216
- values[arg] = value;
5217
- i++;
5218
- continue;
5219
- }
5220
- throw new Error(`Unknown flag: ${arg}`);
5221
- }
5222
- textParts.push(arg);
5223
- }
5224
- return { textParts, values, booleans };
5225
- }
5226
-
5227
5346
  // src/parse-connector-config.ts
5228
5347
  function parseConfigAssignment(raw, flag) {
5229
5348
  const eqIdx = raw.indexOf("=");
@@ -5278,7 +5397,7 @@ function stripConfigArgv(args) {
5278
5397
  }
5279
5398
 
5280
5399
  // src/import-dispatch.ts
5281
- import fs15 from "fs";
5400
+ import fs16 from "fs";
5282
5401
  import {
5283
5402
  runImporter,
5284
5403
  validateImportBatchSize,
@@ -5792,7 +5911,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
5792
5911
  let materializedTarget;
5793
5912
  let materializePromise;
5794
5913
  const io = {
5795
- readFile: ioOverrides.readFile ?? (async (p) => fs15.promises.readFile(p, "utf-8")),
5914
+ readFile: ioOverrides.readFile ?? (async (p) => fs16.promises.readFile(p, "utf-8")),
5796
5915
  loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
5797
5916
  runImporter: ioOverrides.runImporter ?? runImporter,
5798
5917
  getWriteTarget: async () => {
@@ -5905,7 +6024,7 @@ async function cmdCapture(rest, io) {
5905
6024
  }
5906
6025
 
5907
6026
  // src/import-lossless-claw-cmd.ts
5908
- import fs16 from "fs";
6027
+ import fs17 from "fs";
5909
6028
  import path14 from "path";
5910
6029
  import {
5911
6030
  applyLcmSchema,
@@ -6017,15 +6136,15 @@ async function loadImportLosslessClawModule() {
6017
6136
 
6018
6137
  // src/import-lossless-claw-cmd.ts
6019
6138
  function assertDirectoryOrAbsent(p, label) {
6020
- if (fs16.existsSync(p) && !fs16.statSync(p).isDirectory()) {
6139
+ if (fs17.existsSync(p) && !fs17.statSync(p).isDirectory()) {
6021
6140
  throw new Error(`${label} is not a directory: ${p}`);
6022
6141
  }
6023
6142
  }
6024
6143
  function assertFile(p, label) {
6025
- if (!fs16.existsSync(p)) {
6144
+ if (!fs17.existsSync(p)) {
6026
6145
  throw new Error(`${label} does not exist: ${p}`);
6027
6146
  }
6028
- if (!fs16.statSync(p).isFile()) {
6147
+ if (!fs17.statSync(p).isFile()) {
6029
6148
  throw new Error(`${label} is not a file: ${p}`);
6030
6149
  }
6031
6150
  }
@@ -6057,7 +6176,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
6057
6176
  try {
6058
6177
  if (parsed.dryRun) {
6059
6178
  const lcmPath = path14.join(memoryDir, "state", "lcm.sqlite");
6060
- if (fs16.existsSync(lcmPath)) {
6179
+ if (fs17.existsSync(lcmPath)) {
6061
6180
  destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
6062
6181
  } else {
6063
6182
  destDb = mod.openInMemoryDestinationDatabase();
@@ -7409,7 +7528,7 @@ async function resolveAllBenchmarks() {
7409
7528
  if (packageBenchmarks) {
7410
7529
  return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
7411
7530
  }
7412
- if (!fs17.existsSync(EVAL_RUNNER_PATH)) {
7531
+ if (!fs18.existsSync(EVAL_RUNNER_PATH)) {
7413
7532
  return [];
7414
7533
  }
7415
7534
  return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
@@ -7457,7 +7576,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
7457
7576
  `Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
7458
7577
  );
7459
7578
  }
7460
- if (!fs17.existsSync(EVAL_RUNNER_PATH)) {
7579
+ if (!fs18.existsSync(EVAL_RUNNER_PATH)) {
7461
7580
  console.error(
7462
7581
  "Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
7463
7582
  );
@@ -7467,7 +7586,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
7467
7586
  path18.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
7468
7587
  path18.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
7469
7588
  ];
7470
- const tsxCmd = tsxCandidates.find((candidate) => fs17.existsSync(candidate)) ?? "tsx";
7589
+ const tsxCmd = tsxCandidates.find((candidate) => fs18.existsSync(candidate)) ?? "tsx";
7471
7590
  const fallbackOutputDir = createFallbackBenchOutputDir(
7472
7591
  parsed.resultsDir ?? resolveBenchOutputDir(),
7473
7592
  benchmarkId,
@@ -7612,9 +7731,9 @@ var PERSONAMEM_COMPLETION_MARKER = path18.join(
7612
7731
  );
7613
7732
  function resolveRealpathWithinDataset(datasetPath, relativePath) {
7614
7733
  try {
7615
- const datasetRoot = fs17.realpathSync(datasetPath);
7734
+ const datasetRoot = fs18.realpathSync(datasetPath);
7616
7735
  const candidatePath = path18.resolve(datasetRoot, relativePath);
7617
- const candidateRealPath = fs17.realpathSync(candidatePath);
7736
+ const candidateRealPath = fs18.realpathSync(candidatePath);
7618
7737
  const relativeToRoot = path18.relative(datasetRoot, candidateRealPath);
7619
7738
  if (relativeToRoot.startsWith("..") || path18.isAbsolute(relativeToRoot)) {
7620
7739
  return null;
@@ -7673,14 +7792,14 @@ function parseCsvRows(raw) {
7673
7792
  function isPersonaMemDatasetComplete(datasetPath) {
7674
7793
  try {
7675
7794
  const completionMarkerPath = path18.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
7676
- if (fs17.statSync(completionMarkerPath).isFile()) {
7795
+ if (fs18.statSync(completionMarkerPath).isFile()) {
7677
7796
  return true;
7678
7797
  }
7679
7798
  } catch {
7680
7799
  }
7681
7800
  const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
7682
7801
  try {
7683
- return fs17.statSync(path18.join(datasetPath, candidate)).isFile();
7802
+ return fs18.statSync(path18.join(datasetPath, candidate)).isFile();
7684
7803
  } catch {
7685
7804
  return false;
7686
7805
  }
@@ -7689,7 +7808,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7689
7808
  return false;
7690
7809
  }
7691
7810
  try {
7692
- const rows = parseCsvRows(fs17.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
7811
+ const rows = parseCsvRows(fs18.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
7693
7812
  if (rows.length < 2) {
7694
7813
  return false;
7695
7814
  }
@@ -7704,7 +7823,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7704
7823
  }
7705
7824
  return historyPaths.every((relativePath) => {
7706
7825
  const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
7707
- return resolvedPath !== null && fs17.statSync(resolvedPath).isFile();
7826
+ return resolvedPath !== null && fs18.statSync(resolvedPath).isFile();
7708
7827
  });
7709
7828
  } catch {
7710
7829
  return false;
@@ -7712,7 +7831,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7712
7831
  }
7713
7832
  function hasDatasetFile(datasetPath, relativePath) {
7714
7833
  try {
7715
- return fs17.statSync(path18.join(datasetPath, relativePath)).isFile();
7834
+ return fs18.statSync(path18.join(datasetPath, relativePath)).isFile();
7716
7835
  } catch {
7717
7836
  return false;
7718
7837
  }
@@ -7732,10 +7851,10 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
7732
7851
  return candidateFilenames.some((filename) => {
7733
7852
  const filePath = path18.join(datasetPath, filename);
7734
7853
  try {
7735
- if (!fs17.statSync(filePath).isFile()) {
7854
+ if (!fs18.statSync(filePath).isFile()) {
7736
7855
  return false;
7737
7856
  }
7738
- const raw = fs17.readFileSync(filePath, "utf8");
7857
+ const raw = fs18.readFileSync(filePath, "utf8");
7739
7858
  return /"source"\s*:\s*"recsys[_-]/i.test(raw);
7740
7859
  } catch {
7741
7860
  return false;
@@ -7751,7 +7870,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
7751
7870
  function isDatasetDownloaded(datasetPath, benchmarkId) {
7752
7871
  let stats;
7753
7872
  try {
7754
- stats = fs17.statSync(datasetPath);
7873
+ stats = fs18.statSync(datasetPath);
7755
7874
  } catch {
7756
7875
  return false;
7757
7876
  }
@@ -7761,7 +7880,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7761
7880
  const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
7762
7881
  if (!marker) {
7763
7882
  try {
7764
- return fs17.readdirSync(datasetPath).length > 0;
7883
+ return fs18.readdirSync(datasetPath).length > 0;
7765
7884
  } catch {
7766
7885
  return false;
7767
7886
  }
@@ -7769,7 +7888,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7769
7888
  if (marker.allOf) {
7770
7889
  const hasAllRequiredFiles = marker.allOf.every((name) => {
7771
7890
  try {
7772
- return fs17.statSync(path18.join(datasetPath, name)).isFile();
7891
+ return fs18.statSync(path18.join(datasetPath, name)).isFile();
7773
7892
  } catch {
7774
7893
  return false;
7775
7894
  }
@@ -7781,7 +7900,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7781
7900
  if (marker.anyOf) {
7782
7901
  const hasMarkerFile = marker.anyOf.some((name) => {
7783
7902
  try {
7784
- return fs17.statSync(path18.join(datasetPath, name)).isFile();
7903
+ return fs18.statSync(path18.join(datasetPath, name)).isFile();
7785
7904
  } catch {
7786
7905
  return false;
7787
7906
  }
@@ -7799,7 +7918,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7799
7918
  }
7800
7919
  if (marker.ext) {
7801
7920
  try {
7802
- return fs17.readdirSync(datasetPath).some(
7921
+ return fs18.readdirSync(datasetPath).some(
7803
7922
  (name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
7804
7923
  );
7805
7924
  } catch {
@@ -7811,7 +7930,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7811
7930
  async function launchBenchUi(resultsDir) {
7812
7931
  const benchUiDir = path18.join(CLI_REPO_ROOT, "packages", "bench-ui");
7813
7932
  const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
7814
- if (!fs17.existsSync(path18.join(benchUiDir, "package.json"))) {
7933
+ if (!fs18.existsSync(path18.join(benchUiDir, "package.json"))) {
7815
7934
  console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
7816
7935
  process.exit(1);
7817
7936
  }
@@ -7849,13 +7968,13 @@ function listDownloadableBenchmarks() {
7849
7968
  }
7850
7969
  function resolveDatasetDownloadScriptPath() {
7851
7970
  const bundled = path18.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
7852
- if (fs17.existsSync(bundled)) {
7971
+ if (fs18.existsSync(bundled)) {
7853
7972
  return bundled;
7854
7973
  }
7855
7974
  return path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
7856
7975
  }
7857
7976
  function isRepoCheckout() {
7858
- return fs17.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs17.existsSync(path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
7977
+ return fs18.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs18.existsSync(path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
7859
7978
  }
7860
7979
  function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
7861
7980
  const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
@@ -8168,8 +8287,8 @@ async function exportBenchPackageResult(parsed) {
8168
8287
  ...reportCardProvenance ? { reportCardProvenance } : {}
8169
8288
  });
8170
8289
  if (parsed.output) {
8171
- fs17.mkdirSync(path18.dirname(parsed.output), { recursive: true });
8172
- fs17.writeFileSync(parsed.output, rendered);
8290
+ fs18.mkdirSync(path18.dirname(parsed.output), { recursive: true });
8291
+ fs18.writeFileSync(parsed.output, rendered);
8173
8292
  console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
8174
8293
  return;
8175
8294
  }
@@ -8214,7 +8333,7 @@ async function manageBenchDatasets(parsed) {
8214
8333
  process.exit(1);
8215
8334
  }
8216
8335
  const scriptPath = resolveDatasetDownloadScriptPath();
8217
- if (!fs17.existsSync(scriptPath)) {
8336
+ if (!fs18.existsSync(scriptPath)) {
8218
8337
  console.error(`ERROR: dataset download script not found: ${scriptPath}`);
8219
8338
  process.exit(1);
8220
8339
  }
@@ -8414,7 +8533,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
8414
8533
  );
8415
8534
  process.exit(1);
8416
8535
  }
8417
- const sourceResultSha256 = createHash4("sha256").update(fs17.readFileSync(latest.path)).digest("hex");
8536
+ const sourceResultSha256 = createHash4("sha256").update(fs18.readFileSync(latest.path)).digest("hex");
8418
8537
  const expandedManifestPath = expandTilde(manifestPath);
8419
8538
  if (!bench.resolveLocalLabJudgeProviderConfig) {
8420
8539
  console.error(
@@ -8829,7 +8948,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
8829
8948
  }
8830
8949
  let decoded;
8831
8950
  try {
8832
- decoded = JSON.parse(fs17.readFileSync(parsed.taskIdsFile, "utf8"));
8951
+ decoded = JSON.parse(fs18.readFileSync(parsed.taskIdsFile, "utf8"));
8833
8952
  } catch (error) {
8834
8953
  throw new Error(
8835
8954
  `Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
@@ -9504,7 +9623,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
9504
9623
  return void 0;
9505
9624
  }
9506
9625
  try {
9507
- return fs17.realpathSync(datasetDir);
9626
+ return fs18.realpathSync(datasetDir);
9508
9627
  } catch {
9509
9628
  return datasetDir;
9510
9629
  }
@@ -9558,13 +9677,13 @@ async function writeBenchReproManifestForPackageRun(args) {
9558
9677
  }
9559
9678
  function loadStandaloneConvergeCommandConfig() {
9560
9679
  const configPath = resolveConfigPath();
9561
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
9562
- return parseConfig8(resolveRemnicConfigRecord7(raw));
9680
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
9681
+ return parseConfig9(resolveRemnicConfigRecord8(raw));
9563
9682
  }
9564
9683
  function parseConvergePluginConfig(value) {
9565
9684
  if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
9566
9685
  if (Object.keys(value).length === 0) return void 0;
9567
- return parseConfig8(resolveRemnicConfigRecord7(value));
9686
+ return parseConfig9(resolveRemnicConfigRecord8(value));
9568
9687
  }
9569
9688
  function loadConvergeCommandConfig() {
9570
9689
  if (readCompatEnv("REMNIC_CONFIG_PATH", "ENGRAM_CONFIG_PATH")) {
@@ -9587,13 +9706,13 @@ function resolveConfigPath(cliPath) {
9587
9706
  path18.join(resolveHomeDir(), ".config", "engram", "config.json")
9588
9707
  ];
9589
9708
  for (const candidate of candidates) {
9590
- if (fs17.existsSync(candidate)) return candidate;
9709
+ if (fs18.existsSync(candidate)) return candidate;
9591
9710
  }
9592
9711
  return path18.join(resolveHomeDir(), ".config", "remnic", "config.json");
9593
9712
  }
9594
9713
  function resolveExistingBenchRemnicConfigPath(cliPath) {
9595
9714
  const configPath = resolveConfigPath(cliPath);
9596
- if (fs17.existsSync(configPath)) {
9715
+ if (fs18.existsSync(configPath)) {
9597
9716
  return configPath;
9598
9717
  }
9599
9718
  if (cliPath) {
@@ -9603,7 +9722,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
9603
9722
  }
9604
9723
  function resolveExistingBenchOpenclawConfigPath(cliPath) {
9605
9724
  const configPath = resolveOpenclawConfigPath(cliPath);
9606
- if (fs17.existsSync(configPath)) {
9725
+ if (fs18.existsSync(configPath)) {
9607
9726
  return configPath;
9608
9727
  }
9609
9728
  if (cliPath) {
@@ -9710,8 +9829,8 @@ function resolveMemoryDir() {
9710
9829
  const envMemoryDir = readCompatEnv("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
9711
9830
  if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
9712
9831
  const configPath = resolveConfigPath();
9713
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
9714
- const remnicCfg = resolveRemnicConfigRecord7(raw);
9832
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
9833
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
9715
9834
  if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
9716
9835
  return normalizeMemoryDirPath(remnicCfg.memoryDir);
9717
9836
  }
@@ -9719,18 +9838,18 @@ function resolveMemoryDir() {
9719
9838
  const standalonePath = path18.join(home, ".remnic", "memory");
9720
9839
  const legacyStandalonePath = path18.join(home, ".engram", "memory");
9721
9840
  const openclawPath = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
9722
- if (fs17.existsSync(standalonePath)) return standalonePath;
9723
- if (fs17.existsSync(legacyStandalonePath)) return legacyStandalonePath;
9841
+ if (fs18.existsSync(standalonePath)) return standalonePath;
9842
+ if (fs18.existsSync(legacyStandalonePath)) return legacyStandalonePath;
9724
9843
  return openclawPath;
9725
9844
  })();
9726
9845
  const manifestPath = getManifestPath();
9727
- if (fs17.existsSync(manifestPath)) {
9846
+ if (fs18.existsSync(manifestPath)) {
9728
9847
  try {
9729
9848
  const active = getActiveSpace();
9730
9849
  if (active?.memoryDir) {
9731
9850
  const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
9732
- if (!fs17.existsSync(activeMemoryDir)) {
9733
- fs17.mkdirSync(activeMemoryDir, { recursive: true });
9851
+ if (!fs18.existsSync(activeMemoryDir)) {
9852
+ fs18.mkdirSync(activeMemoryDir, { recursive: true });
9734
9853
  }
9735
9854
  return activeMemoryDir;
9736
9855
  }
@@ -9779,13 +9898,13 @@ function resolveOpenclawConfigPath(cliPath) {
9779
9898
  const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
9780
9899
  if (envPath) return path18.resolve(expandTilde(envPath));
9781
9900
  for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
9782
- if (fs17.existsSync(candidate)) return candidate;
9901
+ if (fs18.existsSync(candidate)) return candidate;
9783
9902
  }
9784
9903
  return path18.join(resolveOpenclawStateDir(), "openclaw.json");
9785
9904
  }
9786
9905
  function readOpenclawConfig(configPath) {
9787
- if (!fs17.existsSync(configPath)) return {};
9788
- const raw = fs17.readFileSync(configPath, "utf-8");
9906
+ if (!fs18.existsSync(configPath)) return {};
9907
+ const raw = fs18.readFileSync(configPath, "utf-8");
9789
9908
  let parsed;
9790
9909
  try {
9791
9910
  parsed = JSON.parse(raw);
@@ -9887,9 +10006,9 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
9887
10006
  return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
9888
10007
  }
9889
10008
  function backupPathIfPresent(sourcePath, backupPath) {
9890
- if (!fs17.existsSync(sourcePath)) return false;
9891
- fs17.mkdirSync(path18.dirname(backupPath), { recursive: true });
9892
- fs17.cpSync(sourcePath, backupPath, { recursive: true });
10009
+ if (!fs18.existsSync(sourcePath)) return false;
10010
+ fs18.mkdirSync(path18.dirname(backupPath), { recursive: true });
10011
+ fs18.cpSync(sourcePath, backupPath, { recursive: true });
9893
10012
  return true;
9894
10013
  }
9895
10014
  function restartOpenclawGateway() {
@@ -9908,7 +10027,7 @@ function restartOpenclawGateway() {
9908
10027
  }
9909
10028
  function cmdInit() {
9910
10029
  const configPath = path18.join(process.cwd(), "remnic.config.json");
9911
- if (fs17.existsSync(configPath)) {
10030
+ if (fs18.existsSync(configPath)) {
9912
10031
  console.log(`Config already exists: ${configPath}`);
9913
10032
  return;
9914
10033
  }
@@ -9924,7 +10043,7 @@ function cmdInit() {
9924
10043
  authToken: "${REMNIC_AUTH_TOKEN}"
9925
10044
  }
9926
10045
  };
9927
- fs17.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
10046
+ fs18.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
9928
10047
  console.log(`Created ${configPath}`);
9929
10048
  console.log("\nSet these environment variables:");
9930
10049
  console.log(" export OPENAI_API_KEY=sk-...");
@@ -10344,11 +10463,11 @@ async function cmdQuery(queryText, json, explain) {
10344
10463
  printQueryResult(result, json);
10345
10464
  return;
10346
10465
  }
10347
- initLogger3();
10466
+ initLogger4();
10348
10467
  const configPath = resolveConfigPath();
10349
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10350
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10351
- const config = parseConfig8(remnicCfg);
10468
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
10469
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
10470
+ const config = parseConfig9(remnicCfg);
10352
10471
  const orchestrator = new Orchestrator5(config);
10353
10472
  await orchestrator.initialize();
10354
10473
  const service = new EngramAccessService2(orchestrator);
@@ -10524,11 +10643,11 @@ async function cmdXray(rest) {
10524
10643
  await runXrayCommand(rest, xrayCliIo((request) => remoteRecallXray(remote, request)));
10525
10644
  return;
10526
10645
  }
10527
- initLogger3();
10646
+ initLogger4();
10528
10647
  const configPath = resolveConfigPath();
10529
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10530
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10531
- const config = parseConfig8(remnicCfg);
10648
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
10649
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
10650
+ const config = parseConfig9(remnicCfg);
10532
10651
  const orchestrator = new Orchestrator5(config);
10533
10652
  await orchestrator.initialize();
10534
10653
  await orchestrator.deferredReady;
@@ -10556,36 +10675,45 @@ async function runWhoKnowsCommand(rest, io) {
10556
10675
  });
10557
10676
  io.stdout(renderWhoKnows(result, parsed.json));
10558
10677
  }
10559
- async function cmdWhoKnows(rest) {
10560
- const { topic, options } = extractWhoKnowsRawArgs(rest);
10561
- parseWhoKnowsCliOptions(topic, options);
10562
- if (resolveRemoteDaemon(resolveConfigPath())) {
10563
- throw new Error("who-knows: remote daemon mode is not supported yet; run with a local config");
10564
- }
10565
- initLogger3();
10678
+ async function withLocalService(fn) {
10679
+ initLogger4();
10566
10680
  const configPath = resolveConfigPath();
10567
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10568
- const config = parseConfig8(resolveRemnicConfigRecord7(raw));
10569
- const orchestrator = new Orchestrator5(config);
10681
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
10682
+ const orchestrator = new Orchestrator5(parseConfig9(resolveRemnicConfigRecord8(raw)));
10570
10683
  await orchestrator.initialize();
10571
10684
  await orchestrator.deferredReady;
10572
10685
  const service = new EngramAccessService2(orchestrator);
10573
10686
  try {
10574
- await runWhoKnowsCommand(rest, {
10575
- whoKnows: (request) => service.whoKnows(request),
10576
- stdout: (line) => console.log(line)
10577
- });
10687
+ return await fn(service, orchestrator);
10578
10688
  } finally {
10579
10689
  orchestrator.abortDeferredInit();
10580
10690
  await orchestrator.destroy();
10581
10691
  }
10582
10692
  }
10693
+ async function cmdWhoKnows(rest) {
10694
+ const { topic, options } = extractWhoKnowsRawArgs(rest);
10695
+ parseWhoKnowsCliOptions(topic, options);
10696
+ if (resolveRemoteDaemon(resolveConfigPath())) {
10697
+ throw new Error("who-knows: remote daemon mode is not supported yet; run with a local config");
10698
+ }
10699
+ await withLocalService((service) => runWhoKnowsCommand(rest, {
10700
+ whoKnows: (request) => service.whoKnows(request),
10701
+ stdout: (line) => console.log(line)
10702
+ }));
10703
+ }
10704
+ async function cmdPromotionCandidates(rest) {
10705
+ if (resolveRemoteDaemon(resolveConfigPath())) throw new Error("promotion-candidates: remote daemon mode is not supported yet; run with a local config");
10706
+ await withLocalService((service) => runPromotionCandidatesCommand(rest, {
10707
+ promotionCandidates: (request) => service.promotionCandidates(request),
10708
+ stdout: (line) => console.log(line)
10709
+ }));
10710
+ }
10583
10711
  async function cmdVersions(rest) {
10584
- initLogger3();
10712
+ initLogger4();
10585
10713
  const configPath = resolveConfigPath();
10586
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10587
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10588
- const config = parseConfig8(remnicCfg);
10714
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
10715
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
10716
+ const config = parseConfig9(remnicCfg);
10589
10717
  if (!config.versioningEnabled) {
10590
10718
  console.error("Page versioning is disabled (versioningEnabled = false).");
10591
10719
  process.exit(1);
@@ -10697,11 +10825,11 @@ Options:
10697
10825
  }
10698
10826
  }
10699
10827
  async function cmdEnrich(rest) {
10700
- initLogger3();
10828
+ initLogger4();
10701
10829
  const configPath = resolveConfigPath();
10702
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10703
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10704
- const config = parseConfig8(remnicCfg);
10830
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
10831
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
10832
+ const config = parseConfig9(remnicCfg);
10705
10833
  const subcommand = rest[0];
10706
10834
  if (subcommand === "audit") {
10707
10835
  const memoryDir2 = expandTilde(config.memoryDir);
@@ -10890,80 +11018,12 @@ Registered providers:`);
10890
11018
  ${totalPersisted} candidate(s) persisted to memory store.`);
10891
11019
  }
10892
11020
  }
10893
- async function cmdProcedural(rest) {
10894
- initLogger3();
10895
- const subcommand = rest[0];
10896
- if (!subcommand || subcommand === "--help" || subcommand === "-h") {
10897
- console.log(`remnic procedural \u2014 Procedural memory operations (issue #567)
10898
-
10899
- Usage:
10900
- remnic procedural stats [--format json|text] [--memory-dir <path>]
10901
-
10902
- Subcommands:
10903
- stats Print counts by status + recent activity + active config.
10904
-
10905
- Shared with:
10906
- GET /engram/v1/procedural/stats
10907
- MCP remnic.procedural_stats (alias engram.procedural_stats)`);
10908
- return;
10909
- }
10910
- if (subcommand !== "stats") {
10911
- console.error(
10912
- `Unknown procedural subcommand "${subcommand}". Run \`remnic procedural --help\` for usage.`
10913
- );
10914
- process.exit(1);
10915
- }
10916
- const args = rest.slice(1);
10917
- const formatPresent = hasFlag(args, "--format");
10918
- const formatRaw = resolveFlag(args, "--format");
10919
- if (formatPresent && (formatRaw === void 0 || formatRaw === null)) {
10920
- console.error(
10921
- "--format requires a value. Use `--format json` or `--format text`."
10922
- );
10923
- process.exit(1);
10924
- }
10925
- const format = (() => {
10926
- if (!formatPresent || formatRaw === void 0 || formatRaw === null) {
10927
- return "text";
10928
- }
10929
- const normalized = String(formatRaw).trim().toLowerCase();
10930
- if (normalized !== "text" && normalized !== "json") {
10931
- console.error(
10932
- `Invalid --format "${formatRaw}". Allowed: text, json.`
10933
- );
10934
- process.exit(1);
10935
- }
10936
- return normalized;
10937
- })();
10938
- const memoryDirPresent = hasFlag(args, "--memory-dir");
10939
- const memoryDirOverride = resolveFlag(args, "--memory-dir");
10940
- if (memoryDirPresent && (memoryDirOverride === void 0 || memoryDirOverride === null)) {
10941
- console.error(
10942
- "--memory-dir requires a path. Omit the flag to use the resolved default."
10943
- );
10944
- process.exit(1);
10945
- }
10946
- const configPath = resolveConfigPath();
10947
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10948
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10949
- const config = parseConfig8(remnicCfg);
10950
- const memoryDir = expandTilde(
10951
- typeof memoryDirOverride === "string" && memoryDirOverride.length > 0 ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
10952
- );
10953
- const storage = new StorageManager2(memoryDir);
10954
- const report = await computeProcedureStats({ storage, config });
10955
- if (format === "json") {
10956
- process.stdout.write(JSON.stringify(report, null, 2) + "\n");
10957
- return;
10958
- }
10959
- process.stdout.write(formatProcedureStatsText(report));
10960
- }
10961
11021
  async function cmdExtensions(action, rest) {
10962
- initLogger3();
11022
+ initLogger4();
10963
11023
  const configPath = resolveConfigPath();
10964
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
10965
- const remnicCfg = resolveRemnicConfigRecord7(raw);
10966
- const config = parseConfig8(remnicCfg);
11024
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
11025
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
11026
+ const config = parseConfig9(remnicCfg);
10967
11027
  const root = resolveExtensionsRoot(config);
10968
11028
  const noopLog = { warn: () => {
10969
11029
  }, debug: () => {
@@ -11012,7 +11072,7 @@ Root: ${root}`);
11012
11072
  const extensions = await discoverMemoryExtensions(root, warnLog);
11013
11073
  let entries = [];
11014
11074
  try {
11015
- entries = fs17.readdirSync(root);
11075
+ entries = fs18.readdirSync(root);
11016
11076
  } catch {
11017
11077
  console.log(`Extensions root does not exist: ${root}`);
11018
11078
  process.exitCode = 0;
@@ -11023,7 +11083,7 @@ Root: ${root}`);
11023
11083
  for (const entry of entries) {
11024
11084
  const entryPath = path18.join(root, entry);
11025
11085
  try {
11026
- if (!fs17.statSync(entryPath).isDirectory()) continue;
11086
+ if (!fs18.statSync(entryPath).isDirectory()) continue;
11027
11087
  } catch {
11028
11088
  continue;
11029
11089
  }
@@ -11053,11 +11113,11 @@ Root: ${root}`);
11053
11113
  }
11054
11114
  }
11055
11115
  async function cmdBriefing(rest) {
11056
- initLogger3();
11116
+ initLogger4();
11057
11117
  const configPath = resolveConfigPath();
11058
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
11059
- const remnicCfg = resolveRemnicConfigRecord7(raw);
11060
- const config = parseConfig8(remnicCfg);
11118
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
11119
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
11120
+ const config = parseConfig9(remnicCfg);
11061
11121
  if (!config.briefing.enabled) {
11062
11122
  console.error("Briefing is disabled in config (briefing.enabled = false).");
11063
11123
  process.exit(1);
@@ -11135,10 +11195,10 @@ async function cmdBriefing(rest) {
11135
11195
  if (save) {
11136
11196
  try {
11137
11197
  const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
11138
- fs17.mkdirSync(saveDir, { recursive: true });
11198
+ fs18.mkdirSync(saveDir, { recursive: true });
11139
11199
  const filename = briefingFilename(new Date(result.window.to), format);
11140
11200
  const filePath = path18.join(saveDir, filename);
11141
- fs17.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
11201
+ fs18.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
11142
11202
  console.error(`Saved briefing: ${filePath}`);
11143
11203
  } catch (err) {
11144
11204
  console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
@@ -11156,7 +11216,7 @@ async function cmdDoctor() {
11156
11216
  detail: `${nodeVersion} (requires >= 22.12.0)`
11157
11217
  });
11158
11218
  const configPath = resolveConfigPath();
11159
- const configExists = fs17.existsSync(configPath);
11219
+ const configExists = fs18.existsSync(configPath);
11160
11220
  checks.push({ name: "Config file", ok: configExists, detail: configPath });
11161
11221
  let standaloneConfig;
11162
11222
  let standaloneConfigError;
@@ -11164,11 +11224,11 @@ async function cmdDoctor() {
11164
11224
  let configuredNs = { invalid: false };
11165
11225
  if (configExists) {
11166
11226
  try {
11167
- const raw = JSON.parse(fs17.readFileSync(configPath, "utf8"));
11168
- const remnicCfg = resolveRemnicConfigRecord7(raw);
11227
+ const raw = JSON.parse(fs18.readFileSync(configPath, "utf8"));
11228
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
11169
11229
  standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
11170
11230
  configuredNs = readConfiguredNamespace(remnicCfg);
11171
- standaloneConfig = parseConfig8(remnicCfg);
11231
+ standaloneConfig = parseConfig9(remnicCfg);
11172
11232
  } catch (err) {
11173
11233
  standaloneConfigError = err instanceof Error ? err.message : String(err);
11174
11234
  }
@@ -11177,10 +11237,10 @@ async function cmdDoctor() {
11177
11237
  try {
11178
11238
  memoryDir = resolveMemoryDir();
11179
11239
  } catch {
11180
- memoryDir = parseConfig8({}).memoryDir;
11240
+ memoryDir = parseConfig9({}).memoryDir;
11181
11241
  }
11182
11242
  try {
11183
- fs17.mkdirSync(memoryDir, { recursive: true });
11243
+ fs18.mkdirSync(memoryDir, { recursive: true });
11184
11244
  checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
11185
11245
  } catch {
11186
11246
  checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
@@ -11209,7 +11269,7 @@ async function cmdDoctor() {
11209
11269
  });
11210
11270
  if (nsPolicyCheck) checks.push(nsPolicyCheck);
11211
11271
  const openclawConfigPath = resolveOpenclawConfigPath();
11212
- const openclawConfigExists = fs17.existsSync(openclawConfigPath);
11272
+ const openclawConfigExists = fs18.existsSync(openclawConfigPath);
11213
11273
  let openclawConfig = {};
11214
11274
  let openclawConfigValid = false;
11215
11275
  let openclawPluginModeConfigured = false;
@@ -11217,7 +11277,7 @@ async function cmdDoctor() {
11217
11277
  let activeOpenclawEntryConfig = null;
11218
11278
  if (openclawConfigExists) {
11219
11279
  try {
11220
- const parsed = JSON.parse(fs17.readFileSync(openclawConfigPath, "utf-8"));
11280
+ const parsed = JSON.parse(fs18.readFileSync(openclawConfigPath, "utf-8"));
11221
11281
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
11222
11282
  openclawConfig = parsed;
11223
11283
  openclawConfigValid = true;
@@ -11297,9 +11357,9 @@ async function cmdDoctor() {
11297
11357
  let memDirOk = false;
11298
11358
  let memDirDetail = `${resolvedMemDir} (not found)`;
11299
11359
  let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
11300
- if (fs17.existsSync(resolvedMemDir)) {
11360
+ if (fs18.existsSync(resolvedMemDir)) {
11301
11361
  try {
11302
- const stat2 = fs17.statSync(resolvedMemDir);
11362
+ const stat2 = fs18.statSync(resolvedMemDir);
11303
11363
  if (stat2.isDirectory()) {
11304
11364
  memDirOk = true;
11305
11365
  memDirDetail = resolvedMemDir;
@@ -11454,12 +11514,12 @@ async function cmdDoctor() {
11454
11514
  }
11455
11515
  function cmdConfig() {
11456
11516
  const configPath = resolveConfigPath();
11457
- if (!fs17.existsSync(configPath)) {
11517
+ if (!fs18.existsSync(configPath)) {
11458
11518
  console.log("No config file found. Run `remnic init` to create one.");
11459
11519
  return;
11460
11520
  }
11461
11521
  console.log(`Config: ${configPath}`);
11462
- const rawConfig = fs17.readFileSync(configPath, "utf8");
11522
+ const rawConfig = fs18.readFileSync(configPath, "utf8");
11463
11523
  const redacted = rawConfig.replace(
11464
11524
  /("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
11465
11525
  "$1[REDACTED]$3"
@@ -11563,13 +11623,13 @@ async function cmdReview(action, rest) {
11563
11623
  console.error("Usage: remnic review <approve|dismiss|flag> <id>");
11564
11624
  process.exit(1);
11565
11625
  }
11566
- const storage = new StorageManager2(memoryDir);
11626
+ const storage = new StorageManager3(memoryDir);
11567
11627
  const configPath = resolveConfigPath();
11568
11628
  let tombstonesConfig = null;
11569
11629
  try {
11570
- const rawCfg = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
11571
- const remnicCfg = resolveRemnicConfigRecord7(rawCfg);
11572
- const config = parseConfig8(remnicCfg);
11630
+ const rawCfg = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
11631
+ const remnicCfg = resolveRemnicConfigRecord8(rawCfg);
11632
+ const config = parseConfig9(remnicCfg);
11573
11633
  tombstonesConfig = {
11574
11634
  enabled: config.tombstonesEnabled,
11575
11635
  semanticMatch: config.tombstonesSemanticMatch,
@@ -12311,7 +12371,7 @@ async function pushOfflineFileContent(args) {
12311
12371
  }
12312
12372
  async function pushOfflineFileContentFromChunkReader(args) {
12313
12373
  const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
12314
- const stat2 = fs17.statSync(filePath);
12374
+ const stat2 = fs18.statSync(filePath);
12315
12375
  if (stat2.mtimeMs !== args.file.mtimeMs) {
12316
12376
  throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
12317
12377
  }
@@ -12802,7 +12862,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
12802
12862
  return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
12803
12863
  }
12804
12864
  async function runOfflineSyncOnce(options) {
12805
- fs17.mkdirSync(options.memoryDir, { recursive: true });
12865
+ fs18.mkdirSync(options.memoryDir, { recursive: true });
12806
12866
  let activeStatePath = options.statePath;
12807
12867
  let priorState = await readOfflineSyncState(activeStatePath);
12808
12868
  let syncNamespace = options.namespace ?? priorState?.namespace;
@@ -13435,7 +13495,7 @@ Environment fallbacks:
13435
13495
  const configPath = resolveConfigPath();
13436
13496
  let config;
13437
13497
  try {
13438
- const rawConfig = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
13498
+ const rawConfig = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
13439
13499
  config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
13440
13500
  } catch {
13441
13501
  throw new Error(
@@ -13450,7 +13510,7 @@ Environment fallbacks:
13450
13510
  const statePath = statePathExplicit ? path18.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
13451
13511
  if (action === "prepare") {
13452
13512
  if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
13453
- fs17.mkdirSync(memoryDir, { recursive: true });
13513
+ fs18.mkdirSync(memoryDir, { recursive: true });
13454
13514
  const remoteSnapshot = await fetchOfflineSnapshot({
13455
13515
  remoteUrl,
13456
13516
  token,
@@ -13549,7 +13609,7 @@ Environment fallbacks:
13549
13609
  return;
13550
13610
  }
13551
13611
  if (action === "status") {
13552
- fs17.mkdirSync(memoryDir, { recursive: true });
13612
+ fs18.mkdirSync(memoryDir, { recursive: true });
13553
13613
  const state = statePath ? await readOfflineSyncState(statePath) : null;
13554
13614
  if (state && remoteUrl && statePath) {
13555
13615
  assertOfflineStateMatches({
@@ -13687,7 +13747,7 @@ function cmdDedup(json) {
13687
13747
  function readInstalledConnectorConfig(configPath, fallback) {
13688
13748
  if (!configPath) return fallback;
13689
13749
  try {
13690
- const parsed = JSON.parse(fs17.readFileSync(configPath, "utf8"));
13750
+ const parsed = JSON.parse(fs18.readFileSync(configPath, "utf8"));
13691
13751
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
13692
13752
  const { token: _token, ...config } = parsed;
13693
13753
  return config;
@@ -13865,7 +13925,7 @@ async function cmdConnectors(action, rest, json) {
13865
13925
  const pub = factory();
13866
13926
  const available = await pub.isHostAvailable();
13867
13927
  const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
13868
- const extensionExists = available && extRoot ? fs17.existsSync(extRoot) : false;
13928
+ const extensionExists = available && extRoot ? fs18.existsSync(extRoot) : false;
13869
13929
  publisherChecks.push({
13870
13930
  name: `Publisher: ${targetHostId}`,
13871
13931
  ok: !available || extensionExists,
@@ -13939,7 +13999,7 @@ async function cmdConnectors(action, rest, json) {
13939
13999
  let connectorsCfg;
13940
14000
  const configPath = resolveConfigPath();
13941
14001
  try {
13942
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
14002
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
13943
14003
  connectorsCfg = parseConfigQuietly(raw).connectors;
13944
14004
  } catch {
13945
14005
  process.stderr.write(
@@ -14013,11 +14073,11 @@ async function cmdConnectors(action, rest, json) {
14013
14073
  process.exitCode = 2;
14014
14074
  return;
14015
14075
  }
14016
- initLogger3();
14076
+ initLogger4();
14017
14077
  const configPath = resolveConfigPath();
14018
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
14019
- const remnicCfg = resolveRemnicConfigRecord7(raw);
14020
- const config = parseConfig8(remnicCfg);
14078
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
14079
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
14080
+ const config = parseConfig9(remnicCfg);
14021
14081
  const orchestrator = new Orchestrator5(config);
14022
14082
  try {
14023
14083
  await orchestrator.initialize();
@@ -14140,9 +14200,9 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
14140
14200
  console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
14141
14201
  process.exit(1);
14142
14202
  }
14143
- const rawConfig = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
14144
- const pluginConfig = resolveRemnicConfigRecord7(rawConfig);
14145
- const config = parseConfig8(pluginConfig);
14203
+ const rawConfig = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
14204
+ const pluginConfig = resolveRemnicConfigRecord8(rawConfig);
14205
+ const config = parseConfig9(pluginConfig);
14146
14206
  if (subAction === "generate") {
14147
14207
  let outputDir;
14148
14208
  try {
@@ -14162,13 +14222,13 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
14162
14222
  } else if (subAction === "validate") {
14163
14223
  const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path18.join(process.cwd(), "marketplace.json");
14164
14224
  const resolved = path18.resolve(targetPath);
14165
- if (!fs17.existsSync(resolved)) {
14225
+ if (!fs18.existsSync(resolved)) {
14166
14226
  console.error(`File not found: ${resolved}`);
14167
14227
  process.exit(1);
14168
14228
  }
14169
14229
  let parsed;
14170
14230
  try {
14171
- parsed = JSON.parse(fs17.readFileSync(resolved, "utf8"));
14231
+ parsed = JSON.parse(fs18.readFileSync(resolved, "utf8"));
14172
14232
  } catch {
14173
14233
  console.error(`Invalid JSON in ${resolved}`);
14174
14234
  process.exit(1);
@@ -14339,12 +14399,14 @@ async function cmdSpace(action, rest, json) {
14339
14399
  }
14340
14400
  const result = await promoteSpace(sourceId, targetId, {
14341
14401
  force: rest.includes("--force"),
14342
- forceOverwrite: rest.includes("--force-overwrite")
14402
+ forceOverwrite: rest.includes("--force-overwrite"),
14403
+ allowUserSubject: rest.includes("--allow-user-subject")
14343
14404
  });
14344
14405
  if (json) {
14345
14406
  console.log(JSON.stringify(result, null, 2));
14346
14407
  } else {
14347
14408
  console.log(`Promoted ${result.memoriesPromoted} memories`);
14409
+ if (result.subjectWarnings && result.subjectWarnings.length > 0) console.log(`Subject-guard warnings: ${result.subjectWarnings.length} (see --json)`);
14348
14410
  if (result.conflicts.length > 0) console.log(`Conflicts: ${result.conflicts.length}`);
14349
14411
  console.log(`Duration: ${result.durationMs}ms`);
14350
14412
  }
@@ -14367,11 +14429,11 @@ async function cmdSpace(action, rest, json) {
14367
14429
  }
14368
14430
  }
14369
14431
  async function cmdLegacyBenchmark(action, rest, json) {
14370
- initLogger3();
14432
+ initLogger4();
14371
14433
  const configPath = resolveConfigPath();
14372
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
14373
- const remnicCfg = resolveRemnicConfigRecord7(raw);
14374
- const config = parseConfig8(remnicCfg);
14434
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
14435
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
14436
+ const config = parseConfig9(remnicCfg);
14375
14437
  const orchestrator = new Orchestrator5(config);
14376
14438
  const service = new EngramAccessService2(orchestrator);
14377
14439
  const { runBenchSuite, loadBaseline, checkRegression } = await loadBenchModule();
@@ -14774,7 +14836,7 @@ function readPid() {
14774
14836
  function inferPort() {
14775
14837
  try {
14776
14838
  const configPath = resolveConfigPath();
14777
- const raw = JSON.parse(fs17.readFileSync(configPath, "utf8"));
14839
+ const raw = JSON.parse(fs18.readFileSync(configPath, "utf8"));
14778
14840
  return raw.server?.port ?? 4318;
14779
14841
  } catch {
14780
14842
  return 4318;
@@ -14869,13 +14931,13 @@ function daemonInstall() {
14869
14931
  process.exit(1);
14870
14932
  }
14871
14933
  const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
14872
- fs17.mkdirSync(LOGS_DIR, { recursive: true });
14934
+ fs18.mkdirSync(LOGS_DIR, { recursive: true });
14873
14935
  if (isMacOS()) {
14874
14936
  const templatePath = path18.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
14875
- const template = fs17.readFileSync(templatePath, "utf8");
14937
+ const template = fs18.readFileSync(templatePath, "utf8");
14876
14938
  const plist = renderTemplate(template, vars);
14877
- fs17.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
14878
- fs17.writeFileSync(LAUNCHD_PLIST_PATH, plist);
14939
+ fs18.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
14940
+ fs18.writeFileSync(LAUNCHD_PLIST_PATH, plist);
14879
14941
  try {
14880
14942
  launchdLoadPlist(LAUNCHD_PLIST_PATH);
14881
14943
  } catch (err) {
@@ -14892,10 +14954,10 @@ function daemonInstall() {
14892
14954
  console.log(` Logs: ${LOGS_DIR}/daemon.log`);
14893
14955
  } else if (isLinux()) {
14894
14956
  const templatePath = path18.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
14895
- const template = fs17.readFileSync(templatePath, "utf8");
14957
+ const template = fs18.readFileSync(templatePath, "utf8");
14896
14958
  const unit = renderTemplate(template, vars);
14897
- fs17.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
14898
- fs17.writeFileSync(SYSTEMD_UNIT_PATH, unit);
14959
+ fs18.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
14960
+ fs18.writeFileSync(SYSTEMD_UNIT_PATH, unit);
14899
14961
  try {
14900
14962
  childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
14901
14963
  } catch (err) {
@@ -14931,7 +14993,7 @@ function daemonUninstall() {
14931
14993
  } catch {
14932
14994
  }
14933
14995
  try {
14934
- fs17.unlinkSync(plistPath);
14996
+ fs18.unlinkSync(plistPath);
14935
14997
  removed = true;
14936
14998
  console.log(`Removed launchd service: ${plistPath}`);
14937
14999
  } catch {
@@ -14951,7 +15013,7 @@ function daemonUninstall() {
14951
15013
  let removed = false;
14952
15014
  for (const unitPath of SYSTEMD_UNIT_PATHS) {
14953
15015
  try {
14954
- fs17.unlinkSync(unitPath);
15016
+ fs18.unlinkSync(unitPath);
14955
15017
  removed = true;
14956
15018
  console.log(`Removed systemd service: ${unitPath}`);
14957
15019
  } catch {
@@ -15018,13 +15080,13 @@ async function daemonStatus() {
15018
15080
  console.log(` Port: ${port}`);
15019
15081
  console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
15020
15082
  console.log(` Platform: ${process.platform}`);
15021
- console.log(` PID file: ${fs17.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
15022
- console.log(` Log file: ${fs17.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
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}`);
15023
15085
  try {
15024
15086
  const configPath = resolveConfigPath();
15025
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
15026
- const remnicCfg = resolveRemnicConfigRecord7(raw);
15027
- const config = parseConfig8(remnicCfg);
15087
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
15088
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
15089
+ const config = parseConfig9(remnicCfg);
15028
15090
  const extRoot = resolveExtensionsRoot(config);
15029
15091
  const noopLog = { warn: () => {
15030
15092
  }, debug: () => {
@@ -15063,9 +15125,9 @@ function daemonStart() {
15063
15125
  return;
15064
15126
  }
15065
15127
  }
15066
- fs17.mkdirSync(PID_DIR, { recursive: true });
15067
- fs17.mkdirSync(LOGS_DIR, { recursive: true });
15068
- const logStream = fs17.openSync(LOG_FILE, "a");
15128
+ fs18.mkdirSync(PID_DIR, { recursive: true });
15129
+ fs18.mkdirSync(LOGS_DIR, { recursive: true });
15130
+ const logStream = fs18.openSync(LOG_FILE, "a");
15069
15131
  const serverBin = resolveServerBin();
15070
15132
  const isSource = serverBin.endsWith(".ts");
15071
15133
  let cmd;
@@ -15087,7 +15149,7 @@ function daemonStart() {
15087
15149
  }
15088
15150
  });
15089
15151
  child.unref();
15090
- fs17.writeFileSync(PID_FILE, String(child.pid));
15152
+ fs18.writeFileSync(PID_FILE, String(child.pid));
15091
15153
  console.log(`Started remnic server (pid ${child.pid})`);
15092
15154
  console.log(` Log: ${LOG_FILE}`);
15093
15155
  }
@@ -15121,11 +15183,11 @@ function daemonStop() {
15121
15183
  console.log("Process not found (cleaning up PID file)");
15122
15184
  }
15123
15185
  try {
15124
- fs17.unlinkSync(PID_FILE);
15186
+ fs18.unlinkSync(PID_FILE);
15125
15187
  } catch {
15126
15188
  }
15127
15189
  try {
15128
- fs17.unlinkSync(LEGACY_PID_FILE);
15190
+ fs18.unlinkSync(LEGACY_PID_FILE);
15129
15191
  } catch {
15130
15192
  }
15131
15193
  }
@@ -15251,11 +15313,11 @@ async function promptYesNo(question, defaultYes = true) {
15251
15313
  });
15252
15314
  }
15253
15315
  async function cmdBinary(rest) {
15254
- initLogger3();
15316
+ initLogger4();
15255
15317
  const configPath = resolveConfigPath();
15256
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
15257
- const remnicCfg = resolveRemnicConfigRecord7(raw);
15258
- const config = parseConfig8(remnicCfg);
15318
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
15319
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
15320
+ const config = parseConfig9(remnicCfg);
15259
15321
  const memoryDir = resolveMemoryDir();
15260
15322
  const blConfig = {
15261
15323
  enabled: config.binaryLifecycleEnabled,
@@ -15444,7 +15506,7 @@ async function cmdOpenclawInstall(opts) {
15444
15506
  } else if (slotIsActiveLegacy) {
15445
15507
  changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
15446
15508
  }
15447
- if (!fs17.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
15509
+ if (!fs18.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
15448
15510
  if (hasLegacy && migrateLegacy) {
15449
15511
  changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
15450
15512
  }
@@ -15464,8 +15526,8 @@ async function cmdOpenclawInstall(opts) {
15464
15526
  Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
15465
15527
  return;
15466
15528
  }
15467
- if (fs17.existsSync(memoryDir)) {
15468
- const st = fs17.statSync(memoryDir);
15529
+ if (fs18.existsSync(memoryDir)) {
15530
+ const st = fs18.statSync(memoryDir);
15469
15531
  if (!st.isDirectory()) {
15470
15532
  throw new Error(
15471
15533
  `Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
@@ -15473,12 +15535,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
15473
15535
  );
15474
15536
  }
15475
15537
  } else {
15476
- fs17.mkdirSync(memoryDir, { recursive: true });
15538
+ fs18.mkdirSync(memoryDir, { recursive: true });
15477
15539
  console.log(`Created memory directory: ${memoryDir}`);
15478
15540
  }
15479
15541
  const configDir = path18.dirname(configPath);
15480
- if (!fs17.existsSync(configDir)) {
15481
- fs17.mkdirSync(configDir, { recursive: true });
15542
+ if (!fs18.existsSync(configDir)) {
15543
+ fs18.mkdirSync(configDir, { recursive: true });
15482
15544
  }
15483
15545
  atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
15484
15546
  console.log("\nDone! Summary of changes:");
@@ -15507,7 +15569,7 @@ async function cmdOpenclawUpgrade(opts) {
15507
15569
  const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
15508
15570
  const fallbackMemoryDir = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
15509
15571
  const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
15510
- const configExistedBefore = fs17.existsSync(configPath);
15572
+ const configExistedBefore = fs18.existsSync(configPath);
15511
15573
  const existingConfig = readOpenclawConfig(configPath);
15512
15574
  const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
15513
15575
  const preservedMemoryDir = opts.memoryDir ? path18.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
@@ -15732,15 +15794,15 @@ async function cmdOpenclawMigrateEngram(opts) {
15732
15794
  }
15733
15795
  function createOpenclawUpgradeBackupDir() {
15734
15796
  const backupsRoot = path18.join(resolveOpenclawStateDir(), "backups");
15735
- fs17.mkdirSync(backupsRoot, { recursive: true });
15736
- return fs17.mkdtempSync(path18.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
15797
+ fs18.mkdirSync(backupsRoot, { recursive: true });
15798
+ return fs18.mkdtempSync(path18.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
15737
15799
  }
15738
15800
  async function cmdTaxonomy(rest) {
15739
- initLogger3();
15801
+ initLogger4();
15740
15802
  const configPath = resolveConfigPath();
15741
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
15742
- const remnicCfg = resolveRemnicConfigRecord7(raw);
15743
- const config = parseConfig8(remnicCfg);
15803
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
15804
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
15805
+ const config = parseConfig9(remnicCfg);
15744
15806
  if (!config.taxonomyEnabled) {
15745
15807
  console.error(
15746
15808
  "Taxonomy is disabled in config (taxonomyEnabled = false). Enable it to use taxonomy commands."
@@ -15776,8 +15838,8 @@ async function cmdTaxonomy(rest) {
15776
15838
  console.log(doc);
15777
15839
  if (config.taxonomyAutoGenResolver) {
15778
15840
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15779
- fs17.mkdirSync(path18.dirname(resolverPath), { recursive: true });
15780
- fs17.writeFileSync(resolverPath, doc);
15841
+ fs18.mkdirSync(path18.dirname(resolverPath), { recursive: true });
15842
+ fs18.writeFileSync(resolverPath, doc);
15781
15843
  console.error(`Written: ${resolverPath}`);
15782
15844
  }
15783
15845
  break;
@@ -15823,7 +15885,7 @@ async function cmdTaxonomy(rest) {
15823
15885
  if (config.taxonomyAutoGenResolver) {
15824
15886
  const doc = generateResolverDocument(taxonomy);
15825
15887
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15826
- fs17.writeFileSync(resolverPath, doc);
15888
+ fs18.writeFileSync(resolverPath, doc);
15827
15889
  console.error(`Regenerated: ${resolverPath}`);
15828
15890
  }
15829
15891
  break;
@@ -15854,7 +15916,7 @@ async function cmdTaxonomy(rest) {
15854
15916
  if (config.taxonomyAutoGenResolver) {
15855
15917
  const doc = generateResolverDocument(taxonomy);
15856
15918
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15857
- fs17.writeFileSync(resolverPath, doc);
15919
+ fs18.writeFileSync(resolverPath, doc);
15858
15920
  console.error(`Regenerated: ${resolverPath}`);
15859
15921
  }
15860
15922
  break;
@@ -16045,12 +16107,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
16045
16107
  `Unknown training-export format "${args.format}". ${validList}`
16046
16108
  );
16047
16109
  }
16048
- if (!fs17.existsSync(args.memoryDir)) {
16110
+ if (!fs18.existsSync(args.memoryDir)) {
16049
16111
  throw new Error(
16050
16112
  `--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
16051
16113
  );
16052
16114
  }
16053
- if (!fs17.statSync(args.memoryDir).isDirectory()) {
16115
+ if (!fs18.statSync(args.memoryDir).isDirectory()) {
16054
16116
  throw new Error(
16055
16117
  `--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
16056
16118
  );
@@ -16136,10 +16198,10 @@ async function runTrainingExport(args, stdout = process.stdout) {
16136
16198
  }
16137
16199
  const formatted = adapter.formatRecords(records);
16138
16200
  const outDir = path18.dirname(args.output);
16139
- fs17.mkdirSync(outDir, { recursive: true });
16201
+ fs18.mkdirSync(outDir, { recursive: true });
16140
16202
  const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
16141
- fs17.writeFileSync(tmpPath, formatted, "utf-8");
16142
- fs17.renameSync(tmpPath, args.output);
16203
+ fs18.writeFileSync(tmpPath, formatted, "utf-8");
16204
+ fs18.renameSync(tmpPath, args.output);
16143
16205
  stdout.write(
16144
16206
  `Exported ${records.length} records to ${args.output} (${adapter.name} format)
16145
16207
  `
@@ -16191,6 +16253,9 @@ async function main(argv = process.argv.slice(2)) {
16191
16253
  case "who-knows":
16192
16254
  await cmdWhoKnows(rest);
16193
16255
  break;
16256
+ case "promotion-candidates":
16257
+ await cmdPromotionCandidates(rest);
16258
+ break;
16194
16259
  case "security":
16195
16260
  await cmdSecurity(rest);
16196
16261
  break;
@@ -16314,7 +16379,7 @@ async function main(argv = process.argv.slice(2)) {
16314
16379
  }
16315
16380
  }, 500);
16316
16381
  };
16317
- fs17.watch(memoryDir, { recursive: true }, (_event, filename) => {
16382
+ fs18.watch(memoryDir, { recursive: true }, (_event, filename) => {
16318
16383
  if (filename && filename.startsWith(".")) return;
16319
16384
  rebuild();
16320
16385
  });
@@ -16322,12 +16387,12 @@ async function main(argv = process.argv.slice(2)) {
16322
16387
  });
16323
16388
  } else if (subAction === "validate") {
16324
16389
  const treeDir = outputDir;
16325
- if (!fs17.existsSync(treeDir)) {
16390
+ if (!fs18.existsSync(treeDir)) {
16326
16391
  console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
16327
16392
  process.exit(1);
16328
16393
  }
16329
16394
  const indexPath = path18.join(treeDir, "INDEX.md");
16330
- if (!fs17.existsSync(indexPath)) {
16395
+ if (!fs18.existsSync(indexPath)) {
16331
16396
  console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
16332
16397
  process.exit(1);
16333
16398
  }
@@ -16449,7 +16514,7 @@ Options:
16449
16514
  break;
16450
16515
  }
16451
16516
  case "procedural": {
16452
- await cmdProcedural(rest);
16517
+ await runProceduralBinaryCommand(rest);
16453
16518
  break;
16454
16519
  }
16455
16520
  case "extensions": {
@@ -16509,9 +16574,9 @@ Other:
16509
16574
  let wearablesService;
16510
16575
  try {
16511
16576
  const configPath = resolveConfigPath();
16512
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
16513
- const remnicCfg = resolveRemnicConfigRecord7(raw);
16514
- const config = parseConfig8(remnicCfg);
16577
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
16578
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
16579
+ const config = parseConfig9(remnicCfg);
16515
16580
  wearablesOrchestrator = new Orchestrator5(config);
16516
16581
  await wearablesOrchestrator.initialize();
16517
16582
  await wearablesOrchestrator.deferredReady;
@@ -16567,9 +16632,9 @@ Other:
16567
16632
  const targetFactory = async () => {
16568
16633
  if (!orchestratorSingleton) {
16569
16634
  const configPath = resolveConfigPath();
16570
- const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
16571
- const remnicCfg = resolveRemnicConfigRecord7(raw);
16572
- const config = parseConfig8(remnicCfg);
16635
+ const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
16636
+ const remnicCfg = resolveRemnicConfigRecord8(raw);
16637
+ const config = parseConfig9(remnicCfg);
16573
16638
  orchestratorSingleton = new Orchestrator5(config);
16574
16639
  await orchestratorSingleton.initialize();
16575
16640
  await orchestratorSingleton.deferredReady;
@@ -16821,6 +16886,11 @@ Usage:
16821
16886
  Print procedural memory stats (counts + recency + config). Mirrors
16822
16887
  GET /engram/v1/procedural/stats and remnic.procedural_stats MCP tool
16823
16888
  (issue #567).
16889
+ remnic procedural maintain [--apply] [--format json|text] [--memory-dir <path>]
16890
+ Run procedure library-health maintenance (issue #2370): shadow report of
16891
+ merge / repair-flag / retire proposals from outcome telemetry; --apply
16892
+ executes them (requires procedural.maintenance.enabled). Mirrors the
16893
+ remnic.procedure_library_maintenance MCP tool.
16824
16894
  remnic training:export --format <name> --output <path> [options]
16825
16895
  Export memories as a fine-tuning dataset (issue #459). Run
16826
16896
  'remnic training:export --help' for the full option list.