@remnic/core 9.3.636 → 9.3.638

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 (83) hide show
  1. package/dist/access-cli.js +12 -12
  2. package/dist/access-http.d.ts +2 -2
  3. package/dist/access-http.js +8 -6
  4. package/dist/access-mcp.d.ts +2 -2
  5. package/dist/access-mcp.js +7 -5
  6. package/dist/{access-service-GVOE5U3C.d.ts → access-service-DvEvBv9_.d.ts} +2 -1
  7. package/dist/access-service.d.ts +2 -2
  8. package/dist/access-service.js +6 -4
  9. package/dist/active-recall.js +1 -1
  10. package/dist/bootstrap.d.ts +1 -1
  11. package/dist/causal-behavior.js +2 -2
  12. package/dist/causal-chain.js +2 -2
  13. package/dist/causal-consolidation.js +2 -2
  14. package/dist/causal-retrieval.js +2 -2
  15. package/dist/causal-trajectory-graph.js +1 -1
  16. package/dist/causal-trajectory.js +1 -1
  17. package/dist/{chunk-VTH5SKQW.js → chunk-2JIYTTQJ.js} +4 -4
  18. package/dist/{chunk-HZVIYZYN.js → chunk-7KRYJUTB.js} +6 -6
  19. package/dist/{chunk-7H5WCPBS.js → chunk-A3HKTPPV.js} +21 -6
  20. package/dist/chunk-A3HKTPPV.js.map +1 -0
  21. package/dist/{chunk-2IT7WFYE.js → chunk-FWIROLS6.js} +2 -1
  22. package/dist/chunk-FWIROLS6.js.map +1 -0
  23. package/dist/{chunk-JYFO32V4.js → chunk-I3YAA4BI.js} +9 -9
  24. package/dist/{chunk-A6D7A2FW.js → chunk-IHG27THY.js} +4 -4
  25. package/dist/{chunk-W25I7G6U.js → chunk-KXTLEB4L.js} +3 -3
  26. package/dist/{chunk-XM6M6DHG.js → chunk-MNDFVT4F.js} +195 -6
  27. package/dist/chunk-MNDFVT4F.js.map +1 -0
  28. package/dist/{chunk-7V2SGZ3H.js → chunk-NE566K4E.js} +2 -2
  29. package/dist/{chunk-NFNQ7TWF.js → chunk-OSPVAP56.js} +3 -3
  30. package/dist/{chunk-UXFOGILU.js → chunk-QDAWVW75.js} +1 -1
  31. package/dist/{chunk-TQOU3VAT.js → chunk-SSOMTUCA.js} +1 -1
  32. package/dist/{chunk-TFICNXXU.js → chunk-TJRV4MWX.js} +990 -252
  33. package/dist/chunk-TJRV4MWX.js.map +1 -0
  34. package/dist/{chunk-BK35NOJL.js → chunk-U2YPUWRB.js} +3 -3
  35. package/dist/{chunk-EWC6W6AB.js → chunk-UXA5L2DZ.js} +2 -2
  36. package/dist/{chunk-XL7FK7PJ.js → chunk-Y56J7CXW.js} +33 -16
  37. package/dist/{chunk-XL7FK7PJ.js.map → chunk-Y56J7CXW.js.map} +1 -1
  38. package/dist/{cli-B-fHk59D.d.ts → cli-BJBKNWIS.d.ts} +2 -2
  39. package/dist/cli.d.ts +3 -3
  40. package/dist/cli.js +13 -12
  41. package/dist/compounding/engine.js +1 -1
  42. package/dist/config.js +1 -1
  43. package/dist/explicit-capture.d.ts +1 -1
  44. package/dist/{graph-edge-decay-5ZOK7ZNO.js → graph-edge-decay-PUFNHOBS.js} +2 -2
  45. package/dist/graph-snapshot.js +2 -2
  46. package/dist/graph.d.ts +3 -0
  47. package/dist/graph.js +1 -1
  48. package/dist/index.d.ts +4 -4
  49. package/dist/index.js +17 -17
  50. package/dist/mcp-memory-inspector-app.d.ts +2 -2
  51. package/dist/operator-toolkit.js +3 -3
  52. package/dist/{orchestrator-CoqytbK_.d.ts → orchestrator-ibTTeoUa.d.ts} +9 -0
  53. package/dist/orchestrator.d.ts +1 -1
  54. package/dist/orchestrator.js +9 -9
  55. package/dist/recall-state.d.ts +2 -0
  56. package/dist/recall-state.js +1 -1
  57. package/dist/resume-bundles.js +4 -4
  58. package/dist/summarizer.js +2 -2
  59. package/dist/transcript.js +2 -2
  60. package/package.json +1 -1
  61. package/src/access-service-namespace.test.ts +740 -0
  62. package/src/access-service.ts +222 -3
  63. package/src/config.test.ts +118 -0
  64. package/src/config.ts +45 -10
  65. package/src/graph.ts +39 -17
  66. package/src/orchestrator.ts +1286 -331
  67. package/src/recall-state.ts +3 -0
  68. package/dist/chunk-2IT7WFYE.js.map +0 -1
  69. package/dist/chunk-7H5WCPBS.js.map +0 -1
  70. package/dist/chunk-TFICNXXU.js.map +0 -1
  71. package/dist/chunk-XM6M6DHG.js.map +0 -1
  72. /package/dist/{chunk-VTH5SKQW.js.map → chunk-2JIYTTQJ.js.map} +0 -0
  73. /package/dist/{chunk-HZVIYZYN.js.map → chunk-7KRYJUTB.js.map} +0 -0
  74. /package/dist/{chunk-JYFO32V4.js.map → chunk-I3YAA4BI.js.map} +0 -0
  75. /package/dist/{chunk-A6D7A2FW.js.map → chunk-IHG27THY.js.map} +0 -0
  76. /package/dist/{chunk-W25I7G6U.js.map → chunk-KXTLEB4L.js.map} +0 -0
  77. /package/dist/{chunk-7V2SGZ3H.js.map → chunk-NE566K4E.js.map} +0 -0
  78. /package/dist/{chunk-NFNQ7TWF.js.map → chunk-OSPVAP56.js.map} +0 -0
  79. /package/dist/{chunk-UXFOGILU.js.map → chunk-QDAWVW75.js.map} +0 -0
  80. /package/dist/{chunk-TQOU3VAT.js.map → chunk-SSOMTUCA.js.map} +0 -0
  81. /package/dist/{chunk-BK35NOJL.js.map → chunk-U2YPUWRB.js.map} +0 -0
  82. /package/dist/{chunk-EWC6W6AB.js.map → chunk-UXA5L2DZ.js.map} +0 -0
  83. /package/dist/{graph-edge-decay-5ZOK7ZNO.js.map → graph-edge-decay-PUFNHOBS.js.map} +0 -0
