@joshuaswarren/openclaw-engram 9.1.1 → 9.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/access-cli.js +6 -6
  2. package/dist/{causal-chain-OJCLNNEH.js → causal-chain-NTQJJLVN.js} +3 -3
  3. package/dist/{causal-consolidation-INSQMIFR.js → causal-consolidation-5VSMA2L5.js} +3 -3
  4. package/dist/{causal-retrieval-MEONMWFL.js → causal-retrieval-BMM45BSR.js} +4 -4
  5. package/dist/{causal-trajectory-graph-HQLYU3SO.js → causal-trajectory-graph-RXHMHGG3.js} +2 -2
  6. package/dist/{chunk-BNBG2XP6.js → chunk-6KX4XLQJ.js} +29 -7
  7. package/dist/chunk-6KX4XLQJ.js.map +1 -0
  8. package/dist/{chunk-4E3TGUFK.js → chunk-BIVUV2GJ.js} +3 -3
  9. package/dist/{chunk-TVZ2RTQZ.js → chunk-HZH3QM6D.js} +280 -92
  10. package/dist/chunk-HZH3QM6D.js.map +1 -0
  11. package/dist/{chunk-WSXU2GHQ.js → chunk-IMMYYNXG.js} +2 -2
  12. package/dist/{chunk-AFMNQR7H.js → chunk-MKM2BCQH.js} +45 -20
  13. package/dist/chunk-MKM2BCQH.js.map +1 -0
  14. package/dist/{chunk-3GARBXWR.js → chunk-NEJTYWAH.js} +2 -2
  15. package/dist/{chunk-GCQN37AR.js → chunk-QX3ELIKM.js} +130 -34
  16. package/dist/chunk-QX3ELIKM.js.map +1 -0
  17. package/dist/{engine-L4EPIXXX.js → engine-3TEQ54VW.js} +3 -3
  18. package/dist/index.js +36 -32
  19. package/dist/index.js.map +1 -1
  20. package/dist/{storage-SHA5TWS7.js → storage-7BE5XQTN.js} +2 -2
  21. package/package.json +1 -1
  22. package/dist/chunk-AFMNQR7H.js.map +0 -1
  23. package/dist/chunk-BNBG2XP6.js.map +0 -1
  24. package/dist/chunk-GCQN37AR.js.map +0 -1
  25. package/dist/chunk-TVZ2RTQZ.js.map +0 -1
  26. /package/dist/{causal-chain-OJCLNNEH.js.map → causal-chain-NTQJJLVN.js.map} +0 -0
  27. /package/dist/{causal-consolidation-INSQMIFR.js.map → causal-consolidation-5VSMA2L5.js.map} +0 -0
  28. /package/dist/{causal-retrieval-MEONMWFL.js.map → causal-retrieval-BMM45BSR.js.map} +0 -0
  29. /package/dist/{causal-trajectory-graph-HQLYU3SO.js.map → causal-trajectory-graph-RXHMHGG3.js.map} +0 -0
  30. /package/dist/{chunk-4E3TGUFK.js.map → chunk-BIVUV2GJ.js.map} +0 -0
  31. /package/dist/{chunk-WSXU2GHQ.js.map → chunk-IMMYYNXG.js.map} +0 -0
  32. /package/dist/{chunk-3GARBXWR.js.map → chunk-NEJTYWAH.js.map} +0 -0
  33. /package/dist/{engine-L4EPIXXX.js.map → engine-3TEQ54VW.js.map} +0 -0
  34. /package/dist/{storage-SHA5TWS7.js.map → storage-7BE5XQTN.js.map} +0 -0
