prism-mcp-server 16.1.1 โ†’ 17.0.0

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.
package/README.md CHANGED
@@ -157,6 +157,18 @@ Categories: abstention, adversarial traps, cascade, disambiguation, edge cases,
157
157
  ### ๐Ÿ” L3 Grounding Verifier
158
158
  When `prism_infer` receives an `evidence` payload, the grounding verifier automatically checks the model's response against the provided evidence before returning to the caller. Unverified or hallucinated claims are flagged. This is the third layer (L3) of the cascade โ€” after tool routing (L1) and confidence gating (L2).
159
159
 
160
+ ### ๐Ÿง  HRR Semantic Drift Detection (v17.0)
161
+ Detects when long AI agent sessions drift from their original goal โ€” using Holographic Reduced Representations for temporal trajectory encoding and anomaly detection.
162
+
163
+ **Three domains, one detector:**
164
+ | Domain | Signals | Safety |
165
+ |---|---|---|
166
+ | **BCBA/Clinical** | Client specificity decay, function-intervention alignment (4 functions), contraindication detection (epilepsy/pica/dysphagia/diabetes) | PHI-safe, deterministic |
167
+ | **Coding** | File scope entropy, summary vagueness, test coverage ratio, trajectory HRR divergence | Adaptive threshold for refactors |
168
+ | **AAC** | Prediction accuracy, vocabulary stagnation, topic divergence | Emergency phrases always โ‰ฅ 0.95 |
169
+
170
+ **Research-backed:** trajectory association (Frady et al. 2018), HDAD anomaly detection (Wang et al. 2021), unit-modulus projection (Ganesan et al. NeurIPS 2021). 306 tests across 8 files, zero failures. Use `session_detect_drift` with optional `domain` parameter.
171
+
160
172
  ### โšก Zero-search retrieval *(new in v15.8)*
161
173
  Holographic Reduced Representations (HRR) via Rust WASM for instant memory retrieval without a database query.
162
174
 
@@ -229,6 +241,51 @@ That's it. Open Claude / Cursor and your AI now has memory.
229
241
 
230
242
  More setup details in [`docs/SETUP_GEMINI.md`](docs/SETUP_GEMINI.md).
231
243
 