@@ -99,6 +99,7 @@ var LastRecallStore = class {
99
99
  queryLen: opts.query.length,
100
100
  memoryIds: opts.memoryIds,
101
101
  namespace: opts.namespace,
102
+ recallNamespaces: opts.recallNamespaces,
102
103
  traceId: opts.traceId,
103
104
  plannerMode: opts.plannerMode,
104
105
  requestedMode: opts.requestedMode,
@@ -257,4 +258,4 @@ export {
257
258
  LastRecallStore,
258
259
  TierMigrationStatusStore
259
260
  };
260
- //# sourceMappingURL=chunk-2IT7WFYE.js.map
261
+ //# sourceMappingURL=chunk-FWIROLS6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/recall-state.ts"],"sourcesContent":["import { appendFile, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { log } from \"./logger.js\";\nimport { writeFileAtomically } from \"./maintenance/atomic-file.js\";\nimport type {\n IdentityInjectionMode,\n RecallPlanMode,\n RecallTierExplain,\n} from \"./types.js\";\n\nexport interface LastRecallBudgetSummary {\n requestedTopK?: number;\n appliedTopK: number;\n recallBudgetChars: number;\n maxMemoryTokens: number;\n qmdFetchLimit?: number;\n qmdHybridFetchLimit?: number;\n finalContextChars?: number;\n truncated?: boolean;\n includedSections?: string[];\n omittedSections?: string[];\n}\n\nexport interface LastRecallSnapshot {\n sessionKey: string;\n recordedAt: string;\n queryHash: string;\n queryLen: number;\n memoryIds: string[];\n namespace?: string;\n recallNamespaces?: string[];\n traceId?: string;\n plannerMode?: RecallPlanMode;\n requestedMode?: RecallPlanMode;\n source?: string;\n fallbackUsed?: boolean;\n sourcesUsed?: string[];\n budgetsApplied?: LastRecallBudgetSummary;\n latencyMs?: number;\n resultPaths?: string[];\n policyVersion?: string;\n identityInjectionMode?: IdentityInjectionMode | \"none\";\n identityInjectedChars?: number;\n identityInjectionTruncated?: boolean;\n /**\n * Collision-safe write nonce. Random UUID set on every `record()`\n * call so the observation-mode direct-answer hook can detect stale\n * snapshots and avoid annotating a snapshot that a subsequent recall\n * already replaced (issue #518).\n */\n writeNonce?: string;\n /**\n * Optional tier-level explanation of how recall was served\n * (issue #518). Populated by orchestrator call sites that can\n * identify a concrete tier; surfaces expose the block via\n * `engram query --explain`, the `?explain=1` HTTP flag, and the\n * `remnic_recall_explain` MCP tool. Orthogonal to the existing\n * graph-path `recallExplain` operation.\n */\n tierExplain?: RecallTierExplain;\n}\n\nexport interface GraphRecallExpandedEntry {\n path: string;\n score: number;\n namespace: string;\n seed: string;\n hopDepth: number;\n decayedWeight: number;\n graphType: \"entity\" | \"time\" | \"causal\";\n /**\n * Issue #681 PR 3/3 — confidence of the edge that produced this entry's\n * recorded provenance (strongest edge along the chosen entry path).\n * Range `[0, 1]`. Optional so persisted snapshots from older builds\n * round-trip through `clampGraphRecallExpandedEntries` without dropping.\n */\n edgeConfidence?: number;\n}\n\nexport function clampGraphRecallExpandedEntries(\n entries: unknown,\n maxEntries: number = 64,\n): GraphRecallExpandedEntry[] {\n const limit = Math.max(1, Math.floor(maxEntries));\n if (!Array.isArray(entries)) return [];\n return entries\n .filter((item): item is Record<string, unknown> => !!item && typeof item === \"object\")\n .map((item) => {\n const graphType: \"entity\" | \"time\" | \"causal\" =\n item.graphType === \"entity\" || item.graphType === \"time\" || item.graphType === \"causal\"\n ? item.graphType\n : \"entity\";\n const out: GraphRecallExpandedEntry = {\n path: typeof item.path === \"string\" ? item.path : \"\",\n score: typeof item.score === \"number\" && Number.isFinite(item.score) ? item.score : 0,\n namespace: typeof item.namespace === \"string\" ? item.namespace : \"\",\n seed: typeof item.seed === \"string\" ? item.seed : \"\",\n hopDepth:\n typeof item.hopDepth === \"number\" && Number.isFinite(item.hopDepth)\n ? Math.max(0, Math.floor(item.hopDepth))\n : 0,\n decayedWeight:\n typeof item.decayedWeight === \"number\" && Number.isFinite(item.decayedWeight)\n ? Math.max(0, item.decayedWeight)\n : 0,\n graphType,\n };\n // Issue #681 PR 3/3: clamp `edgeConfidence` into [0, 1] when present.\n // Older snapshots without the field round-trip cleanly via the\n // optional shape; legacy callers always rendered as 1.0.\n if (\n typeof item.edgeConfidence === \"number\" &&\n Number.isFinite(item.edgeConfidence)\n ) {\n out.edgeConfidence = Math.min(1, Math.max(0, item.edgeConfidence));\n }\n return out;\n })\n .filter((item) => item.path.length > 0 && item.namespace.length > 0)\n .slice(0, limit);\n}\n\ntype LastRecallState = Record<string, LastRecallSnapshot>;\ntype StateFileWriter = (filePath: string, content: string) => Promise<void>;\n\n/**\n * Deep-copy a RecallTierExplain block. Used by both the write path\n * (so caller mutation after `record()` cannot tear the persisted\n * snapshot) and the read path (so caller mutation after `get()` /\n * `getMostRecent()` cannot tear the in-memory store).\n *\n * Uses structuredClone so future additions to RecallTierExplain do\n * not silently share references through hand-enumerated fields —\n * matching the pattern used elsewhere in the codebase (e.g.,\n * qmd-recall-cache.ts). The payload is pure JSON-shaped data, so\n * structuredClone is both safe and complete here.\n */\nfunction cloneTierExplain(\n tierExplain: RecallTierExplain | undefined,\n): RecallTierExplain | undefined {\n if (!tierExplain) return undefined;\n return structuredClone(tierExplain);\n}\n\n/**\n * Deep-copy a LastRecallSnapshot so callers that receive it cannot\n * mutate the store's internal state through mutable array/object\n * fields. Same structuredClone rationale as cloneTierExplain above.\n */\nfunction cloneLastRecallSnapshot(\n snapshot: LastRecallSnapshot | null,\n): LastRecallSnapshot | null {\n if (!snapshot) return null;\n return structuredClone(snapshot);\n}\n\nexport interface TierMigrationCycleSummary {\n trigger: \"extraction\" | \"maintenance\" | \"manual\";\n scanned: number;\n migrated: number;\n promoted: number;\n demoted: number;\n limit: number;\n dryRun: boolean;\n skipped?: string;\n errorCount?: number;\n}\n\nexport interface TierMigrationStatusSnapshot {\n updatedAt: string;\n lastCycle: TierMigrationCycleSummary | null;\n totals: {\n cycles: number;\n scanned: number;\n migrated: number;\n promoted: number;\n demoted: number;\n errors: number;\n };\n}\n\nconst DEFAULT_TIER_MIGRATION_STATUS: TierMigrationStatusSnapshot = {\n updatedAt: new Date(0).toISOString(),\n lastCycle: null,\n totals: {\n cycles: 0,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n errors: 0,\n },\n};\n\nexport class LastRecallStore {\n private readonly statePath: string;\n private readonly impressionsPath: string;\n private readonly writeStateFile: StateFileWriter;\n private state: LastRecallState = {};\n private stateWriteChain: Promise<void> = Promise.resolve();\n\n constructor(memoryDir: string, options: { writeStateFile?: StateFileWriter } = {}) {\n this.statePath = path.join(memoryDir, \"state\", \"last_recall.json\");\n this.impressionsPath = path.join(memoryDir, \"state\", \"recall_impressions.jsonl\");\n this.writeStateFile =\n options.writeStateFile ??\n (async (filePath, content) => {\n await writeFileAtomically(filePath, content);\n });\n }\n\n async load(): Promise<void> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n const parsed = JSON.parse(raw) as LastRecallState;\n if (parsed && typeof parsed === \"object\") this.state = parsed;\n } catch {\n this.state = {};\n }\n }\n\n get(sessionKey: string): LastRecallSnapshot | null {\n // Defensive copy: callers must not be able to mutate internal state\n // by reaching into array/object fields on the returned snapshot.\n return cloneLastRecallSnapshot(this.state[sessionKey] ?? null);\n }\n\n getMostRecent(): LastRecallSnapshot | null {\n const snapshots = Object.values(this.state);\n if (snapshots.length === 0) return null;\n // Secondary key on sessionKey keeps the sort stable when two\n // snapshots share a recordedAt timestamp (CLAUDE.md rule 19).\n snapshots.sort((a, b) => {\n const byTime = b.recordedAt.localeCompare(a.recordedAt);\n if (byTime !== 0) return byTime;\n return a.sessionKey.localeCompare(b.sessionKey);\n });\n return cloneLastRecallSnapshot(snapshots[0] ?? null);\n }\n\n /**\n * Persist last-recall snapshot and append an impression log entry.\n * Does not store raw query text; uses a stable hash for correlation.\n */\n async record(opts: {\n sessionKey: string;\n query: string;\n memoryIds: string[];\n namespace?: string;\n recallNamespaces?: string[];\n traceId?: string;\n plannerMode?: RecallPlanMode;\n requestedMode?: RecallPlanMode;\n source?: string;\n fallbackUsed?: boolean;\n sourcesUsed?: string[];\n budgetsApplied?: LastRecallBudgetSummary;\n latencyMs?: number;\n resultPaths?: string[];\n policyVersion?: string;\n appendImpression?: boolean;\n identityInjection?: {\n mode: IdentityInjectionMode | \"none\";\n injectedChars: number;\n truncated: boolean;\n };\n /**\n * Per-tier explain annotation (issue #518). When supplied, the\n * snapshot carries it so downstream surfaces (CLI / HTTP / MCP)\n * can render which retrieval tier served the query.\n */\n tierExplain?: RecallTierExplain;\n }): Promise<void> {\n const now = new Date().toISOString();\n const queryHash = createHash(\"sha256\").update(opts.query).digest(\"hex\");\n\n // Build the snapshot from opts, then deep-copy it via\n // cloneLastRecallSnapshot so caller arrays/objects passed in\n // `opts` cannot retain a live reference to the persisted state\n // and tear it after record() returns.\n const liveSnapshot: LastRecallSnapshot = {\n sessionKey: opts.sessionKey,\n recordedAt: now,\n queryHash,\n writeNonce: randomUUID(),\n queryLen: opts.query.length,\n memoryIds: opts.memoryIds,\n namespace: opts.namespace,\n recallNamespaces: opts.recallNamespaces,\n traceId: opts.traceId,\n plannerMode: opts.plannerMode,\n requestedMode: opts.requestedMode,\n source: opts.source,\n fallbackUsed: opts.fallbackUsed,\n sourcesUsed: opts.sourcesUsed,\n budgetsApplied: opts.budgetsApplied,\n latencyMs: opts.latencyMs,\n resultPaths: opts.resultPaths,\n policyVersion: opts.policyVersion,\n identityInjectionMode: opts.identityInjection?.mode,\n identityInjectedChars: opts.identityInjection?.injectedChars,\n identityInjectionTruncated: opts.identityInjection?.truncated,\n tierExplain: opts.tierExplain,\n };\n // `cloneLastRecallSnapshot` handles `null` but that never applies\n // at this call site — the non-null assertion keeps the type\n // checker honest.\n const snapshot = cloneLastRecallSnapshot(liveSnapshot)!;\n\n this.state[opts.sessionKey] = snapshot;\n\n // Keep the state bounded; the impression log is append-only.\n const keys = Object.keys(this.state);\n if (keys.length > 50) {\n const ordered = keys\n .map((k) => ({ k, at: this.state[k]?.recordedAt ?? \"\" }))\n .sort((a, b) => b.at.localeCompare(a.at));\n for (const doomed of ordered.slice(50)) {\n delete this.state[doomed.k];\n }\n }\n\n try {\n await this.flushState();\n } catch (err) {\n log.debug(`last recall store write failed: ${err}`);\n }\n\n if (opts.appendImpression !== false) {\n try {\n await mkdir(path.dirname(this.impressionsPath), { recursive: true });\n await appendFile(this.impressionsPath, JSON.stringify(snapshot) + \"\\n\", \"utf-8\");\n } catch (err) {\n log.debug(`recall impressions append failed: ${err}`);\n }\n }\n }\n\n /**\n * Attach a RecallTierExplain block to the existing snapshot for a\n * session without rewriting the entire snapshot. Used by the\n * post-recall direct-answer annotation path (issue #518 slice 3c):\n * recallInternal records the snapshot first, then the orchestrator\n * fires the direct-answer tier in observation mode and annotates\n * the stored snapshot with whichever tier served the query.\n *\n * No-op when no snapshot exists for the given session; callers do\n * not need to guard on existence.\n */\n async annotateTierExplain(\n sessionKey: string,\n tierExplain: RecallTierExplain,\n expected?: { writeNonce?: string; traceId?: string; recordedAt?: string },\n ): Promise<void> {\n const current = this.state[sessionKey];\n if (!current) return;\n if (expected) {\n if (\n typeof expected.writeNonce === \"string\" &&\n expected.writeNonce.length > 0\n ) {\n if (current.writeNonce !== expected.writeNonce) return;\n } else {\n const hasExpectedTraceId =\n typeof expected.traceId === \"string\" && expected.traceId.length > 0;\n const traceIdMatches =\n hasExpectedTraceId && current.traceId === expected.traceId;\n const recordedAtMatches =\n expected.recordedAt !== undefined &&\n current.recordedAt === expected.recordedAt;\n if (hasExpectedTraceId) {\n if (!traceIdMatches) return;\n } else if (expected.recordedAt !== undefined && !recordedAtMatches) {\n return;\n }\n }\n }\n this.state[sessionKey] = {\n ...current,\n tierExplain: cloneTierExplain(tierExplain),\n };\n try {\n await this.flushState();\n } catch (err) {\n log.debug(`last recall tier-explain annotate failed: ${err}`);\n }\n }\n\n private flushState(): Promise<void> {\n const run = this.stateWriteChain.catch(() => undefined).then(async () => {\n await mkdir(path.dirname(this.statePath), { recursive: true });\n await this.writeStateFile(this.statePath, JSON.stringify(this.state, null, 2));\n });\n this.stateWriteChain = run.then(\n () => undefined,\n () => undefined,\n );\n return run;\n }\n}\n\nexport class TierMigrationStatusStore {\n private readonly statePath: string;\n private state: TierMigrationStatusSnapshot = structuredClone(DEFAULT_TIER_MIGRATION_STATUS);\n\n constructor(memoryDir: string) {\n this.statePath = path.join(memoryDir, \"state\", \"tier-migration-status.json\");\n }\n\n async load(): Promise<void> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<TierMigrationStatusSnapshot> | null;\n if (!parsed || typeof parsed !== \"object\") {\n this.state = structuredClone(DEFAULT_TIER_MIGRATION_STATUS);\n return;\n }\n const totals = parsed.totals && typeof parsed.totals === \"object\"\n ? parsed.totals\n : DEFAULT_TIER_MIGRATION_STATUS.totals;\n this.state = {\n updatedAt:\n typeof parsed.updatedAt === \"string\" && parsed.updatedAt.length > 0\n ? parsed.updatedAt\n : DEFAULT_TIER_MIGRATION_STATUS.updatedAt,\n lastCycle:\n parsed.lastCycle && typeof parsed.lastCycle === \"object\"\n ? (parsed.lastCycle as TierMigrationCycleSummary)\n : null,\n totals: {\n cycles: typeof totals.cycles === \"number\" && Number.isFinite(totals.cycles) ? totals.cycles : 0,\n scanned: typeof totals.scanned === \"number\" && Number.isFinite(totals.scanned) ? totals.scanned : 0,\n migrated: typeof totals.migrated === \"number\" && Number.isFinite(totals.migrated) ? totals.migrated : 0,\n promoted: typeof totals.promoted === \"number\" && Number.isFinite(totals.promoted) ? totals.promoted : 0,\n demoted: typeof totals.demoted === \"number\" && Number.isFinite(totals.demoted) ? totals.demoted : 0,\n errors: typeof totals.errors === \"number\" && Number.isFinite(totals.errors) ? totals.errors : 0,\n },\n };\n } catch {\n this.state = structuredClone(DEFAULT_TIER_MIGRATION_STATUS);\n }\n }\n\n get(): TierMigrationStatusSnapshot {\n return {\n updatedAt: this.state.updatedAt,\n lastCycle: this.state.lastCycle ? { ...this.state.lastCycle } : null,\n totals: { ...this.state.totals },\n };\n }\n\n async recordCycle(summary: TierMigrationCycleSummary): Promise<void> {\n const now = new Date().toISOString();\n const migratedDelta = summary.dryRun ? 0 : Math.max(0, summary.migrated);\n const promotedDelta = summary.dryRun ? 0 : Math.max(0, summary.promoted);\n const demotedDelta = summary.dryRun ? 0 : Math.max(0, summary.demoted);\n const next: TierMigrationStatusSnapshot = {\n updatedAt: now,\n lastCycle: { ...summary },\n totals: {\n cycles: this.state.totals.cycles + 1,\n scanned: this.state.totals.scanned + Math.max(0, summary.scanned),\n migrated: this.state.totals.migrated + migratedDelta,\n promoted: this.state.totals.promoted + promotedDelta,\n demoted: this.state.totals.demoted + demotedDelta,\n errors: this.state.totals.errors + Math.max(0, summary.errorCount ?? 0),\n },\n };\n this.state = next;\n try {\n await mkdir(path.dirname(this.statePath), { recursive: true });\n await writeFile(this.statePath, JSON.stringify(next, null, 2), \"utf-8\");\n } catch (err) {\n log.debug(`tier migration status write failed: ${err}`);\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -75,7 +75,7 @@ import {
75
75
  buildResumeBundleFromState,
76
76
  getResumeBundleStatus,
77
77
  recordResumeBundle
78
- } from "./chunk-W25I7G6U.js";
78
+ } from "./chunk-KXTLEB4L.js";
79
79
  import {
80
80
  parseXrayCliOptions
81
81
  } from "./chunk-QHXW3LZV.js";