@@ -3,12 +3,12 @@ import {
3
3
  EngramAccessService,
4
4
  Orchestrator,
5
5
  parseConfig
6
- } from "./chunk-TVZ2RTQZ.js";
7
- import "./chunk-4E3TGUFK.js";
8
- import "./chunk-WSXU2GHQ.js";
9
- import "./chunk-GCQN37AR.js";
10
- import "./chunk-BNBG2XP6.js";
11
- import "./chunk-AFMNQR7H.js";
6
+ } from "./chunk-HZH3QM6D.js";
7
+ import "./chunk-BIVUV2GJ.js";
8
+ import "./chunk-IMMYYNXG.js";
9
+ import "./chunk-QX3ELIKM.js";
10
+ import "./chunk-6KX4XLQJ.js";
11
+ import "./chunk-MKM2BCQH.js";
12
12
  import "./chunk-V2E2ORE5.js";
13
13
  import "./chunk-DEIBZP3O.js";
14
14
  import "./chunk-SSIIJJKA.js";
@@ -7,8 +7,8 @@ import {
7
7
  stitchCausalChain,
8
8
  validateCausalEdge,
9
9
  writeChainIndex
10
- } from "./chunk-3GARBXWR.js";
11
- import "./chunk-AFMNQR7H.js";
10
+ } from "./chunk-NEJTYWAH.js";
11
+ import "./chunk-MKM2BCQH.js";
12
12
  import "./chunk-DEIBZP3O.js";
13
13
  import "./chunk-SSIIJJKA.js";
14
14
  export {
@@ -20,4 +20,4 @@ export {
20
20
  validateCausalEdge,
21
21
  writeChainIndex
22
22
  };
23
- //# sourceMappingURL=causal-chain-OJCLNNEH.js.map
23
+ //# sourceMappingURL=causal-chain-NTQJJLVN.js.map
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  readChainIndex,
4
4
  resolveChainsDir
5
- } from "./chunk-3GARBXWR.js";
5
+ } from "./chunk-NEJTYWAH.js";
6
6
  import {
7
7
  isRecord
8
- } from "./chunk-AFMNQR7H.js";
8
+ } from "./chunk-MKM2BCQH.js";
9
9
  import {
10
10
  FallbackLlmClient
11
11
  } from "./chunk-V2E2ORE5.js";
@@ -203,4 +203,4 @@ export {
203
203
  deriveCausalPromotionCandidates,
204
204
  synthesizeCausalPreferencesViaLlm
205
205
  };
206
- //# sourceMappingURL=causal-consolidation-INSQMIFR.js.map
206
+ //# sourceMappingURL=causal-consolidation-5VSMA2L5.js.map
@@ -1,12 +1,12 @@
1
1
  // openclaw-engram: Local-first memory plugin
2
2
  import {
3
3
  searchCausalTrajectories
4
- } from "./chunk-WSXU2GHQ.js";
4
+ } from "./chunk-IMMYYNXG.js";
5
5
  import {
6
6
  readChainIndex,
7
7
  resolveChainsDir
8
- } from "./chunk-3GARBXWR.js";
9
- import "./chunk-AFMNQR7H.js";
8
+ } from "./chunk-NEJTYWAH.js";
9
+ import "./chunk-MKM2BCQH.js";
10
10
  import "./chunk-DEIBZP3O.js";
11
11
  import {
12
12
  log
@@ -180,4 +180,4 @@ export {
180
180
  formatCausalRetrievalSection,
181
181
  retrieveCausalChains
182
182
  };
183
- //# sourceMappingURL=causal-retrieval-MEONMWFL.js.map
183
+ //# sourceMappingURL=causal-retrieval-BMM45BSR.js.map
@@ -1,7 +1,7 @@
1
1
  // openclaw-engram: Local-first memory plugin
2
2
  import {
3
3
  appendEdge
4
- } from "./chunk-BNBG2XP6.js";
4
+ } from "./chunk-6KX4XLQJ.js";
5
5
 
6
6
  // src/causal-trajectory-graph.ts
