From c1f0cb4a5bfb3deac203f3dfb703dc0e16116fa6 Mon Sep 17 00:00:00 2001 From: Daniel Moellenbeck Date: Sun, 5 Apr 2026 10:03:08 +0200 Subject: [PATCH] fix(mcp): align hooks_learn persistence path with hooks_batch_learn hooks_learn, hooks_learning_config, hooks_learning_stats, and hooks_learning_update all used `intel.learning` (instance property, in-memory only, lost on restart). hooks_batch_learn used `intel.data.learning` (inside `this.data`, persisted by `save()`). This caused two bugs: 1. hooks_learn Q-table updates lost on MCP restart 2. hooks_learn and hooks_batch_learn maintained separate Q-tables Fix: change all 7 occurrences of `intel.learning` to `intel.data.learning` so all handlers share the same persisted path. Ref: ruvnet/RuVector#280 --- npm/packages/ruvector/bin/mcp-server.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/npm/packages/ruvector/bin/mcp-server.js b/npm/packages/ruvector/bin/mcp-server.js index a900a6f1c..e3216caf5 100644 --- a/npm/packages/ruvector/bin/mcp-server.js +++ b/npm/packages/ruvector/bin/mcp-server.js @@ -2373,7 +2373,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { } const engine = new LearningEngine(); - if (intel.learning) engine.import(intel.learning); + if (intel.data.learning) engine.import(intel.data.learning); if (args.task && args.algorithm) { const config = {}; @@ -2382,7 +2382,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { if (args.discountFactor !== undefined) config.discountFactor = args.discountFactor; if (args.epsilon !== undefined) config.epsilon = args.epsilon; engine.configure(args.task, config); - intel.learning = engine.export(); + intel.data.learning = engine.export(); intel.save(); } @@ -2403,7 +2403,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { } const engine = new LearningEngine(); - if (intel.learning) engine.import(intel.learning); + if (intel.data.learning) engine.import(intel.data.learning); const summary = engine.getStatsSummary(); return { content: [{ type: 'text', text: JSON.stringify({ success: true, ...summary }, null, 2) }] }; @@ -2418,7 +2418,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { } const engine = new LearningEngine(); - if (intel.learning) engine.import(intel.learning); + if (intel.data.learning) engine.import(intel.data.learning); const experience = { state: args.state, @@ -2430,7 +2430,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { }; const delta = engine.update(args.task, experience); - intel.learning = engine.export(); + intel.data.learning = engine.export(); intel.save(); return { content: [{ type: 'text', text: JSON.stringify({ @@ -2451,7 +2451,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { } const engine = new LearningEngine(); - if (intel.learning) engine.import(intel.learning); + if (intel.data.learning) engine.import(intel.data.learning); const task = args.task || 'agent-routing'; let result = { success: true }; @@ -2474,7 +2474,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { result.recommendation = best; } - intel.learning = engine.export(); + intel.data.learning = engine.export(); intel.save(); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };