prism-mcp-server 8.0.0 → 8.0.1

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.
@@ -1642,7 +1642,7 @@ export class SqliteStorage {
1642
1642
  if (missingIds.length > 0) {
1643
1643
  const placeholders = missingIds.map(() => '?').join(',');
1644
1644
  const missingQuery = `
1645
- SELECT id, project, summary, session_date, decisions, files_changed
1645
+ SELECT id, project, summary, session_date, decisions, files_changed, keywords, is_rollup, importance, last_accessed_at
1646
1646
  FROM session_ledger
1647
1647
  WHERE id IN (${placeholders}) AND deleted_at IS NULL AND user_id = ?
1648
1648
  `;
@@ -1655,6 +1655,9 @@ export class SqliteStorage {
1655
1655
  session_date: row.session_date,
1656
1656
  decisions: this.parseJsonColumn(row.decisions),
1657
1657
  files_changed: this.parseJsonColumn(row.files_changed),
1658
+ is_rollup: Boolean(row.is_rollup),
1659
+ importance: Number(row.importance) || 0,
1660
+ last_accessed_at: row.last_accessed_at || null,
1658
1661
  similarity: 0.0,
1659
1662
  });
1660
1663
  }
@@ -1666,6 +1669,7 @@ export class SqliteStorage {
1666
1669
  const normEnergy = normalizeActivationEnergy(r.activationEnergy);
1667
1670
  node.activationScore = normEnergy;
1668
1671
  node.rawActivationEnergy = r.activationEnergy;
1672
+ node.isDiscovered = r.isDiscovered;
1669
1673
  // Hybrid blend: 70% original match relevance, 30% structural energy
1670
1674
  node.hybridScore = (node.similarity * 0.7) + (normEnergy * 0.3);
1671
1675
  finalResults.push(node);
@@ -374,7 +374,7 @@ export class SupabaseStorage {
374
374
  id: `in.(${missingIds.join(",")})`,
375
375
  user_id: `eq.${userId}`,
376
376
  deleted_at: "is.null",
377
- select: "id,project,summary,session_date,decisions,files_changed",
377
+ select: "id,project,summary,session_date,decisions,files_changed,is_rollup,importance,last_accessed_at",
378
378
  });
379
379
  for (const row of (Array.isArray(rows) ? rows : [])) {
380
380
  fullNodeMap.set(row.id, {
@@ -384,6 +384,9 @@ export class SupabaseStorage {
384
384
  session_date: row.session_date,
385
385
  decisions: Array.isArray(row.decisions) ? row.decisions : [],
386
386
  files_changed: Array.isArray(row.files_changed) ? row.files_changed : [],
387
+ is_rollup: Boolean(row.is_rollup),
388
+ importance: Number(row.importance) || 0,
389
+ last_accessed_at: row.last_accessed_at || null,
387
390
  similarity: 0.0,
388
391
  });
389
392
  }
@@ -400,6 +403,7 @@ export class SupabaseStorage {
400
403
  const normEnergy = normalizeActivationEnergy(r.activationEnergy);
401
404
  node.activationScore = normEnergy;
402
405
  node.rawActivationEnergy = r.activationEnergy;
406
+ node.isDiscovered = r.isDiscovered;
403
407
  // Hybrid blend: 70% original match relevance, 30% structural energy
404
408
  node.hybridScore = (node.similarity * 0.7) + (normEnergy * 0.3);
405
409
  finalResults.push(node);
@@ -146,67 +146,9 @@ export async function knowledgeSearchHandler(args) {
146
146
  });
147
147
  contentBlocks.push(traceToContentBlock(trace));
148
148
  }