7
7
  function causalTrajectoryGraphNodeId(trajectoryId, stage) {
@@ -57,4 +57,4 @@ export {
57
57
  buildCausalTrajectoryGraphEdges,
58
58
  causalTrajectoryGraphNodeId
59
59
  };
60
- //# sourceMappingURL=causal-trajectory-graph-HQLYU3SO.js.map
60
+ //# sourceMappingURL=causal-trajectory-graph-RXHMHGG3.js.map
@@ -144,13 +144,37 @@ function detectCausalPhrase(text) {
144
144
  }
145
145
  return null;
146
146
  }
147
- var GraphIndex = class {
147
+ var GraphIndex = class _GraphIndex {
148
148
  memoryDir;
149
149
  cfg;
150
+ // Cache for readAllEdges() result. With 30k+ entity edges (6 MB JSONL) the
151
+ // file read + JSON parse takes 2-4 s per call. This instance-level cache
152
+ // eliminates that overhead on every spreadingActivation() call; it is
153
+ // invalidated (set to null) in onMemoryWritten() so new edges appear promptly.
154
+ edgeCache = null;
155
+ static EDGE_CACHE_TTL_MS = 3e5;
156
+ // 5 minutes
150
157
  constructor(memoryDir, cfg) {
151
158
  this.memoryDir = memoryDir;
152
159
  this.cfg = cfg;
153
160
  }
161
+ /** Clear the edge cache so the next spreadingActivation() re-reads from disk.
162
+ * Call after any code path that appends edges outside of onMemoryWritten(). */
163
+ invalidateEdgeCache() {
164
+ this.edgeCache = null;
165
+ }
166
+ async loadEdgesCached() {
167
+ if (this.edgeCache && Date.now() - this.edgeCache.loadedAt < _GraphIndex.EDGE_CACHE_TTL_MS) {
168
+ return this.edgeCache.allEdges;
169
+ }
170
+ const allEdges = await readAllEdges(this.memoryDir, {
171
+ entityGraphEnabled: this.cfg.entityGraphEnabled,
172
+ timeGraphEnabled: this.cfg.timeGraphEnabled,
173
+ causalGraphEnabled: this.cfg.causalGraphEnabled
174
+ });
175
+ this.edgeCache = { allEdges, loadedAt: Date.now() };
176
+ return allEdges;
177
+ }
154
178
  /**
155
179
  * Called after a memory is written to disk.
156
180
  *
@@ -208,6 +232,8 @@ var GraphIndex = class {
208
232
  } catch (err) {
209
233
  const { log } = await import("./logger-KPTKTANX.js");
210
234
  log.warn(`[graph] onMemoryWritten error: ${err}`);
235
+ } finally {
236
+ this.edgeCache = null;
211
237
  }
212
238
  }
213
239
  /**
@@ -226,11 +252,7 @@ var GraphIndex = class {
226
252
  const steps = maxSteps ?? this.cfg.maxGraphTraversalSteps;
227
253
  const decay = this.cfg.graphActivationDecay;
228
254
  try {
229
- const allEdges = await readAllEdges(this.memoryDir, {
230
- entityGraphEnabled: this.cfg.entityGraphEnabled,
231
- timeGraphEnabled: this.cfg.timeGraphEnabled,
232
- causalGraphEnabled: this.cfg.causalGraphEnabled
233
- });
255
+ const allEdges = await this.loadEdgesCached();
234
256
  const adj = /* @__PURE__ */ new Map();
235
257
  for (const edge of allEdges) {
236
258
  if (!adj.has(edge.from)) adj.set(edge.from, []);
@@ -318,4 +340,4 @@ export {
318
340
  analyzeGraphHealth,
319
341
  GraphIndex
320
342
  };
321
- //# sourceMappingURL=chunk-BNBG2XP6.js.map
343
+ //# sourceMappingURL=chunk-6KX4XLQJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/graph.ts"],"sourcesContent":["/**\n * Multi-Graph Memory (MAGMA/SYNAPSE-inspired, v8.2)\n *\n * Maintains three typed edge graphs:\n * entity.jsonl — memories sharing a named entity (entityRef)\n * time.jsonl — consecutive memories in the same thread/session\n * causal.jsonl — memories linked by causal language heuristics\n *\n * Stored under `<memoryDir>/state/graphs/`.\n * All writes are fail-open: errors are caught/logged, never thrown.\n */\n\nimport { mkdir, appendFile, readFile } from \"node:fs/promises\";\nimport * as path from \"path\";\n\nexport type GraphType = \"entity\" | \"time\" | \"causal\";\n\nexport interface GraphEdge {\n from: string; // relative memory path (e.g. \"facts/2026-02-22/abc.md\")\n to: string; // relative memory path\n type: GraphType;\n weight: number; // 1.0 default, decay applied during traversal\n label: string; // entity name, threadId, or matched causal phrase\n ts: string; // ISO timestamp of edge creation\n}\n\nexport interface GraphConfig {\n multiGraphMemoryEnabled: boolean;\n entityGraphEnabled: boolean;\n timeGraphEnabled: boolean;\n causalGraphEnabled: boolean;\n maxGraphTraversalSteps: number;\n graphActivationDecay: number;\n maxEntityGraphEdgesPerMemory: number;\n graphLateralInhibitionEnabled: boolean;\n graphLateralInhibitionBeta: number;\n graphLateralInhibitionTopM: number;\n}\n\n// Causal signal phrases — order matters (most specific first)\nexport const CAUSAL_PHRASES = [\n \"as a result\",\n \"led to\",\n \"because of\",\n \"therefore\",\n \"caused\",\n \"because\",\n];\n\nexport function graphsDir(memoryDir: string): string {\n return path.join(memoryDir, \"state\", \"graphs\");\n}\n\nexport function graphFilePath(memoryDir: string, type: GraphType): string {\n return path.join(graphsDir(memoryDir), `${type}.jsonl`);\n}\n\nexport async function ensureGraphsDir(memoryDir: string): Promise<void> {\n await mkdir(graphsDir(memoryDir), { recursive: true });\n}\n\nexport async function appendEdge(memoryDir: string, edge: GraphEdge): Promise<void> {\n await ensureGraphsDir(memoryDir);\n const line = JSON.stringify(edge) + \"\\n\";\n await appendFile(graphFilePath(memoryDir, edge.type), line, \"utf8\");\n}\n\n/**\n * Read all edges of a given type from the JSONL file.\n * Returns [] if the file doesn't exist or is corrupt (fail-open).\n */\nexport async function readEdges(memoryDir: string, type: GraphType): Promise<GraphEdge[]> {\n const filePath = graphFilePath(memoryDir, type);\n try {\n const raw = await readFile(filePath, \"utf8\");\n const edges: GraphEdge[] = [];\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n edges.push(JSON.parse(trimmed) as GraphEdge);\n } catch {\n // skip corrupt lines\n }\n }\n return edges;\n } catch {\n return [];\n }\n}\n\n/**\n * Read edges from all enabled graph types.\n */\nexport async function readAllEdges(\n memoryDir: string,\n config: Pick<GraphConfig, \"entityGraphEnabled\" | \"timeGraphEnabled\" | \"causalGraphEnabled\">,\n): Promise<GraphEdge[]> {\n const parts: GraphEdge[][] = await Promise.all([\n config.entityGraphEnabled ? readEdges(memoryDir, \"entity\") : Promise.resolve([]),\n config.timeGraphEnabled ? readEdges(memoryDir, \"time\") : Promise.resolve([]),\n config.causalGraphEnabled ? readEdges(memoryDir, \"causal\") : Promise.resolve([]),\n ]);\n return parts.flat();\n}\n\nexport interface GraphHealthFileStats {\n type: GraphType;\n filePath: string;\n exists: boolean;\n totalLines: number;\n validEdges: number;\n corruptLines: number;\n uniqueNodes: number;\n}\n\nexport interface GraphHealthReport {\n generatedAt: string;\n enabledTypes: GraphType[];\n totals: {\n totalLines: number;\n validEdges: number;\n corruptLines: number;\n uniqueNodes: number;\n };\n files: GraphHealthFileStats[];\n repairGuidance?: string[];\n}\n\nfunction isValidGraphEdge(raw: unknown, expectedType: GraphType): raw is GraphEdge {\n if (!raw || typeof raw !== \"object\") return false;\n const edge = raw as Record<string, unknown>;\n return (\n edge.type === expectedType &&\n typeof edge.from === \"string\" && edge.from.length > 0 &&\n typeof edge.to === \"string\" && edge.to.length > 0 &&\n typeof edge.weight === \"number\" && Number.isFinite(edge.weight) &&\n typeof edge.label === \"string\" &&\n typeof edge.ts === \"string\"\n );\n}\n\nexport async function analyzeGraphHealth(\n memoryDir: string,\n options?: {\n entityGraphEnabled?: boolean;\n timeGraphEnabled?: boolean;\n causalGraphEnabled?: boolean;\n includeRepairGuidance?: boolean;\n },\n): Promise<GraphHealthReport> {\n const enabledTypes: GraphType[] = [];\n if (options?.entityGraphEnabled !== false) enabledTypes.push(\"entity\");\n if (options?.timeGraphEnabled !== false) enabledTypes.push(\"time\");\n if (options?.causalGraphEnabled !== false) enabledTypes.push(\"causal\");\n\n const files: GraphHealthFileStats[] = [];\n const globalNodes = new Set<string>();\n\n for (const type of enabledTypes) {\n const filePath = graphFilePath(memoryDir, type);\n let exists = true;\n let totalLines = 0;\n let validEdges = 0;\n let corruptLines = 0;\n const nodes = new Set<string>();\n\n try {\n const raw = await readFile(filePath, \"utf8\");\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n totalLines += 1;\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (!isValidGraphEdge(parsed, type)) {\n corruptLines += 1;\n continue;\n }\n validEdges += 1;\n nodes.add(parsed.from);\n nodes.add(parsed.to);\n globalNodes.add(parsed.from);\n globalNodes.add(parsed.to);\n } catch {\n corruptLines += 1;\n }\n }\n } catch {\n exists = false;\n }\n\n files.push({\n type,\n filePath,\n exists,\n totalLines,\n validEdges,\n corruptLines,\n uniqueNodes: nodes.size,\n });\n }\n\n const totals = files.reduce(\n (acc, item) => {\n acc.totalLines += item.totalLines;\n acc.validEdges += item.validEdges;\n acc.corruptLines += item.corruptLines;\n return acc;\n },\n {\n totalLines: 0,\n validEdges: 0,\n corruptLines: 0,\n uniqueNodes: globalNodes.size,\n },\n );\n totals.uniqueNodes = globalNodes.size;\n\n const report: GraphHealthReport = {\n generatedAt: new Date().toISOString(),\n enabledTypes,\n totals,\n files,\n };\n\n if (options?.includeRepairGuidance === true) {\n const guidance: string[] = [];\n if (totals.corruptLines > 0) {\n guidance.push(\"Corrupt graph lines detected: back up memory/state/graphs, then rebuild graphs from clean memory replay/extraction runs.\");\n }\n if (totals.validEdges === 0) {\n guidance.push(\"No valid edges detected yet: run normal extraction traffic (or replay ingestion) to seed graph files.\");\n }\n if (guidance.length > 0) report.repairGuidance = guidance;\n }\n\n return report;\n}\n\n/**\n * Detect causal signal phrases in text. Returns the first matched phrase, or null.\n */\nexport function detectCausalPhrase(text: string): string | null {\n const lower = text.toLowerCase();\n for (const phrase of CAUSAL_PHRASES) {\n if (lower.includes(phrase)) return phrase;\n }\n return null;\n}\n\n/**\n * GraphIndex — builds and updates the three memory graphs.\n *\n * Usage (orchestrator):\n * this.graphIndex = new GraphIndex(config.memoryDir, config);\n *\n * // After each memory write:\n * await this.graphIndex.onMemoryWritten(memoryPath, frontmatter, threadId, recentInThread);\n */\nexport class GraphIndex {\n private readonly memoryDir: string;\n private readonly cfg: GraphConfig;\n\n // Cache for readAllEdges() result. With 30k+ entity edges (6 MB JSONL) the\n // file read + JSON parse takes 2-4 s per call. This instance-level cache\n // eliminates that overhead on every spreadingActivation() call; it is\n // invalidated (set to null) in onMemoryWritten() so new edges appear promptly.\n private edgeCache: { allEdges: GraphEdge[]; loadedAt: number } | null = null;\n private static readonly EDGE_CACHE_TTL_MS = 300_000; // 5 minutes\n\n constructor(memoryDir: string, cfg: GraphConfig) {\n this.memoryDir = memoryDir;\n this.cfg = cfg;\n }\n\n /** Clear the edge cache so the next spreadingActivation() re-reads from disk.\n * Call after any code path that appends edges outside of onMemoryWritten(). */\n invalidateEdgeCache(): void {\n this.edgeCache = null;\n }\n\n private async loadEdgesCached(): Promise<GraphEdge[]> {\n if (\n this.edgeCache &&\n Date.now() - this.edgeCache.loadedAt < GraphIndex.EDGE_CACHE_TTL_MS\n ) {\n return this.edgeCache.allEdges;\n }\n const allEdges = await readAllEdges(this.memoryDir, {\n entityGraphEnabled: this.cfg.entityGraphEnabled,\n timeGraphEnabled: this.cfg.timeGraphEnabled,\n causalGraphEnabled: this.cfg.causalGraphEnabled,\n });\n this.edgeCache = { allEdges, loadedAt: Date.now() };\n return allEdges;\n }\n\n /**\n * Called after a memory is written to disk.\n *\n * @param memoryPath - relative path from memoryDir (e.g. \"facts/2026-02-22/abc.md\")\n * @param entityRef - entityRef frontmatter field (if any)\n * @param content - full memory text (for causal detection)\n * @param created - ISO timestamp of this memory\n * @param threadId - current thread ID (for time graph)\n * @param recentInThread - paths of the N most-recent memories in this thread (for time graph)\n * @param entitySiblings - paths of other memories that share the same entityRef (for entity graph)\n */\n async onMemoryWritten(opts: {\n memoryPath: string;\n entityRef?: string;\n content: string;\n created: string;\n threadId?: string;\n recentInThread?: string[];\n entitySiblings?: string[];\n causalPredecessor?: string;\n }): Promise<void> {\n if (!this.cfg.multiGraphMemoryEnabled) return;\n const ts = new Date().toISOString();\n\n try {\n // Entity graph\n if (this.cfg.entityGraphEnabled && opts.entityRef && opts.entitySiblings?.length) {\n const siblings = opts.entitySiblings.slice(0, this.cfg.maxEntityGraphEdgesPerMemory);\n for (const sibling of siblings) {\n await appendEdge(this.memoryDir, {\n from: opts.memoryPath,\n to: sibling,\n type: \"entity\",\n weight: 1.0,\n label: opts.entityRef,\n ts,\n });\n }\n }\n\n // Time graph — link to most recent memory in same thread\n if (this.cfg.timeGraphEnabled && opts.threadId && opts.recentInThread?.length) {\n const predecessor = opts.recentInThread[opts.recentInThread.length - 1];\n if (predecessor && predecessor !== opts.memoryPath) {\n await appendEdge(this.memoryDir, {\n from: predecessor,\n to: opts.memoryPath,\n type: \"time\",\n weight: 1.0,\n label: opts.threadId,\n ts,\n });\n }\n }\n\n // Causal graph\n if (this.cfg.causalGraphEnabled && opts.causalPredecessor) {\n const phrase = detectCausalPhrase(opts.content);\n if (phrase) {\n await appendEdge(this.memoryDir, {\n from: opts.causalPredecessor,\n to: opts.memoryPath,\n type: \"causal\",\n weight: 1.0,\n label: phrase,\n ts,\n });\n }\n }\n } catch (err) {\n // Fail-open: graph write errors must never surface to caller\n const { log } = await import(\"./logger.js\");\n log.warn(`[graph] onMemoryWritten error: ${err}`);\n } finally {\n // Invalidate edge cache so spreadingActivation() picks up new edges.\n // In `finally` so the cache is cleared even on partial write failure.\n this.edgeCache = null;\n }\n }\n\n /**\n * Spreading activation BFS (SYNAPSE-inspired).\n *\n * Starting from `seeds`, traverse the combined graph for up to `maxSteps` hops.\n * Each candidate gets an activation score = edge.weight × decay^hop.\n * Returns top-N candidate paths sorted by descending activation score.\n *\n * @param seeds - initial memory paths to expand from (e.g. QMD top results)\n * @param maxSteps - max BFS hops (from config: maxGraphTraversalSteps)\n * @returns Array of {path, score} sorted descending, not including seed paths\n */\n async spreadingActivation(\n seeds: string[],\n maxSteps?: number,\n ): Promise<Array<{\n path: string;\n score: number;\n seed: string;\n hopDepth: number;\n decayedWeight: number;\n graphType: \"entity\" | \"time\" | \"causal\";\n }>> {\n if (!this.cfg.multiGraphMemoryEnabled) return [];\n const steps = maxSteps ?? this.cfg.maxGraphTraversalSteps;\n const decay = this.cfg.graphActivationDecay;\n\n try {\n const allEdges = await this.loadEdgesCached();\n\n // Build adjacency index: from → edges, to → edges (bidirectional for entity/time, directional for causal)\n const adj = new Map<string, GraphEdge[]>();\n for (const edge of allEdges) {\n if (!adj.has(edge.from)) adj.set(edge.from, []);\n adj.get(edge.from)!.push(edge);\n // Entity and time edges are bidirectional\n if (edge.type !== \"causal\") {\n if (!adj.has(edge.to)) adj.set(edge.to, []);\n adj.get(edge.to)!.push({ ...edge, from: edge.to, to: edge.from });\n }\n }\n\n const seedSet = new Set(seeds);\n const scores = new Map<string, number>(); // candidate path → accumulated activation score\n const provenance = new Map<\n string,\n { seed: string; hopDepth: number; decayedWeight: number; graphType: \"entity\" | \"time\" | \"causal\" }\n >();\n const visited = new Set<string>(seeds);\n\n // BFS queue: [nodePath, hop, seedPath]\n const queue: Array<[string, number, string]> = seeds.map((s) => [s, 0, s]);\n\n while (queue.length > 0) {\n const [node, hop, sourceSeed] = queue.shift()!;\n if (hop >= steps) continue;\n\n const edges = adj.get(node) ?? [];\n for (const edge of edges) {\n const neighbor = edge.to === node ? edge.from : edge.to;\n const score = edge.weight * Math.pow(decay, hop + 1);\n\n if (!seedSet.has(neighbor)) {\n const existing = scores.get(neighbor) ?? 0;\n scores.set(neighbor, existing + score);\n\n const prev = provenance.get(neighbor);\n if (\n !prev ||\n hop + 1 < prev.hopDepth ||\n (hop + 1 === prev.hopDepth && score > prev.decayedWeight)\n ) {\n provenance.set(neighbor, {\n seed: sourceSeed,\n hopDepth: hop + 1,\n decayedWeight: score,\n graphType: edge.type,\n });\n }\n }\n\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n queue.push([neighbor, hop + 1, sourceSeed]);\n }\n }\n }\n\n // Apply lateral inhibition if enabled (Synapse-inspired competitive suppression)\n if (this.cfg.graphLateralInhibitionEnabled && scores.size > 1) {\n const inhibited = applyLateralInhibition(scores, {\n beta: this.cfg.graphLateralInhibitionBeta,\n topM: this.cfg.graphLateralInhibitionTopM,\n });\n for (const [k, v] of inhibited) {\n scores.set(k, v);\n }\n }\n\n return Array.from(scores.entries())\n .map(([p, score]) => ({\n path: p,\n score,\n seed: provenance.get(p)?.seed ?? \"\",\n hopDepth: provenance.get(p)?.hopDepth ?? 0,\n decayedWeight: provenance.get(p)?.decayedWeight ?? 0,\n graphType: provenance.get(p)?.graphType ?? \"entity\",\n }))\n .sort((a, b) => b.score - a.score);\n } catch (err) {\n const { log } = await import(\"./logger.js\");\n log.warn(`[graph] spreadingActivation error: ${err}`);\n return [];\n }\n }\n}\n\n/**\n * Lateral inhibition (Synapse-inspired).\n *\n * For each node, the top-M higher-activation competitors exert inhibition\n * proportional to their activation difference. Output is clamped to [0, ∞).\n *\n * No sigmoid is applied here — downstream `normalizeGraphActivationScore`\n * already applies x/(1+x) soft squash, so adding a sigmoid would double-\n * normalize and cap graph influence at ~50%.\n *\n * Formula: u_hat_i = max(0, u_i - beta * sum_{k in top-M where u_k > u_i}(u_k - u_i))\n *\n * When beta=0 or topM=0, returns original scores unchanged (no-op).\n */\nexport function applyLateralInhibition(\n scores: Map<string, number>,\n opts: { beta: number; topM: number },\n): Map<string, number> {\n const { beta, topM } = opts;\n if (beta === 0 || topM === 0) return new Map(scores);\n\n const sorted = Array.from(scores.entries()).sort((a, b) => b[1] - a[1]);\n const topCompetitors = sorted.slice(0, topM);\n\n const result = new Map<string, number>();\n for (const [node, u] of scores) {\n let inhibition = 0;\n for (const [, uK] of topCompetitors) {\n if (uK > u) {\n inhibition += uK - u;\n }\n }\n result.set(node, Math.max(0, u - beta * inhibition));\n }\n\n return result;\n}\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  parseContinuityImprovementLoops,
5
5
  parseContinuityIncident,
6
6
  sanitizeMemoryContent
7
- } from "./chunk-GCQN37AR.js";
7
+ } from "./chunk-QX3ELIKM.js";
8
8
  import {
9
9
  log
10
10
  } from "./chunk-SSIIJJKA.js";
@@ -830,7 +830,7 @@ var CompoundingEngine = class {
830
830
  let promotionCandidates = this.config.compoundingSemanticEnabled ? this.derivePromotionCandidates(outcomeSummary, mistakes.registry, rubrics) : [];
831
831
  if (this.config.cmcConsolidationEnabled) {
832
832
  try {
833
- const { deriveCausalPromotionCandidates } = await import("./causal-consolidation-INSQMIFR.js");
833
+ const { deriveCausalPromotionCandidates } = await import("./causal-consolidation-5VSMA2L5.js");
834
834
  const causalCandidates = await deriveCausalPromotionCandidates({
835
835
  memoryDir: this.config.memoryDir,
836
836
  causalTrajectoryStoreDir: this.config.causalTrajectoryStoreDir,
@@ -1837,4 +1837,4 @@ export {
1837
1837
  defaultTierMigrationCycleBudget,
1838
1838
  CompoundingEngine
1839
1839
  };
1840
- //# sourceMappingURL=chunk-4E3TGUFK.js.map
1840
+ //# sourceMappingURL=chunk-BIVUV2GJ.js.map