@remnic/plugin-openclaw 1.0.11 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dist/capsule-cli-GBM3WPAM.js +33 -0
  2. package/dist/capsule-export-IXVERCQG.js +17 -0
  3. package/dist/{capsule-import-CFX7BY5W.js → capsule-import-IA6VIOPQ.js} +3 -3
  4. package/dist/{capsule-merge-7RVOHJK3.js → capsule-merge-IWOQ34KL.js} +2 -2
  5. package/dist/{causal-consolidation-JD6KJJH6.js → causal-consolidation-YI53C2AO.js} +3 -3
  6. package/dist/{chunk-K7EUBNDD.js → chunk-4LYQ4ONL.js} +1 -1
  7. package/dist/{chunk-N7EOZY6F.js → chunk-6F6EKSVP.js} +54 -1
  8. package/dist/{chunk-TNH24SF6.js → chunk-7UZNLMW5.js} +301 -125
  9. package/dist/{chunk-TVKKIS53.js → chunk-CDAZGIGT.js} +1 -1
  10. package/dist/{chunk-XMSDA5WA.js → chunk-EXDYWXMB.js} +1 -0
  11. package/dist/{capsule-export-CVA3CKUQ.js → chunk-FGTYFLL5.js} +21 -12
  12. package/dist/{chunk-ETJZRIAM.js → chunk-L6I4MQKO.js} +1 -1
  13. package/dist/{capsule-cli-TFKLAG3S.js → chunk-LLUROTZJ.js} +11 -12
  14. package/dist/{chunk-L4PRBB2A.js → chunk-OAE7AQ6R.js} +63 -91
  15. package/dist/{chunk-3I7RHWYT.js → chunk-RKR6PTPA.js} +105 -11
  16. package/dist/{chunk-P3DIW2SD.js → chunk-TILAJIJR.js} +1 -1
  17. package/dist/{engine-VMTFKFGO.js → engine-BIYI3P4J.js} +6 -4
  18. package/dist/index.js +1020 -308
  19. package/dist/{memory-governance-DWGFV4FX.js → memory-governance-SJ5DGRB3.js} +3 -3
  20. package/dist/{secure-store-FWJ7LBPH.js → secure-store-A4NGCNXV.js} +8 -2
  21. package/dist/{storage-T2OGFUF4.js → storage-PTQ2H2YJ.js} +2 -2
  22. package/dist/{types-H5R5D3WF.js → types-R4DO7AKM.js} +2 -2
  23. package/package.json +2 -2
  24. package/dist/chunk-YGXXBRV7.js +0 -10
package/dist/index.js CHANGED
@@ -1,10 +1,6 @@
1
1
  import {
2
2
  compareVersions
3
3
  } from "./chunk-GUSMRW4H.js";
4
- import {
5
- EXPORT_FORMAT,
6
- EXPORT_SCHEMA_VERSION
7
- } from "./chunk-YGXXBRV7.js";
8
4
  import {
9
5
  isSafeRouteNamespace,
10
6
  selectRouteRule,
@@ -12,10 +8,20 @@ import {
12
8
  } from "./chunk-FQRSVYY4.js";
13
9
  import {
14
10
  importCapsule
15
- } from "./chunk-ETJZRIAM.js";
11
+ } from "./chunk-L6I4MQKO.js";
12
+ import {
13
+ EXPORT_FORMAT,
14
+ EXPORT_SCHEMA_VERSION,
15
+ exportCapsule,
16
+ isValidCapsuleSince
17
+ } from "./chunk-FGTYFLL5.js";
16
18
  import {
19
+ CAPSULE_ID_PATTERN,
17
20
  ExportBundleV1Schema
18
- } from "./chunk-K7EUBNDD.js";
21
+ } from "./chunk-4LYQ4ONL.js";
22
+ import {
23
+ defaultCapsulesDir
24
+ } from "./chunk-LLUROTZJ.js";
19
25
  import {
20
26
  TierMigrationExecutor
21
27
  } from "./chunk-BU5KJVWF.js";
@@ -37,7 +43,7 @@ import {
37
43
  readMemoryGovernanceRunArtifact,
38
44
  restoreMemoryGovernanceRun,
39
45
  runMemoryGovernance
40
- } from "./chunk-TVKKIS53.js";
46
+ } from "./chunk-CDAZGIGT.js";
41
47
  import {
42
48
  clamp01,
43
49
  clampLifecycleThreshold,
@@ -84,7 +90,7 @@ import {
84
90
  parseOperatorAwareConsolidationResponse,
85
91
  renderExtensionsFooter,
86
92
  resolveExtensionsRoot
87
- } from "./chunk-P3DIW2SD.js";
93
+ } from "./chunk-TILAJIJR.js";
88
94
  import {
89
95
  BoxBuilder,
90
96
  countRecallTokenOverlap,
@@ -109,11 +115,12 @@ import {
109
115
  CompoundingEngine,
110
116
  SharedContextManager,
111
117
  defaultTierMigrationCycleBudget
112
- } from "./chunk-L4PRBB2A.js";
118
+ } from "./chunk-OAE7AQ6R.js";
113
119
  import {
120
+ ZodError,
114
121
  external_exports
115
- } from "./chunk-XMSDA5WA.js";
116
- import "./chunk-N7EOZY6F.js";
122
+ } from "./chunk-EXDYWXMB.js";
123
+ import "./chunk-6F6EKSVP.js";
117
124
  import {
118
125
  keyring_exports,
119
126
  secureStoreDir
@@ -181,11 +188,11 @@ import {
181
188
  sortMemoryLifecycleEvents,
182
189
  stripCitationForTemplate,
183
190
  toMemoryPathRel
184
- } from "./chunk-TNH24SF6.js";
191
+ } from "./chunk-7UZNLMW5.js";
185
192
  import {
186
193
  sidecarKey
187
194
  } from "./chunk-6OJAU466.js";