@@ -89,7 +89,7 @@ import {
89
89
  runOperatorInventory,
90
90
  runOperatorRepair,
91
91
  runOperatorSetup
92
- } from "./chunk-VTH5SKQW.js";
92
+ } from "./chunk-2JIYTTQJ.js";
93
93
  import {
94
94
  listNamespaces,
95
95
  runNamespaceMigration,
@@ -203,22 +203,22 @@ import {
203
203
  } from "./chunk-UQ7RN5HK.js";
204
204
  import {
205
205
  parseConfig
206
- } from "./chunk-7H5WCPBS.js";
206
+ } from "./chunk-A3HKTPPV.js";
207
207
  import {
208
208
  getAbstractionNodeStoreStatus
209
209
  } from "./chunk-OADWQ5CR.js";
210
210
  import {
211
211
  EngramAccessHttpServer
212
- } from "./chunk-BK35NOJL.js";
212
+ } from "./chunk-U2YPUWRB.js";
213
213
  import {
214
214
  WearablesInputError
215
215
  } from "./chunk-7WV3F5DQ.js";
216
216
  import {
217
217
  EngramMcpServer
218
- } from "./chunk-NFNQ7TWF.js";
218
+ } from "./chunk-OSPVAP56.js";
219
219
  import {
220
220
  EngramAccessService
221
- } from "./chunk-XM6M6DHG.js";
221
+ } from "./chunk-MNDFVT4F.js";
222
222
  import {
223
223
  WorkStorage
224
224
  } from "./chunk-GDB4J2H3.js";