149
- // ── v6.0 Phase 3: 1-Hop Graph Expansion ──────────────────
150
- // Same pattern as sessionSearchMemoryHandler:
151
- // Traverse outbound links from direct hits to find associated memories.
152
- // Graph-expanded results are BONUS — don't consume limit slots.
153
- try {
154
- // Extract IDs from the knowledge search results
155
- const directIds = new Set();
156
- if (data.results && Array.isArray(data.results)) {
157
- for (const entry of data.results) {
158
- if (entry?.id)
159
- directIds.add(entry.id);
160
- }
161
- }
162
- if (directIds.size > 0) {
163
- const enrichedIds = new Set();
164
- const maxGraphResults = Math.min(limit, 10);
165
- for (const directId of directIds) {
166
- if (enrichedIds.size >= maxGraphResults)
167
- break;
168
- const links = await storage.getLinksFrom(directId, PRISM_USER_ID, 0.3, 5);
169
- for (const link of links) {
170
- if (!directIds.has(link.target_id) && !enrichedIds.has(link.target_id)) {
171
- enrichedIds.add(link.target_id);
172
- if (enrichedIds.size >= maxGraphResults)
173
- break;
174
- }
175
- }
176
- }
177
- if (enrichedIds.size > 0) {
178
- const enrichedEntries = await storage.getLedgerEntries({
179
- user_id: `eq.${PRISM_USER_ID}`,
180
- ids: [...enrichedIds],
181
- select: "id,summary,project,created_at",
182
- });
183
- if (enrichedEntries.length > 0) {
184
- const graphFormatted = enrichedEntries.map((e) => `[🔗] ${e.created_at?.split("T")[0] || "unknown"} — ${e.project || "unknown"}\n` +
185
- ` Summary: ${e.summary}`).join("\n");
186
- contentBlocks[0] = {
187
- type: "text",
188
- text: contentBlocks[0].text +
189
- `\n\n🔗 Graph-connected memories (${enrichedEntries.length} via 1-hop expansion):\n\n${graphFormatted}`,
190
- };
191
- // Fire-and-forget: reinforce traversed links
192
- for (const directId of directIds) {
193
- storage.getLinksFrom(directId, PRISM_USER_ID, 0.3, 5)
194
- .then(links => {
195
- for (const link of links) {
196
- if (enrichedIds.has(link.target_id)) {
197
- storage.reinforceLink(directId, link.target_id, link.link_type).catch(() => { });
198
- }
199
- }
200
- })
201
- .catch(() => { });
202
- }
203
- }
204
- }
205
- }
206
- }
207
- catch (graphErr) {
208
- debugLog(`[knowledge_search] Graph expansion failed (non-fatal): ${graphErr instanceof Error ? graphErr.message : String(graphErr)}`);
209
- }
149
+ // v8.0: Legacy v6.0 1-Hop Graph Expansion has been removed.
150
+ // The Synapse Engine now handles multi-hop traversal at the storage layer,
151
+ // integrating discovered nodes into the main ranked result array.
210
152
  return { content: contentBlocks, isError: false };
211
153
  }