188
- import "./chunk-3I7RHWYT.js";
195
+ import "./chunk-RKR6PTPA.js";
189
196
  import {
190
197
  initLogger,
191
198
  log
@@ -32443,7 +32450,7 @@ var Orchestrator = class _Orchestrator {
32443
32450
  this.conversationFaiss = conversationIndexRuntime.faiss;
32444
32451
  this.conversationIndexBackend = conversationIndexRuntime.backend;
32445
32452
  this.sharedContext = config.sharedContextEnabled ? new SharedContextManager(config) : void 0;
32446
- this.compounding = config.compoundingEnabled ? new CompoundingEngine(config) : void 0;
32453
+ this.compounding = config.compoundingEnabled ? new CompoundingEngine(config, this.storage) : void 0;
32447
32454
  this.buffer = new SmartBuffer(config, this.storage);
32448
32455
  this.transcript = new TranscriptManager(config);
32449
32456
  this.conversationIndexDir = path43.join(
@@ -32745,8 +32752,7 @@ var Orchestrator = class _Orchestrator {
32745
32752
  promotionByOutcomeEnabled: this.config.promotionByOutcomeEnabled
32746
32753
  });
32747
32754
  if (this.config.factDeduplicationEnabled) {
32748
- const stateDir2 = path43.join(this.config.memoryDir, "state");
32749
- this.contentHashIndex = new ContentHashIndex(stateDir2);
32755
+ this.contentHashIndex = this.storage.createContentHashIndex();
32750
32756
  await this.contentHashIndex.load();
32751
32757
  log.info(
32752
32758
  `content-hash dedup: loaded ${this.contentHashIndex.size} hashes`
@@ -33404,7 +33410,7 @@ ${doc.content}` : doc.content,
33404
33410
  }
33405
33411
  async runDeepSleepGovernanceNow(options) {
33406
33412
  const targetStorage = options?.storage ?? this.storage;
33407
- const { runMemoryGovernance: runMemoryGovernance2 } = await import("./memory-governance-DWGFV4FX.js");
33413
+ const { runMemoryGovernance: runMemoryGovernance2 } = await import("./memory-governance-SJ5DGRB3.js");
33408
33414
  const { summarizeGovernanceResultForDreams } = await import("./dreams-ledger-3I52ISYR.js");
33409
33415
  const govResult = await runMemoryGovernance2({
33410
33416
  memoryDir: targetStorage.dir,
@@ -45905,8 +45911,8 @@ Returns: Performance trace data with timing breakdown`,
45905
45911
 
45906
45912
  // ../remnic-core/src/cli.ts
45907
45913
  import path74 from "path";
45908
- import { access as access6, readFile as readFile46, readdir as readdir27, unlink as unlink12 } from "fs/promises";
45909
- import { createHash as createHash13 } from "crypto";
45914
+ import { access as access7, readFile as readFile47, readdir as readdir28, unlink as unlink12 } from "fs/promises";
45915
+ import { createHash as createHash14 } from "crypto";
45910
45916
 
45911
45917
  // ../remnic-core/src/transfer/export-json.ts
45912
45918
  import path45 from "path";
@@ -46020,7 +46026,7 @@ async function backupMemoryDir(opts) {
46020
46026
  const ts = timestampDirName(/* @__PURE__ */ new Date());
46021
46027
  if (opts.encrypt === true) {
46022
46028
  const { listFilesRecursive: listFilesRecursive3, toPosixRelPath: toPosixRelPath2 } = await import("./fs-utils-PZRI2HDZ.js");
46023
- const { readFile: readFile53 } = await import("fs/promises");
46029
+ const { readFile: readFile54 } = await import("fs/promises");
46024
46030
  const memoryDirAbs = path47.resolve(opts.memoryDir);
46025
46031
  const filesAbs = await listFilesRecursive3(memoryDirAbs);
46026
46032
  const includeTranscripts = opts.includeTranscripts === true;
@@ -46030,7 +46036,7 @@ async function backupMemoryDir(opts) {
46030
46036
  const parts = relPosix.split("/");
46031
46037
  if (parts.some((p) => p === "node_modules" || p === ".git" || p === ".secure-store" || p === ".capsules")) continue;
46032
46038
  if (!includeTranscripts && parts[0] === "transcripts") continue;
46033
- const content = await readFile53(abs, "utf-8");
46039
+ const content = await readFile54(abs, "utf-8");
46034
46040
  records.push({ path: relPosix, content });
46035
46041
  }
46036
46042
  records.sort((a, b) => a.path.localeCompare(b.path));
@@ -49052,7 +49058,7 @@ function removeManagedCaptureInstructions(existing) {
49052
49058
  async function runOperatorSetup(options) {
49053
49059
  const now = options.now ?? /* @__PURE__ */ new Date();
49054
49060
  const configStatus = await loadCliPluginConfig(options.configPath);
49055
- const storage = new StorageManager(options.orchestrator.config.memoryDir);
49061
+ const storage = options.orchestrator.storage;
49056
49062
  await storage.ensureDirectories();
49057
49063
  await mkdir42(options.orchestrator.config.workspaceDir, { recursive: true });
49058
49064
  const qmdAvailable = await options.orchestrator.qmd.probe();
@@ -49329,6 +49335,7 @@ async function runOperatorDoctor(options) {
49329
49335
  const configStatus = await loadCliPluginConfig(options.configPath);
49330
49336
  const checks = [];
49331
49337
  const config = options.orchestrator.config;
49338
+ const storage = options.orchestrator.storage;
49332
49339
  const configReview = await buildOperatorConfigReviewReport({
49333
49340
  now,
49334
49341
  configStatus,
@@ -49379,7 +49386,7 @@ async function runOperatorDoctor(options) {
49379
49386
  remediation: conversationIndex.enabled && conversationIndex.status !== "ok" ? "Run `openclaw engram rebuild-index` to refresh the conversation index artifacts." : void 0,
49380
49387
  details: conversationIndex
49381
49388
  });
49382
- const meta = await new StorageManager(config.memoryDir).loadMeta();
49389
+ const meta = await storage.loadMeta();
49383
49390
  checks.push({
49384
49391
  key: "maintenance",
49385
49392
  status: meta.lastExtractionAt || meta.lastConsolidationAt ? "ok" : "warn",
@@ -49412,14 +49419,14 @@ async function runOperatorDoctor(options) {
49412
49419
  warnRatio: config.fileHygiene.lintWarnRatio
49413
49420
  }) : [];
49414
49421
  checks.push(summarizeHygieneWarnings(warnings, config.fileHygiene));
49415
- checks.push(await summarizeMemoryWorthLegacyCounters(new StorageManager(config.memoryDir)));
49422
+ checks.push(await summarizeMemoryWorthLegacyCounters(storage));
49416
49423
  checks.push(
49417
- await summarizeBufferSurpriseDistribution(new StorageManager(config.memoryDir), config)
49424
+ await summarizeBufferSurpriseDistribution(storage, config)
49418
49425
  );
49419
- checks.push(await summarizeConsolidationProvenance(new StorageManager(config.memoryDir), config));
49426
+ checks.push(await summarizeConsolidationProvenance(storage, config));
49420
49427
  checks.push(await summarizeGraphEdgeDecayStatus(config));
49421
49428
  checks.push(await summarizeTierDistribution(options.orchestrator.storage));
49422
- checks.push(await summarizeDreamsPhases(config));
49429
+ checks.push(await summarizeDreamsPhases(config, storage));
49423
49430
  checks.push(summarizeSecurityMitigations(config));
49424
49431
  checks.push(await summarizeObservationThroughput(config.memoryDir));
49425
49432
  const summary = checks.reduce(
@@ -49569,8 +49576,8 @@ async function summarizeTierDistribution(storage) {
49569
49576
  const sevenDaysAgoMs = Date.now() - 7 * 864e5;
49570
49577
  if (journalPath) {
49571
49578
  try {
49572
- const { readFile: readFile53 } = await import("fs/promises");
49573
- const raw = await readFile53(journalPath, "utf-8");
49579
+ const { readFile: readFile54 } = await import("fs/promises");
49580
+ const raw = await readFile54(journalPath, "utf-8");
49574
49581
  for (const line of raw.split("\n")) {
49575
49582
  const trimmed = line.trim();
49576
49583
  if (trimmed.length === 0) continue;
@@ -49615,9 +49622,8 @@ async function summarizeTierDistribution(storage) {
49615
49622
  };
49616
49623
  }
49617
49624
  }
49618
- async function summarizeDreamsPhases(config) {
49625
+ async function summarizeDreamsPhases(config, storage = new StorageManager(config.memoryDir)) {
49619
49626
  const phases = config.dreamsPhases;
49620
- const storage = new StorageManager(config.memoryDir);
49621
49627
  const meta = await storage.loadMeta();
49622
49628
  let deepSleepLastRun = null;
49623
49629
  let deepSleepLastRunWarning = null;
@@ -50868,6 +50874,8 @@ var GraphDashboardServer = class {
50868
50874
  // ../remnic-core/src/access-service.ts
50869
50875
  import { stat as stat19 } from "fs/promises";
50870
50876
  import * as nodeFs from "fs/promises";
50877
+ import { constants as fsConstants2 } from "fs";
50878
+ import { createHash as createHash13 } from "crypto";
50871
50879
 
50872
50880
  // ../remnic-core/src/access-idempotency.ts
50873
50881
  import { mkdir as mkdir44, open as open4, readFile as readFile40, rename as rename7, stat as stat18, unlink as unlink11, utimes as utimes2, writeFile as writeFile39 } from "fs/promises";
@@ -53338,6 +53346,18 @@ async function recordMemoryOutcome(storage, input) {
53338
53346
  // ../remnic-core/src/access-service.ts
53339
53347
  var EngramAccessInputError = class extends Error {
53340
53348
  };
53349
+ var cachedPackageVersion = null;
53350
+ async function getPackageVersion() {
53351
+ if (cachedPackageVersion !== null) return cachedPackageVersion;
53352
+ try {
53353
+ const raw = await nodeFs.readFile(new URL("../package.json", import.meta.url), "utf-8");
53354
+ const parsed = JSON.parse(raw);
53355
+ cachedPackageVersion = typeof parsed.version === "string" && parsed.version.length > 0 ? parsed.version : "unknown";
53356
+ } catch {
53357
+ cachedPackageVersion = "unknown";
53358
+ }
53359
+ return cachedPackageVersion;
53360
+ }
53341
53361
  function normalizeTrustZoneInputError(error) {
53342
53362
  const message = error instanceof Error ? error.message : null;
53343
53363
  if (!message) {
@@ -54942,6 +54962,147 @@ var EngramAccessService = class {
54942
54962
  });
54943
54963
  return { namespace: resolvedNamespace, ...report };
54944
54964
  }
54965
+ async memorySummarizeHourly() {
54966
+ await this.orchestrator.summarizer.runHourly();
54967
+ return {
54968
+ ok: true,
54969
+ message: "Hourly summarization completed. Check the summaries directory for results."
54970
+ };
54971
+ }
54972
+ async conversationIndexUpdate(request = {}) {
54973
+ if (!this.orchestrator.config.conversationIndexEnabled) {
54974
+ return {
54975
+ enabled: false,
54976
+ sessions: 0,
54977
+ chunks: 0,
54978
+ skipped: 0,
54979
+ skippedSessionKeys: [],
54980
+ embeddedRuns: 0,
54981
+ reason: "disabled"
54982
+ };
54983
+ }
54984
+ const hours = typeof request.hours === "number" && Number.isFinite(request.hours) ? Math.max(1, Math.floor(request.hours)) : 24;
54985
+ let sessionKey;
54986
+ if (request.sessionKey !== void 0) {
54987
+ if (typeof request.sessionKey !== "string" || request.sessionKey.trim().length === 0) {
54988
+ throw new EngramAccessInputError("sessionKey must be a non-empty string when provided");
54989
+ }
54990
+ sessionKey = request.sessionKey.trim();
54991
+ }
54992
+ if (sessionKey) {
54993
+ const result = await this.orchestrator.updateConversationIndex(
54994
+ sessionKey,
54995
+ hours,
54996
+ { embed: request.embed }
54997
+ );
54998
+ return {
54999
+ enabled: true,
55000
+ sessionKey,
55001
+ sessions: 1,
55002
+ chunks: result.chunks,
55003
+ skipped: result.skipped ? 1 : 0,
55004
+ skippedSessionKeys: result.skipped ? [sessionKey] : [],
55005
+ embeddedRuns: result.embedded ? 1 : 0,
55006
+ reason: result.reason,
55007
+ retryAfterMs: result.retryAfterMs
55008
+ };
55009
+ }
55010
+ const sessionKeys = await this.orchestrator.transcript.listSessionKeys();
55011
+ let chunks = 0;
55012
+ let skipped = 0;
55013
+ const skippedSessionKeys = [];
55014
+ let embeddedRuns = 0;
55015
+ for (const sessionKey2 of sessionKeys) {
55016
+ const result = await this.orchestrator.updateConversationIndex(
55017
+ sessionKey2,
55018
+ hours,
55019
+ { embed: request.embed }
55020
+ );
55021
+ chunks += result.chunks;
55022
+ if (result.skipped) {
55023
+ skipped += 1;
55024
+ skippedSessionKeys.push(sessionKey2);
55025
+ }
55026
+ if (result.embedded) {
55027
+ embeddedRuns += 1;
55028
+ }
55029
+ }
55030
+ return {
55031
+ enabled: true,
55032
+ sessions: sessionKeys.length,
55033
+ chunks,
55034
+ skipped,
55035
+ skippedSessionKeys,
55036
+ embeddedRuns
55037
+ };
55038
+ }
55039
+ async profilingReport(request = {}) {
55040
+ const profiler = this.orchestrator.profiler;
55041
+ if (!profiler.isEnabled) {
55042
+ return {
55043
+ enabled: false,
55044
+ reason: "disabled",
55045
+ message: "Profiling is disabled. Set profilingEnabled: true in your plugin config to enable."
55046
+ };
55047
+ }
55048
+ const format = request.format ?? "ascii";
55049
+ if (format !== "ascii" && format !== "json") {
55050
+ throw new EngramAccessInputError("format must be one of: ascii, json");
55051
+ }
55052
+ const limit = request.limit ?? 5;
55053
+ if (!Number.isInteger(limit) || limit < 1 || limit > 20) {
55054
+ throw new EngramAccessInputError("limit must be an integer between 1 and 20");
55055
+ }
55056
+ const traces = profiler.getRecentTraces(limit);
55057
+ const stats = profiler.getStats();
55058
+ const bottleneck = profiler.identifyBottleneck();
55059
+ if (format === "json") {
55060
+ return {
55061
+ enabled: true,
55062
+ format,
55063
+ traces,
55064
+ stats,
55065
+ bottleneck
55066
+ };
55067
+ }
55068
+ const lines = [];
55069
+ lines.push("Engram Profiling Report");
55070
+ lines.push("=".repeat(60));
55071
+ lines.push("");
55072
+ const allBuckets = [
55073
+ ["byKind", stats.byKind],
55074
+ ["bySpan", stats.bySpan]
55075
+ ];
55076
+ const hasStats = allBuckets.some(([, entries]) => Object.keys(entries).length > 0);
55077
+ if (hasStats) {
55078
+ lines.push("Aggregate Stats (all retained traces):");
55079
+ for (const [bucket, entries] of allBuckets) {
55080
+ for (const [key, summary] of Object.entries(entries)) {
55081
+ lines.push(
55082
+ ` ${bucket}/${key}: avg=${summary.avgMs}ms p50=${summary.p50Ms}ms p95=${summary.p95Ms}ms max=${summary.maxMs}ms (n=${summary.count})`
55083
+ );
55084
+ }
55085
+ }
55086
+ lines.push("");
55087
+ }
55088
+ if (bottleneck) {
55089
+ lines.push(`Bottleneck: ${bottleneck}`);
55090
+ lines.push("");
55091
+ }
55092
+ if (traces.length === 0) {
55093
+ lines.push("No traces recorded yet. Trigger a recall or extraction to see timing data.");
55094
+ } else {
55095
+ for (const trace of traces) {
55096
+ lines.push(formatProfileTraceAscii(trace));
55097
+ lines.push("");
55098
+ }
55099
+ }
55100
+ return {
55101
+ enabled: true,
55102
+ format,
55103
+ report: lines.join("\n")
55104
+ };
55105
+ }
54945
55106
  async trustZoneStatus(namespace, principal) {
54946
55107
  const resolvedNamespace = this.resolveReadableNamespace(namespace, principal);
54947
55108
  const storage = await this.orchestrator.getStorage(resolvedNamespace);
@@ -55861,22 +56022,82 @@ ${next}`);
55861
56022
  });
55862
56023
  return { promoted: true, memoryId: request.memoryId };
55863
56024
  }
56025
+ async memoryActionApply(request) {
56026
+ const actionTypes = /* @__PURE__ */ new Set([
56027
+ "store_episode",
56028
+ "store_note",
56029
+ "update_note",
56030
+ "create_artifact",
56031
+ "summarize_node",
56032
+ "discard",
56033
+ "link_graph"
56034
+ ]);
56035
+ if (!actionTypes.has(request.action)) {
56036
+ throw new EngramAccessInputError(
56037
+ `memory_action_apply: invalid action ${JSON.stringify(request.action)}`
56038
+ );
56039
+ }
56040
+ if (this.orchestrator.config.contextCompressionActionsEnabled !== true) {
56041
+ throw new EngramAccessInputError(
56042
+ "memory_action_apply is disabled; enable contextCompressionActionsEnabled to use this tool"
56043
+ );
56044
+ }
56045
+ const outcome = request.outcome ?? "skipped";
56046
+ if (outcome !== "applied" && outcome !== "skipped" && outcome !== "failed") {
56047
+ throw new EngramAccessInputError(
56048
+ `memory_action_apply: outcome must be "applied", "skipped", or "failed"; got ${JSON.stringify(outcome)}`
56049
+ );
56050
+ }
56051
+ const resolvedNs = this.resolveWritableNamespace(
56052
+ request.namespace,
56053
+ request.sessionKey,
56054
+ request.principal
56055
+ );
56056
+ const inputSummaryParts = [
56057
+ request.content,
56058
+ request.category ? `category=${request.category}` : void 0,
56059
+ request.linkTargetId ? `linkTargetId=${request.linkTargetId}` : void 0,
56060
+ request.linkType ? `linkType=${request.linkType}` : void 0,
56061
+ typeof request.linkStrength === "number" ? `linkStrength=${request.linkStrength}` : void 0,
56062
+ request.artifactType ? `artifactType=${request.artifactType}` : void 0,
56063
+ typeof request.execute === "boolean" ? `execute=${request.execute}` : void 0
56064
+ ].filter((part) => typeof part === "string" && part.length > 0);
56065
+ const event = {
56066
+ action: request.action,
56067
+ outcome,
56068
+ namespace: resolvedNs,
56069
+ actor: "access.memory_action_apply",
56070
+ subsystem: "access.memory_action_apply",
56071
+ reason: request.reason,
56072
+ memoryId: request.memoryId,
56073
+ sourceSessionKey: request.sessionKey,
56074
+ inputSummary: inputSummaryParts.length > 0 ? inputSummaryParts.join(" | ").slice(0, 500) : void 0,
56075
+ dryRun: request.dryRun === true,
56076
+ promptHash: typeof request.sourcePrompt === "string" && request.sourcePrompt.length > 0 ? createHash13("sha256").update(request.sourcePrompt).digest("hex") : void 0
56077
+ };
56078
+ const preview = this.orchestrator.previewMemoryActionEvent(event);
56079
+ if (request.dryRun === true) {
56080
+ return { recorded: false, dryRun: true, event: preview };
56081
+ }
56082
+ const recorded = await this.orchestrator.appendMemoryActionEvent(event);
56083
+ return { recorded, event: preview };
56084
+ }
55864
56085
  async contextCheckpoint(request) {
55865
56086
  const resolvedNs = this.resolveWritableNamespace(request.namespace, request.sessionKey, request.principal);
55866
56087
  const storage = await this.orchestrator.getStorage(resolvedNs);
55867
56088
  const storageDir = storage.dir;
55868
56089
  const { writeFile: writeFile45, mkdir: mkdir52 } = await import("fs/promises");
55869
- const { join: join5, resolve: resolve2 } = await import("path");
56090
+ const { join: join6, resolve: resolve2 } = await import("path");
55870
56091
  const safeKey = request.sessionKey.replace(/[^a-zA-Z0-9_-]/g, "_");
55871
56092
  if (!safeKey) throw new EngramAccessInputError("sessionKey is required");
55872
- const checkpointDir = join5(storageDir, "checkpoints", safeKey);
56093
+ const checkpointDir = join6(storageDir, "checkpoints", safeKey);
55873
56094
  const resolved = resolve2(checkpointDir);
55874
56095
  if (!resolved.startsWith(resolve2(storageDir))) {
55875
56096
  throw new EngramAccessInputError("Invalid sessionKey");
55876
56097
  }
55877
56098
  await mkdir52(checkpointDir, { recursive: true });
55878
56099
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
55879
- const filePath = join5(checkpointDir, `checkpoint-${ts}.md`);
56100
+ const filePath = join6(checkpointDir, `checkpoint-${ts}.md`);
55880
56101
  await writeFile45(filePath, request.context, "utf-8");
55881
56102
  return { saved: true };
55882
56103
  }
@@ -56157,13 +56378,158 @@ ${next}`);
56157
56378
  * caller having to construct the config object.
56158
56379
  */
56159
56380
  async capsuleImport(opts) {
56160
- const root = opts.root ?? this.orchestrator.config.memoryDir;
56161
- const versioning = opts.versioning ?? {
56381
+ const { namespace, principal, root: explicitRoot, memoryDir: explicitMemoryDir, ...importOptions } = opts;
56382
+ const resolvedNamespace = this.resolveWritableNamespace(namespace, void 0, principal);
56383
+ const storage = await this.orchestrator.getStorage(resolvedNamespace);
56384
+ const root = explicitRoot ?? storage.dir;
56385
+ const memoryDir = explicitMemoryDir ?? this.orchestrator.config.memoryDir;
56386
+ const versioning = importOptions.versioning ?? {
56162
56387
  enabled: this.orchestrator.config.versioningEnabled,
56163
56388
  maxVersionsPerPage: this.orchestrator.config.versioningMaxPerPage,
56164
56389
  sidecarDir: this.orchestrator.config.versioningSidecarDir
56165
56390
  };
56166
- return importCapsule({ ...opts, root, versioning });
56391
+ await this.validateCapsuleImportArchivePath(importOptions.archivePath);
56392
+ try {
56393
+ return await importCapsule({ ...importOptions, root, memoryDir, versioning });
56394
+ } catch (err) {
56395
+ const message = err instanceof Error ? err.message : String(err);
56396
+ if (this.isCapsuleImportArchiveInputError(err, message)) {
56397
+ throw new EngramAccessInputError(`capsule import failed: ${message}`);
56398
+ }
56399
+ throw err;
56400
+ }
56401
+ }
56402
+ async validateCapsuleImportArchivePath(archivePath) {
56403
+ let archiveStat;
56404
+ try {
56405
+ archiveStat = await stat19(archivePath);
56406
+ } catch (err) {
56407
+ if (!this.isCapsuleImportPathInputFsError(err)) throw err;
56408
+ const message = err instanceof Error ? err.message : String(err);
56409
+ throw new EngramAccessInputError(`capsule import failed: archive is not readable: ${message}`);
56410
+ }
56411
+ if (!archiveStat.isFile()) {
56412
+ throw new EngramAccessInputError("capsule import failed: archivePath must point to a file");
56413
+ }
56414
+ try {
56415
+ await nodeFs.access(archivePath, fsConstants2.R_OK);
56416
+ } catch (err) {
56417
+ if (!this.isCapsuleImportPathInputFsError(err)) throw err;
56418
+ const message = err instanceof Error ? err.message : String(err);
56419
+ throw new EngramAccessInputError(`capsule import failed: archive is not readable: ${message}`);
56420
+ }
56421
+ }
56422
+ isCapsuleImportPathInputFsError(err) {
56423
+ const code = typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
56424
+ return code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "EPERM" || code === "ELOOP";
56425
+ }
56426
+ isCapsuleImportArchiveInputError(err, message) {
56427
+ if (err instanceof ZodError) return true;
56428
+ const code = typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
56429
+ if (typeof code === "string" && code.startsWith("Z_")) return true;
56430
+ return message.startsWith("importCapsule: archive") || message.startsWith("importCapsule: bundle") || message.startsWith("importCapsule: manifest") || message.startsWith("importCapsule: record") || /incorrect header check|invalid stored block lengths|not in gzip format|unexpected end of file/i.test(message);
56431
+ }
56432
+ /**
56433
+ * Export a capsule archive from the orchestrator's memory directory.
56434
+ *
56435
+ * HTTP and future MCP surfaces use this rather than calling the transfer
56436
+ * helper directly so namespace ACL checks stay consistent with the archive
56437
+ * write side effect. The exporter still owns archive construction and
56438
+ * validation.
56439
+ */
56440
+ async capsuleExport(opts) {
56441
+ const { namespace, principal, root: explicitRoot, memoryDir: explicitMemoryDir, ...exportOptions } = opts;
56442
+ const resolvedNamespace = this.resolveWritableNamespace(namespace, void 0, principal);
56443
+ const storage = await this.orchestrator.getStorage(resolvedNamespace);
56444
+ const root = explicitRoot ?? storage.dir;
56445
+ const memoryDir = explicitMemoryDir ?? this.orchestrator.config.memoryDir;
56446
+ const pluginVersion = exportOptions.pluginVersion ?? await getPackageVersion();
56447
+ return exportCapsule({
56448
+ ...exportOptions,
56449
+ pluginVersion,
56450
+ root,
56451
+ memoryDir: exportOptions.encrypt === true ? memoryDir : void 0
56452
+ });
56453
+ }
56454
+ /**
56455
+ * List capsule archives in the namespace-scoped capsule store.
56456
+ *
56457
+ * MCP uses this access-layer method instead of reading arbitrary paths so
56458
+ * capsule discovery remains bound to the same namespace ACLs as export and
56459
+ * import.
56460
+ */
56461
+ async capsuleList(options) {
56462
+ const resolvedNamespace = this.resolveReadableNamespace(options?.namespace, options?.principal);
56463
+ const storage = await this.orchestrator.getStorage(resolvedNamespace);
56464
+ const capsulesDir = defaultCapsulesDir(storage.dir);
56465
+ let dirEntries;
56466
+ try {
56467
+ const capsulesDirStat = await nodeFs.lstat(capsulesDir);
56468
+ if (capsulesDirStat.isSymbolicLink()) {
56469
+ throw new EngramAccessInputError("capsule list failed: capsule store directory must not be a symlink");
56470
+ }
56471
+ if (!capsulesDirStat.isDirectory()) {
56472
+ throw new EngramAccessInputError("capsule list failed: capsule store path must be a directory");
56473
+ }
56474
+ dirEntries = await nodeFs.readdir(capsulesDir, { withFileTypes: true });
56475
+ } catch (err) {
56476
+ const code = typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
56477
+ if (code === "ENOENT") {
56478
+ return { namespace: resolvedNamespace, capsulesDir, capsules: [] };
56479
+ }
56480
+ throw err;
56481
+ }
56482
+ const archiveNames = dirEntries.filter(
56483
+ (entry) => entry.isFile() && (entry.name.endsWith(".capsule.json.gz") || entry.name.endsWith(".capsule.json.gz.enc"))
56484
+ ).map((entry) => entry.name).sort();
56485
+ const capsules = [];
56486
+ for (const archiveName of archiveNames) {
56487
+ const archivePath = nodePath.join(capsulesDir, archiveName);
56488
+ const id = archiveName.replace(/\.capsule\.json\.gz\.enc$/, "").replace(/\.capsule\.json\.gz$/, "");
56489
+ const manifestPath2 = nodePath.join(capsulesDir, `${id}.manifest.json`);
56490
+ let createdAt = null;
56491
+ let pluginVersion = null;
56492
+ let fileCount = null;
56493
+ let description = null;
56494
+ let manifestPathOrNull = manifestPath2;
56495
+ try {
56496
+ const manifestStat = await nodeFs.lstat(manifestPath2);
56497
+ if (manifestStat.isSymbolicLink() || !manifestStat.isFile()) {
56498
+ capsules.push({
56499
+ id,
56500
+ archivePath,
56501
+ manifestPath: manifestPathOrNull,
56502
+ createdAt,
56503
+ pluginVersion,
56504
+ fileCount,
56505
+ description
56506
+ });
56507
+ continue;
56508
+ }
56509
+ const raw = await nodeFs.readFile(manifestPath2, "utf-8");
56510
+ const sidecar = JSON.parse(raw);
56511
+ createdAt = typeof sidecar.createdAt === "string" ? sidecar.createdAt : null;
56512
+ pluginVersion = typeof sidecar.pluginVersion === "string" ? sidecar.pluginVersion : null;
56513
+ fileCount = Array.isArray(sidecar.files) ? sidecar.files.length : null;
56514
+ const capsule = sidecar.capsule;
56515
+ description = capsule && typeof capsule.description === "string" ? capsule.description : null;
56516
+ } catch (err) {
56517
+ const code = typeof err === "object" && err !== null && "code" in err ? err.code : void 0;
56518
+ if (code === "ENOENT") {
56519
+ manifestPathOrNull = null;
56520
+ }
56521
+ }
56522
+ capsules.push({
56523
+ id,
56524
+ archivePath,
56525
+ manifestPath: manifestPathOrNull,
56526
+ createdAt,
56527
+ pluginVersion,
56528
+ fileCount,
56529
+ description
56530
+ });
56531
+ }
56532
+ return { namespace: resolvedNamespace, capsulesDir, capsules };
56167
56533
  }
56168
56534
  // ── Dreams pipeline telemetry surfaces (issue #678 PR 3+4) ──────────────
56169
56535
  /**
@@ -56257,14 +56623,247 @@ import { createServer as createServer3 } from "http";
56257
56623
  import { randomUUID as randomUUID6, timingSafeEqual as timingSafeEqual2 } from "crypto";
56258
56624
  import { AsyncLocalStorage } from "async_hooks";
56259
56625
  import { existsSync as existsSync9 } from "fs";
56260
- import { readFile as readFile43 } from "fs/promises";
56626
+ import { readFile as readFile44 } from "fs/promises";
56261
56627
  import path70 from "path";
56262
56628
  import { fileURLToPath as fileURLToPath3, URL as URL3 } from "url";
56263
56629
 
56264
56630
  // ../remnic-core/src/access-mcp.ts
56265
- import { readFile as readFile42 } from "fs/promises";
56631
+ import { readFile as readFile43 } from "fs/promises";
56266
56632
  import { randomUUID as randomUUID5 } from "crypto";
56267
56633
 
56634
+ // ../remnic-core/src/access-schema.ts
56635
+ function formatZodError(error) {
56636
+ return {
56637
+ error: "request validation failed",
56638
+ code: "validation_error",
56639
+ details: error.issues.map((issue) => ({
56640
+ field: issue.path.join(".") || "(root)",
56641
+ message: issue.message
56642
+ }))
56643
+ };
56644
+ }
56645
+ var namespaceSchema = external_exports.string().trim().max(256).optional();
56646
+ var sessionKeySchema = external_exports.string().trim().min(1).max(512).optional();
56647
+ var idempotencyKeySchema = external_exports.string().trim().min(1).max(256).optional();
56648
+ var dryRunSchema = external_exports.boolean().optional();
56649
+ var schemaVersionSchema = external_exports.number().int().optional();
56650
+ var codingContextSchema = external_exports.object({
56651
+ projectId: external_exports.string().trim().min(1, "codingContext.projectId is required").max(128),
56652
+ branch: external_exports.string().trim().max(256).nullable(),
56653
+ rootPath: external_exports.string().trim().min(1, "codingContext.rootPath is required").max(1024),
56654
+ defaultBranch: external_exports.string().trim().max(256).nullable()
56655
+ }).nullable();
56656
+ var recallDisclosureSchema = external_exports.enum(["chunk", "section", "raw"]);
56657
+ var tagMatchSchema = external_exports.enum(["any", "all"]);
56658
+ var recallRequestSchema = external_exports.object({
56659
+ query: external_exports.string().min(1, "query is required"),
56660
+ sessionKey: sessionKeySchema,
56661
+ namespace: namespaceSchema,
56662
+ topK: external_exports.number().int().min(0).max(200).optional(),
56663
+ mode: external_exports.enum(["auto", "no_recall", "minimal", "full", "graph_mode"]).optional(),
56664
+ includeDebug: external_exports.boolean().optional(),
56665
+ disclosure: recallDisclosureSchema.optional(),
56666
+ codingContext: codingContextSchema.optional(),
56667
+ /** Working directory for auto git-context resolution (issue #569). */
56668
+ cwd: external_exports.string().trim().min(1, "cwd must be non-empty when provided").max(2048).optional(),
56669
+ /**
56670
+ * Arbitrary project tag for non-git-based project scoping (issue #569).
56671
+ * Creates a coding context with `projectId: "tag:<projectTag>"`.
56672
+ */
56673
+ projectTag: external_exports.string().trim().min(1, "projectTag must be non-empty when provided").max(256).optional(),
56674
+ /**
56675
+ * Historical recall pin (issue #680). ISO 8601 timestamp. The
56676
+ * schema only enforces the basic shape; the access service runs
56677
+ * `Date.parse` and emits a structured 400 on malformed input
56678
+ * (CLAUDE.md rule 51).
56679
+ */
56680
+ asOf: external_exports.string().trim().min(1, "asOf must be a non-empty ISO 8601 timestamp").max(64).optional(),
56681
+ /**
56682
+ * Free-form recall tag filter (issue #689). When provided, recall results
56683
+ * whose frontmatter `tags` do not match the filter are removed before the
56684
+ * response is returned. Comparison is case-sensitive exact match.
56685
+ */
56686
+ tags: external_exports.array(external_exports.string().trim().min(1).max(256)).max(50).optional(),
56687
+ /**
56688
+ * Match mode for `tags` (issue #689). Defaults to `"any"` when `tags` is
56689
+ * provided and `tagMatch` is omitted. Ignored when `tags` is absent.
56690
+ */
56691
+ tagMatch: tagMatchSchema.optional(),
56692
+ /**
56693
+ * Include graph edges below `graphTraversalConfidenceFloor` for diagnostic
56694
+ * recall traversal (issue #681). Defaults to false.
56695
+ */
56696
+ includeLowConfidence: external_exports.boolean().optional()
56697
+ });
56698
+ var recallExplainRequestSchema = external_exports.object({
56699
+ sessionKey: sessionKeySchema,
56700
+ namespace: namespaceSchema
56701
+ });
56702
+ var setCodingContextRequestSchema = external_exports.object({
56703
+ sessionKey: external_exports.string().trim().min(1, "sessionKey is required").max(512),
56704
+ codingContext: codingContextSchema
56705
+ });
56706
+ var messageSchema = external_exports.object({
56707
+ role: external_exports.enum(["user", "assistant"]),
56708
+ content: external_exports.string().min(1, "message content must be non-empty")
56709
+ });
56710
+ var observeRequestSchema = external_exports.object({
56711
+ sessionKey: external_exports.string().trim().min(1, "sessionKey is required").max(512),
56712
+ messages: external_exports.array(messageSchema).min(1, "messages must be a non-empty array"),
56713
+ namespace: namespaceSchema,
56714
+ skipExtraction: external_exports.boolean().optional(),
56715
+ /** Working directory for auto git-context resolution (issue #569). */
56716
+ cwd: external_exports.string().trim().min(1, "cwd must be non-empty when provided").max(2048).optional(),
56717
+ /**
56718
+ * Arbitrary project tag for non-git-based project scoping (issue #569).
56719
+ * Creates a coding context with `projectId: "tag:<projectTag>"`.
56720
+ */
56721
+ projectTag: external_exports.string().trim().min(1, "projectTag must be non-empty when provided").max(256).optional()
56722
+ });
56723
+ var writeContentSchema = external_exports.string().min(1, "content is required").max(5e4);
56724
+ var categorySchema = external_exports.enum([
56725
+ "fact",
56726
+ "preference",
56727
+ "correction",
56728
+ "entity",
56729
+ "decision",
56730
+ "relationship",
56731
+ "principle",
56732
+ "commitment",
56733
+ "moment",
56734
+ "skill",
56735
+ "rule",
56736
+ "procedure",
56737
+ "reasoning_trace"
56738
+ ]).optional();
56739
+ var confidenceSchema = external_exports.number().min(0).max(1).optional();
56740
+ var tagsSchema = external_exports.array(external_exports.string().max(256)).max(50).optional();
56741
+ var entityRefSchema = external_exports.string().trim().max(512).optional();
56742
+ var ttlSchema = external_exports.string().trim().max(128).optional();
56743
+ var sourceReasonSchema = external_exports.string().trim().max(2e3).optional();
56744
+ var memoryStoreRequestSchema = external_exports.object({
56745
+ schemaVersion: schemaVersionSchema,
56746
+ idempotencyKey: idempotencyKeySchema,
56747
+ dryRun: dryRunSchema,
56748
+ sessionKey: sessionKeySchema,
56749
+ content: writeContentSchema,
56750
+ category: categorySchema,
56751
+ confidence: confidenceSchema,
56752
+ namespace: namespaceSchema,
56753
+ tags: tagsSchema,
56754
+ entityRef: entityRefSchema,
56755
+ ttl: ttlSchema,
56756
+ sourceReason: sourceReasonSchema
56757
+ });
56758
+ var suggestionSubmitRequestSchema = memoryStoreRequestSchema;
56759
+ var reviewDispositionRequestSchema = external_exports.object({
56760
+ memoryId: external_exports.string().trim().min(1, "memoryId is required"),
56761
+ status: external_exports.enum([
56762
+ "active",
56763
+ "pending_review",
56764
+ "quarantined",
56765
+ "rejected",
56766
+ "superseded",
56767
+ "archived"
56768
+ ]),
56769
+ reasonCode: external_exports.string().trim().min(1, "reasonCode is required"),
56770
+ namespace: namespaceSchema
56771
+ });
56772
+ var trustZonePromoteRequestSchema = external_exports.object({
56773
+ recordId: external_exports.string().trim().min(1, "recordId is required"),
56774
+ targetZone: external_exports.enum(["working", "trusted"], {
56775
+ errorMap: () => ({ message: "targetZone must be 'working' or 'trusted'" })
56776
+ }),
56777
+ promotionReason: external_exports.string().trim().min(1, "promotionReason is required"),
56778
+ recordedAt: external_exports.string().trim().optional(),
56779
+ summary: external_exports.string().trim().max(5e3).optional(),
56780
+ dryRun: dryRunSchema,
56781
+ namespace: namespaceSchema
56782
+ });
56783
+ var trustZoneDemoSeedRequestSchema = external_exports.object({
56784
+ scenario: external_exports.string().trim().max(256).optional(),
56785
+ recordedAt: external_exports.string().trim().optional(),
56786
+ dryRun: dryRunSchema,
56787
+ namespace: namespaceSchema
56788
+ });
56789
+ var lcmSearchRequestSchema = external_exports.object({
56790
+ query: external_exports.string().min(1, "query is required"),
56791
+ sessionKey: sessionKeySchema,
56792
+ namespace: namespaceSchema,
56793
+ limit: external_exports.number().int().min(1).max(100).optional()
56794
+ });
56795
+ var daySummaryRequestSchema = external_exports.object({
56796
+ memories: external_exports.string().max(1e5).optional(),
56797
+ sessionKey: sessionKeySchema,
56798
+ namespace: namespaceSchema
56799
+ });
56800
+ var capsuleTopLevelSegmentSchema = external_exports.string().trim().min(1).max(128).refine(
56801
+ (value) => !value.includes("/") && !value.includes("\\"),
56802
+ "must be a top-level directory name without path separators"
56803
+ );
56804
+ var capsulePeerIdSchema = external_exports.string().trim().min(1).max(256).refine(
56805
+ (value) => value !== "." && value !== ".." && !value.includes("/") && !value.includes("\\"),
56806
+ "must be a plain peer id without path separators"
56807
+ );
56808
+ var capsuleIsoSinceSchema = external_exports.string().trim().min(1, "since must be a non-empty ISO 8601 timestamp").max(128).refine(
56809
+ isValidCapsuleSince,
56810
+ "since must be a valid ISO 8601 timestamp with no calendar overflow"
56811
+ );
56812
+ var capsuleExportRequestSchema = external_exports.object({
56813
+ name: external_exports.string().trim().min(1, "name is required").max(64, "name must be 64 characters or fewer").regex(
56814
+ CAPSULE_ID_PATTERN,
56815
+ "name must be alphanumeric with single dashes (no spaces, no leading/trailing dashes)"
56816
+ ),
56817
+ namespace: namespaceSchema,
56818
+ since: capsuleIsoSinceSchema.optional(),
56819
+ includeKinds: external_exports.array(capsuleTopLevelSegmentSchema).max(50).optional(),
56820
+ peerIds: external_exports.array(capsulePeerIdSchema).max(100).optional(),
56821
+ includeTranscripts: external_exports.boolean().optional(),
56822
+ encrypt: external_exports.boolean().optional()
56823
+ });
56824
+ var capsuleImportRequestSchema = external_exports.object({
56825
+ archivePath: external_exports.string().trim().min(1, "archivePath is required").max(4096),
56826
+ namespace: namespaceSchema,
56827
+ mode: external_exports.enum(["skip", "overwrite", "fork"]).optional()
56828
+ });
56829
+ var capsuleListRequestSchema = external_exports.object({
56830
+ namespace: namespaceSchema
56831
+ });
56832
+ var schemas = {
56833
+ recall: recallRequestSchema,
56834
+ recallExplain: recallExplainRequestSchema,
56835
+ setCodingContext: setCodingContextRequestSchema,
56836
+ observe: observeRequestSchema,
56837
+ memoryStore: memoryStoreRequestSchema,
56838
+ suggestionSubmit: suggestionSubmitRequestSchema,
56839
+ reviewDisposition: reviewDispositionRequestSchema,
56840
+ trustZonePromote: trustZonePromoteRequestSchema,
56841
+ trustZoneDemoSeed: trustZoneDemoSeedRequestSchema,
56842
+ lcmSearch: lcmSearchRequestSchema,
56843
+ daySummary: daySummaryRequestSchema,
56844
+ capsuleExport: capsuleExportRequestSchema,
56845
+ capsuleImport: capsuleImportRequestSchema,
56846
+ capsuleList: capsuleListRequestSchema
56847
+ };
56848
+ function validateRequest(schemaName, body) {
56849
+ const schema = schemas[schemaName];
56850
+ if (!schema) {
56851
+ return {
56852
+ success: false,
56853
+ error: {
56854
+ error: `unknown schema: ${schemaName}`,
56855
+ code: "validation_error",
56856
+ details: []
56857
+ }
56858
+ };
56859
+ }
56860
+ const result = schema.safeParse(body);
56861
+ if (result.success) {
56862
+ return { success: true, data: result.data };
56863
+ }
56864
+ return { success: false, error: formatZodError(result.error) };
56865
+ }
56866
+
56268
56867
  // ../remnic-core/src/citations.ts
56269
56868
  var OPEN_TAG = "<oai-mem-citation>";
56270
56869
  var CLOSE_TAG = "</oai-mem-citation>";
@@ -56321,12 +56920,43 @@ function withToolAliases(tool) {
56321
56920
  if (canonicalName === tool.name) return [canonicalTool];
56322
56921
  return [canonicalTool, tool];
56323
56922
  }
56923
+ var STRICT_MCP_SCHEMA_KEYS = {
56924
+ capsuleExport: [
56925
+ "name",
56926
+ "namespace",
56927
+ "since",
56928
+ "includeKinds",
56929
+ "peerIds",
56930
+ "includeTranscripts",
56931
+ "encrypt"
56932
+ ],
56933
+ capsuleImport: ["archivePath", "namespace", "mode"],
56934
+ capsuleList: ["namespace"]
56935
+ };
56936
+ function parseMcpRequest(schemaName, args) {
56937
+ const allowedKeys = STRICT_MCP_SCHEMA_KEYS[schemaName];
56938
+ if (allowedKeys) {
56939
+ const allowed = new Set(allowedKeys);
56940
+ const unexpected = Object.keys(args).filter((key) => !allowed.has(key));
56941
+ if (unexpected.length > 0) {
56942
+ throw new EngramAccessInputError(
56943
+ `request validation failed: (root): Unrecognized key(s) in object: ${unexpected.join(", ")}`
56944
+ );
56945
+ }
56946
+ }
56947
+ const validation = validateRequest(schemaName, args);
56948
+ if (validation.success) return validation.data;
56949
+ const details = validation.error.details.map((detail) => `${detail.field}: ${detail.message}`).join("; ");
56950
+ throw new EngramAccessInputError(
56951
+ details.length > 0 ? `${validation.error.error}: ${details}` : validation.error.error
56952
+ );
56953
+ }
56324
56954
  async function getMcpServerVersion() {
56325
56955
  const envVersion = readEnvVar("OPENCLAW_ENGRAM_VERSION")?.trim() || readEnvVar("npm_package_version")?.trim();
56326
56956
  if (envVersion) return envVersion;
56327
56957
  try {
56328
56958
  const pkgPath = new URL("../package.json", import.meta.url);
56329
- const raw = await readFile42(pkgPath, "utf-8");
56959
+ const raw = await readFile43(pkgPath, "utf-8");
56330
56960
  const parsed = JSON.parse(raw);
56331
56961
  return parsed.version?.trim() || "unknown";
56332
56962
  } catch {
@@ -56494,6 +57124,70 @@ var EngramMcpServer = class {
56494
57124
  additionalProperties: false
56495
57125
  }
56496
57126
  },
57127
+ {
57128
+ name: "engram.capsule_export",
57129
+ description: "Export a portable Remnic capsule archive from the namespace-scoped memory store.",
57130
+ inputSchema: {
57131
+ type: "object",
57132
+ properties: {
57133
+ name: {
57134
+ type: "string",
57135
+ description: "Capsule id (alphanumeric with single dashes, max 64 characters)."
57136
+ },
57137
+ namespace: { type: "string" },
57138
+ since: {
57139
+ type: "string",
57140
+ description: "Only include files modified on or after this ISO 8601 timestamp."
57141
+ },
57142
+ includeKinds: {
57143
+ type: "array",
57144
+ items: { type: "string" },
57145
+ description: "Optional top-level directory allow-list."
57146
+ },
57147
+ peerIds: {
57148
+ type: "array",
57149
+ items: { type: "string" },
57150
+ description: "Optional peer id allow-list for the peers/ subtree."
57151
+ },
57152
+ includeTranscripts: { type: "boolean" },
57153
+ encrypt: { type: "boolean" }
57154
+ },
57155
+ required: ["name"],
57156
+ additionalProperties: false
57157
+ }
57158
+ },
57159
+ {
57160
+ name: "engram.capsule_import",
57161
+ description: "Import a Remnic capsule archive into the namespace-scoped memory store.",
57162
+ inputSchema: {
57163
+ type: "object",
57164
+ properties: {
57165
+ archivePath: {
57166
+ type: "string",
57167
+ description: "Path to a .capsule.json.gz or .capsule.json.gz.enc archive."
57168
+ },
57169
+ namespace: { type: "string" },
57170
+ mode: {
57171
+ type: "string",
57172
+ enum: ["skip", "overwrite", "fork"],
57173
+ description: "Conflict handling mode. Defaults to skip."
57174
+ }
57175
+ },
57176
+ required: ["archivePath"],
57177
+ additionalProperties: false
57178
+ }
57179
+ },
57180
+ {
57181
+ name: "engram.capsule_list",
57182
+ description: "List capsule archives in the namespace-scoped capsule store.",
57183
+ inputSchema: {
57184
+ type: "object",
57185
+ properties: {
57186
+ namespace: { type: "string" }
57187
+ },
57188
+ additionalProperties: false
57189
+ }
57190
+ },
56497
57191
  {
56498
57192
  name: "engram.memory_governance_run",
56499
57193
  description: "Run Remnic memory governance in a bounded shadow/apply pass.",
@@ -57149,6 +57843,43 @@ var EngramMcpServer = class {
57149
57843
  additionalProperties: false
57150
57844
  }
57151
57845
  },
57846
+ {
57847
+ name: "engram.memory_action_apply",
57848
+ description: "Record a memory-action application event for policy-learning telemetry.",
57849
+ inputSchema: {
57850
+ type: "object",
57851
+ properties: {
57852
+ action: {
57853
+ type: "string",
57854
+ enum: [
57855
+ "store_episode",
57856
+ "store_note",
57857
+ "update_note",
57858
+ "create_artifact",
57859
+ "summarize_node",
57860
+ "discard",
57861
+ "link_graph"
57862
+ ]
57863
+ },
57864
+ category: { type: "string" },
57865
+ content: { type: "string" },
57866
+ outcome: { type: "string", enum: ["applied", "skipped", "failed"] },
57867
+ reason: { type: "string" },
57868
+ memoryId: { type: "string" },
57869
+ sessionKey: { type: "string" },
57870
+ linkTargetId: { type: "string" },
57871
+ linkType: { type: "string" },
57872
+ linkStrength: { type: "number" },
57873
+ artifactType: { type: "string" },
57874
+ execute: { type: "boolean" },
57875
+ sourcePrompt: { type: "string" },
57876
+ namespace: { type: "string" },
57877
+ dryRun: { type: "boolean" }
57878
+ },
57879
+ required: ["action"],
57880
+ additionalProperties: false
57881
+ }
57882
+ },
57152
57883
  {
57153
57884
  name: "engram.context_checkpoint",
57154
57885
  description: "Save a structured context checkpoint for a session (preserves conversation state to disk).",
@@ -57220,6 +57951,49 @@ var EngramMcpServer = class {
57220
57951
  additionalProperties: false
57221
57952
  }
57222
57953
  },
57954
+ {
57955
+ name: "engram.memory_summarize_hourly",
57956
+ description: "Generate hourly summaries for recent conversations.",
57957
+ inputSchema: {
57958
+ type: "object",
57959
+ properties: {},
57960
+ additionalProperties: false
57961
+ }
57962
+ },
57963
+ {
57964
+ name: "engram.conversation_index_update",
57965
+ description: "Chunk transcript history into conversation-index documents.",
57966
+ inputSchema: {
57967
+ type: "object",
57968
+ properties: {
57969
+ sessionKey: { type: "string" },
57970
+ hours: { type: "number", description: "How many hours of transcript history to include." },
57971
+ embed: { type: "boolean", description: "If true, run QMD embed after update for this invocation." }
57972
+ },
57973
+ additionalProperties: false
57974
+ }
57975
+ },
57976
+ {
57977
+ name: "engram.profiling_report",
57978
+ description: "Return timing and performance data for Remnic recall and extraction pipelines. Requires profilingEnabled: true.",
57979
+ inputSchema: {
57980
+ type: "object",
57981
+ properties: {
57982
+ format: {
57983
+ type: "string",
57984
+ enum: ["ascii", "json"],
57985
+ description: "Output format. Defaults to ascii."
57986
+ },
57987
+ limit: {
57988
+ type: "integer",
57989
+ minimum: 1,
57990
+ maximum: 20,
57991
+ description: "Number of recent traces to include. Defaults to 5."
57992
+ }
57993
+ },
57994
+ additionalProperties: false
57995
+ }
57996
+ },
57223
57997
  {
57224
57998
  name: "engram.graph_edge_decay_run",
57225
57999
  description: "Run the graph-edge-confidence decay maintenance pass (issue #681 PR 2/3). Respects graphEdgeDecayEnabled; writes a structured telemetry record to state/graph-edge-decay-status.json.",
@@ -57472,8 +58246,14 @@ var EngramMcpServer = class {
57472
58246
  if (method === "tools/call") {
57473
58247
  const params = request.params ?? {};
57474
58248
  const name = typeof params.name === "string" ? params.name : "";
57475
- const argumentsObject = params.arguments && typeof params.arguments === "object" && !Array.isArray(params.arguments) ? params.arguments : {};
57476
58249
  try {
58250
+ let argumentsObject = {};
58251
+ if ("arguments" in params && params.arguments !== void 0) {
58252
+ if (params.arguments === null || typeof params.arguments !== "object" || Array.isArray(params.arguments)) {
58253
+ throw new EngramAccessInputError("tools/call arguments must be an object when provided");
58254
+ }
58255
+ argumentsObject = params.arguments;
58256
+ }
57477
58257
  const effectivePrincipal = options?.principalOverride ?? this.authenticatedPrincipal;
57478
58258
  const result = await this.callTool(name, argumentsObject, effectivePrincipal, options?.sessionId);
57479
58259
  return {
@@ -57792,6 +58572,35 @@ ${body}`;
57792
58572
  sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
57793
58573
  namespace: typeof args.namespace === "string" ? args.namespace : void 0
57794
58574
  });
58575
+ case "engram.capsule_export": {
58576
+ const body = parseMcpRequest("capsuleExport", args);
58577
+ return this.service.capsuleExport({
58578
+ name: body.name,
58579
+ namespace: body.namespace,
58580
+ principal: effectivePrincipal,
58581
+ since: body.since,
58582
+ includeKinds: body.includeKinds,
58583
+ peerIds: body.peerIds,
58584
+ includeTranscripts: body.includeTranscripts,
58585
+ encrypt: body.encrypt
58586
+ });
58587
+ }
58588
+ case "engram.capsule_import": {
58589
+ const body = parseMcpRequest("capsuleImport", args);
58590
+ return this.service.capsuleImport({
58591
+ archivePath: expandTildePath(body.archivePath),
58592
+ namespace: body.namespace,
58593
+ principal: effectivePrincipal,
58594
+ mode: body.mode
58595
+ });
58596
+ }
58597
+ case "engram.capsule_list": {
58598
+ const body = parseMcpRequest("capsuleList", args);
58599
+ return this.service.capsuleList({
58600
+ namespace: body.namespace,
58601
+ principal: effectivePrincipal
58602
+ });
58603
+ }
57795
58604
  case "engram.memory_governance_run":
57796
58605
  return this.service.governanceRun({
57797
58606
  namespace: typeof args.namespace === "string" ? args.namespace : void 0,
@@ -58176,6 +58985,25 @@ ${body}`;
58176
58985
  timestamp: typeof args.timestamp === "string" ? args.timestamp : void 0
58177
58986
  });
58178
58987
  }
58988
+ case "engram.memory_action_apply":
58989
+ return this.service.memoryActionApply({
58990
+ action: typeof args.action === "string" ? args.action : "",
58991
+ outcome: typeof args.outcome === "string" ? args.outcome : void 0,
58992
+ reason: typeof args.reason === "string" ? args.reason : void 0,
58993
+ memoryId: typeof args.memoryId === "string" ? args.memoryId : void 0,
58994
+ namespace: typeof args.namespace === "string" ? args.namespace : void 0,
58995
+ principal: effectivePrincipal,
58996
+ sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
58997
+ content: typeof args.content === "string" ? args.content : void 0,
58998
+ category: typeof args.category === "string" ? args.category : void 0,
58999
+ linkTargetId: typeof args.linkTargetId === "string" ? args.linkTargetId : void 0,
59000
+ linkType: typeof args.linkType === "string" ? args.linkType : void 0,
59001
+ linkStrength: typeof args.linkStrength === "number" ? args.linkStrength : void 0,
59002
+ artifactType: typeof args.artifactType === "string" ? args.artifactType : void 0,
59003
+ execute: typeof args.execute === "boolean" ? args.execute : void 0,
59004
+ sourcePrompt: typeof args.sourcePrompt === "string" ? args.sourcePrompt : void 0,
59005
+ dryRun: args.dryRun === true
59006
+ });
58179
59007
  case "engram.context_checkpoint":
58180
59008
  return this.service.contextCheckpoint({
58181
59009
  sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : "",
@@ -58235,6 +59063,34 @@ ${body}`;
58235
59063
  namespace: typeof args.namespace === "string" ? args.namespace : void 0
58236
59064
  });
58237
59065
  }
59066
+ case "engram.memory_summarize_hourly":
59067
+ case "remnic.memory_summarize_hourly":
59068
+ return this.service.memorySummarizeHourly();
59069
+ case "engram.conversation_index_update":
59070
+ case "remnic.conversation_index_update": {
59071
+ if ("sessionKey" in args && args.sessionKey !== void 0 && typeof args.sessionKey !== "string") {
59072
+ throw new Error("sessionKey must be a string when provided");
59073
+ }
59074
+ const sessionKey = typeof args.sessionKey === "string" ? args.sessionKey : void 0;
59075
+ return this.service.conversationIndexUpdate({
59076
+ sessionKey,
59077
+ hours: typeof args.hours === "number" && Number.isFinite(args.hours) ? args.hours : void 0,
59078
+ embed: typeof args.embed === "boolean" ? args.embed : void 0
59079
+ });
59080
+ }
59081
+ case "engram.profiling_report":
59082
+ case "remnic.profiling_report": {
59083
+ if ("format" in args && args.format !== void 0 && typeof args.format !== "string") {
59084
+ throw new EngramAccessInputError("format must be a string when provided");
59085
+ }
59086
+ if ("limit" in args && args.limit !== void 0 && typeof args.limit !== "number") {
59087
+ throw new EngramAccessInputError("limit must be a number when provided");
59088
+ }
59089
+ return this.service.profilingReport({
59090
+ format: typeof args.format === "string" ? args.format : void 0,
59091
+ limit: typeof args.limit === "number" ? args.limit : void 0
59092
+ });
59093
+ }
58238
59094
  case "engram.graph_edge_decay_run":
58239
59095
  case "remnic.graph_edge_decay_run": {
58240
59096
  const cfg = this.service.configRef;
@@ -58383,204 +59239,6 @@ ${body}`;
58383
59239
  }
58384
59240
  };
58385
59241
 
58386
- // ../remnic-core/src/access-schema.ts
58387
- function formatZodError(error) {
58388
- return {
58389
- error: "request validation failed",
58390
- code: "validation_error",
58391
- details: error.issues.map((issue) => ({
58392
- field: issue.path.join(".") || "(root)",
58393
- message: issue.message
58394
- }))
58395
- };
58396
- }
58397
- var namespaceSchema = external_exports.string().trim().max(256).optional();
58398
- var sessionKeySchema = external_exports.string().trim().min(1).max(512).optional();
58399
- var idempotencyKeySchema = external_exports.string().trim().min(1).max(256).optional();
58400
- var dryRunSchema = external_exports.boolean().optional();
58401
- var schemaVersionSchema = external_exports.number().int().optional();
58402
- var codingContextSchema = external_exports.object({
58403
- projectId: external_exports.string().trim().min(1, "codingContext.projectId is required").max(128),
58404
- branch: external_exports.string().trim().max(256).nullable(),
58405
- rootPath: external_exports.string().trim().min(1, "codingContext.rootPath is required").max(1024),
58406
- defaultBranch: external_exports.string().trim().max(256).nullable()
58407
- }).nullable();
58408
- var recallDisclosureSchema = external_exports.enum(["chunk", "section", "raw"]);
58409
- var tagMatchSchema = external_exports.enum(["any", "all"]);
58410
- var recallRequestSchema = external_exports.object({
58411
- query: external_exports.string().min(1, "query is required"),
58412
- sessionKey: sessionKeySchema,
58413
- namespace: namespaceSchema,
58414
- topK: external_exports.number().int().min(0).max(200).optional(),
58415
- mode: external_exports.enum(["auto", "no_recall", "minimal", "full", "graph_mode"]).optional(),
58416
- includeDebug: external_exports.boolean().optional(),
58417
- disclosure: recallDisclosureSchema.optional(),
58418
- codingContext: codingContextSchema.optional(),
58419
- /** Working directory for auto git-context resolution (issue #569). */
58420
- cwd: external_exports.string().trim().min(1, "cwd must be non-empty when provided").max(2048).optional(),
58421
- /**
58422
- * Arbitrary project tag for non-git-based project scoping (issue #569).
58423
- * Creates a coding context with `projectId: "tag:<projectTag>"`.
58424
- */
58425
- projectTag: external_exports.string().trim().min(1, "projectTag must be non-empty when provided").max(256).optional(),
58426
- /**
58427
- * Historical recall pin (issue #680). ISO 8601 timestamp. The
58428
- * schema only enforces the basic shape; the access service runs
58429
- * `Date.parse` and emits a structured 400 on malformed input
58430
- * (CLAUDE.md rule 51).
58431
- */
58432
- asOf: external_exports.string().trim().min(1, "asOf must be a non-empty ISO 8601 timestamp").max(64).optional(),
58433
- /**
58434
- * Free-form recall tag filter (issue #689). When provided, recall results
58435
- * whose frontmatter `tags` do not match the filter are removed before the
58436
- * response is returned. Comparison is case-sensitive exact match.
58437
- */
58438
- tags: external_exports.array(external_exports.string().trim().min(1).max(256)).max(50).optional(),
58439
- /**
58440
- * Match mode for `tags` (issue #689). Defaults to `"any"` when `tags` is
58441
- * provided and `tagMatch` is omitted. Ignored when `tags` is absent.
58442
- */
58443
- tagMatch: tagMatchSchema.optional(),
58444
- /**
58445
- * Include graph edges below `graphTraversalConfidenceFloor` for diagnostic
58446
- * recall traversal (issue #681). Defaults to false.
58447
- */
58448
- includeLowConfidence: external_exports.boolean().optional()
58449
- });
58450
- var recallExplainRequestSchema = external_exports.object({
58451
- sessionKey: sessionKeySchema,
58452
- namespace: namespaceSchema
58453
- });
58454
- var setCodingContextRequestSchema = external_exports.object({
58455
- sessionKey: external_exports.string().trim().min(1, "sessionKey is required").max(512),
58456
- codingContext: codingContextSchema
58457
- });
58458
- var messageSchema = external_exports.object({
58459
- role: external_exports.enum(["user", "assistant"]),
58460
- content: external_exports.string().min(1, "message content must be non-empty")
58461
- });
58462
- var observeRequestSchema = external_exports.object({
58463
- sessionKey: external_exports.string().trim().min(1, "sessionKey is required").max(512),
58464
- messages: external_exports.array(messageSchema).min(1, "messages must be a non-empty array"),
58465
- namespace: namespaceSchema,
58466
- skipExtraction: external_exports.boolean().optional(),
58467
- /** Working directory for auto git-context resolution (issue #569). */
58468
- cwd: external_exports.string().trim().min(1, "cwd must be non-empty when provided").max(2048).optional(),
58469
- /**
58470
- * Arbitrary project tag for non-git-based project scoping (issue #569).
58471
- * Creates a coding context with `projectId: "tag:<projectTag>"`.
58472
- */
58473
- projectTag: external_exports.string().trim().min(1, "projectTag must be non-empty when provided").max(256).optional()
58474
- });
58475
- var writeContentSchema = external_exports.string().min(1, "content is required").max(5e4);
58476
- var categorySchema = external_exports.enum([
58477
- "fact",
58478
- "preference",
58479
- "correction",
58480
- "entity",
58481
- "decision",
58482
- "relationship",
58483
- "principle",
58484
- "commitment",
58485
- "moment",
58486
- "skill",
58487
- "rule",
58488
- "procedure",
58489
- "reasoning_trace"
58490
- ]).optional();
58491
- var confidenceSchema = external_exports.number().min(0).max(1).optional();
58492
- var tagsSchema = external_exports.array(external_exports.string().max(256)).max(50).optional();
58493
- var entityRefSchema = external_exports.string().trim().max(512).optional();
58494
- var ttlSchema = external_exports.string().trim().max(128).optional();
58495
- var sourceReasonSchema = external_exports.string().trim().max(2e3).optional();
58496
- var memoryStoreRequestSchema = external_exports.object({
58497
- schemaVersion: schemaVersionSchema,
58498
- idempotencyKey: idempotencyKeySchema,
58499
- dryRun: dryRunSchema,
58500
- sessionKey: sessionKeySchema,
58501
- content: writeContentSchema,
58502
- category: categorySchema,
58503
- confidence: confidenceSchema,
58504
- namespace: namespaceSchema,
58505
- tags: tagsSchema,
58506
- entityRef: entityRefSchema,
58507
- ttl: ttlSchema,
58508
- sourceReason: sourceReasonSchema
58509
- });
58510
- var suggestionSubmitRequestSchema = memoryStoreRequestSchema;
58511
- var reviewDispositionRequestSchema = external_exports.object({
58512
- memoryId: external_exports.string().trim().min(1, "memoryId is required"),
58513
- status: external_exports.enum([
58514
- "active",
58515
- "pending_review",
58516
- "quarantined",
58517
- "rejected",
58518
- "superseded",
58519
- "archived"
58520
- ]),
58521
- reasonCode: external_exports.string().trim().min(1, "reasonCode is required"),
58522
- namespace: namespaceSchema
58523
- });
58524
- var trustZonePromoteRequestSchema = external_exports.object({
58525
- recordId: external_exports.string().trim().min(1, "recordId is required"),
58526
- targetZone: external_exports.enum(["working", "trusted"], {
58527
- errorMap: () => ({ message: "targetZone must be 'working' or 'trusted'" })
58528
- }),
58529
- promotionReason: external_exports.string().trim().min(1, "promotionReason is required"),
58530
- recordedAt: external_exports.string().trim().optional(),
58531
- summary: external_exports.string().trim().max(5e3).optional(),
58532
- dryRun: dryRunSchema,
58533
- namespace: namespaceSchema
58534
- });
58535
- var trustZoneDemoSeedRequestSchema = external_exports.object({
58536
- scenario: external_exports.string().trim().max(256).optional(),
58537
- recordedAt: external_exports.string().trim().optional(),
58538
- dryRun: dryRunSchema,
58539
- namespace: namespaceSchema
58540
- });
58541
- var lcmSearchRequestSchema = external_exports.object({
58542
- query: external_exports.string().min(1, "query is required"),
58543
- sessionKey: sessionKeySchema,
58544
- namespace: namespaceSchema,
58545
- limit: external_exports.number().int().min(1).max(100).optional()
58546
- });
58547
- var daySummaryRequestSchema = external_exports.object({
58548
- memories: external_exports.string().max(1e5).optional(),
58549
- sessionKey: sessionKeySchema,
58550
- namespace: namespaceSchema
58551
- });
58552
- var schemas = {
58553
- recall: recallRequestSchema,
58554
- recallExplain: recallExplainRequestSchema,
58555
- setCodingContext: setCodingContextRequestSchema,
58556
- observe: observeRequestSchema,
58557
- memoryStore: memoryStoreRequestSchema,
58558
- suggestionSubmit: suggestionSubmitRequestSchema,
58559
- reviewDisposition: reviewDispositionRequestSchema,
58560
- trustZonePromote: trustZonePromoteRequestSchema,
58561
- trustZoneDemoSeed: trustZoneDemoSeedRequestSchema,
58562
- lcmSearch: lcmSearchRequestSchema,
58563
- daySummary: daySummaryRequestSchema
58564
- };
58565
- function validateRequest(schemaName, body) {
58566
- const schema = schemas[schemaName];
58567
- if (!schema) {
58568
- return {
58569
- success: false,
58570
- error: {
58571
- error: `unknown schema: ${schemaName}`,
58572
- code: "validation_error",
58573
- details: []
58574
- }
58575
- };
58576
- }
58577
- const result = schema.safeParse(body);
58578
- if (result.success) {
58579
- return { success: true, data: result.data };
58580
- }
58581
- return { success: false, error: formatZodError(result.error) };
58582
- }
58583
-
58584
59242
  // ../remnic-core/src/adapters/types.ts
58585
59243
  function headerValue(headers, key) {
58586
59244
  const raw = headers[key];
@@ -59099,6 +59757,36 @@ var EngramAccessHttpServer = class {
59099
59757
  this.respondJson(res, 200, { ok: true });
59100
59758
  return;
59101
59759
  }
59760
+ if (req.method === "POST" && (pathname === "/engram/v1/capsules/export" || pathname === "/remnic/v1/capsules/export")) {
59761
+ const body = await this.readValidatedBody(req, "capsuleExport");
59762
+ this.ensureWriteRateLimitAvailable();
59763
+ const result = await this.service.capsuleExport({
59764
+ name: body.name,
59765
+ namespace: this.resolveNamespace(req, body.namespace),
59766
+ principal: this.resolveRequestPrincipal(req),
59767
+ since: body.since,
59768
+ includeKinds: body.includeKinds,
59769
+ peerIds: body.peerIds,
59770
+ includeTranscripts: body.includeTranscripts,
59771
+ encrypt: body.encrypt
59772
+ });
59773
+ this.recordWriteRateLimitHit();
59774
+ this.respondJson(res, 200, result);
59775
+ return;
59776
+ }
59777
+ if (req.method === "POST" && (pathname === "/engram/v1/capsules/import" || pathname === "/remnic/v1/capsules/import")) {
59778
+ const body = await this.readValidatedBody(req, "capsuleImport");
59779
+ this.ensureWriteRateLimitAvailable();
59780
+ const result = await this.service.capsuleImport({
59781
+ archivePath: expandTildePath(body.archivePath),
59782
+ namespace: this.resolveNamespace(req, body.namespace),
59783
+ principal: this.resolveRequestPrincipal(req),
59784
+ mode: body.mode
59785
+ });
59786
+ this.recordWriteRateLimitHit();
59787
+ this.respondJson(res, 200, result);
59788
+ return;
59789
+ }
59102
59790
  if (req.method === "POST" && pathname === "/engram/v1/recall/explain") {
59103
59791
  const body = await this.readValidatedBody(req, "recallExplain");
59104
59792
  const response = await this.service.recallExplain({
@@ -59882,7 +60570,8 @@ var EngramAccessHttpServer = class {
59882
60570
  const toolName = typeof request.params?.name === "string" ? request.params.name : "";
59883
60571
  const toolArgs = request.params?.arguments;
59884
60572
  const dreamsRunDryRun = (toolName === "engram.dreams_run" || toolName === "remnic.dreams_run") && toolArgs !== null && typeof toolArgs === "object" && !Array.isArray(toolArgs) && toolArgs.dryRun === true;
59885
- const isMcpWrite = request.method === "tools/call" && (toolName === "engram.memory_store" || toolName === "remnic.memory_store" || toolName === "engram.suggestion_submit" || toolName === "remnic.suggestion_submit" || toolName === "engram.observe" || toolName === "remnic.observe" || !dreamsRunDryRun && (toolName === "engram.dreams_run" || toolName === "remnic.dreams_run"));
60573
+ const memoryActionApplyDryRun = (toolName === "engram.memory_action_apply" || toolName === "remnic.memory_action_apply") && toolArgs !== null && typeof toolArgs === "object" && !Array.isArray(toolArgs) && toolArgs.dryRun === true;
60574
+ const isMcpWrite = request.method === "tools/call" && (toolName === "engram.memory_store" || toolName === "remnic.memory_store" || toolName === "engram.suggestion_submit" || toolName === "remnic.suggestion_submit" || toolName === "engram.observe" || toolName === "remnic.observe" || toolName === "engram.capsule_export" || toolName === "remnic.capsule_export" || toolName === "engram.capsule_import" || toolName === "remnic.capsule_import" || !dreamsRunDryRun && (toolName === "engram.dreams_run" || toolName === "remnic.dreams_run") || !memoryActionApplyDryRun && (toolName === "engram.memory_action_apply" || toolName === "remnic.memory_action_apply"));
59886
60575
  if (isMcpWrite) {
59887
60576
  this.ensureWriteRateLimitAvailable();
59888
60577
  }
@@ -59946,7 +60635,7 @@ var EngramAccessHttpServer = class {
59946
60635
  }
59947
60636
  async respondStatic(res, filePath, contentType) {
59948
60637
  try {
59949
- const body = await readFile43(filePath, "utf-8");
60638
+ const body = await readFile44(filePath, "utf-8");
59950
60639
  res.statusCode = 200;
59951
60640
  res.setHeader("content-type", contentType);
59952
60641
  res.setHeader("content-length", String(Buffer.byteLength(body)));
@@ -60121,7 +60810,7 @@ async function resolveAgentAccessAuthToken(value, options = {}) {
60121
60810
  }
60122
60811
 
60123
60812
  // ../remnic-core/src/compat/checks.ts
60124
- import { access as access5, readFile as readFile44 } from "fs/promises";
60813
+ import { access as access6, readFile as readFile45 } from "fs/promises";
60125
60814
  import path71 from "path";
60126
60815
  var REQUIRED_HOOKS_LEGACY = ["before_agent_start", "agent_end"];
60127
60816
  var REQUIRED_HOOKS_NEW = ["before_prompt_build", "agent_end"];
@@ -60303,7 +60992,7 @@ async function runCompatChecks(options) {
60303
60992
  let pluginRaw = "";
60304
60993
  let pluginManifestPresent = false;
60305
60994
  try {
60306
- pluginRaw = await readFile44(pluginJsonPath, "utf-8");
60995
+ pluginRaw = await readFile45(pluginJsonPath, "utf-8");
60307
60996
  pluginManifestPresent = true;
60308
60997
  checks.push({
60309
60998
  id: "plugin-manifest-present",
@@ -60353,7 +61042,7 @@ async function runCompatChecks(options) {
60353
61042
  let packageRaw = "";
60354
61043
  let packageJsonPresent = false;
60355
61044
  try {
60356
- packageRaw = await readFile44(packageJsonPath, "utf-8");
61045
+ packageRaw = await readFile45(packageJsonPath, "utf-8");
60357
61046
  packageJsonPresent = true;
60358
61047
  } catch {
60359
61048
  checks.push({
@@ -60423,8 +61112,8 @@ async function runCompatChecks(options) {
60423
61112
  }
60424
61113
  }
60425
61114
  try {
60426
- await access5(indexPath);
60427
- const indexRaw = await readFile44(indexPath, "utf-8");
61115
+ await access6(indexPath);
61116
+ const indexRaw = await readFile45(indexPath, "utf-8");
60428
61117
  const structuralSource = stripCommentsAndStrings(indexRaw);
60429
61118
  const hooks = parseHookRegistrations(indexRaw);
60430
61119
  const missingLegacy = REQUIRED_HOOKS_LEGACY.filter((hook) => !hooks.has(hook));
@@ -60849,7 +61538,7 @@ async function promoteSemanticRuleFromMemory(options) {
60849
61538
  }
60850
61539
 
60851
61540
  // ../remnic-core/src/training-export/converter.ts
60852
- import { lstat as lstat2, readdir as readdir26, readFile as readFile45, realpath as realpath4 } from "fs/promises";
61541
+ import { lstat as lstat3, readdir as readdir27, readFile as readFile46, realpath as realpath4 } from "fs/promises";
60853
61542
  import path73 from "path";
60854
61543
 
60855
61544
  // ../remnic-core/src/training-export/date-parse.ts
@@ -61455,7 +62144,7 @@ async function runRepairMemoryProjectionCliCommand(options) {
61455
62144
  });
61456
62145
  }
61457
62146
  async function runMemoryTimelineCliCommand(options) {
61458
- const storage = new (await import("./storage-T2OGFUF4.js")).StorageManager(options.memoryDir);
62147
+ const storage = new (await import("./storage-PTQ2H2YJ.js")).StorageManager(options.memoryDir);
61459
62148
  return storage.getMemoryTimeline(options.memoryId, options.limit);
61460
62149
  }
61461
62150
  async function runMemoryGovernanceCliCommand(options) {
@@ -61483,7 +62172,7 @@ async function runMemoryGovernanceRestoreCliCommand(options) {
61483
62172
  });
61484
62173
  }
61485
62174
  async function runMemoryReviewDispositionCliCommand(options) {
61486
- const storage = new (await import("./storage-T2OGFUF4.js")).StorageManager(options.memoryDir);
62175
+ const storage = new (await import("./storage-PTQ2H2YJ.js")).StorageManager(options.memoryDir);
61487
62176
  const memory = await storage.getMemoryById(options.memoryId);
61488
62177
  if (!memory) throw new Error(`memory not found: ${options.memoryId}`);
61489
62178
  const updated = await storage.writeMemoryFrontmatter(memory, {
@@ -61662,7 +62351,7 @@ async function runSemanticRulePromoteCliCommand(options) {
61662
62351
  });
61663
62352
  }
61664
62353
  async function runCompoundingPromoteCliCommand(options) {
61665
- const { CompoundingEngine: CompoundingEngine2 } = await import("./engine-VMTFKFGO.js");
62354
+ const { CompoundingEngine: CompoundingEngine2 } = await import("./engine-BIYI3P4J.js");
61666
62355
  const config = parseConfig({
61667
62356
  memoryDir: options.memoryDir,
61668
62357
  qmdEnabled: false,
@@ -62076,7 +62765,7 @@ function effectivePolicyValuesForVersion(values, config) {
62076
62765
  }
62077
62766
  function policyVersionForValues(values, config) {
62078
62767
  const normalized = effectivePolicyValuesForVersion(values, config);
62079
- return createHash13("sha256").update(JSON.stringify(normalized)).digest("hex").slice(0, 12);
62768
+ return createHash14("sha256").update(JSON.stringify(normalized)).digest("hex").slice(0, 12);
62080
62769
  }
62081
62770
  async function readRuntimePolicySnapshot2(config, fileName) {
62082
62771
  const filePath = path74.join(config.memoryDir, "state", fileName);
@@ -62667,7 +63356,7 @@ async function withTimeout(promise, timeoutMs, timeoutMessage) {
62667
63356
  }
62668
63357
  async function runReplayCliCommand(orchestrator, options) {
62669
63358
  const extractionIdleTimeoutMs = Number.isFinite(options.extractionIdleTimeoutMs) ? Math.max(1e3, Math.floor(options.extractionIdleTimeoutMs)) : 15 * 6e4;
62670
- const inputRaw = await readFile46(options.inputPath, "utf-8");
63359
+ const inputRaw = await readFile47(options.inputPath, "utf-8");
62671
63360
  const registry = buildReplayNormalizerRegistry([
62672
63361
  openclawReplayNormalizer,
62673
63362
  claudeReplayNormalizer,
@@ -62759,7 +63448,7 @@ async function runBulkImportCliCommand(opts) {
62759
63448
  "Bulk import persistence is not wired: no ingestBatch callback was provided by the host CLI. Use --dry-run to validate without persisting, or invoke via `openclaw engram bulk-import` which supplies the orchestrator-backed ingestion path."
62760
63449
  );
62761
63450
  }
62762
- const inputRaw = await readFile46(opts.file, "utf-8");
63451
+ const inputRaw = await readFile47(opts.file, "utf-8");
62763
63452
  let inputParsed;
62764
63453
  try {
62765
63454
  inputParsed = JSON.parse(inputRaw);
@@ -62823,7 +63512,7 @@ async function runBulkImportCliCommand(opts) {
62823
63512
  async function getPluginVersion() {
62824
63513
  try {
62825
63514
  const pkgPath = new URL("../package.json", import.meta.url);
62826
- const raw = await readFile46(pkgPath, "utf-8");
63515
+ const raw = await readFile47(pkgPath, "utf-8");
62827
63516
  const parsed = JSON.parse(raw);
62828
63517
  return parsed.version ?? "unknown";
62829
63518
  } catch {
@@ -62832,7 +63521,7 @@ async function getPluginVersion() {
62832
63521
  }
62833
63522
  async function exists3(p) {
62834
63523
  try {
62835
- await access6(p);
63524
+ await access7(p);
62836
63525
  return true;
62837
63526
  } catch {
62838
63527
  return false;
@@ -62858,7 +63547,7 @@ async function walkMemoryMarkdownFiles(memoryDir, visit) {
62858
63547
  const walk = async (dir) => {
62859
63548
  let entries;
62860
63549
  try {
62861
- entries = await readdir27(dir, { withFileTypes: true });
63550
+ entries = await readdir28(dir, { withFileTypes: true });
62862
63551
  } catch {
62863
63552
  return;
62864
63553
  }
@@ -62888,7 +63577,7 @@ async function readAllMemoryFiles(memoryDir) {
62888
63577
  const out = [];
62889
63578
  await walkMemoryMarkdownFiles(memoryDir, async (fullPath) => {
62890
63579
  try {
62891
- const raw = await readFile46(fullPath, "utf-8");
63580
+ const raw = await readFile47(fullPath, "utf-8");
62892
63581
  const parsed = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
62893
63582
  if (!parsed) return;
62894
63583
  const fmRaw = parsed[1];
@@ -63634,8 +64323,8 @@ function registerCli(api, orchestrator, registerOptions = {}) {
63634
64323
  const memoryDir = await resolveMemoryDirForNamespace(orchestrator, namespace, {
63635
64324
  rejectUnsupportedOverride: true
63636
64325
  });
63637
- const { exportCapsule } = await import("./capsule-export-CVA3CKUQ.js");
63638
- const result = await exportCapsule({
64326
+ const { exportCapsule: exportCapsule2 } = await import("./capsule-export-IXVERCQG.js");
64327
+ const result = await exportCapsule2({
63639
64328
  name,
63640
64329
  root: memoryDir,
63641
64330
  since,
@@ -63680,7 +64369,7 @@ function registerCli(api, orchestrator, registerOptions = {}) {
63680
64369
  const memoryDir = await resolveMemoryDirForNamespace(orchestrator, namespace, {
63681
64370
  rejectUnsupportedOverride: true
63682
64371
  });
63683
- const { importCapsule: importCapsule2 } = await import("./capsule-import-CFX7BY5W.js");
64372
+ const { importCapsule: importCapsule2 } = await import("./capsule-import-IA6VIOPQ.js");
63684
64373
  const result = await importCapsule2({
63685
64374
  archivePath: expandTildePath(archivePath),
63686
64375
  root: memoryDir,
@@ -63703,11 +64392,11 @@ function registerCli(api, orchestrator, registerOptions = {}) {
63703
64392
  const opts = args[1] ?? {};
63704
64393
  const {
63705
64394
  parseCapsuleMergeOptions,
63706
- defaultCapsulesDir
63707
- } = await import("./capsule-cli-TFKLAG3S.js");
64395
+ defaultCapsulesDir: defaultCapsulesDir2
64396
+ } = await import("./capsule-cli-GBM3WPAM.js");
63708
64397
  const parsed = parseCapsuleMergeOptions(archiveArg, opts);
63709
64398
  const memoryDir = expandTildePath(orchestrator.config.memoryDir);
63710
- const capsulesDir = defaultCapsulesDir(memoryDir);
64399
+ const capsulesDir = defaultCapsulesDir2(memoryDir);
63711
64400
  const { stat: statMerge } = await import("fs/promises");
63712
64401
  let sourceArchive = expandTildePath(parsed.archive);
63713
64402
  const looksLikePath = sourceArchive.startsWith("/") || sourceArchive.startsWith("./") || sourceArchive.startsWith("../") || sourceArchive.includes(path74.sep);
@@ -63739,7 +64428,7 @@ function registerCli(api, orchestrator, registerOptions = {}) {
63739
64428
  );
63740
64429
  }
63741
64430
  }
63742
- const { mergeCapsule } = await import("./capsule-merge-7RVOHJK3.js");
64431
+ const { mergeCapsule } = await import("./capsule-merge-IWOQ34KL.js");
63743
64432
  const result = await mergeCapsule({
63744
64433
  sourceArchive,
63745
64434
  targetRoot: memoryDir,
@@ -63769,17 +64458,17 @@ function registerCli(api, orchestrator, registerOptions = {}) {
63769
64458
  const {
63770
64459
  parseCapsuleListOptions,
63771
64460
  renderCapsuleList,
63772
- defaultCapsulesDir
63773
- } = await import("./capsule-cli-TFKLAG3S.js");
64461
+ defaultCapsulesDir: defaultCapsulesDir2
64462
+ } = await import("./capsule-cli-GBM3WPAM.js");
63774
64463
  const memoryDir = expandTildePath(orchestrator.config.memoryDir);
63775
- const defaultDir = defaultCapsulesDir(memoryDir);
64464
+ const defaultDir = defaultCapsulesDir2(memoryDir);
63776
64465
  const dirWasExplicit = typeof opts.dir === "string" && opts.dir.trim() !== "";
63777
64466
  const parsed = parseCapsuleListOptions(opts, defaultDir);
63778
64467
  const capsulesDir = expandTildePath(parsed.capsulesDir);
63779
- const { readdir: readdir29, readFile: readFile53, stat: stat21 } = await import("fs/promises");
64468
+ const { readdir: readdir30, readFile: readFile54, stat: stat21 } = await import("fs/promises");
63780
64469
  let dirEntries;
63781
64470
  try {
63782
- dirEntries = await readdir29(capsulesDir);
64471
+ dirEntries = await readdir30(capsulesDir);
63783
64472
  } catch (err) {
63784
64473
  const code = err.code;
63785
64474
  if (dirWasExplicit) {
@@ -63815,7 +64504,7 @@ function registerCli(api, orchestrator, registerOptions = {}) {
63815
64504
  }
63816
64505
  if (hasManifest) {
63817
64506
  try {
63818
- const raw = await readFile53(manifestPath2, "utf-8");
64507
+ const raw = await readFile54(manifestPath2, "utf-8");
63819
64508
  const sidecar = JSON.parse(raw);
63820
64509
  createdAt = typeof sidecar.createdAt === "string" ? sidecar.createdAt : null;
63821
64510
  pluginVersion = typeof sidecar.pluginVersion === "string" ? sidecar.pluginVersion : null;
@@ -63850,10 +64539,10 @@ function registerCli(api, orchestrator, registerOptions = {}) {
63850
64539
  const {
63851
64540
  parseCapsuleInspectOptions,
63852
64541
  renderCapsuleInspect,
63853
- defaultCapsulesDir
63854
- } = await import("./capsule-cli-TFKLAG3S.js");
64542
+ defaultCapsulesDir: defaultCapsulesDir2
64543
+ } = await import("./capsule-cli-GBM3WPAM.js");
63855
64544
  const memoryDir = expandTildePath(orchestrator.config.memoryDir);
63856
- const capsulesDir = defaultCapsulesDir(memoryDir);
64545
+ const capsulesDir = defaultCapsulesDir2(memoryDir);
63857
64546
  const parsed = parseCapsuleInspectOptions(archiveArg, opts);
63858
64547
  const { stat: stat21 } = await import("fs/promises");
63859
64548
  let archivePath = expandTildePath(parsed.archive);
@@ -63881,8 +64570,8 @@ function registerCli(api, orchestrator, registerOptions = {}) {
63881
64570
  const sidecarPath = archivePath.replace(/\.enc$/, "").replace(/\.capsule\.json\.gz$/, ".manifest.json");
63882
64571
  let sidecar = null;
63883
64572
  try {
63884
- const { readFile: readFile53 } = await import("fs/promises");
63885
- const raw = await readFile53(sidecarPath, "utf-8");
64573
+ const { readFile: readFile54 } = await import("fs/promises");
64574
+ const raw = await readFile54(sidecarPath, "utf-8");
63886
64575
  sidecar = JSON.parse(raw);
63887
64576
  } catch {
63888
64577
  }
@@ -63891,7 +64580,7 @@ function registerCli(api, orchestrator, registerOptions = {}) {
63891
64580
  manifest = sidecar;
63892
64581
  } else if (isEncrypted) {
63893
64582
  const { gunzipSync } = await import("zlib");
63894
- const { parseExportBundle } = await import("./types-H5R5D3WF.js");
64583
+ const { parseExportBundle } = await import("./types-R4DO7AKM.js");
63895
64584
  let decryptedBuf;
63896
64585
  try {
63897
64586
  const { decryptCapsuleFileInMemory } = await import("./capsule-crypto-K3IRTKRH.js");
@@ -63919,10 +64608,10 @@ function registerCli(api, orchestrator, registerOptions = {}) {
63919
64608
  }
63920
64609
  manifest = parsed2.bundle.manifest;
63921
64610
  } else {
63922
- const { readFile: readFile53 } = await import("fs/promises");
64611
+ const { readFile: readFile54 } = await import("fs/promises");
63923
64612
  const { gunzipSync } = await import("zlib");
63924
- const { parseExportBundle } = await import("./types-H5R5D3WF.js");
63925
- const buf = await readFile53(archivePath);
64613
+ const { parseExportBundle } = await import("./types-R4DO7AKM.js");
64614
+ const buf = await readFile54(archivePath);
63926
64615
  const json = gunzipSync(buf).toString("utf-8");
63927
64616
  const parsed2 = parseExportBundle(JSON.parse(json));
63928
64617
  if (parsed2.capsuleVersion !== 2) {
@@ -66689,7 +67378,7 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
66689
67378
  runSecureStoreInit,
66690
67379
  createPassphraseReader,
66691
67380
  renderInitReport
66692
- } = await import("./secure-store-FWJ7LBPH.js");
67381
+ } = await import("./secure-store-A4NGCNXV.js");
66693
67382
  const memoryDir = expandTildePath(orchestrator.config.memoryDir);
66694
67383
  const kdf = typeof options.kdf === "string" ? options.kdf.trim() : "argon2id";
66695
67384
  if (kdf !== "argon2id" && kdf !== "scrypt") {
@@ -66717,7 +67406,7 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
66717
67406
  runSecureStoreUnlock,
66718
67407
  createPassphraseReader,
66719
67408
  renderUnlockReport
66720
- } = await import("./secure-store-FWJ7LBPH.js");
67409
+ } = await import("./secure-store-A4NGCNXV.js");
66721
67410
  const memoryDir = expandTildePath(orchestrator.config.memoryDir);
66722
67411
  const report = await runSecureStoreUnlock({
66723
67412
  memoryDir,
@@ -66736,7 +67425,7 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
66736
67425
  "Lock the secure-store. Clears the master key from the daemon's in-memory keyring. Idempotent \u2014 succeeds even if the store is already locked."
66737
67426
  ).option("--json", "Emit machine-readable JSON only").action(async (...args) => {
66738
67427
  const options = args[0] ?? {};
66739
- const { runSecureStoreLock, renderLockReport } = await import("./secure-store-FWJ7LBPH.js");
67428
+ const { runSecureStoreLock, renderLockReport } = await import("./secure-store-A4NGCNXV.js");
66740
67429
  const memoryDir = expandTildePath(orchestrator.config.memoryDir);
66741
67430
  const report = runSecureStoreLock({ memoryDir });
66742
67431
  if (options.json === true) {
@@ -66749,7 +67438,7 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
66749
67438
  "Encrypt existing plaintext storage-managed memory files in an initialized, unlocked secure-store. Idempotent; already-encrypted files are skipped."
66750
67439
  ).option("--json", "Emit machine-readable JSON only").action(async (...args) => {
66751
67440
  const options = args[0] ?? {};
66752
- const { runSecureStoreMigrate, renderMigrateReport } = await import("./secure-store-FWJ7LBPH.js");
67441
+ const { runSecureStoreMigrate, renderMigrateReport } = await import("./secure-store-A4NGCNXV.js");
66753
67442
  const memoryDir = expandTildePath(orchestrator.config.memoryDir);
66754
67443
  const report = await runSecureStoreMigrate({ memoryDir });
66755
67444
  if (options.json === true) {
@@ -66761,11 +67450,34 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
66761
67450
  process.exitCode = 1;
66762
67451
  }
66763
67452
  });
67453
+ async function runSecureStoreDisableCommand(options) {
67454
+ const { runSecureStoreDisable, renderDisableReport } = await import("./secure-store-A4NGCNXV.js");
67455
+ const memoryDir = expandTildePath(orchestrator.config.memoryDir);
67456
+ const report = await runSecureStoreDisable({ memoryDir });
67457
+ if (options.json === true) {
67458
+ console.log(JSON.stringify(report, null, 2));
67459
+ } else {
67460
+ console.log(renderDisableReport(report));
67461
+ }
67462
+ if (!report.ok) {
67463
+ process.exitCode = 1;
67464
+ }
67465
+ }
67466
+ secureStoreCmd.command("disable").description(
67467
+ "Decrypt storage-managed secure-store files back to plaintext. Requires an initialized, unlocked secure-store and keeps .secure-store metadata in place."
67468
+ ).option("--json", "Emit machine-readable JSON only").action(async (...args) => {
67469
+ const options = args[0] ?? {};
67470
+ await runSecureStoreDisableCommand(options);
67471
+ });
67472
+ secureStoreCmd.command("decrypt").description("Alias for `secure-store disable`.").option("--json", "Emit machine-readable JSON only").action(async (...args) => {
67473
+ const options = args[0] ?? {};
67474
+ await runSecureStoreDisableCommand(options);
67475
+ });
66764
67476
  secureStoreCmd.command("status").description(
66765
67477
  "Report secure-store status: whether a header exists, whether the daemon currently holds the key, KDF parameters, and last-unlock timestamp."
66766
67478
  ).option("--json", "Emit machine-readable JSON only").action(async (...args) => {
66767
67479
  const options = args[0] ?? {};
66768
- const { runSecureStoreStatus, renderStatusReport } = await import("./secure-store-FWJ7LBPH.js");
67480
+ const { runSecureStoreStatus, renderStatusReport } = await import("./secure-store-A4NGCNXV.js");
66769
67481
  const memoryDir = expandTildePath(orchestrator.config.memoryDir);
66770
67482
  const report = await runSecureStoreStatus({ memoryDir });
66771
67483
  if (options.json === true) {
@@ -67425,13 +68137,13 @@ async function probeQmdAvailability(host) {
67425
68137
  }
67426
68138
 
67427
68139
  // ../../src/index.ts
67428
- import { readFile as readFile52, realpath as realpath7, writeFile as writeFile44 } from "fs/promises";
68140
+ import { readFile as readFile53, realpath as realpath7, writeFile as writeFile44 } from "fs/promises";
67429
68141
  import { existsSync as existsSync12, readFileSync as readFileSync6 } from "fs";
67430
68142
  import path99 from "path";
67431
68143
  import os7 from "os";
67432
68144
 
67433
68145
  // ../remnic-core/src/opik-exporter.ts
67434
- import { createHash as createHash14, randomBytes as randomBytes2 } from "crypto";
68146
+ import { createHash as createHash15, randomBytes as randomBytes2 } from "crypto";
67435
68147
  import { readFileSync as readFileSync4 } from "fs";
67436
68148
  import path75 from "path";
67437
68149
  var OPIK_EXPORTER_SLOT = "__openclawOpikExporter";
@@ -67752,7 +68464,7 @@ var OpikExporter = class _OpikExporter {
67752
68464
  * the version/variant bits, not timestamp ordering.
67753
68465
  */
67754
68466
  sessionToTraceId(sessionKey) {
67755
- const digest = createHash14("sha256").update(sessionKey).digest();
68467
+ const digest = createHash15("sha256").update(sessionKey).digest();
67756
68468
  digest[6] = digest[6] & 15 | 112;
67757
68469
  digest[8] = digest[8] & 63 | 128;
67758
68470
  const hex = digest.slice(0, 16).toString("hex");
@@ -67799,7 +68511,7 @@ function cleanUserMessage(content) {
67799
68511
  }
67800
68512
 
67801
68513
  // src/public-artifacts.ts
67802
- import { readdir as readdir28, access as access7, stat as stat20, lstat as lstat3, realpath as realpath5 } from "fs/promises";
68514
+ import { readdir as readdir29, access as access8, stat as stat20, lstat as lstat4, realpath as realpath5 } from "fs/promises";
67803
68515
  import path76 from "path";
67804
68516
  var PUBLIC_DIRS = [
67805
68517
  { dir: "facts", kind: "fact", contentType: "markdown" },
@@ -67832,7 +68544,7 @@ async function listMarkdownFilesRecursive(rootDir, boundary, ancestorRealPaths)
67832
68544
  nextAncestors.add(resolvedRoot);
67833
68545
  let entries;
67834
68546
  try {
67835
- entries = await readdir28(rootDir, { withFileTypes: true });
68547
+ entries = await readdir29(rootDir, { withFileTypes: true });
67836
68548
  } catch {
67837
68549
  return [];
67838
68550
  }
@@ -67843,7 +68555,7 @@ async function listMarkdownFilesRecursive(rootDir, boundary, ancestorRealPaths)
67843
68555
  let isDir = entry.isDirectory();
67844
68556
  let isFile = entry.isFile();
67845
68557
  try {
67846
- const linkStat = await lstat3(fullPath);
68558
+ const linkStat = await lstat4(fullPath);
67847
68559
  if (linkStat.isSymbolicLink()) {
67848
68560
  if (!await isContainedWithin(fullPath, boundaryDir)) {
67849
68561
  continue;
@@ -67867,7 +68579,7 @@ async function listMarkdownFilesRecursive(rootDir, boundary, ancestorRealPaths)
67867
68579
  }
67868
68580
  async function pathExists2(inputPath) {
67869
68581
  try {
67870
- await access7(inputPath);
68582
+ await access8(inputPath);
67871
68583
  return true;
67872
68584
  } catch {
67873
68585
  return false;
@@ -67907,7 +68619,7 @@ async function listRemnicPublicArtifacts(params) {
67907
68619
  if (!await pathExists2(absolutePath)) continue;
67908
68620
  if (!await isContainedWithin(absolutePath, memoryDir)) continue;
67909
68621
  try {
67910
- const linkStat = await lstat3(absolutePath);
68622
+ const linkStat = await lstat4(absolutePath);
67911
68623
  if (linkStat.isSymbolicLink()) {
67912
68624
  const resolvedPath = await realpath5(absolutePath);
67913
68625
  const expectedParent = await realpath5(memoryDir);
@@ -68158,12 +68870,12 @@ import os6 from "os";
68158
68870
  import path92 from "path";
68159
68871
 
68160
68872
  // ../remnic-core/src/enrichment/audit.ts
68161
- import { mkdir as mkdir47, readFile as readFile47, appendFile as appendFile5 } from "fs/promises";
68873
+ import { mkdir as mkdir47, readFile as readFile48, appendFile as appendFile5 } from "fs/promises";
68162
68874
  import { existsSync as existsSync11 } from "fs";
68163
68875
  import path93 from "path";
68164
68876
 
68165
68877
  // ../remnic-core/src/transfer/capsule-fork.ts
68166
- import { lstat as lstat4, mkdir as mkdir48, readFile as readFile48, realpath as realpath6, writeFile as writeFile41 } from "fs/promises";
68878
+ import { lstat as lstat5, mkdir as mkdir48, readFile as readFile49, realpath as realpath6, writeFile as writeFile41 } from "fs/promises";
68167
68879
  import path94 from "path";
68168
68880
 
68169
68881
  // src/openclaw-tools/shapes.ts
@@ -68943,7 +69655,7 @@ function validateSlotSelection(ctx) {
68943
69655
  }
68944
69656
 
68945
69657
  // ../remnic-core/src/session-toggles.ts
68946
- import { mkdir as mkdir49, readFile as readFile49, writeFile as writeFile42 } from "fs/promises";
69658
+ import { mkdir as mkdir49, readFile as readFile50, writeFile as writeFile42 } from "fs/promises";
68947
69659
  import path95 from "path";
68948
69660
  function encodeToggleKey(sessionKey, agentId) {
68949
69661
  return `${encodeURIComponent(sessionKey)}::${encodeURIComponent(agentId)}`;
@@ -68958,7 +69670,7 @@ function decodeToggleKey(key) {
68958
69670
  }
68959
69671
  async function safeReadToggleFile(filePath) {
68960
69672
  try {
68961
- const raw = await readFile49(filePath, "utf8");
69673
+ const raw = await readFile50(filePath, "utf8");
68962
69674
  const parsed = JSON.parse(raw);
68963
69675
  if (!parsed || typeof parsed !== "object" || typeof parsed.entries !== "object") {
68964
69676
  return { version: 1, entries: {} };
@@ -69441,14 +70153,14 @@ import {
69441
70153
  } from "@remnic/core";
69442
70154
 
69443
70155
  // ../remnic-core/src/surfaces/dreams.ts
69444
- import { createHash as createHash15 } from "crypto";
70156
+ import { createHash as createHash16 } from "crypto";
69445
70157
  import { statSync, watch as watch2 } from "fs";
69446
- import { mkdir as mkdir51, readFile as readFile50, writeFile as writeFile43 } from "fs/promises";
70158
+ import { mkdir as mkdir51, readFile as readFile51, writeFile as writeFile43 } from "fs/promises";
69447
70159
  import path97 from "path";
69448
70160
  var DIARY_START_MARKER = "<!-- openclaw:dreaming:diary:start -->";
69449
70161
  var DIARY_END_MARKER = "<!-- openclaw:dreaming:diary:end -->";
69450
70162
  function stableDreamId(params) {
69451
- const digest = createHash15("sha1").update(
70163
+ const digest = createHash16("sha1").update(
69452
70164
  JSON.stringify({
69453
70165
  timestamp: params.timestamp,
69454
70166
  occurrence: params.occurrence
@@ -69609,7 +70321,7 @@ function createDreamsSurface() {
69609
70321
  return {
69610
70322
  async read(filePath) {
69611
70323
  try {
69612
- const content = await readFile50(filePath, "utf8");
70324
+ const content = await readFile51(filePath, "utf8");
69613
70325
  return parseDreamEntries(content);
69614
70326
  } catch (error) {
69615
70327
  if (error.code === "ENOENT") {
@@ -69622,7 +70334,7 @@ function createDreamsSurface() {
69622
70334
  await mkdir51(path97.dirname(filePath), { recursive: true });
69623
70335
  let content = "";
69624
70336
  try {
69625
- content = await readFile50(filePath, "utf8");
70337
+ content = await readFile51(filePath, "utf8");
69626
70338
  } catch (error) {
69627
70339
  if (error.code !== "ENOENT") throw error;
69628
70340
  }
@@ -69718,12 +70430,12 @@ ${ensured.slice(endIndex)}` : `${ensureDiary("")}${block}`;
69718
70430
  }
69719
70431
 
69720
70432
  // ../remnic-core/src/surfaces/heartbeat.ts
69721
- import { createHash as createHash16 } from "crypto";
70433
+ import { createHash as createHash17 } from "crypto";
69722
70434
  import { statSync as statSync2, watch as watch3 } from "fs";
69723
- import { readFile as readFile51 } from "fs/promises";
70435
+ import { readFile as readFile52 } from "fs/promises";
69724
70436
  import path98 from "path";
69725
70437
  function stableHeartbeatId(params) {
69726
- const digest = createHash16("sha1").update(
70438
+ const digest = createHash17("sha1").update(
69727
70439
  JSON.stringify({
69728
70440
  sourceOffset: params.sourceOffset
69729
70441
  })
@@ -69735,7 +70447,7 @@ function slugify(value) {
69735
70447
  if (normalized.length > 0) return normalized;
69736
70448
  const trimmed = value.trim();
69737
70449
  if (trimmed.length === 0) return "heartbeat-untitled";
69738
- return `heartbeat-${createHash16("sha1").update(trimmed).digest("hex").slice(0, 8)}`;
70450
+ return `heartbeat-${createHash17("sha1").update(trimmed).digest("hex").slice(0, 8)}`;
69739
70451
  }
69740
70452
  function parseTags(line) {
69741
70453
  const match = /^Tags:\s*(.*)$/i.exec(line.trim());
@@ -69884,7 +70596,7 @@ function createHeartbeatSurface() {
69884
70596
  return {
69885
70597
  async read(filePath) {
69886
70598
  try {
69887
- const content = await readFile51(filePath, "utf8");
70599
+ const content = await readFile52(filePath, "utf8");
69888
70600
  return parseHeartbeatEntries(content);
69889
70601
  } catch (error) {
69890
70602
  if (error.code === "ENOENT") {
@@ -71562,7 +72274,7 @@ Keep the reflection grounded in the evidence below.
71562
72274
  async readFile(params) {
71563
72275
  const requestedPath = normalizeWorkspacePath(params.relPath);
71564
72276
  const absolutePath = await resolveReadablePath(params.relPath);
71565
- const text = await readFile52(absolutePath, "utf-8");
72277
+ const text = await readFile53(absolutePath, "utf-8");
71566
72278
  const allLines = text.split(/\r?\n/);
71567
72279
  const from = typeof params.from === "number" ? Math.max(1, Math.floor(params.from)) : 1;
71568
72280
  const lines = typeof params.lines === "number" && Number.isFinite(params.lines) ? Math.max(1, Math.floor(params.lines)) : void 0;
@@ -72218,7 +72930,7 @@ Keep the reflection grounded in the evidence below.
72218
72930
  jobs: []
72219
72931
  };
72220
72932
  try {
72221
- const content = await readFile52(cronFilePath, "utf-8");
72933
+ const content = await readFile53(cronFilePath, "utf-8");
72222
72934
  jobsData = JSON.parse(content);
72223
72935
  } catch {
72224
72936
  }