244
+ ### Monitoring & Observability *(new in v16.2)*
245
+
246
+ Built-in Datadog integration โ€” every tool call is logged with tool name, project, and latency. Zero config for self-hosted users (logs to stdout); set `DD_API_KEY` to send structured logs to Datadog HTTP intake.
247
+
248
+ ```bash
249
+ # Enable Datadog logging (optional)
250
+ export DD_API_KEY=your_datadog_api_key
251
+
252
+ # Enable OpenTelemetry tracing (optional โ€” works with Jaeger, Zipkin, Datadog, Grafana Tempo)
253
+ export PRISM_OTEL_ENABLED=true
254
+ export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
255
+ ```
256
+
257
+ **What's tracked automatically:**
258
+ - `mcp.tool.success` โ€” tool name, project, duration (ms) on every successful call
259
+ - `mcp.tool.error` โ€” tool name, error message, stack trace on failures
260
+ - OpenTelemetry spans with `tool.name` and `project` attributes on all 50 tool handlers
261
+
262
+ | Dashboard | What it tracks |
263
+ |-----------|---------------|
264
+ | [Prism MCP โ€” Server Analytics](https://app.datadoghq.com/dashboard/tdm-92f-myh/prism-mcp--server-analytics) | Tool call volume, latency per tool (avg/p95), errors by tool, project activity, knowledge search/ingest, session memory ops |
265
+
266
+ ### In-app analytics for paid users *(new in v16.2)*
267
+
268
+ Paid Synalux subscribers get a built-in analytics dashboard at `/app/memory-analytics`:
269
+
270
+ ```
271
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
272
+ โ”‚ Analytics [standard] plan โ”‚
273
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
274
+ โ”‚ ๐Ÿ“ Sessions: 147 ๐Ÿ”„ Handoffs: 23 ๐Ÿ“š Knowledge: 89 โ”‚
275
+ โ”‚ ๐Ÿ“ Projects: 5 ๐Ÿ’พ Memory: 42 KB โ”‚
276
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
277
+ โ”‚ Today's Usage ๐Ÿง  47/200 ๐Ÿ”Ž 12/50 ๐Ÿ’ฌ 85/200 โ”‚
278
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
279
+ โ”‚ 30-Day Trend โ–‚โ–ƒโ–…โ–‡โ–†โ–„โ–ƒโ–…โ–†โ–‡โ–ˆโ–‡โ–…โ–ƒโ–‚โ–ƒโ–…โ–†โ–‡โ–…โ–ƒโ–‚โ–โ–‚โ–ƒโ–…โ–‡โ–†โ–…โ–ƒ โ”‚
280
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
281
+ โ”‚ Top Projects prism-mcp (45) ยท portal (32) ยท ... โ”‚
282
+ โ”‚ Compaction 3 entries > 5KB โ€” run compact_ledger โ”‚
283
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
284
+ ```
285
+
286
+ - **Free tier**: paywall with upgrade CTA
287
+ - **Standard+**: session counts, handoffs, knowledge entries, daily quotas with tier limits, 30-day activity trend, project breakdown, compaction candidates
288
+
232
289
  ---
233
290
 
234
291
  ## How AI agents use it
@@ -319,6 +376,98 @@ python3 tests/benchmarks/cascade-14b-32b-opus/cascade_eval.py
319
376
  |---|---|---|
320
377
  | Per-model BFCL | [`tests/benchmarks/prism-routing-100/`](tests/benchmarks/prism-routing-100/) | Solo accuracy per model, 12 categories |
321
378
  | Cascade vs Opus | [`tests/benchmarks/cascade-14b-32b-opus/`](tests/benchmarks/cascade-14b-32b-opus/) | Tier distribution, Opus engagement rate, cascade accuracy |
379
+ | LoCoMo-Plus (Cognitive) | [`dcostenco/Locomo-Plus`](https://github.com/dcostenco/Locomo-Plus) | Long-context dialogue coherence and historical memory retention |
380
+
381
+ ### Cognitive Dialogue Memory (LoCoMo-Plus Benchmark)
382
+
383
+ LoCoMo-Plus is a long-context, multi-day dialogue benchmark designed to test an AI agent's memory retention, context awareness, and ability to coherently reference historical dialogue evidence.
384
+
385
+ The **Cognitive** subset (401 multi-day dialogue scenarios) was evaluated head-to-head comparing raw baseline models against the **Prism-MCP** framework (using local SQLite semantic memory). Graded by a neutral `gemini-2.5-flash` model acting as judge (scoring on coherence, continuity, and fact accuracy):
386
+
387
+ | Configuration | Samples | Total Score | Average Score | Absolute Delta | Relative Error Reduction |
388
+ | :--- | :---: | :---: | :---: | :---: | :---: |
389
+ | **Gemini-2.5-flash (Baseline)** | 401 | 278.0 / 401 | **69.33%** | โ€” | โ€” |
390
+ | **Prism-MCP (Gemini-2.5-flash + Memory)** | 401 | 361.0 / 401 | **90.02%** | **+20.69pp** | **67.5%** |
391
+ | **Gemini-3.1-pro-preview (Baseline)** | 401 | 272.0 / 401 | **67.83%** | โ€” | โ€” |
392
+ | **Prism-MCP (Gemini-3.1-pro + Memory)** | 401 | 382.0 / 401 | **95.26%** | **+27.43pp** | **85.3%** |
393
+ | **Gemini-3.5-flash (Baseline)** | 401 | 237.0 / 401 | **59.10%** | โ€” | โ€” |
394
+ | **Prism-MCP (Gemini-3.5-flash + Memory)** | 401 | 388.0 / 401 | **96.76%** | **+37.66pp** | **92.1%** |
395
+ | **Claude Sonnet 4.6 (Baseline)** | 401 | 290.0 / 401 | **72.32%** | โ€” | โ€” |
396
+ | **Prism-MCP (Claude Sonnet 4.6 + Memory)** | 401 | 357.0 / 401 | **89.03%** | **+16.71pp** | **60.4%** |
397
+
398
+ **Key Takeaways**:
399
+ * **Pure attention limits**: Even the strongest frontier model tested โ€” Claude Sonnet 4.6 at **72.32%** โ€” misses over a quarter of cognitive memory cues without external memory. Gemini 3.5 Flash baseline sits at **59.10%**. Both suffer from attention dilution when parsing massive multi-day transcripts directly in active context.
400
+ * **Prism lifts every model**: Prism-MCP yields large gains regardless of base model โ€” from +16.71pp (Claude) to +37.66pp (Gemini 3.5 Flash). Even Claude's stronger native recall benefits from structured retrieval, jumping from 72.32% to **89.03%**.
401
+ * **Best overall**: Prism-MCP + Gemini 3.5 Flash achieves the highest score (**96.76%**), eliminating 92.1% of baseline errors. This makes the cheapest model + Prism more accurate than the most expensive model alone.
402
+ * **Claude vs Gemini (raw)**: Claude Sonnet 4.6 outperforms all Gemini baselines by a wide margin (+13.22pp over Flash 3.5, +4.49pp over Pro 3.1), confirming stronger native long-context recall.
403
+
404
+ <details>
405
+ <summary>๐Ÿ” View Test Case Schema & Sample</summary>
406
+
407
+ A representative test sample from the `unified_cognitive_only.json` ([GitHub source](https://github.com/dcostenco/Locomo-Plus/blob/main/data/unified_cognitive_only.json)) dataset contains a multi-turn chat history with a memory "needle" placed days prior, followed by a cued dialogue prompt:
408
+
409
+ ```json
410
+ {
411
+ "category": "Cognitive",
412
+ "input_prompt": "Caroline said, \"...\"\nMelanie said, \"...\"",
413
+ "trigger": "Melanie said, \"Hey, Caroline! Nice to hear from you! Love the necklace, any special meaning to it?\"",
414
+ "evidence": "Swedish grandmother's necklace was gifted to Caroline",
415
+ "answer": "Yes, this necklace was a gift from my grandmother in my home country, Sweden."
416
+ }
417
+ ```
418
+
419
+ When evaluated:
420
+ * **Baseline models** without memory frequently output a generic guess (e.g., "Thanks, it was a gift from a friend") or fail to reference the Sweden/grandmother relationship.
421
+ * **Prism-MCP** automatically embeds the prior turns, stores them in SQLite, and when cued, retrieves the precise "Swedish grandmother" evidence turn via semantic vectors to inject it into active context.
422
+ </details>
423
+
424
+ <details>
425
+ <summary>๐Ÿ’ป View How to Reproduce Publicly (Test Source & Guide)</summary>
426
+
427
+ To run and review the evaluation suite on your local setup using the benchmark runner scripts (`evaluate_qa.py` and `llm_as_judge.py`):
428
+
429
+ ```bash
430
+ # 1. Clone the LoCoMo-Plus evaluation codebase
431
+ git clone https://github.com/dcostenco/Locomo-Plus /tmp/Locomo-Plus
432
+ cd /tmp/Locomo-Plus
433
+
434
+ # 2. Run Baseline Gemini 3.1 Pro Evaluation (concurrency 5)
435
+ export GOOGLE_API_KEY="your-api-key"
436
+ PYTHONPATH=/tmp/Locomo-Plus python3 evaluation_framework/task_eval/evaluate_qa.py \
437
+ --data-file data/unified_cognitive_only.json \
438
+ --out-file output/gemini_3.1_pro_pred.json \
439
+ --model gemini-3.1-pro-preview \
440
+ --backend call_gemini \
441
+ --concurrency 5
442
+
443
+ # 3. Run Prism-MCP powered by Gemini 3.1 Pro Evaluation (concurrency 1 to guard SQLite locks)
444
+ export PRISM_TEXT_MODEL=gemini-3.1-pro-preview
445
+ PYTHONPATH=/tmp/Locomo-Plus python3 evaluation_framework/task_eval/evaluate_qa.py \
446
+ --data-file data/unified_cognitive_only.json \
447
+ --out-file output/prism_gemini_3.1_pro_pred.json \
448
+ --model gemini-3.1-pro-preview \
449
+ --backend call_prism \
450
+ --concurrency 1
451
+
452
+ # 4. Run Claude Sonnet 4.6 Baseline Evaluation (concurrency 3, rate-limit safe)
453
+ export ANTHROPIC_API_KEY="your-api-key"
454
+ PYTHONPATH=/tmp/Locomo-Plus python3 evaluation_framework/task_eval/evaluate_qa.py \
455
+ --data-file data/unified_cognitive_only.json \
456
+ --out-file output/claude_sonnet46_pred.json \
457
+ --model claude-sonnet-4-6 \
458
+ --backend call_claude \
459
+ --concurrency 3
460
+
461
+ # 5. Grade results using the LLM-as-a-Judge script
462
+ PYTHONPATH=/tmp/Locomo-Plus python3 evaluation_framework/task_eval/llm_as_judge.py \
463
+ --input-file output/prism_gemini_3.1_pro_pred.json \
464
+ --out-file output/prism_gemini_3.1_pro_judged.json \
465
+ --model gemini-2.5-flash \
466
+ --backend call_gemini \
467
+ --concurrency 5 \
468
+ --summary-file output/prism_gemini_3.1_pro_summary.json
469
+ ```
470
+ </details>
322
471
 
323
472
  ### Models on HuggingFace
324
473
 
package/dist/server.js CHANGED
@@ -77,6 +77,7 @@ import { getSettingSync, initConfigStorage } from "./storage/configStorage.js";
77
77
  import { sanitizeMcpOutput } from "./utils/sanitizer.js";
78
78
  import { getTracer, initTelemetry } from "./utils/telemetry.js";
79
79
  import { context as otelContext, trace, SpanStatusCode } from "@opentelemetry/api";
80
+ import { ddInfo, ddError as ddLogError } from "./utils/ddLogger.js";
80
81
  // โ”€โ”€โ”€ Import Tool Definitions (schemas) and Handlers (implementations) โ”€โ”€โ”€โ”€โ”€
81
82
  import { WEB_SEARCH_TOOL, BRAVE_WEB_SEARCH_CODE_MODE_TOOL, LOCAL_SEARCH_TOOL, BRAVE_LOCAL_SEARCH_CODE_MODE_TOOL, CODE_MODE_TRANSFORM_TOOL, BRAVE_ANSWERS_TOOL, RESEARCH_PAPER_ANALYSIS_TOOL, webSearchHandler, braveWebSearchCodeModeHandler, localSearchHandler, braveLocalSearchCodeModeHandler, codeModeTransformHandler, braveAnswersHandler, researchPaperAnalysisHandler, } from "./tools/index.js";
82
83
  // Session memory tools โ€” only used if Supabase is configured
@@ -103,6 +104,8 @@ SESSION_SAVE_EXPERIENCE_TOOL, KNOWLEDGE_UPVOTE_TOOL, KNOWLEDGE_DOWNVOTE_TOOL,
103
104
  SESSION_BACKFILL_LINKS_TOOL, SESSION_SYNTHESIZE_EDGES_TOOL, SESSION_COGNITIVE_ROUTE_TOOL,
104
105
  // v7.1: Task Router
105
106
  SESSION_TASK_ROUTE_TOOL,
107
+ // Session Drift Detection
108
+ SESSION_DETECT_DRIFT_TOOL,
106
109
  // v12: Developer Onboarding & Enterprise Observability
107
110
  ONBOARDING_WIZARD_TOOL, EXTRACT_ENTITIES_TOOL, API_ANALYTICS_TOOL, BACKUP_DATABASE_TOOL, CONFIGURE_NOTIFICATIONS_TOOL, QUERY_MEMORY_NATURAL_TOOL,
108
111
  // v15.5: Knowledge Ingestion
@@ -133,6 +136,8 @@ MAINTENANCE_VACUUM_TOOL, maintenanceVacuumHandler,
133
136
  AGENT_REGISTRY_TOOLS, agentRegisterHandler, agentHeartbeatHandler, agentListTeamHandler,
134
137
  // v7.1: Task Router
135
138
  sessionTaskRouteHandler,
139
+ // Session Drift Detection
140
+ sessionDetectDriftHandler,
136
141
  // v7.3: Dark Factory Pipeline tools
137
142
  SESSION_START_PIPELINE_TOOL, SESSION_CHECK_PIPELINE_STATUS_TOOL, SESSION_ABORT_PIPELINE_TOOL, sessionStartPipelineHandler, sessionCheckPipelineStatusHandler, sessionAbortPipelineHandler,
138
143
  // v12: Handler implementations
@@ -224,6 +229,7 @@ function buildSessionMemoryTools(autoloadList) {
224
229
  SESSION_BACKFILL_LINKS_TOOL, // session_backfill_links โ€” retroactive graph edge creation
225
230
  SESSION_SYNTHESIZE_EDGES_TOOL, // session_synthesize_edges โ€” inferred semantic graph enrichment
226
231
  SESSION_COGNITIVE_ROUTE_TOOL, // session_cognitive_route โ€” HDC policy-gated concept routing (v6.5)
232
+ SESSION_DETECT_DRIFT_TOOL, // session_detect_drift โ€” semantic goal drift detection (synalux)
227
233
  // โ”€โ”€โ”€ v6.1: Storage Hygiene tool โ”€โ”€โ”€
228
234
  MAINTENANCE_VACUUM_TOOL, // maintenance_vacuum โ€” reclaim SQLite disk space post-purge
229
235
  // โ”€โ”€โ”€ v12.1: Developer Onboarding & Framework Bridge โ”€โ”€โ”€
@@ -672,6 +678,7 @@ export function createServer() {
672
678
  // through await chains โ€” including fire-and-forget workers launched
673
679
  // within the handler body (e.g. imageCaptioner, embeddings backfill).
674
680
  return otelContext.with(trace.setSpan(otelContext.active(), rootSpan), async () => {
681
+ const _ddStart = Date.now();
675
682
  try {
676
683
  if (!args) {
677
684
  throw new Error("No arguments provided");
@@ -879,6 +886,12 @@ export function createServer() {
879
886
  throw new Error("Task router not enabled. Enable it in the dashboard or set PRISM_TASK_ROUTER_ENABLED=true.");
880
887
  result = await sessionTaskRouteHandler(args);
881
888
  break;
889
+ // โ”€โ”€โ”€ Session Drift Detection โ”€โ”€โ”€
890
+ case "session_detect_drift":
891
+ if (!SESSION_MEMORY_ENABLED)
892
+ throw new Error("Session memory not configured. Set SUPABASE_URL and SUPABASE_KEY.");
893
+ result = await sessionDetectDriftHandler(args);
894
+ break;
882
895
  // โ”€โ”€โ”€ v7.3: Dark Factory Pipeline Tools โ”€โ”€โ”€
883
896
  case "session_start_pipeline":
884
897
  if (!SESSION_MEMORY_ENABLED)
@@ -945,6 +958,7 @@ export function createServer() {
945
958
  };
946
959
  }
947
960
  rootSpan.setStatus({ code: SpanStatusCode.OK });
961
+ ddInfo("mcp.tool.success", { tool: name, project: args?.project, durationMs: Date.now() - _ddStart });
948
962
  // โ•โ•โ• v5.3: Hivemind Watchdog Alert Injection (Telepathy) โ•โ•โ•
949
963
  // CRITICAL: Append alerts DIRECTLY to tool response content
950
964
  // so the LLM actually reads them. sendLoggingMessage goes to
@@ -985,6 +999,7 @@ export function createServer() {
985
999
  }
986
1000
  catch (error) {
987
1001
  console.error(`Error in tool handler: ${error instanceof Error ? error.message : String(error)}`);
1002
+ ddLogError("mcp.tool.error", error instanceof Error ? error : undefined, { tool: name, project: args?.project, durationMs: Date.now() - _ddStart });
988
1003
  rootSpan.recordException(error instanceof Error ? error : new Error(String(error)));
989
1004
  rootSpan.setStatus({
990
1005
  code: SpanStatusCode.ERROR,
@@ -346,6 +346,22 @@ export class SynaluxStorage extends SupabaseStorage {
346
346
  };
347
347
  }
348
348
  }
349
+ /**
350
+ * Detect semantic drift between the session goal and recent ledger entries.
351
+ * Delegates embedding + detection to the Synalux portal (source of truth for
352
+ * the HRR/GloVe/cosine stack). Prism-mcp never does NLP directly.
353
+ */
354
+ async detectDrift(project, goal, windowHours, minDirectionalRatio, extraParams) {
355
+ const body = { action: "detect_drift", project, goal };
356
+ if (typeof windowHours === "number")
357
+ body.window_hours = windowHours;
358
+ if (typeof minDirectionalRatio === "number")
359
+ body.min_directional_ratio = minDirectionalRatio;
360
+ if (extraParams)
361
+ Object.assign(body, extraParams);
362
+ const result = await this.portalPost("/api/v1/prism/memory", body);
363
+ return result;
364
+ }
349
365
  /**
350
366
  * Fetch skill content from Synalux portal (paid-tier single source of truth).
351
367
  * Returns a map of { skillName โ†’ SKILL.md content } for all names that exist.
@@ -54,6 +54,9 @@ export { SESSION_START_PIPELINE_TOOL, SESSION_CHECK_PIPELINE_STATUS_TOOL, SESSIO
54
54
  export { sessionStartPipelineHandler, sessionCheckPipelineStatusHandler, sessionAbortPipelineHandler, } from "./pipelineHandlers.js";
55
55
  // โ”€โ”€ v12 Tool Handlers (Developer Onboarding & Enterprise Observability) โ”€โ”€
56
56
  export { onboardingWizardHandler, extractEntitiesHandler, apiAnalyticsHandler, backupDatabaseHandler, configureNotificationsHandler, queryMemoryNaturalHandler, } from "./v12Handlers.js";
57
+ // โ”€โ”€ Session Drift Detection โ”€โ”€
58
+ export { SESSION_DETECT_DRIFT_TOOL, isSessionDetectDriftArgs } from "./sessionMemoryDefinitions.js";
59
+ export { sessionDetectDriftHandler } from "./sessionDriftHandler.js";
57
60
  // โ”€โ”€ Knowledge Ingestion (v15.5 โ€” Open Interface) โ”€โ”€
58
61
  // Chunks source code, generates Q&A via Claude Haiku, stores in knowledge graph.
59
62
  // Three entry points: MCP tool, REST API, GitHub webhook.
@@ -0,0 +1,62 @@
1
+ /**
2
+ * session_detect_drift โ€” MCP Tool Handler
3
+ *
4
+ * Thin-client dispatcher: validates args, delegates to the Synalux portal
5
+ * (POST /api/v1/prism/memory action=detect_drift) which owns the embedding
6
+ * + detection logic, and returns the structured result.
7
+ *
8
+ * Prism-mcp never does NLP or embedding here โ€” that lives in synalux-private.
9
+ */
10
+ import { isSessionDetectDriftArgs } from "./sessionMemoryDefinitions.js";
11
+ import { getStorage } from "../storage/index.js";
12
+ import { debugLog } from "../utils/logger.js";
13
+ export async function sessionDetectDriftHandler(args) {
14
+ if (!isSessionDetectDriftArgs(args)) {
15
+ return {
16
+ content: [{ type: "text", text: "Invalid arguments for session_detect_drift. Required: project (string), goal (string). Optional: window_hours (number), min_directional_ratio (number)." }],
17
+ isError: true,
18
+ };
19
+ }
20
+ try {
21
+ const storage = await getStorage();
22
+ // SynaluxStorage exposes detectDrift(); SqliteStorage falls through to
23
+ // an error because it has no embedding stack. Free-tier users without
24
+ // portal access receive a clear upgrade message.
25
+ if (typeof storage.detectDrift !== "function") {
26
+ return {
27
+ content: [{
28
+ type: "text",
29
+ text: JSON.stringify({
30
+ status: "error",
31
+ error: "session_detect_drift requires cloud memory (Standard plan or higher). Set SUPABASE_URL and SUPABASE_KEY to enable.",
32
+ upgrade_url: "/pricing",
33
+ }),
34
+ }],
35
+ isError: true,
36
+ };
37
+ }
38
+ // Build extra params for domain-specific signals
39
+ const extra = {};
40
+ if (args.domain)
41
+ extra.domain = args.domain;
42
+ if (args.behavior_functions)
43
+ extra.behavior_functions = args.behavior_functions;
44
+ if (args.contraindications)
45
+ extra.contraindications = args.contraindications;
46
+ if (args.client_descriptors)
47
+ extra.client_descriptors = args.client_descriptors;
48
+ if (args.assessment_type)
49
+ extra.assessment_type = args.assessment_type;
50
+ const result = await storage.detectDrift(args.project, args.goal, args.window_hours, args.min_directional_ratio, Object.keys(extra).length > 0 ? extra : undefined);
51
+ return {
52
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
53
+ };
54
+ }
55
+ catch (err) {
56
+ debugLog(`[session_detect_drift] Failed: ${err instanceof Error ? err.message : String(err)}`);
57
+ return {
58
+ content: [{ type: "text", text: `Error running drift detection: ${err instanceof Error ? err.message : String(err)}` }],
59
+ isError: true,
60
+ };
61
+ }
62
+ }
@@ -1664,3 +1664,89 @@ export function isQueryMemoryNaturalArgs(args) {
1664
1664
  return false;
1665
1665
  return true;
1666
1666
  }
1667
+ // โ”€โ”€โ”€ Session Detect Drift โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
1668
+ export const SESSION_DETECT_DRIFT_TOOL = {
1669
+ name: "session_detect_drift",
1670
+ description: "Detect whether the current agent session has semantically drifted from its " +
1671
+ "original goal. Scores recent ledger entries against the goal using synalux's " +
1672
+ "HRR embedding stack (GloVe โ†’ Gemini/Voyage โ†’ cosine similarity), then runs " +
1673
+ "the rolling-window drift detector algorithm.\n\n" +
1674
+ "**Triggers:**\n" +
1675
+ "- `goal-drift` โ€” cumulative alignment loss is high and monotonic (not random tangents)\n" +
1676
+ "- `context-collapse` โ€” average output quality has dropped below floor\n\n" +
1677
+ "**Pre-warning:**\n" +
1678
+ "- `quality-degrading` โ€” quality slope steeply negative before collapse\n\n" +
1679
+ "**Returns:** drifted, reason, warning, drift_score (0..1), goal_alignment, " +
1680
+ "quality_avg, sample_count, adaptive_threshold, recommendation.\n\n" +
1681
+ "Use alongside GATE 5 (60-minute drift check): call this tool instead of " +
1682
+ "session_cognitive_route for goal-alignment drift detection.",
1683
+ inputSchema: {
1684
+ type: "object",
1685
+ properties: {
1686
+ project: {
1687
+ type: "string",
1688
+ description: "Project identifier. Must match the project used in session_save_ledger.",
1689
+ },
1690
+ goal: {
1691
+ type: "string",
1692
+ description: "The original session goal โ€” the task you started this session to accomplish. " +
1693
+ "Used as the semantic reference vector. Be specific: 'implement drift detection for prism-mcp' " +
1694
+ "is better than 'work on prism'.",
1695
+ },
1696
+ window_hours: {
1697
+ type: "number",
1698
+ description: "How many hours of ledger history to evaluate. Default 1. Range 0.083โ€“24 (5 min to 24 h).",
1699
+ },
1700
+ min_directional_ratio: {
1701
+ type: "number",
1702
+ description: "Directional ratio floor for the tremor filter (0..1). " +
1703
+ "Random topic tangents that return to the goal are suppressed below this threshold. " +
1704
+ "Default 0.2. Set to 0 to disable filter.",
1705
+ },
1706
+ domain: {
1707
+ type: "string",
1708
+ enum: ["coder", "bcba", "aac"],
1709
+ description: "Optional domain for domain-specific drift signals. " +
1710
+ "'coder' adds file_entropy, summary_vagueness, test_coverage_ratio, trajectory_divergence. " +
1711
+ "'bcba' adds clinical_specificity, function_aligned, contraindication_safe (requires behavior_functions, contraindications, client_descriptors params). " +
1712
+ "'aac' is reserved for future AAC prediction drift (use the AAC-specific endpoint instead).",
1713
+ },
1714
+ behavior_functions: {
1715
+ type: "array",
1716
+ items: { type: "string" },
1717
+ description: "BCBA domain only: identified behavior functions for this client (e.g. ['escape-maintained', 'attention-maintained']).",
1718
+ },
1719
+ contraindications: {
1720
+ type: "array",
1721
+ items: { type: "string" },
1722
+ description: "BCBA domain only: known medical conditions (e.g. ['epilepsy', 'pica']).",
1723
+ },
1724
+ client_descriptors: {
1725
+ type: "array",
1726
+ items: { type: "string" },
1727
+ description: "BCBA domain only: client-specific terms to check for specificity (e.g. ['7-year-old', 'aggression at transitions']).",
1728
+ },
1729
+ assessment_type: {
1730
+ type: "string",
1731
+ description: "BCBA domain only: assessment instrument name (e.g. 'vb-mapp', 'vineland', 'ablls-r').",
1732
+ },
1733
+ },
1734
+ required: ["project", "goal"],
1735
+ },
1736
+ };
1737
+ export function isSessionDetectDriftArgs(args) {
1738
+ if (typeof args !== "object" || args === null)
1739
+ return false;
1740
+ const a = args;
1741
+ if (typeof a.project !== "string" || !a.project.trim())
1742
+ return false;
1743
+ if (typeof a.goal !== "string" || !a.goal.trim())
1744
+ return false;
1745
+ if (a.window_hours !== undefined && typeof a.window_hours !== "number")
1746
+ return false;
1747
+ if (a.min_directional_ratio !== undefined && typeof a.min_directional_ratio !== "number")
1748
+ return false;
1749
+ if (a.domain !== undefined && !["coder", "bcba", "aac"].includes(a.domain))
1750
+ return false;
1751
+ return true;
1752
+ }
@@ -1,15 +1,16 @@
1
1
  /**
2
- * Datadog Server-Side Logger
2
+ * Telemetry Logger โ€” Prism MCP Server
3
3
  *
4
- * Sends structured logs to Datadog HTTP Logs API.
5
- * No agent needed โ€” direct HTTPS POST to intake.
4
+ * Sends structured events to Synalux portal (/api/v1/telemetry)
5
+ * which stores in Supabase with 15-day retention.
6
6
  *
7
- * Env: DD_API_KEY, DD_SITE (default datadoghq.com)
7
+ * Falls back to Datadog HTTP Logs if DD_API_KEY is set.
8
+ * Env: PRISM_SYNALUX_BASE_URL (default https://synalux.ai)
8
9
  */
10
+ const SYNALUX_BASE = process.env.PRISM_SYNALUX_BASE_URL || "https://synalux.ai";
9
11
  const DD_API_KEY = process.env.DD_API_KEY || "";
10
12
  const DD_SITE = process.env.DD_SITE || "datadoghq.com";
11
13
  const SERVICE = "prism-mcp";
12
- const INTAKE_URL = `https://http-intake.logs.${DD_SITE}/api/v2/logs`;
13
14
  const queue = [];
14
15
  let flushTimer = null;
15
16
  const FLUSH_INTERVAL_MS = 5_000;
@@ -21,29 +22,46 @@ function scheduleFlush() {
21
22
  }
22
23
  async function flush() {
23
24
  flushTimer = null;
24
- if (queue.length === 0 || !DD_API_KEY)
25
+ if (queue.length === 0)
25
26
  return;
26
27
  const batch = queue.splice(0, MAX_BATCH);
28
+ // Primary: Synalux portal โ†’ Supabase (always available)
27
29
  try {
28
- await fetch(INTAKE_URL, {
30
+ await fetch(`${SYNALUX_BASE}/api/v1/telemetry`, {
29
31
  method: "POST",
30
- headers: {
31
- "Content-Type": "application/json",
32
- "DD-API-KEY": DD_API_KEY,
33
- },
34
- body: JSON.stringify(batch),
32
+ headers: { "Content-Type": "application/json" },
33
+ body: JSON.stringify(batch.map(e => ({
34
+ service: SERVICE,
35
+ event_type: e.status === "error" ? "error" : "action",
36
+ message: e.message,
37
+ context: { ...e, service: undefined, message: undefined },
38
+ user_id: e.user_id,
39
+ user_plan: e.user_plan,
40
+ }))),
35
41
  signal: AbortSignal.timeout(5_000),
36
42
  });
37
43
  }
38
44
  catch {
39
- // Silent โ€” don't crash the app if DD is unreachable
45
+ // Silent โ€” don't crash the MCP server
46
+ }
47
+ // Secondary: Datadog Logs (if API key is set AND Logs product is enabled)
48
+ if (DD_API_KEY) {
49
+ try {
50
+ await fetch(`https://http-intake.logs.${DD_SITE}/api/v2/logs`, {
51
+ method: "POST",
52
+ headers: { "Content-Type": "application/json", "DD-API-KEY": DD_API_KEY },
53
+ body: JSON.stringify(batch),
54
+ signal: AbortSignal.timeout(5_000),
55
+ });
56
+ }
57
+ catch {
58
+ // Silent
59
+ }
40
60
  }
41
61
  if (queue.length > 0)
42
62
  scheduleFlush();
43
63
  }
44
64
  export function ddLog(level, message, context) {
45
- if (!DD_API_KEY)
46
- return;
47
65
  queue.push({
48
66
  ddsource: "nodejs",
49
67
  ddtags: `env:${process.env.NODE_ENV || "development"},service:${SERVICE}`,
@@ -37,7 +37,7 @@ import { debugLog } from "../../logger.js";
37
37
  // โ”€โ”€โ”€ Model Constants โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
38
38
  // Defined as constants (not hardcoded strings) so external reviewers can see
39
39
  // all model choices at a glance, and future changes only need one edit.
40
- const TEXT_MODEL = "gemini-2.5-flash"; // chat/instruction-following model
40
+ const TEXT_MODEL = process.env.PRISM_TEXT_MODEL || "gemini-2.5-flash"; // chat/instruction-following model
41
41
  const EMBEDDING_MODEL = "gemini-embedding-001"; // vector embedding model (MRL-enabled)
42
42
  const EMBEDDING_DIMS = 768; // fixed output dims โ€” must match DB schema
43
43
  // โ”€โ”€โ”€ Embedding Truncation Constants โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "prism-mcp-server",
3
- "version": "16.1.1",
3
+ "version": "17.0.0",
4
4
  "mcpName": "io.github.dcostenco/prism-coder",
5
- "description": "Prism Coder โ€” Cognitive memory + tool-calling intelligence for AI agents. Mind Palace persistent memory (BFCL Gold Certified, 100% Tool-Call Accuracy, 54 Agent Skills, Zero-Search HDC/HRR retrieval, HIPAA-hardened local-first storage, SLERP-optimized GRPO alignment) plus the prism-coder:7b / 14b open-weights LLM fleet.",
5
+ "description": "Prism Coder โ€” Cognitive memory + tool-calling intelligence for AI agents. Mind Palace persistent memory (BFCL Gold Certified, 100% Tool-Call Accuracy, 54 Agent Skills, Zero-Search HDC/HRR retrieval, HRR Semantic Drift Detection across BCBA/Coding/AAC domains, HIPAA-hardened local-first storage, SLERP-optimized GRPO alignment) plus the prism-coder:7b / 14b open-weights LLM fleet.",
6
6
  "module": "index.ts",
7
7
  "type": "module",
8
8
  "main": "dist/server.js",