212
154
  export async function knowledgeForgetHandler(args) {
@@ -437,9 +379,12 @@ export async function sessionSearchMemoryHandler(args) {
437
379
  // They should decay 50% slower than raw episodic chatter to retain long-term context.
438
380
  const decayRate = r.is_rollup ? PRISM_ACTR_DECAY * 0.5 : PRISM_ACTR_DECAY;
439
381
  const Bi = baseLevelActivation(timestamps, now, decayRate);
440
- // S_i: Structural activation energy from Synapse logic
382
+ // S_i: Normalized structural activation energy from Synapse logic
441
383
  // (computed during applySynapse in storage layer)
442
- const Si = (typeof r.rawActivationEnergy === 'number') ? r.rawActivationEnergy : 0;
384
+ // v8.0: Use normalized 0-1 activationScore, NOT unbounded rawActivationEnergy.
385
+ // Raw energy can reach 15+ for hub nodes, which saturates the sigmoid
386
+ // and erases Bi (recency/frequency) from the composite score.
387
+ const Si = (typeof r.activationScore === 'number') ? r.activationScore : 0;
443
388
  // Composite retrieval score
444
389
  const composite = compositeRetrievalScore(typeof r.similarity === "number" ? r.similarity : 0, Bi + Si, PRISM_ACTR_WEIGHT_SIMILARITY, PRISM_ACTR_WEIGHT_ACTIVATION, PRISM_ACTR_SIGMOID_MIDPOINT, PRISM_ACTR_SIGMOID_STEEPNESS);
445
390
  // Attach to result for re-sorting and display
@@ -510,7 +455,9 @@ export async function sessionSearchMemoryHandler(args) {
510
455
  const actrStr = r._actr_composite !== undefined
511
456
  ? ` ACT-R: composite=${r._actr_composite.toFixed(3)} (B=${r._actr_Bi?.toFixed(2)}, S=${r._actr_Si?.toFixed(3)})\n`
512
457
  : "";
513
- return `[${i + 1}] ${simScore} similar ${r.session_date || "unknown date"}\n` +
458
+ // v8.0: Tag nodes discovered via Synapse multi-hop traversal
459
+ const synapseTag = r.isDiscovered ? " [🌐 Synapse]" : "";
460
+ return `[${i + 1}] ${simScore} similar${synapseTag} — ${r.session_date || "unknown date"}\n` +
514
461
  ` Project: ${r.project}\n` +
515
462
  ` Summary: ${r.summary}\n` +
516
463
  importanceStr +
@@ -551,62 +498,9 @@ export async function sessionSearchMemoryHandler(args) {
551
498
  });
552
499
  contentBlocks.push(traceToContentBlock(trace));
553
500
  }
554
- // ── v6.0 Phase 3: 1-Hop Graph Expansion ──────────────────
555
- // After direct hits, traverse outbound links from each result to
556
- // find associated memories. Graph-expanded results are BONUS they
557
- // don't consume limit slots. Hard-capped at `limit` additional results
558
- // to protect LLM context windows.
559
- //
560
- // Fire-and-forget: errors degrade gracefully to just direct hits.
561
- try {
562
- const directIds = new Set(results.map((r) => r.id).filter(Boolean));
563
- const enrichedIds = new Set();
564
- const maxGraphResults = Math.min(limit, 10); // Hard cap
565
- for (const directId of directIds) {
566
- if (enrichedIds.size >= maxGraphResults)
567
- break;
568
- const links = await storage.getLinksFrom(directId, PRISM_USER_ID, 0.3, 5);
569
- for (const link of links) {
570
- if (!directIds.has(link.target_id) && !enrichedIds.has(link.target_id)) {
571
- enrichedIds.add(link.target_id);
572
- if (enrichedIds.size >= maxGraphResults)
573
- break;
574
- }
575
- }
576
- }
577
- if (enrichedIds.size > 0) {
578
- // Fetch the actual entries for enriched IDs
579
- const enrichedEntries = await storage.getLedgerEntries({
580
- user_id: `eq.${PRISM_USER_ID}`,
581
- ids: [...enrichedIds],
582
- select: "id,summary,project,created_at",
583
- });
584
- if (enrichedEntries.length > 0) {
585
- const graphFormatted = enrichedEntries.map((e) => `[🔗] ${e.created_at?.split("T")[0] || "unknown"} — ${e.project || "unknown"}\n` +
586
- ` Summary: ${e.summary}`).join("\n");
587
- contentBlocks[0] = {
588
- type: "text",
589
- text: contentBlocks[0].text +
590
- `\n\n🔗 Graph-connected memories (${enrichedEntries.length} via 1-hop expansion):\n\n${graphFormatted}`,
591
- };
592
- // Fire-and-forget: reinforce traversed links
593
- for (const directId of directIds) {
594
- storage.getLinksFrom(directId, PRISM_USER_ID, 0.3, 5)
595
- .then(links => {
596
- for (const link of links) {
597
- if (enrichedIds.has(link.target_id)) {
598
- storage.reinforceLink(directId, link.target_id, link.link_type).catch(() => { });
599
- }
600
- }
601
- })
602
- .catch(() => { });
603
- }
604
- }
605
- }
606
- }
607
- catch (graphErr) {
608
- debugLog(`[session_search_memory] Graph expansion failed (non-fatal): ${graphErr instanceof Error ? graphErr.message : String(graphErr)}`);
609
- }
501
+ // v8.0: Legacy v6.0 1-Hop Graph Expansion has been removed.
502
+ // The Synapse Engine now handles multi-hop traversal at the storage layer,
503
+ // integrating discovered nodes into the main ranked result array.
610
504
  return { content: contentBlocks, isError: false };
611
505
  }
612
506
  catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prism-mcp-server",
3
- "version": "8.0.0",
3
+ "version": "8.0.1",
4
4
  "mcpName": "io.github.dcostenco/prism-mcp",
5
5
  "description": "The Mind Palace for AI Agents — a true Cognitive Architecture with Hebbian learning (episodic→semantic consolidation), ACT-R spreading activation (multi-hop causal reasoning), uncertainty-aware rejection gates (agents that know when they don't know), adversarial evaluation (anti-sycophancy), fail-closed Dark Factory pipelines, persistent memory (SQLite/Supabase), multi-agent Hivemind, time travel & visual dashboard. Zero-config local mode.",
6
6
  "module": "index.ts",