@@ -243,14 +243,14 @@ import {
243
243
  } from "./chunk-6HMYUWXR.js";
244
244
  import {
245
245
  analyzeGraphHealth
246
- } from "./chunk-XL7FK7PJ.js";
246
+ } from "./chunk-Y56J7CXW.js";
247
247
  import {
248
248
  RECALL_DISCLOSURE_LEVELS,
249
249
  isRecallDisclosure
250
250
  } from "./chunk-FPNQF475.js";
251
251
  import {
252
252
  getCausalTrajectoryStoreStatus
253
- } from "./chunk-TQOU3VAT.js";
253
+ } from "./chunk-SSOMTUCA.js";
254
254
  import {
255
255
  selectRouteRule,
256
256
  validateRouteTarget
@@ -7152,4 +7152,4 @@ export {
7152
7152
  resolveMemoryDirForNamespace,
7153
7153
  registerCli
7154
7154
  };
7155
- //# sourceMappingURL=chunk-JYFO32V4.js.map
7155
+ //# sourceMappingURL=chunk-I3YAA4BI.js.map
@@ -1,3 +1,6 @@
1
+ import {
2
+ analyzeSessionIntegrity
3
+ } from "./chunk-KFY3SGN7.js";
1
4
  import {
2
5
  encodeStoragePathSegment,
3
6
  encodeStoragePathSegmentWithHash,
@@ -5,9 +8,6 @@ import {
5
8
  resolveSafeStoragePath,
6
9
  storagePathHash
7
10
  } from "./chunk-FF4KLI5W.js";
8
- import {
9
- analyzeSessionIntegrity
10
- } from "./chunk-KFY3SGN7.js";
11
11
  import {
12
12
  log
13
13
  } from "./chunk-2ODBA7MQ.js";
@@ -911,4 +911,4 @@ var TranscriptManager = class _TranscriptManager {
911
911
  export {
912
912
  TranscriptManager
913
913
  };
914
- //# sourceMappingURL=chunk-A6D7A2FW.js.map
914
+ //# sourceMappingURL=chunk-IHG27THY.js.map
@@ -4,14 +4,14 @@ import {
4
4
  } from "./chunk-ZRWB5D4H.js";
5
5
  import {
6
6
  TranscriptManager
7
- } from "./chunk-A6D7A2FW.js";
7
+ } from "./chunk-IHG27THY.js";
8
8
  import {
9
9
  resolveCommitmentLedgerDir,
10
10
  validateCommitmentLedgerEntry
11
11
  } from "./chunk-LMDRGRJ2.js";
12
12
  import {
13
13
  parseConfig
14
- } from "./chunk-7H5WCPBS.js";
14
+ } from "./chunk-A3HKTPPV.js";
15
15
  import {
16
16
  resolveObjectiveStateStoreDir,
17
17
  validateObjectiveStateSnapshot
@@ -268,4 +268,4 @@ export {
268
268
  recordResumeBundle,
269
269
  getResumeBundleStatus
270
270
  };
271
- //# sourceMappingURL=chunk-W25I7G6U.js.map
271
+ //# sourceMappingURL=chunk-KXTLEB4L.js.map
@@ -44,12 +44,18 @@ import {
44
44
  seedTrustZoneDemoDataset,
45
45
  summarizeTrustZonePromotionReadiness
46
46
  } from "./chunk-JGSKJHF7.js";
47
+ import {
48
+ isPathInsideStorageRoot
49
+ } from "./chunk-FF4KLI5W.js";
47
50
  import {
48
51
  estimateRecallTokens
49
52
  } from "./chunk-YQNADJCT.js";
50
53
  import {
51
54
  namespaceCollectionName
52
55
  } from "./chunk-LASA46TQ.js";
56
+ import {
57
+ namespaceIdentityFromToken
58
+ } from "./chunk-ZFXCQPNO.js";
53
59
  import {
54
60
  recordObjectiveStateSnapshotsFromObservedMessages
55
61
  } from "./chunk-BMFZLLNI.js";
@@ -61,7 +67,7 @@ import {
61
67
  } from "./chunk-EIR5VLIH.js";
62
68
  import {
63
69
  buildGraphSnapshot
64
- } from "./chunk-7V2SGZ3H.js";
70
+ } from "./chunk-NE566K4E.js";
65
71
  import {
66
72
  wrapWorkLayerContext
67
73
  } from "./chunk-EI6V5UXY.js";
@@ -110,7 +116,7 @@ import {
110
116
  import {
111
117
  filterTrajectoriesByLookbackDays,
112
118
  readCausalTrajectoryRecords
113
- } from "./chunk-TQOU3VAT.js";
119
+ } from "./chunk-SSOMTUCA.js";
114
120
  import {
115
121
  canReadNamespace,
116
122
  canWriteNamespace,
@@ -141,6 +147,9 @@ import {
141
147
  iterateOfflineSyncSnapshotFileRecords,
142
148
  readOfflineSyncFileContentChunk
143
149
  } from "./chunk-ZLDUQWT2.js";
150
+ import {
151
+ SecureStoreLockedError
152
+ } from "./chunk-ILXTATKK.js";
144
153
  import {
145
154
  evaluateActionConfidence
146
155
  } from "./chunk-AH2JUU6X.js";
@@ -449,6 +458,42 @@ function formatProcedureStatsText(report) {
449
458
  import * as nodePath from "path";
450
459
  var EngramAccessInputError = class extends Error {
451
460
  };
461
+ function qmdCollectionPathParts(resultPath) {
462
+ if (!resultPath || nodePath.isAbsolute(resultPath)) return null;
463
+ const normalized = resultPath.replace(/\\/g, "/").replace(/^\/+/, "");
464
+ const slashIndex = normalized.indexOf("/");
465
+ if (slashIndex <= 0 || slashIndex >= normalized.length - 1) return null;
466
+ const collection = normalized.slice(0, slashIndex);
467
+ if (/^\d{4}-\d{2}-\d{2}$/.test(collection)) return null;
468
+ return {
469
+ collection,
470
+ relativePath: normalized.slice(slashIndex + 1)
471
+ };
472
+ }
473
+ function qmdResultPathCandidates(storageDir, resultPath) {
474
+ const candidates = /* @__PURE__ */ new Set();
475
+ const storageRoot = nodePath.resolve(storageDir);
476
+ const addCandidate = (candidate) => {
477
+ const resolved = nodePath.resolve(candidate);
478
+ if (isPathInsideStorageRoot(storageRoot, resolved)) {
479
+ candidates.add(resolved);
480
+ }
481
+ };
482
+ const addRelativeCandidates = (relativePath) => {
483
+ const normalized = relativePath.replace(/\\/g, "/").replace(/^\/+/, "");
484
+ if (!normalized) return;
485
+ addCandidate(nodePath.join(storageRoot, normalized));
486
+ if (/^\d{4}-\d{2}-\d{2}\//.test(normalized)) {
487
+ addCandidate(nodePath.join(storageRoot, "facts", normalized));
488
+ }
489
+ };
490
+ if (nodePath.isAbsolute(resultPath)) {
491
+ addCandidate(resultPath);
492
+ } else {
493
+ addRelativeCandidates(resultPath);
494
+ }
495
+ return [...candidates];
496
+ }
452
497
  var cachedPackageVersion = null;
453
498
  async function getPackageVersion() {
454
499
  if (cachedPackageVersion !== null) return cachedPackageVersion;
@@ -874,6 +919,7 @@ var EngramAccessService = class {
874
919
  queryLen: options.query.length,
875
920
  memoryIds,
876
921
  namespace,
922
+ recallNamespaces: [namespace],
877
923
  traceId: options.snapshot.traceId,
878
924
  plannerMode: options.normalizedMode,
879
925
  requestedMode: options.requestedMode && options.requestedMode !== "auto" ? options.requestedMode : void 0,
@@ -922,8 +968,108 @@ var EngramAccessService = class {
922
968
  const namespace = snapshot.namespace ? this.resolveNamespace(snapshot.namespace) : this.orchestrator.config.defaultNamespace;
923
969
  const storage = await this.orchestrator.getStorage(namespace);
924
970
  const storageDir = storage.dir;
971
+ const recallNamespaces = Array.from(
972
+ new Set(
973
+ [
974
+ namespace,
975
+ ...Array.isArray(snapshot.recallNamespaces) ? snapshot.recallNamespaces.map((ns) => this.resolveNamespace(ns)) : [],
976
+ this.orchestrator.config.defaultNamespace,
977
+ this.orchestrator.config.sharedNamespace,
978
+ ...(this.orchestrator.config.namespacePolicies ?? []).map((p) => p.name)
979
+ ].filter((ns) => typeof ns === "string" && ns.length > 0)
980
+ )
981
+ );
925
982
  const results = [];
926
983
  const seen = /* @__PURE__ */ new Set();
984
+ const collectionNamespaceFromPrefix = (collectionPrefix) => {
985
+ const baseCollection = this.orchestrator.config.qmdCollection;
986
+ if (collectionPrefix === baseCollection) return this.orchestrator.config.defaultNamespace;
987
+ const namespaceSuffix = collectionPrefix.startsWith(`${baseCollection}--`) ? collectionPrefix.slice(baseCollection.length + 2) : "";
988
+ if (!namespaceSuffix) return null;
989
+ const decoded = namespaceIdentityFromToken(namespaceSuffix);
990
+ if (decoded !== null) return decoded || this.orchestrator.config.defaultNamespace;
991
+ if (namespaceSuffix.startsWith("ns--")) {
992
+ const legacyNamespace = namespaceSuffix.slice("ns--".length).trim();
993
+ return legacyNamespace || null;
994
+ }
995
+ return null;
996
+ };
997
+ const readResultPath = async (memoryPath) => {
998
+ const parts = qmdCollectionPathParts(memoryPath);
999
+ const coldCollection = this.orchestrator.config.qmdColdCollection ?? "openclaw-engram-cold";
1000
+ if (parts && parts.collection === coldCollection) {
1001
+ const storages = [];
1002
+ const seenStorageDirs = /* @__PURE__ */ new Set();
1003
+ const addStorage = (candidateStorage) => {
1004
+ const candidateDir = nodePath.resolve(candidateStorage.dir);
1005
+ if (seenStorageDirs.has(candidateDir)) return;
1006
+ seenStorageDirs.add(candidateDir);
1007
+ storages.push({ storage: candidateStorage, dir: candidateDir });
1008
+ };
1009
+ addStorage(storage);
1010
+ for (const recallNamespace of recallNamespaces) {
1011
+ try {
1012
+ addStorage(await this.orchestrator.getStorage(recallNamespace));
1013
+ } catch {
1014
+ continue;
1015
+ }
1016
+ }
1017
+ for (const candidateStorage of storages) {
1018
+ try {
1019
+ const coldRoot = nodePath.join(candidateStorage.dir, "cold");
1020
+ for (const candidatePath of qmdResultPathCandidates(
1021
+ coldRoot,
1022
+ parts.relativePath
1023
+ )) {
1024
+ const memory = await candidateStorage.storage.readMemoryByPath(candidatePath);
1025
+ if (memory) return { memory, baseDir: candidateStorage.dir };
1026
+ }
1027
+ } catch (err) {
1028
+ if (err instanceof SecureStoreLockedError) throw err;
1029
+ continue;
1030
+ }
1031
+ }
1032
+ return null;
1033
+ }
1034
+ const collectionNamespace = parts ? collectionNamespaceFromPrefix(parts.collection) : null;
1035
+ if (parts && collectionNamespace) {
1036
+ try {
1037
+ const collectionStorage = await this.orchestrator.getStorage(collectionNamespace);
1038
+ for (const candidate of qmdResultPathCandidates(
1039
+ collectionStorage.dir,
1040
+ parts.relativePath
1041
+ )) {
1042
+ const memory = await collectionStorage.readMemoryByPath(candidate);
1043
+ if (memory) return { memory, baseDir: collectionStorage.dir };
1044
+ }
1045
+ return null;
1046
+ } catch (err) {
1047
+ if (err instanceof SecureStoreLockedError) throw err;
1048
+ return null;
1049
+ }
1050
+ }
1051
+ if (nodePath.isAbsolute(memoryPath)) {
1052
+ const ownerStorage = await this.storageForAbsoluteRecallPath(
1053
+ memoryPath,
1054
+ namespace,
1055
+ recallNamespaces
1056
+ );
1057
+ if (!ownerStorage) return null;
1058
+ for (const candidate of qmdResultPathCandidates(
1059
+ ownerStorage.dir,
1060
+ memoryPath
1061
+ )) {
1062
+ const memory = await ownerStorage.storage.readMemoryByPath(candidate);
1063
+ if (memory) return { memory, baseDir: ownerStorage.dir };
1064
+ }
1065
+ return null;
1066
+ }
1067
+ for (const candidate of qmdResultPathCandidates(storageDir, memoryPath)) {
1068
+ const memory = await storage.readMemoryByPath(candidate);
1069
+ if (memory) return { memory, baseDir: storageDir };
1070
+ }
1071
+ return null;
1072
+ };
927
1073
  const rawExcerptsResult = await this.fetchRawExcerpts(
928
1074
  disclosure,
929
1075
  rawContext ? { ...rawContext, namespace } : null
@@ -931,13 +1077,14 @@ var EngramAccessService = class {
931
1077
  const rawExcerpts = rawExcerptsResult ?? void 0;
932
1078
  for (const memoryPath of snapshot.resultPaths ?? []) {
933
1079
  if (!memoryPath || seen.has(memoryPath)) continue;
934
- const memory = await storage.readMemoryByPath(memoryPath);
935
- if (!memory) continue;
1080
+ const resolved = await readResultPath(memoryPath);
1081
+ if (!resolved) continue;
1082
+ const { memory, baseDir } = resolved;
936
1083
  seen.add(memoryPath);
937
1084
  results.push(
938
1085
  this.serializeMemorySummary(
939
1086
  memory,
940
- storageDir,
1087
+ baseDir,
941
1088
  disclosure,
942
1089
  // Attach the (possibly empty) raw excerpts to the first raw
943
1090
  // result; subsequent results do not duplicate the array.
@@ -961,6 +1108,48 @@ var EngramAccessService = class {
961
1108
  }
962
1109
  return results;
963
1110
  }
1111
+ async storageForAbsoluteRecallPath(memoryPath, primaryNamespace, recallNamespaces = []) {
1112
+ const resolvedPath = nodePath.resolve(memoryPath);
1113
+ const memoryRoot = nodePath.resolve(this.orchestrator.config.memoryDir);
1114
+ const namespacesRoot = nodePath.join(memoryRoot, "namespaces");
1115
+ const configuredNamespaces = /* @__PURE__ */ new Set();
1116
+ configuredNamespaces.add(primaryNamespace);
1117
+ for (const namespace of recallNamespaces) {
1118
+ configuredNamespaces.add(namespace);
1119
+ }
1120
+ configuredNamespaces.add(this.orchestrator.config.defaultNamespace);
1121
+ configuredNamespaces.add(this.orchestrator.config.sharedNamespace);
1122
+ if (isPathInsideStorageRoot(namespacesRoot, resolvedPath)) {
1123
+ const relativeToNamespaces = nodePath.relative(namespacesRoot, resolvedPath);
1124
+ const [namespaceSegment] = relativeToNamespaces.split(/[\\/]/);
1125
+ if (namespaceSegment) {
1126
+ configuredNamespaces.add(
1127
+ namespaceIdentityFromToken(namespaceSegment) ?? namespaceSegment
1128
+ );
1129
+ }
1130
+ }
1131
+ for (const policy of this.orchestrator.config.namespacePolicies ?? []) {
1132
+ configuredNamespaces.add(policy.name);
1133
+ }
1134
+ const matches = [];
1135
+ for (const ns of configuredNamespaces) {
1136
+ if (!ns) continue;
1137
+ let candidateStorage;
1138
+ try {
1139
+ candidateStorage = await this.orchestrator.getStorage(ns);
1140
+ } catch {
1141
+ continue;
1142
+ }
1143
+ const candidateRoot = nodePath.resolve(candidateStorage.dir);
1144
+ if (!isPathInsideStorageRoot(candidateRoot, resolvedPath)) continue;
1145
+ if (candidateRoot === memoryRoot && isPathInsideStorageRoot(namespacesRoot, resolvedPath)) {
1146
+ continue;
1147
+ }
1148
+ matches.push({ storage: candidateStorage, dir: candidateRoot });
1149
+ }
1150
+ matches.sort((a, b) => b.dir.length - a.dir.length);
1151
+ return matches[0] ?? null;
1152
+ }
964
1153
  /**
965
1154
  * Fetch raw transcript excerpts from the LCM archive for `disclosure ===
966
1155
  * "raw"` recalls (issue #677 PR 2/4). Returns `null` for non-raw recall
@@ -4458,4 +4647,4 @@ export {
4458
4647
  shapeMemorySummary,
4459
4648
  EngramAccessService
4460
4649
  };
4461
- //# sourceMappingURL=chunk-XM6M6DHG.js.map
4650
+ //# sourceMappingURL=chunk-MNDFVT4F.js.map