prism-mcp-server 6.2.2 β 6.5.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.
- package/README.md +75 -37
- package/dist/config.js +55 -30
- package/dist/dashboard/graphRouter.js +54 -0
- package/dist/dashboard/ui.js +124 -1
- package/dist/observability/graphMetrics.js +92 -4
- package/dist/server.js +11 -3
- package/dist/storage/index.js +11 -16
- package/dist/tools/graphHandlers.js +114 -2
- package/dist/tools/index.js +2 -2
- package/dist/tools/sessionMemoryDefinitions.js +64 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/prism-mcp-server)
|
|
4
4
|
[](https://registry.modelcontextprotocol.io)
|
|
5
5
|
[](https://glama.ai/mcp/servers/dcostenco/prism-mcp)
|
|
6
|
-
[](https://smithery.ai
|
|
6
|
+
[](https://smithery.ai)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://www.typescriptlang.org/)
|
|
9
9
|
[](https://nodejs.org/)
|
|
@@ -395,8 +395,18 @@ Soft/hard delete (Art. 17), full export in JSON, Markdown, or Obsidian vault `.z
|
|
|
395
395
|
|
|
396
396
|
## π What's New
|
|
397
397
|
|
|
398
|
-
### v6.
|
|
399
|
-
> **Current stable release
|
|
398
|
+
### v6.5 β HDC Cognitive Routing β
|
|
399
|
+
> **Current stable release.** The Mind Palace gains a brain-inspired routing engine.
|
|
400
|
+
|
|
401
|
+
- π§ **Hyperdimensional Cognitive Routing** β New `session_cognitive_route` tool composes the agent's current state, role, and action into a single 768-dim binary hypervector via XOR binding, then resolves it to a semantic concept via Hamming distance. Three-outcome policy gateway: `direct` / `clarify` / `fallback`.
|
|
402
|
+
- ποΈ **Per-Project Threshold Overrides** β Fallback and clarify thresholds are configurable per-project and persisted via the existing `getSetting`/`setSetting` contract (no new migrations).
|
|
403
|
+
- π¬ **Explainability Mode** β When `explain: true`, responses include convergence steps, raw Hamming distance, and ambiguity flags for full auditability.
|
|
404
|
+
- π **Cognitive Observability** β `graphMetrics.ts` tracks route distribution (direct/clarify/fallback), rolling confidence/distance averages, ambiguity rates, and null-concept counts. Warning heuristics for fallback > 30% and ambiguity > 40%.
|
|
405
|
+
- π₯οΈ **Dashboard Integration** β Cognitive metrics card with route distribution bar, confidence gauges, and warning badges. On-demand "Cognitive Route" button in the Node Editor panel.
|
|
406
|
+
- π **Feature Gating** β Entire pipeline gated behind `PRISM_HDC_ENABLED` (default: `true`). Clean error + zero telemetry when disabled.
|
|
407
|
+
|
|
408
|
+
<details>
|
|
409
|
+
<summary><strong>v6.2 β The "Synthesize & Prune" Phase</strong></summary>
|
|
400
410
|
|
|
401
411
|
- πΈοΈ **Edge Synthesis ("The Dream Procedure")** β Automated background linker discovers semantically similar but disconnected memory nodes via cosine similarity (β₯ 0.7 threshold). Batch-limited to 50 sources Γ 3 neighbors. New `session_synthesize_edges` tool for on-demand graph enrichment.
|
|
402
412
|
- βοΈ **Graph Pruning (Soft-Prune)** β Configurable strength-based pruning soft-deletes weak links. Includes per-project cooldown, backpressure guards, and sweep budget controls. Enable with `PRISM_GRAPH_PRUNING_ENABLED=true`.
|
|
@@ -406,6 +416,8 @@ Soft/hard delete (Art. 17), full export in JSON, Markdown, or Obsidian vault `.z
|
|
|
406
416
|
- β‘ **Supabase Weak-Link RPC (WS4.1)** β New `prism_summarize_weak_links` Postgres function (migration 036) aggregates pruning server-side, eliminating N+1 network roundtrips.
|
|
407
417
|
- π **Migration 035** β Tenant-safe graph writes + soft-delete hardening for MemoryLinks.
|
|
408
418
|
|
|
419
|
+
</details>
|
|
420
|
+
|
|
409
421
|
<details>
|
|
410
422
|
<summary><strong>v6.1 β Prism-Port, Cognitive Load & Semantic Search</strong></summary>
|
|
411
423
|
|
|
@@ -447,41 +459,49 @@ Soft/hard delete (Art. 17), full export in JSON, Markdown, or Obsidian vault `.z
|
|
|
447
459
|
|
|
448
460
|
## βοΈ How Prism Compares
|
|
449
461
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
| Feature | π§ **Prism MCP** | Official Anthropic Memory | Cloud APIs (Mem0 / Zep) | Simple SQLite/File MCPs |
|
|
453
|
-
|:---|:---:|:---:|:---:|:---:|
|
|
454
|
-
| **Paradigm** | **Active & Autonomous** | Passive Entity Graph | Passive Vector Store | Passive Log |
|
|
455
|
-
| **Context Assembly** | **Progressive (Quick/Std/Deep)** | Manual JSON retrieval | Similarity Search only | Dump all / exact match |
|
|
456
|
-
| **Graph Generation** | **Auto-Synthesized (Edges)** | Manual (LLM must write JSON) | Often none / black box | None |
|
|
457
|
-
| **Context Window Mgmt** | **Auto-Compaction & Decay** | Endless unbounded growth | Requires paid API logic | Manual deletion required |
|
|
458
|
-
| **Storage Engine** | **Local SQLite OR Supabase** | Local File | Cloud Only (Vendor lock-in) | Local SQLite |
|
|
459
|
-
| **Vector Search** | **Three-Tier (Native / TQ / FTS5)** | β None | β
Yes (Remote) | β None |
|
|
460
|
-
| **Vector Compression** | **TurboQuant (10Γ smaller)** | β N/A | β Expensive/Opaque | β N/A |
|
|
461
|
-
| **Multi-Agent Sync** | **CRDTs + Hivemind Watchdog** | β Single-agent only | β
Paid feature | β Data collisions |
|
|
462
|
-
| **Observability** | **OTel Traces + Web Dashboard** | β None | β
Web Dashboard | β None |
|
|
463
|
-
| **Data Portability** | **Prism-Port (Obsidian Vault ZIP)** | β Raw JSON | β API Export | β Raw DB file |
|
|
464
|
-
| **Cost Model** | **Free + BYOM (Ollama)** | Free (limited) | Per-API-call pricing | Free (limited) |
|
|
465
|
-
|
|
466
|
-
### π Why Prism Wins: The "Big Three" Differentiators
|
|
467
|
-
|
|
468
|
-
**1. Zero Cold-Starts with Progressive Loading & OCC**
|
|
469
|
-
Other systems require the LLM to waste tokens and reasoning steps asking "What was I doing?" and calling tools to fetch memory. Prism uses MCP Resources to instantly inject the live project state into the context window *before* the LLM generates its first token. CRDT-backed Optimistic Concurrency Control ensures multiple agents (e.g., Claude + Cursor) can work on the same project simultaneously without data collisions.
|
|
470
|
-
|
|
471
|
-
**2. Self-Cleaning & Self-Optimizing**
|
|
472
|
-
If you use a standard memory tool long enough, it clogs the LLM's context window with thousands of obsolete tokens. Prism runs an autonomous Background Scheduler that:
|
|
473
|
-
- **Ebbinghaus Decays** older, unreferenced memories β importance fades unless reinforced.
|
|
474
|
-
- **Auto-Compacts** large session histories into dense, LLM-generated summaries.
|
|
475
|
-
- **Deep Purges** high-precision vectors, replacing them with 400-byte TurboQuant compressed blobs, saving ~90% of disk space.
|
|
462
|
+
Standard memory servers (like Mem0, Zep, or the baseline Anthropic MCP) act as passive filing cabinets β they wait for the LLM to search them. **Prism is an active cognitive architecture.** Designed specifically for the **Model Context Protocol (MCP)**, Prism doesn't just store vectors; it manages the LLM's context window autonomously.
|
|
476
463
|
|
|
477
|
-
|
|
464
|
+
### π Feature-by-Feature Comparison
|
|
478
465
|
|
|
479
|
-
|
|
480
|
-
|
|
466
|
+
| Feature / Architecture | π§ Prism MCP | π Mem0 | β‘ Zep | π§ͺ Anthropic Base MCP |
|
|
467
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
468
|
+
| **Primary Interface** | **Native MCP** (Tools, Prompts, Resources) | REST API & Python/TS SDKs | REST API & Python/TS SDKs | Native MCP (Tools only) |
|
|
469
|
+
| **Storage Engine** | **BYO SQLite or Supabase** | Managed Cloud / VectorDBs | Managed Cloud / Postgres | Local SQLite only |
|
|
470
|
+
| **Context Assembly** | **Progressive (Quick/Std/Deep)** | Top-K Semantic Search | Top-K + Temporal Summaries | Basic Entity Search |
|
|
471
|
+
| **Memory Mechanics** | **Ebbinghaus Decay, SDM, HDC** | Basic Vector + Entity | Fading Temporal Graph | None (Infinite growth) |
|
|
472
|
+
| **Multi-Agent Sync** | **CRDT (Add-Wins / LWW)** | Cloud locks | Postgres locks | β None (Data races) |
|
|
473
|
+
| **Data Compression** | **TurboQuant (7x smaller vectors)** | β Standard F32 Vectors | β Standard Vectors | β No Vectors |
|
|
474
|
+
| **Observability** | **OTel Traces + Built-in PWA UI** | Cloud Dashboard | Cloud Dashboard | β None |
|
|
475
|
+
| **Maintenance** | **Autonomous Background Scheduler** | Manual/API driven | Automated (Cloud) | β Manual |
|
|
476
|
+
| **Data Portability** | **Prism-Port (Obsidian/Logseq Vault)** | JSON Export | JSON Export | Raw `.db` file |
|
|
477
|
+
| **Cost Model** | **Free + BYOM (Ollama)** | Per-API-call pricing | Per-API-call pricing | Free (limited) |
|
|
481
478
|
|
|
482
|
-
|
|
479
|
+
### π Where Prism Crushes the Giants
|
|
480
|
+
|
|
481
|
+
#### 1. MCP-Native, Not an Adapted API
|
|
482
|
+
Mem0 and Zep are APIs that *can* be wrapped into an MCP server. Prism was built *for* MCP from day one. Instead of wasting tokens on "search" tool calls, Prism uses **MCP Prompts** (`/resume_session`) to inject context *before* the LLM thinks, and **MCP Resources** (`memory://project/handoff`) to attach live, subscribing context.
|
|
483
|
+
|
|
484
|
+
#### 2. Academic-Grade Cognitive Computer Science
|
|
485
|
+
The giants use standard RAG (Retrieval-Augmented Generation). Prism uses biological and academic models of memory: **TurboQuant** for extreme vector compression, **Ebbinghaus curves** for importance decay, and **Sparse Distributed Memory (SDM)**. This makes Prism vastly more efficient on a local machine than running a giant Postgres/pgvector instance.
|
|
486
|
+
|
|
487
|
+
#### 3. True Multi-Agent Coordination (CRDTs)
|
|
488
|
+
If Cursor (Agent A) and Claude Desktop (Agent B) try to update a Mem0 or standard SQLite database at the exact same time, you get a race condition and data loss. Prism uses **Optimistic Concurrency Control (OCC) with CRDT OR-Maps** β mathematically guaranteeing that simultaneous agent edits merge safely. Enterprise-grade distributed systems on a local machine.
|
|
489
|
+
|
|
490
|
+
#### 4. The PKM "Prism-Port" Export
|
|
491
|
+
AI memory is a black box. Developers hate black boxes. Prism exports memory directly into an **Obsidian/Logseq-compatible Markdown Vault** with YAML frontmatter and `[[Wikilinks]]`. Neither Mem0 nor Zep do this.
|
|
492
|
+
|
|
493
|
+
#### 5. Self-Cleaning & Self-Optimizing
|
|
494
|
+
If you use a standard memory tool long enough, it clogs the LLM's context window with thousands of obsolete tokens. Prism runs an autonomous [Background Scheduler](src/backgroundScheduler.ts) that Ebbinghaus-decays older memories, auto-compacts session histories into dense summaries, and deep-purges high-precision vectors β saving ~90% of disk space automatically.
|
|
495
|
+
|
|
496
|
+
### π€ Where the Giants Currently Win (Honest Trade-offs)
|
|
497
|
+
|
|
498
|
+
1. **Framework Integrations:** Mem0 and Zep have pre-built integrations for LangChain, LlamaIndex, Flowise, AutoGen, CrewAI, etc. Prism requires the host application to support the MCP protocol.
|
|
499
|
+
2. **Managed Cloud Infrastructure:** The giants offer SaaS. Users pay $20/month and don't think about databases. Prism users must set up their own local SQLite or provision their own Supabase instance.
|
|
500
|
+
3. **Implicit Memory Extraction (NER):** Zep automatically extracts names, places, and facts from raw chat logs using NLP models. Prism relies on the LLM explicitly calling the `session_save_ledger` tool to structure its own memories.
|
|
501
|
+
|
|
502
|
+
> π° **Token Economics:** Progressive Context Loading (Quick ~50 tokens / Standard ~200 / Deep ~1000+) plus auto-compaction means you never blow your Claude/OpenAI token budget fetching 50 pages of raw chat history.
|
|
483
503
|
>
|
|
484
|
-
>
|
|
504
|
+
> π **BYOM (Bring Your Own Model):** While tools like Mem0 charge per API call, Prism's pluggable architecture lets you run `nomic-embed-text` locally via Ollama for **free vectors**, while using Claude or GPT for high-level reasoning. Zero vendor lock-in.
|
|
485
505
|
|
|
486
506
|
---
|
|
487
507
|
|
|
@@ -557,6 +577,17 @@ Prism ships 30+ tools, but **90% of your workflow uses just three:**
|
|
|
557
577
|
|
|
558
578
|
</details>
|
|
559
579
|
|
|
580
|
+
<details>
|
|
581
|
+
<summary><strong>Cognitive Architecture (1 tool)</strong></summary>
|
|
582
|
+
|
|
583
|
+
Requires `PRISM_HDC_ENABLED=true` (default).
|
|
584
|
+
|
|
585
|
+
| Tool | Purpose |
|
|
586
|
+
|------|---------|
|
|
587
|
+
| `session_cognitive_route` | HDC compositional state resolution with policy-gated routing |
|
|
588
|
+
|
|
589
|
+
</details>
|
|
590
|
+
|
|
560
591
|
<details>
|
|
561
592
|
<summary><strong>Multi-Agent Hivemind (3 tools)</strong></summary>
|
|
562
593
|
|
|
@@ -600,6 +631,8 @@ Requires `PRISM_ENABLE_HIVEMIND=true`.
|
|
|
600
631
|
| `PRISM_SCHOLAR_INTERVAL_MS` | No | Scholar interval in ms (default: `0` = manual only) |
|
|
601
632
|
| `PRISM_SCHOLAR_TOPICS` | No | Comma-separated research topics (default: `"ai,agents"`) |
|
|
602
633
|
| `PRISM_SCHOLAR_MAX_ARTICLES_PER_RUN` | No | Max articles per Scholar run (default: `3`) |
|
|
634
|
+
| `PRISM_HDC_ENABLED` | No | `"true"` (default) to enable HDC cognitive routing pipeline |
|
|
635
|
+
| `PRISM_HDC_EXPLAINABILITY_ENABLED` | No | `"true"` (default) to include convergence/distance/ambiguity in cognitive route responses |
|
|
603
636
|
|
|
604
637
|
</details>
|
|
605
638
|
|
|
@@ -684,7 +717,8 @@ Prism is evolving from smart session logging toward a **cognitive memory archite
|
|
|
684
717
|
| **v5.5** | SDM Decoder Foundation β pre-allocated typed-array hot loop, zero GC thrash | Kanerva's Sparse Distributed Memory (1988) | β
Shipped |
|
|
685
718
|
| **v5.5** | Architectural Hardening β transactional migrations, graceful shutdown, thundering herd prevention | Production reliability engineering | β
Shipped |
|
|
686
719
|
| **v6.1** | Intuitive Recall β proactive surface of relevant past decisions without explicit search; `session_intuitive_recall` tool | Predictive memory (cognitive science) | β
Shipped |
|
|
687
|
-
| **v6.
|
|
720
|
+
| **v6.5** | HDC Cognitive Routing β compositional state-machine with XOR binding, Hamming resolution, and policy-gated routing | Hyperdimensional Computing (Kanerva, Gayler) | β
Shipped |
|
|
721
|
+
| **v6.5** | Cognitive Observability β route distribution, confidence/distance tracking, ambiguity warnings | Production reliability engineering | β
Shipped |
|
|
688
722
|
| **v6.1** | Prism-Port Vault Export β Obsidian/Logseq `.zip` with YAML frontmatter & `[[Wikilinks]]` | Data sovereignty, PKM interop | β
Shipped |
|
|
689
723
|
| **v6.1** | Cognitive Load & Semantic Search β dynamic graph thinning, search highlights | Contextual working memory | β
Shipped |
|
|
690
724
|
| **v6.2** | Synthesize & Prune β automated edge synthesis, graph pruning, SLO observability | Implicit associative memory | β
Shipped |
|
|
@@ -702,8 +736,12 @@ Prism is evolving from smart session logging toward a **cognitive memory archite
|
|
|
702
736
|
### v6.2: The "Synthesize & Prune" Phase β
|
|
703
737
|
Shipped in v6.2.0. Edge synthesis, graph pruning with SLO observability, temporal decay heatmaps, active recall prompt generation, and full dashboard metrics integration.
|
|
704
738
|
|
|
705
|
-
###
|
|
706
|
-
|
|
739
|
+
### v6.5: Cognitive Architecture (Primary)
|
|
740
|
+
Full Superposed Memory (SDM) + Hyperdimensional Computing (HDC/VSA) becomes the next major implementation phase, targeting compositional memory states and faster associative retrieval at scale.
|
|
741
|
+
|
|
742
|
+
### After v6.5: Future Tracks
|
|
743
|
+
- **v7.x: Affect-Tagged Memory** β Recall prioritization improves by weighting memories with affective/contextual valence, making surfaced context more behaviorally useful.
|
|
744
|
+
- **v8+: Zero-Search Retrieval** β Direct vector-addressed recall (βjust ask the vectorβ) reduces retrieval indirection and moves Prism toward truly native associative memory.
|
|
707
745
|
|
|
708
746
|
---
|
|
709
747
|
|
package/dist/config.js
CHANGED
|
@@ -73,38 +73,39 @@ export const PRISM_STORAGE = process.env.PRISM_STORAGE || "supabase";
|
|
|
73
73
|
// When both SUPABASE_URL and SUPABASE_KEY are set, session memory tools
|
|
74
74
|
// are registered. These tools allow AI agents to persist and recover
|
|
75
75
|
// context between sessions.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
* it is always enabled.
|
|
85
|
-
*
|
|
86
|
-
* The flag is kept (rather than removed) because several modules import
|
|
87
|
-
* it for conditional registration of MCP tools. Removing it would require
|
|
88
|
-
* a broader refactor with no functional benefit.
|
|
89
|
-
*/
|
|
90
|
-
export const SESSION_MEMORY_ENABLED = true;
|
|
91
|
-
// Note: debug() is defined at the bottom of this file; these lines
|
|
92
|
-
// execute at import time after the full module is loaded by Node.
|
|
93
|
-
if (!SESSION_MEMORY_ENABLED) {
|
|
94
|
-
console.error("Info: Session memory disabled (set PRISM_STORAGE=local or configure Supabase)");
|
|
76
|
+
function sanitizeEnv(value) {
|
|
77
|
+
if (!value)
|
|
78
|
+
return undefined;
|
|
79
|
+
const trimmed = value.trim();
|
|
80
|
+
// Treat unresolved template placeholders as unset (e.g. "${SUPABASE_URL}")
|
|
81
|
+
if (!trimmed || trimmed.includes("${"))
|
|
82
|
+
return undefined;
|
|
83
|
+
return trimmed;
|
|
95
84
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
85
|
+
function isHttpUrl(value) {
|
|
86
|
+
try {
|
|
87
|
+
const parsed = new URL(value);
|
|
88
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export const SUPABASE_URL = sanitizeEnv(process.env.SUPABASE_URL);
|
|
95
|
+
export const SUPABASE_KEY = sanitizeEnv(process.env.SUPABASE_KEY);
|
|
96
|
+
export const SUPABASE_CONFIGURED = !!SUPABASE_URL &&
|
|
97
|
+
!!SUPABASE_KEY &&
|
|
98
|
+
isHttpUrl(SUPABASE_URL);
|
|
99
|
+
if (process.env.SUPABASE_URL && !SUPABASE_URL) {
|
|
100
|
+
console.error("Warning: SUPABASE_URL appears unresolved/empty (e.g. template placeholder). Falling back to local storage unless explicitly fixed.");
|
|
101
|
+
}
|
|
102
|
+
if (SUPABASE_URL && !isHttpUrl(SUPABASE_URL)) {
|
|
103
|
+
console.error("Warning: SUPABASE_URL is not a valid http(s) URL. Falling back to local storage.");
|
|
104
|
+
}
|
|
105
|
+
// Session memory remains core-enabled in both local and Supabase modes.
|
|
106
|
+
export const SESSION_MEMORY_ENABLED = true;
|
|
107
|
+
// Optional multi-tenant scope ID (used by storage queries and handoffs).
|
|
106
108
|
export const PRISM_USER_ID = process.env.PRISM_USER_ID || "default";
|
|
107
|
-
// Multi-tenant info logged at debug level in startServer()
|
|
108
109
|
// βββ v2.1: Auto-Capture Feature βββββββββββββββββββββββββββββ
|
|
109
110
|
// REVIEWER NOTE: Automatically captures HTML snapshots of local dev servers
|
|
110
111
|
// when handoffs are saved. Prevents UI context loss between sessions.
|
|
@@ -175,6 +176,30 @@ export const PRISM_SCHOLAR_TOPICS = (process.env.PRISM_SCHOLAR_TOPICS || "ai,age
|
|
|
175
176
|
// Controls the age threshold for link strength decay.
|
|
176
177
|
// Links not traversed in the last N days lose 0.1 strength per sweep.
|
|
177
178
|
export const PRISM_LINK_DECAY_DAYS = parseInt(process.env.PRISM_LINK_DECAY_DAYS || "30", 10);
|
|
179
|
+
// βββ v6.5: Cognitive Architecture (HDC Policy Gateway) βββββββββββββ
|
|
180
|
+
// Master feature flag for HDC-driven cognitive routing APIs.
|
|
181
|
+
export const PRISM_HDC_ENABLED = process.env.PRISM_HDC_ENABLED === "true";
|
|
182
|
+
// Explainability payload toggle for cognitive routing responses.
|
|
183
|
+
export const PRISM_HDC_EXPLAINABILITY_ENABLED = process.env.PRISM_HDC_EXPLAINABILITY_ENABLED !== "false"; // default true
|
|
184
|
+
const DEFAULT_HDC_FALLBACK_THRESHOLD = 0.85;
|
|
185
|
+
const DEFAULT_HDC_CLARIFY_THRESHOLD = 0.95;
|
|
186
|
+
const rawHdcFallbackThreshold = parseFloat(process.env.PRISM_HDC_POLICY_FALLBACK_THRESHOLD || String(DEFAULT_HDC_FALLBACK_THRESHOLD));
|
|
187
|
+
const rawHdcClarifyThreshold = parseFloat(process.env.PRISM_HDC_POLICY_CLARIFY_THRESHOLD || String(DEFAULT_HDC_CLARIFY_THRESHOLD));
|
|
188
|
+
const hdcThresholdsValid = Number.isFinite(rawHdcFallbackThreshold) &&
|
|
189
|
+
Number.isFinite(rawHdcClarifyThreshold) &&
|
|
190
|
+
rawHdcFallbackThreshold >= 0 &&
|
|
191
|
+
rawHdcFallbackThreshold < rawHdcClarifyThreshold &&
|
|
192
|
+
rawHdcClarifyThreshold <= 1;
|
|
193
|
+
if (!hdcThresholdsValid) {
|
|
194
|
+
console.error("Warning: Invalid HDC policy thresholds. Falling back to defaults " +
|
|
195
|
+
`(fallback=${DEFAULT_HDC_FALLBACK_THRESHOLD}, clarify=${DEFAULT_HDC_CLARIFY_THRESHOLD}).`);
|
|
196
|
+
}
|
|
197
|
+
export const PRISM_HDC_POLICY_FALLBACK_THRESHOLD = hdcThresholdsValid
|
|
198
|
+
? rawHdcFallbackThreshold
|
|
199
|
+
: DEFAULT_HDC_FALLBACK_THRESHOLD;
|
|
200
|
+
export const PRISM_HDC_POLICY_CLARIFY_THRESHOLD = hdcThresholdsValid
|
|
201
|
+
? rawHdcClarifyThreshold
|
|
202
|
+
: DEFAULT_HDC_CLARIFY_THRESHOLD;
|
|
178
203
|
// βββ v6.2: Graph Soft-Pruning βββββββββββββββββββββββββββββββ
|
|
179
204
|
// Soft-pruning filters weak links from graph/retrieval reads while preserving
|
|
180
205
|
// underlying rows for provenance. This does NOT delete links.
|
|
@@ -312,6 +312,60 @@ export async function handleGraphRoutes(url, req, res, getStorageSafe) {
|
|
|
312
312
|
return true;
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
|
+
// βββ API: Cognitive Route Explainability (v6.5) βββ
|
|
316
|
+
if (url.pathname === "/api/graph/cognitive-route" && req.method === "GET") {
|
|
317
|
+
const project = url.searchParams.get("project");
|
|
318
|
+
const state = url.searchParams.get("state");
|
|
319
|
+
const role = url.searchParams.get("role");
|
|
320
|
+
const action = url.searchParams.get("action");
|
|
321
|
+
const explain = url.searchParams.get("explain");
|
|
322
|
+
const fallbackThresholdRaw = url.searchParams.get("fallback_threshold");
|
|
323
|
+
const clarifyThresholdRaw = url.searchParams.get("clarify_threshold");
|
|
324
|
+
if (!project || !state || !role || !action) {
|
|
325
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
326
|
+
res.end(JSON.stringify({
|
|
327
|
+
error: "project, state, role, and action are required",
|
|
328
|
+
}));
|
|
329
|
+
return true;
|
|
330
|
+
}
|
|
331
|
+
try {
|
|
332
|
+
const { sessionCognitiveRouteHandler } = await import("../tools/graphHandlers.js");
|
|
333
|
+
const args = {
|
|
334
|
+
project,
|
|
335
|
+
state,
|
|
336
|
+
role,
|
|
337
|
+
action,
|
|
338
|
+
explain: explain === null ? true : explain !== "false",
|
|
339
|
+
};
|
|
340
|
+
if (fallbackThresholdRaw !== null) {
|
|
341
|
+
const parsed = Number(fallbackThresholdRaw);
|
|
342
|
+
if (!Number.isNaN(parsed))
|
|
343
|
+
args.fallback_threshold = parsed;
|
|
344
|
+
}
|
|
345
|
+
if (clarifyThresholdRaw !== null) {
|
|
346
|
+
const parsed = Number(clarifyThresholdRaw);
|
|
347
|
+
if (!Number.isNaN(parsed))
|
|
348
|
+
args.clarify_threshold = parsed;
|
|
349
|
+
}
|
|
350
|
+
const result = await sessionCognitiveRouteHandler(args);
|
|
351
|
+
const contentText = result.content && result.content.length > 0
|
|
352
|
+
? result.content[0].text
|
|
353
|
+
: "";
|
|
354
|
+
res.writeHead(result.isError ? 400 : 200, { "Content-Type": "application/json" });
|
|
355
|
+
res.end(JSON.stringify({
|
|
356
|
+
ok: !result.isError,
|
|
357
|
+
isError: !!result.isError,
|
|
358
|
+
text: contentText,
|
|
359
|
+
}));
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
catch (err) {
|
|
363
|
+
console.error("[Dashboard] Cognitive route error:", err);
|
|
364
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
365
|
+
res.end(JSON.stringify({ error: err instanceof Error ? err.message : "Cognitive route failed" }));
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
315
369
|
// βββ API: Graph Metrics (v6.0 Observability) βββ
|
|
316
370
|
if (url.pathname === "/api/graph/metrics" && req.method === "GET") {
|
|
317
371
|
const snapshot = getGraphMetricsSnapshot();
|
package/dist/dashboard/ui.js
CHANGED
|
@@ -842,6 +842,12 @@ export function renderDashboardHTML(version) {
|
|
|
842
842
|
<button id="testMeBtn" onclick="triggerTestMe()" class="btn-modern" style="padding:0.3rem 0.6rem; font-size:0.75rem; background:var(--accent-teal); border-color:var(--accent-teal);" title="Generate 3 quiz questions using AI">π Test Me</button>
|
|
843
843
|
</div>
|
|
844
844
|
<div id="testMeContainer" style="margin-top:0.8rem; display:flex; flex-direction:column; gap:0.5rem;"></div>
|
|
845
|
+
<div style="display:flex; justify-content:space-between; align-items:center; margin-top:0.8rem;">
|
|
846
|
+
<span style="font-size:0.75rem; color:var(--text-muted); font-weight:600;">Cognitive Route (v6.5)</span>
|
|
847
|
+
<button id="cognitiveRouteBtn" onclick="triggerCognitiveRoute()" class="btn-modern" style="padding:0.3rem 0.6rem; font-size:0.75rem; background:var(--accent-blue); border-color:var(--accent-blue);" title="Resolve concept route and explain why it surfaced">π§ Route</button>
|
|
848
|
+
</div>
|
|
849
|
+
<div id="cognitiveRouteContainer" style="margin-top:0.6rem; display:flex; flex-direction:column; gap:0.4rem;"></div>
|
|
850
|
+
|
|
845
851
|
</div>
|
|
846
852
|
</div>
|
|
847
853
|
|
|
@@ -2372,7 +2378,66 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
2372
2378
|
}
|
|
2373
2379
|
}
|
|
2374
2380
|
|
|
2375
|
-
|
|
2381
|
+
|
|
2382
|
+
|
|
2383
|
+
async function triggerCognitiveRoute() {
|
|
2384
|
+
var input = document.getElementById('nodeEditorInput');
|
|
2385
|
+
var state = input && input.dataset && input.dataset.oldId ? input.dataset.oldId : '';
|
|
2386
|
+
var _gpf = document.getElementById('graphProjectFilter');
|
|
2387
|
+
var _ps = document.getElementById('projectSelect');
|
|
2388
|
+
var project = (_gpf ? _gpf.value : '') || (_ps ? _ps.value : '');
|
|
2389
|
+
var container = document.getElementById('cognitiveRouteContainer');
|
|
2390
|
+
var btn = document.getElementById('cognitiveRouteBtn');
|
|
2391
|
+
|
|
2392
|
+
if (!project || !state) {
|
|
2393
|
+
if (container) {
|
|
2394
|
+
container.innerHTML = '<div style="font-size:0.75rem;color:var(--accent-rose);">Select a project and click a graph node first.</div>';
|
|
2395
|
+
}
|
|
2396
|
+
return;
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
if (btn) {
|
|
2400
|
+
btn.disabled = true;
|
|
2401
|
+
btn.textContent = '...';
|
|
2402
|
+
}
|
|
2403
|
+
if (container) {
|
|
2404
|
+
container.innerHTML = '<div style="font-size:0.75rem;color:var(--text-muted);text-align:center;padding:0.6rem 0;">Resolving cognitive route...</div>';
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
try {
|
|
2408
|
+
var url = '/api/graph/cognitive-route' +
|
|
2409
|
+
'?project=' + encodeURIComponent(project) +
|
|
2410
|
+
'&state=' + encodeURIComponent('State:' + state) +
|
|
2411
|
+
'&role=' + encodeURIComponent('Role:dev') +
|
|
2412
|
+
'&action=' + encodeURIComponent('Action:inspect') +
|
|
2413
|
+
'&explain=true';
|
|
2414
|
+
|
|
2415
|
+
var res = await fetch(url);
|
|
2416
|
+
var data = await res.json();
|
|
2417
|
+
|
|
2418
|
+
if (!res.ok || data.isError) {
|
|
2419
|
+
if (container) {
|
|
2420
|
+
container.innerHTML = '<div style="font-size:0.75rem;color:var(--accent-rose);">' + escapeHtml(data.error || data.text || 'Cognitive route failed') + '</div>';
|
|
2421
|
+
}
|
|
2422
|
+
return;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
if (container) {
|
|
2426
|
+
var txt = data.text || '';
|
|
2427
|
+
container.innerHTML = '<pre style="margin:0;white-space:pre-wrap;font-size:0.72rem;line-height:1.45;background:var(--bg-secondary);border:1px solid var(--border-subtle);border-radius:6px;padding:0.6rem;color:var(--text-secondary);">' + escapeHtml(txt) + '</pre>';
|
|
2428
|
+
}
|
|
2429
|
+
} catch (err) {
|
|
2430
|
+
if (container) {
|
|
2431
|
+
container.innerHTML = '<div style="font-size:0.75rem;color:var(--accent-rose);">' + escapeHtml(err.message || 'Route error') + '</div>';
|
|
2432
|
+
}
|
|
2433
|
+
} finally {
|
|
2434
|
+
if (btn) {
|
|
2435
|
+
btn.disabled = false;
|
|
2436
|
+
btn.textContent = 'π§ Route';
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2376
2441
|
async function triggerTestMe() {
|
|
2377
2442
|
var input = document.getElementById('nodeEditorInput');
|
|
2378
2443
|
var oldId = input.dataset.oldId;
|
|
@@ -3057,6 +3122,58 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
3057
3122
|
parts.push('</div>');
|
|
3058
3123
|
}
|
|
3059
3124
|
|
|
3125
|
+
// Cognitive Routing row (v6.5)
|
|
3126
|
+
if (m.cognitive && m.cognitive.evaluations_total > 0) {
|
|
3127
|
+
parts.push('<div style="border-top:1px solid var(--border-glass);padding-top:0.4rem;margin-top:0.2rem;font-size:0.75rem">');
|
|
3128
|
+
parts.push('<strong>π§ Cognitive Routing</strong>');
|
|
3129
|
+
parts.push('<br>Evaluations: <strong>' + m.cognitive.evaluations_total + '</strong>');
|
|
3130
|
+
|
|
3131
|
+
// Route distribution bar
|
|
3132
|
+
var cogTotal = m.cognitive.evaluations_total;
|
|
3133
|
+
var autoP = Math.round((m.cognitive.route_auto_total / cogTotal) * 100);
|
|
3134
|
+
var clarP = Math.round((m.cognitive.route_clarify_total / cogTotal) * 100);
|
|
3135
|
+
var fallP = 100 - autoP - clarP;
|
|
3136
|
+
parts.push('<div style="display:flex;height:8px;border-radius:4px;overflow:hidden;margin:4px 0;background:var(--surface-glass)">');
|
|
3137
|
+
if (autoP > 0) parts.push('<div style="width:' + autoP + '%;background:var(--accent-green)" title="Auto: ' + autoP + '%"></div>');
|
|
3138
|
+
if (clarP > 0) parts.push('<div style="width:' + clarP + '%;background:var(--accent-amber)" title="Clarify: ' + clarP + '%"></div>');
|
|
3139
|
+
if (fallP > 0) parts.push('<div style="width:' + fallP + '%;background:var(--accent-rose)" title="Fallback: ' + fallP + '%"></div>');
|
|
3140
|
+
parts.push('</div>');
|
|
3141
|
+
parts.push('<span style="color:var(--accent-green)">β Auto ' + autoP + '%</span>');
|
|
3142
|
+
parts.push(' <span style="color:var(--accent-amber)">β Clarify ' + clarP + '%</span>');
|
|
3143
|
+
parts.push(' <span style="color:var(--accent-rose)">β Fallback ' + fallP + '%</span>');
|
|
3144
|
+
|
|
3145
|
+
// Rates
|
|
3146
|
+
if (m.cognitive.ambiguity_rate !== null) {
|
|
3147
|
+
var ambPct = Math.round(m.cognitive.ambiguity_rate * 100);
|
|
3148
|
+
var ambColor = ambPct > 40 ? 'var(--accent-rose)' : ambPct > 20 ? 'var(--accent-amber)' : 'var(--accent-green)';
|
|
3149
|
+
parts.push('<br>Ambiguity: <span style="color:' + ambColor + ';font-weight:600">' + ambPct + '%</span>');
|
|
3150
|
+
}
|
|
3151
|
+
if (m.cognitive.fallback_rate !== null) {
|
|
3152
|
+
var fbPct = Math.round(m.cognitive.fallback_rate * 100);
|
|
3153
|
+
var fbColor = fbPct > 30 ? 'var(--accent-rose)' : fbPct > 15 ? 'var(--accent-amber)' : 'var(--accent-green)';
|
|
3154
|
+
parts.push(' Β· Fallback: <span style="color:' + fbColor + ';font-weight:600">' + fbPct + '%</span>');
|
|
3155
|
+
}
|
|
3156
|
+
|
|
3157
|
+
// Convergence steps
|
|
3158
|
+
if (m.cognitive.median_convergence_steps !== null) {
|
|
3159
|
+
parts.push('<br>Convergence: ' + m.cognitive.median_convergence_steps + ' steps (avg)');
|
|
3160
|
+
}
|
|
3161
|
+
if (m.cognitive.duration_p50_ms !== null) {
|
|
3162
|
+
parts.push(' Β· p50: ' + m.cognitive.duration_p50_ms + 'ms');
|
|
3163
|
+
}
|
|
3164
|
+
|
|
3165
|
+
// Last evaluation
|
|
3166
|
+
if (m.cognitive.last_run_at) {
|
|
3167
|
+
var lastRoute = m.cognitive.last_route || 'β';
|
|
3168
|
+
var lastConcept = m.cognitive.last_concept || '(none)';
|
|
3169
|
+
var lastConf = m.cognitive.last_confidence !== null ? Math.round(m.cognitive.last_confidence * 100) + '%' : 'β';
|
|
3170
|
+
parts.push('<br>Last: ' + lastRoute + ' β ' + lastConcept + ' (' + lastConf + ')');
|
|
3171
|
+
parts.push('<br><span style="color:var(--text-muted)">' + timeAgo(m.cognitive.last_run_at) + '</span>');
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3174
|
+
parts.push('</div>');
|
|
3175
|
+
}
|
|
3176
|
+
|
|
3060
3177
|
|
|
3061
3178
|
el.innerHTML = parts.join('');
|
|
3062
3179
|
|
|
@@ -3072,6 +3189,12 @@ Example:\n## Dev Rules\n- Always write tests first\n- Use TypeScript strict mode
|
|
|
3072
3189
|
if (m.warnings.synthesis_failure_warning) {
|
|
3073
3190
|
badges.push('<span style="background:var(--accent-rose);color:#fff;padding:2px 6px;border-radius:3px;font-size:0.65rem;font-weight:600" title="Over 20% of synthesis runs are failing">β Failures</span>');
|
|
3074
3191
|
}
|
|
3192
|
+
if (m.warnings.cognitive_fallback_rate_warning) {
|
|
3193
|
+
badges.push('<span style="background:var(--accent-rose);color:#fff;padding:2px 6px;border-radius:3px;font-size:0.65rem;font-weight:600" title="Over 30% of cognitive routes land on FALLBACK">β Cog Fallback</span>');
|
|
3194
|
+
}
|
|
3195
|
+
if (m.warnings.cognitive_ambiguity_rate_warning) {
|
|
3196
|
+
badges.push('<span style="background:var(--accent-amber);color:#000;padding:2px 6px;border-radius:3px;font-size:0.65rem;font-weight:600" title="Over 40% of cognitive evaluations are ambiguous">β Cog Ambiguity</span>');
|
|
3197
|
+
}
|
|
3075
3198
|
warn.innerHTML = badges.join('');
|
|
3076
3199
|
}
|
|
3077
3200
|
} catch(e) {
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
5
5
|
* PURPOSE:
|
|
6
|
-
* Lightweight, zero-dependency metrics collection for graph synthesis
|
|
7
|
-
*
|
|
6
|
+
* Lightweight, zero-dependency metrics collection for graph synthesis,
|
|
7
|
+
* test-me flows, and v6.5 cognitive routing.
|
|
8
|
+
* All state is in-memory (resets on restart).
|
|
8
9
|
*
|
|
9
10
|
* DESIGN:
|
|
10
|
-
* - Singleton counters + timestamps for synthesis
|
|
11
|
+
* - Singleton counters + timestamps for synthesis, test-me, and cognitive
|
|
11
12
|
* - Bounded ring buffer (100 entries) for duration p50 approximation
|
|
12
13
|
* - Warning flags computed on snapshot (not continuously)
|
|
13
14
|
* - Structured JSON log emission via debugLog channel
|
|
@@ -16,8 +17,9 @@
|
|
|
16
17
|
* METRICS MODEL:
|
|
17
18
|
* A) Synthesis: runs, failures, links created, candidates, below-threshold, duration
|
|
18
19
|
* B) Test-Me: requests, success, no_api_key, generation_failed, bad_request, duration
|
|
19
|
-
* C) Warning flags: quality drift, provider issues, failure rate
|
|
20
|
+
* C) Warning flags: quality drift, provider issues, failure rate, cognitive fallback/ambiguity
|
|
20
21
|
* D) SLO derivations: success rate, net new links, prune ratio, sweep duration (WS4)
|
|
22
|
+
* E) Cognitive (v6.5): intent evaluations, route distribution, ambiguity rate, convergence steps
|
|
21
23
|
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
22
24
|
*/
|
|
23
25
|
import { debugLog } from "../utils/logger.js";
|
|
@@ -63,6 +65,7 @@ let synthesis = createFreshSynthesisMetrics();
|
|
|
63
65
|
let testMe = createFreshTestMeMetrics();
|
|
64
66
|
let schedulerSynthesis = createFreshSchedulerMetrics();
|
|
65
67
|
let pruning = createFreshPruningMetrics();
|
|
68
|
+
let cognitive = createFreshCognitiveMetrics();
|
|
66
69
|
function createFreshSynthesisMetrics() {
|
|
67
70
|
return {
|
|
68
71
|
runs_total: 0,
|
|
@@ -119,6 +122,21 @@ function createFreshPruningMetrics() {
|
|
|
119
122
|
last_run_at: null,
|
|
120
123
|
};
|
|
121
124
|
}
|
|
125
|
+
function createFreshCognitiveMetrics() {
|
|
126
|
+
return {
|
|
127
|
+
evaluations_total: 0,
|
|
128
|
+
route_auto_total: 0,
|
|
129
|
+
route_clarify_total: 0,
|
|
130
|
+
route_fallback_total: 0,
|
|
131
|
+
ambiguous_total: 0,
|
|
132
|
+
convergence_steps_total: 0,
|
|
133
|
+
last_run_at: null,
|
|
134
|
+
last_route: null,
|
|
135
|
+
last_concept: null,
|
|
136
|
+
last_confidence: null,
|
|
137
|
+
duration_buffer: new DurationBuffer(),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
122
140
|
function emitGraphEvent(event) {
|
|
123
141
|
try {
|
|
124
142
|
debugLog(JSON.stringify(event));
|
|
@@ -246,6 +264,40 @@ export function recordSweepDuration(duration_ms) {
|
|
|
246
264
|
duration_ms,
|
|
247
265
|
});
|
|
248
266
|
}
|
|
267
|
+
export function recordCognitiveRoute(data) {
|
|
268
|
+
const now = new Date().toISOString();
|
|
269
|
+
cognitive.evaluations_total++;
|
|
270
|
+
cognitive.last_run_at = now;
|
|
271
|
+
cognitive.last_route = data.route;
|
|
272
|
+
cognitive.last_concept = data.concept;
|
|
273
|
+
cognitive.last_confidence = data.confidence;
|
|
274
|
+
cognitive.duration_buffer.push(data.duration_ms);
|
|
275
|
+
cognitive.convergence_steps_total += data.steps;
|
|
276
|
+
if (data.ambiguous) {
|
|
277
|
+
cognitive.ambiguous_total++;
|
|
278
|
+
}
|
|
279
|
+
// Route distribution β match ActionRoute enum values
|
|
280
|
+
if (data.route === "ACTION_AUTO_ROUTE") {
|
|
281
|
+
cognitive.route_auto_total++;
|
|
282
|
+
}
|
|
283
|
+
else if (data.route === "ACTION_CLARIFY") {
|
|
284
|
+
cognitive.route_clarify_total++;
|
|
285
|
+
}
|
|
286
|
+
else if (data.route === "ACTION_FALLBACK") {
|
|
287
|
+
cognitive.route_fallback_total++;
|
|
288
|
+
}
|
|
289
|
+
emitGraphEvent({
|
|
290
|
+
event: "cognitive_route_evaluation",
|
|
291
|
+
project: data.project,
|
|
292
|
+
route: data.route,
|
|
293
|
+
concept: data.concept,
|
|
294
|
+
confidence: data.confidence,
|
|
295
|
+
distance: data.distance,
|
|
296
|
+
ambiguous: data.ambiguous,
|
|
297
|
+
steps: data.steps,
|
|
298
|
+
duration_ms: data.duration_ms,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
249
301
|
// βββ Warning Flag Computation ββββββββββββββββββββββββββββββββββββ
|
|
250
302
|
function computeWarningFlags() {
|
|
251
303
|
// Quality warning: >85% of candidates are below threshold (min 50 candidates)
|
|
@@ -256,10 +308,18 @@ function computeWarningFlags() {
|
|
|
256
308
|
// Failure rate warning: >20% of synthesis runs failed (min 5 runs)
|
|
257
309
|
const synthesis_failure_warning = synthesis.runs_total >= 5 &&
|
|
258
310
|
synthesis.runs_failed / synthesis.runs_total > 0.2;
|
|
311
|
+
// Cognitive fallback rate warning: >30% routes go to FALLBACK (min 10 evaluations)
|
|
312
|
+
const cognitive_fallback_rate_warning = cognitive.evaluations_total >= 10 &&
|
|
313
|
+
cognitive.route_fallback_total / cognitive.evaluations_total > 0.3;
|
|
314
|
+
// Cognitive ambiguity rate warning: >40% evaluations are ambiguous (min 10 evaluations)
|
|
315
|
+
const cognitive_ambiguity_rate_warning = cognitive.evaluations_total >= 10 &&
|
|
316
|
+
cognitive.ambiguous_total / cognitive.evaluations_total > 0.4;
|
|
259
317
|
return {
|
|
260
318
|
synthesis_quality_warning,
|
|
261
319
|
testme_provider_warning,
|
|
262
320
|
synthesis_failure_warning,
|
|
321
|
+
cognitive_fallback_rate_warning,
|
|
322
|
+
cognitive_ambiguity_rate_warning,
|
|
263
323
|
};
|
|
264
324
|
}
|
|
265
325
|
// βββ SLO Derivation (WS4) ββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -283,6 +343,17 @@ function computeSloMetrics() {
|
|
|
283
343
|
};
|
|
284
344
|
}
|
|
285
345
|
export function getGraphMetricsSnapshot() {
|
|
346
|
+
// Derived cognitive rates
|
|
347
|
+
const cogEvalTotal = cognitive.evaluations_total;
|
|
348
|
+
const ambiguity_rate = cogEvalTotal > 0
|
|
349
|
+
? parseFloat((cognitive.ambiguous_total / cogEvalTotal).toFixed(4))
|
|
350
|
+
: null;
|
|
351
|
+
const fallback_rate = cogEvalTotal > 0
|
|
352
|
+
? parseFloat((cognitive.route_fallback_total / cogEvalTotal).toFixed(4))
|
|
353
|
+
: null;
|
|
354
|
+
const median_convergence_steps = cogEvalTotal > 0
|
|
355
|
+
? parseFloat((cognitive.convergence_steps_total / cogEvalTotal).toFixed(2))
|
|
356
|
+
: null;
|
|
286
357
|
return {
|
|
287
358
|
synthesis: {
|
|
288
359
|
runs_total: synthesis.runs_total,
|
|
@@ -332,6 +403,22 @@ export function getGraphMetricsSnapshot() {
|
|
|
332
403
|
skipped_budget_last: pruning.skipped_budget_last,
|
|
333
404
|
last_run_at: pruning.last_run_at,
|
|
334
405
|
},
|
|
406
|
+
cognitive: {
|
|
407
|
+
evaluations_total: cognitive.evaluations_total,
|
|
408
|
+
route_auto_total: cognitive.route_auto_total,
|
|
409
|
+
route_clarify_total: cognitive.route_clarify_total,
|
|
410
|
+
route_fallback_total: cognitive.route_fallback_total,
|
|
411
|
+
ambiguous_total: cognitive.ambiguous_total,
|
|
412
|
+
convergence_steps_total: cognitive.convergence_steps_total,
|
|
413
|
+
median_convergence_steps,
|
|
414
|
+
ambiguity_rate,
|
|
415
|
+
fallback_rate,
|
|
416
|
+
last_run_at: cognitive.last_run_at,
|
|
417
|
+
last_route: cognitive.last_route,
|
|
418
|
+
last_concept: cognitive.last_concept,
|
|
419
|
+
last_confidence: cognitive.last_confidence,
|
|
420
|
+
duration_p50_ms: cognitive.duration_buffer.getP50(),
|
|
421
|
+
},
|
|
335
422
|
slo: computeSloMetrics(),
|
|
336
423
|
warnings: computeWarningFlags(),
|
|
337
424
|
};
|
|
@@ -342,6 +429,7 @@ export function resetGraphMetricsForTests() {
|
|
|
342
429
|
testMe = createFreshTestMeMetrics();
|
|
343
430
|
schedulerSynthesis = createFreshSchedulerMetrics();
|
|
344
431
|
pruning = createFreshPruningMetrics();
|
|
432
|
+
cognitive = createFreshCognitiveMetrics();
|
|
345
433
|
sweepDurationMsLast = 0;
|
|
346
434
|
sweepLastAt = null;
|
|
347
435
|
}
|
package/dist/server.js
CHANGED
|
@@ -58,7 +58,7 @@ ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ReadResourceRequ
|
|
|
58
58
|
// Claude Desktop that the attached resource has changed.
|
|
59
59
|
// Without this, the paperclipped context becomes stale.
|
|
60
60
|
SubscribeRequestSchema, UnsubscribeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
61
|
-
import { SERVER_CONFIG, SESSION_MEMORY_ENABLED, PRISM_USER_ID, PRISM_ENABLE_HIVEMIND, WATCHDOG_INTERVAL_MS, WATCHDOG_STALE_MIN, WATCHDOG_FROZEN_MIN, WATCHDOG_OFFLINE_MIN, WATCHDOG_LOOP_THRESHOLD, PRISM_SCHEDULER_ENABLED, PRISM_SCHEDULER_INTERVAL_MS, PRISM_SCHOLAR_ENABLED, } from "./config.js";
|
|
61
|
+
import { SERVER_CONFIG, SESSION_MEMORY_ENABLED, PRISM_USER_ID, PRISM_ENABLE_HIVEMIND, WATCHDOG_INTERVAL_MS, WATCHDOG_STALE_MIN, WATCHDOG_FROZEN_MIN, WATCHDOG_OFFLINE_MIN, WATCHDOG_LOOP_THRESHOLD, PRISM_SCHEDULER_ENABLED, PRISM_SCHEDULER_INTERVAL_MS, PRISM_SCHOLAR_ENABLED, PRISM_HDC_ENABLED, } from "./config.js";
|
|
62
62
|
import { startWatchdog, drainAlerts } from "./hivemindWatchdog.js";
|
|
63
63
|
import { startScheduler, startScholarScheduler } from "./backgroundScheduler.js";
|
|
64
64
|
import { getSyncBus } from "./sync/factory.js";
|
|
@@ -95,9 +95,9 @@ KNOWLEDGE_SET_RETENTION_TOOL,
|
|
|
95
95
|
// v4.0: Active Behavioral Memory tools
|
|
96
96
|
SESSION_SAVE_EXPERIENCE_TOOL, KNOWLEDGE_UPVOTE_TOOL, KNOWLEDGE_DOWNVOTE_TOOL,
|
|
97
97
|
// v6.0: Associative Memory Graph tools
|
|
98
|
-
SESSION_BACKFILL_LINKS_TOOL, SESSION_SYNTHESIZE_EDGES_TOOL, sessionSaveLedgerHandler, sessionSaveHandoffHandler, sessionLoadContextHandler, knowledgeSearchHandler, knowledgeForgetHandler,
|
|
98
|
+
SESSION_BACKFILL_LINKS_TOOL, SESSION_SYNTHESIZE_EDGES_TOOL, SESSION_COGNITIVE_ROUTE_TOOL, sessionSaveLedgerHandler, sessionSaveHandoffHandler, sessionLoadContextHandler, knowledgeSearchHandler, knowledgeForgetHandler,
|
|
99
99
|
// βββ v0.4.0: New tool handlers βββ
|
|
100
|
-
compactLedgerHandler, sessionSearchMemoryHandler, backfillEmbeddingsHandler, sessionBackfillLinksHandler, sessionSynthesizeEdgesHandler,
|
|
100
|
+
compactLedgerHandler, sessionSearchMemoryHandler, backfillEmbeddingsHandler, sessionBackfillLinksHandler, sessionSynthesizeEdgesHandler, sessionCognitiveRouteHandler,
|
|
101
101
|
// βββ v2.0: Time Travel handlers βββ
|
|
102
102
|
memoryHistoryHandler, memoryCheckoutHandler,
|
|
103
103
|
// βββ v2.0: Visual Memory handlers βββ
|
|
@@ -193,6 +193,7 @@ function buildSessionMemoryTools(autoloadList) {
|
|
|
193
193
|
// βββ v6.0: Associative Memory Graph tools βββ
|
|
194
194
|
SESSION_BACKFILL_LINKS_TOOL, // session_backfill_links β retroactive graph edge creation
|
|
195
195
|
SESSION_SYNTHESIZE_EDGES_TOOL, // session_synthesize_edges β inferred semantic graph enrichment
|
|
196
|
+
SESSION_COGNITIVE_ROUTE_TOOL, // session_cognitive_route β HDC policy-gated concept routing (v6.5)
|
|
196
197
|
// βββ v6.1: Storage Hygiene tool βββ
|
|
197
198
|
MAINTENANCE_VACUUM_TOOL, // maintenance_vacuum β reclaim SQLite disk space post-purge
|
|
198
199
|
];
|
|
@@ -756,6 +757,13 @@ export function createServer() {
|
|
|
756
757
|
throw new Error("Session memory not configured. Set SUPABASE_URL and SUPABASE_KEY.");
|
|
757
758
|
result = await sessionSynthesizeEdgesHandler(args);
|
|
758
759
|
break;
|
|
760
|
+
case "session_cognitive_route":
|
|
761
|
+
if (!SESSION_MEMORY_ENABLED)
|
|
762
|
+
throw new Error("Session memory not configured. Set SUPABASE_URL and SUPABASE_KEY.");
|
|
763
|
+
if (!PRISM_HDC_ENABLED)
|
|
764
|
+
throw new Error("HDC cognitive routing not enabled. Set PRISM_HDC_ENABLED=true.");
|
|
765
|
+
result = await sessionCognitiveRouteHandler(args);
|
|
766
|
+
break;
|
|
759
767
|
case "session_backfill_embeddings":
|
|
760
768
|
if (!SESSION_MEMORY_ENABLED)
|
|
761
769
|
throw new Error("Session memory not configured. Set SUPABASE_URL and SUPABASE_KEY.");
|
package/dist/storage/index.js
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Storage Factory (v2.0 β Step 1)
|
|
3
|
-
*
|
|
4
|
-
* Unified entry point for storage initialization.
|
|
5
|
-
* Routes between Supabase (cloud) and SQLite (local) based on
|
|
6
|
-
* the PRISM_STORAGE environment variable.
|
|
7
|
-
*
|
|
8
|
-
* Usage in server.ts:
|
|
9
|
-
* const storage = await getStorage();
|
|
10
|
-
* // Pass `storage` to all session memory handlers
|
|
11
|
-
*/
|
|
12
|
-
import { PRISM_STORAGE as ENV_PRISM_STORAGE } from "../config.js";
|
|
1
|
+
import { PRISM_STORAGE as ENV_PRISM_STORAGE, SUPABASE_CONFIGURED } from "../config.js";
|
|
13
2
|
import { debugLog } from "../utils/logger.js";
|
|
14
3
|
import { SupabaseStorage } from "./supabase.js";
|
|
15
4
|
import { getSetting } from "./configStorage.js";
|
|
@@ -20,16 +9,22 @@ export let activeStorageBackend = "local";
|
|
|
20
9
|
*
|
|
21
10
|
* On first call: creates and initializes the appropriate backend.
|
|
22
11
|
* On subsequent calls: returns the cached instance.
|
|
23
|
-
*
|
|
24
|
-
* @throws Error if PRISM_STORAGE=local (not yet implemented in Step 1)
|
|
25
|
-
* @throws Error if PRISM_STORAGE=supabase but Supabase is not configured
|
|
26
12
|
*/
|
|
27
13
|
export async function getStorage() {
|
|
28
14
|
if (storageInstance)
|
|
29
15
|
return storageInstance;
|
|
30
16
|
// Use environment variable if explicitly set, otherwise fall back to db config
|
|
31
17
|
const envStorage = process.env.PRISM_STORAGE;
|
|
32
|
-
|
|
18
|
+
const requestedBackend = (envStorage || await getSetting("PRISM_STORAGE", ENV_PRISM_STORAGE));
|
|
19
|
+
// Guardrail: if Supabase is requested but credentials are unresolved/invalid,
|
|
20
|
+
// transparently fall back to local mode to keep dashboard + core tools usable.
|
|
21
|
+
if (requestedBackend === "supabase" && !SUPABASE_CONFIGURED) {
|
|
22
|
+
activeStorageBackend = "local";
|
|
23
|
+
console.error("[Prism Storage] Supabase backend requested but SUPABASE_URL/SUPABASE_KEY are invalid or unresolved. Falling back to local storage.");
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
activeStorageBackend = requestedBackend;
|
|
27
|
+
}
|
|
33
28
|
debugLog(`[Prism Storage] Initializing backend: ${activeStorageBackend}`);
|
|
34
29
|
if (activeStorageBackend === "local") {
|
|
35
30
|
const { SqliteStorage } = await import("./sqlite.js");
|
|
@@ -17,6 +17,7 @@ import { formatRulesBlock, applySentinelBlock } from "./commonHelpers.js";
|
|
|
17
17
|
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
18
18
|
*/
|
|
19
19
|
import { debugLog } from "../utils/logger.js";
|
|
20
|
+
import { recordCognitiveRoute } from "../observability/graphMetrics.js";
|
|
20
21
|
import { getStorage } from "../storage/index.js";
|
|
21
22
|
import { toKeywordArray } from "../utils/keywordExtractor.js";
|
|
22
23
|
import { getLLMProvider } from "../utils/llm/factory.js";
|
|
@@ -31,7 +32,7 @@ import { createMemoryTrace, traceToContentBlock } from "../utils/tracing.js";
|
|
|
31
32
|
import { GOOGLE_API_KEY, PRISM_USER_ID } from "../config.js";
|
|
32
33
|
import { isKnowledgeSearchArgs, isKnowledgeForgetArgs, isSessionSearchMemoryArgs, isKnowledgeVoteArgs,
|
|
33
34
|
// v4.2: Sync Rules type guard
|
|
34
|
-
isKnowledgeSyncRulesArgs, isSessionIntuitiveRecallArgs, isSessionSynthesizeEdgesArgs, } from "./sessionMemoryDefinitions.js";
|
|
35
|
+
isKnowledgeSyncRulesArgs, isSessionIntuitiveRecallArgs, isSessionSynthesizeEdgesArgs, isSessionCognitiveRouteArgs, } from "./sessionMemoryDefinitions.js";
|
|
35
36
|
// v4.2: File system access for knowledge_sync_rules
|
|
36
37
|
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
37
38
|
import { existsSync } from "node:fs";
|
|
@@ -50,6 +51,11 @@ const activeCompactions = new Set();
|
|
|
50
51
|
* After saving, generates an embedding vector for the entry via fire-and-forget.
|
|
51
52
|
*/
|
|
52
53
|
import { computeEffectiveImportance, updateLastAccessed } from "../utils/cognitiveMemory.js";
|
|
54
|
+
import { HdcStateMachine } from "../sdm/stateMachine.js";
|
|
55
|
+
import { ConceptDictionary } from "../sdm/conceptDictionary.js";
|
|
56
|
+
import { PolicyGateway } from "../sdm/policyGateway.js";
|
|
57
|
+
import { getSdmEngine } from "../sdm/sdmEngine.js";
|
|
58
|
+
import { PRISM_HDC_ENABLED, PRISM_HDC_EXPLAINABILITY_ENABLED, PRISM_HDC_POLICY_FALLBACK_THRESHOLD, PRISM_HDC_POLICY_CLARIFY_THRESHOLD, } from "../config.js";
|
|
53
59
|
export async function knowledgeSearchHandler(args) {
|
|
54
60
|
if (!isKnowledgeSearchArgs(args)) {
|
|
55
61
|
throw new Error("Invalid arguments for knowledge_search");
|
|
@@ -670,7 +676,6 @@ export async function sessionIntuitiveRecallHandler(args) {
|
|
|
670
676
|
};
|
|
671
677
|
}
|
|
672
678
|
try {
|
|
673
|
-
const { getSdmEngine } = await import("../sdm/sdmEngine.js");
|
|
674
679
|
const { decodeSdmVector } = await import("../sdm/sdmDecoder.js");
|
|
675
680
|
const queryVector = await getLLMProvider().generateEmbedding(args.query);
|
|
676
681
|
const sdmEngine = getSdmEngine(args.project);
|
|
@@ -702,6 +707,113 @@ export async function sessionIntuitiveRecallHandler(args) {
|
|
|
702
707
|
};
|
|
703
708
|
}
|
|
704
709
|
}
|
|
710
|
+
export async function sessionCognitiveRouteHandler(args) {
|
|
711
|
+
if (!isSessionCognitiveRouteArgs(args)) {
|
|
712
|
+
return {
|
|
713
|
+
content: [{ type: "text", text: "Invalid arguments for session_cognitive_route" }],
|
|
714
|
+
isError: true,
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
if (!PRISM_HDC_ENABLED) {
|
|
718
|
+
return {
|
|
719
|
+
content: [{
|
|
720
|
+
type: "text",
|
|
721
|
+
text: "β οΈ session_cognitive_route is disabled. Set PRISM_HDC_ENABLED=true to enable v6.5 cognitive routing.",
|
|
722
|
+
}],
|
|
723
|
+
isError: true,
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
try {
|
|
727
|
+
const storage = await getStorage();
|
|
728
|
+
const sdmEngine = getSdmEngine(args.project);
|
|
729
|
+
const dict = new ConceptDictionary(storage);
|
|
730
|
+
const stateVector = await dict.getConcept(args.state);
|
|
731
|
+
const roleVector = await dict.getConcept(args.role);
|
|
732
|
+
const actionVector = await dict.getConcept(args.action);
|
|
733
|
+
const machine = new HdcStateMachine(stateVector, sdmEngine);
|
|
734
|
+
machine.transition(roleVector, actionVector);
|
|
735
|
+
const fallbackKey = `hdc:fallback_threshold:${args.project}`;
|
|
736
|
+
const clarifyKey = `hdc:clarify_threshold:${args.project}`;
|
|
737
|
+
const persistedFallbackRaw = await storage.getSetting(fallbackKey);
|
|
738
|
+
const persistedClarifyRaw = await storage.getSetting(clarifyKey);
|
|
739
|
+
const persistedFallback = persistedFallbackRaw !== null ? Number(persistedFallbackRaw) : NaN;
|
|
740
|
+
const persistedClarify = persistedClarifyRaw !== null ? Number(persistedClarifyRaw) : NaN;
|
|
741
|
+
const baseFallbackThreshold = Number.isFinite(persistedFallback)
|
|
742
|
+
? persistedFallback
|
|
743
|
+
: PRISM_HDC_POLICY_FALLBACK_THRESHOLD;
|
|
744
|
+
const baseClarifyThreshold = Number.isFinite(persistedClarify)
|
|
745
|
+
? persistedClarify
|
|
746
|
+
: PRISM_HDC_POLICY_CLARIFY_THRESHOLD;
|
|
747
|
+
const fallbackThreshold = args.fallback_threshold ?? baseFallbackThreshold;
|
|
748
|
+
const clarifyThreshold = args.clarify_threshold ?? baseClarifyThreshold;
|
|
749
|
+
const explain = args.explain !== undefined ? args.explain : true;
|
|
750
|
+
if (!(fallbackThreshold >= 0 && fallbackThreshold < clarifyThreshold && clarifyThreshold <= 1)) {
|
|
751
|
+
return {
|
|
752
|
+
content: [{
|
|
753
|
+
type: "text",
|
|
754
|
+
text: `Invalid policy thresholds for project "${args.project}": ` +
|
|
755
|
+
`fallback=${fallbackThreshold}, clarify=${clarifyThreshold}. ` +
|
|
756
|
+
"Expected 0 <= fallback < clarify <= 1.",
|
|
757
|
+
}],
|
|
758
|
+
isError: true,
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
// Phase 2 parity hook: persist project-specific threshold overrides via storage settings.
|
|
762
|
+
// This works on both SQLite and Supabase backends through the shared StorageBackend API.
|
|
763
|
+
if (args.fallback_threshold !== undefined || args.clarify_threshold !== undefined) {
|
|
764
|
+
await storage.setSetting(fallbackKey, String(fallbackThreshold));
|
|
765
|
+
await storage.setSetting(clarifyKey, String(clarifyThreshold));
|
|
766
|
+
}
|
|
767
|
+
const gateway = new PolicyGateway(dict, {
|
|
768
|
+
fallbackThreshold,
|
|
769
|
+
clarifyThreshold,
|
|
770
|
+
});
|
|
771
|
+
const cogStart = Date.now();
|
|
772
|
+
const result = await gateway.evaluateIntent(machine);
|
|
773
|
+
const cogDuration = Date.now() - cogStart;
|
|
774
|
+
// Phase 4: Record cognitive route telemetry
|
|
775
|
+
recordCognitiveRoute({
|
|
776
|
+
project: args.project,
|
|
777
|
+
route: result.route,
|
|
778
|
+
concept: result.concept || null,
|
|
779
|
+
confidence: result.confidence,
|
|
780
|
+
distance: result.distance,
|
|
781
|
+
ambiguous: result.ambiguous,
|
|
782
|
+
steps: result.steps,
|
|
783
|
+
duration_ms: cogDuration,
|
|
784
|
+
});
|
|
785
|
+
const lines = [];
|
|
786
|
+
lines.push(`π§ Cognitive Route β project \"${args.project}\"`);
|
|
787
|
+
lines.push("");
|
|
788
|
+
lines.push(`State: ${args.state}`);
|
|
789
|
+
lines.push(`Role: ${args.role}`);
|
|
790
|
+
lines.push(`Action: ${args.action}`);
|
|
791
|
+
lines.push("");
|
|
792
|
+
lines.push(`Route: ${result.route}`);
|
|
793
|
+
lines.push(`Concept: ${result.concept || "(none)"}`);
|
|
794
|
+
lines.push(`Confidence: ${(result.confidence * 100).toFixed(2)}%`);
|
|
795
|
+
lines.push(`Distance: ${result.distance}`);
|
|
796
|
+
lines.push(`Ambiguous: ${result.ambiguous ? "yes" : "no"}`);
|
|
797
|
+
lines.push(`Convergence Steps: ${result.steps}`);
|
|
798
|
+
if (PRISM_HDC_EXPLAINABILITY_ENABLED && explain) {
|
|
799
|
+
lines.push("");
|
|
800
|
+
lines.push("Explainability:");
|
|
801
|
+
lines.push(`- Policy thresholds: fallback=${fallbackThreshold}, clarify=${clarifyThreshold}`);
|
|
802
|
+
lines.push("- Routing logic: below fallback => FALLBACK, ambiguous/below clarify => CLARIFY, else AUTO_ROUTE");
|
|
803
|
+
}
|
|
804
|
+
return {
|
|
805
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
806
|
+
isError: false,
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
catch (err) {
|
|
810
|
+
debugLog(`[session_cognitive_route] Failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
811
|
+
return {
|
|
812
|
+
content: [{ type: "text", text: `Error triggering cognitive route: ${err instanceof Error ? err.message : String(err)}` }],
|
|
813
|
+
isError: true,
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
}
|
|
705
817
|
export async function synthesizeEdgesCore({ project, similarity_threshold = 0.7, max_entries = 50, max_neighbors_per_entry = 3, randomize_selection = false, }) {
|
|
706
818
|
const storage = await getStorage();
|
|
707
819
|
const llm = getLLMProvider();
|
package/dist/tools/index.js
CHANGED
|
@@ -26,11 +26,11 @@ export { webSearchHandler, braveWebSearchCodeModeHandler, localSearchHandler, br
|
|
|
26
26
|
// This file always exports them β server.ts decides whether to include them in the tool list.
|
|
27
27
|
//
|
|
28
28
|
// v0.4.0: Added SESSION_COMPACT_LEDGER_TOOL and SESSION_SEARCH_MEMORY_TOOL
|
|
29
|
-
export { SESSION_SAVE_LEDGER_TOOL, SESSION_SAVE_HANDOFF_TOOL, SESSION_LOAD_CONTEXT_TOOL, KNOWLEDGE_SEARCH_TOOL, KNOWLEDGE_FORGET_TOOL, SESSION_COMPACT_LEDGER_TOOL, SESSION_SEARCH_MEMORY_TOOL, MEMORY_HISTORY_TOOL, MEMORY_CHECKOUT_TOOL, SESSION_SAVE_IMAGE_TOOL, SESSION_VIEW_IMAGE_TOOL, SESSION_HEALTH_CHECK_TOOL, SESSION_FORGET_MEMORY_TOOL, SESSION_EXPORT_MEMORY_TOOL, KNOWLEDGE_SET_RETENTION_TOOL, SESSION_SAVE_EXPERIENCE_TOOL, KNOWLEDGE_UPVOTE_TOOL, KNOWLEDGE_DOWNVOTE_TOOL, KNOWLEDGE_SYNC_RULES_TOOL, DEEP_STORAGE_PURGE_TOOL, SESSION_INTUITIVE_RECALL_TOOL, SESSION_BACKFILL_LINKS_TOOL, MAINTENANCE_VACUUM_TOOL, isDeepStoragePurgeArgs, SESSION_SYNTHESIZE_EDGES_TOOL, isSessionSynthesizeEdgesArgs } from "./sessionMemoryDefinitions.js";
|
|
29
|
+
export { SESSION_SAVE_LEDGER_TOOL, SESSION_SAVE_HANDOFF_TOOL, SESSION_LOAD_CONTEXT_TOOL, KNOWLEDGE_SEARCH_TOOL, KNOWLEDGE_FORGET_TOOL, SESSION_COMPACT_LEDGER_TOOL, SESSION_SEARCH_MEMORY_TOOL, MEMORY_HISTORY_TOOL, MEMORY_CHECKOUT_TOOL, SESSION_SAVE_IMAGE_TOOL, SESSION_VIEW_IMAGE_TOOL, SESSION_HEALTH_CHECK_TOOL, SESSION_FORGET_MEMORY_TOOL, SESSION_EXPORT_MEMORY_TOOL, KNOWLEDGE_SET_RETENTION_TOOL, SESSION_SAVE_EXPERIENCE_TOOL, KNOWLEDGE_UPVOTE_TOOL, KNOWLEDGE_DOWNVOTE_TOOL, KNOWLEDGE_SYNC_RULES_TOOL, DEEP_STORAGE_PURGE_TOOL, SESSION_INTUITIVE_RECALL_TOOL, SESSION_BACKFILL_LINKS_TOOL, MAINTENANCE_VACUUM_TOOL, isDeepStoragePurgeArgs, SESSION_SYNTHESIZE_EDGES_TOOL, isSessionSynthesizeEdgesArgs, SESSION_COGNITIVE_ROUTE_TOOL, isSessionCognitiveRouteArgs } from "./sessionMemoryDefinitions.js";
|
|
30
30
|
// 1. Ledger (Core CRUD & State)
|
|
31
31
|
export { sessionSaveLedgerHandler, sessionSaveHandoffHandler, sessionLoadContextHandler, sessionSaveExperienceHandler, sessionSaveImageHandler, sessionViewImageHandler, memoryHistoryHandler, memoryCheckoutHandler, sessionForgetMemoryHandler, sessionExportMemoryHandler } from "./ledgerHandlers.js";
|
|
32
32
|
// 2. Graph (Semantic Search & Weighting)
|
|
33
|
-
export { sessionSearchMemoryHandler, knowledgeSearchHandler, sessionIntuitiveRecallHandler, knowledgeUpvoteHandler, knowledgeDownvoteHandler, knowledgeForgetHandler, knowledgeSyncRulesHandler, sessionSynthesizeEdgesHandler } from "./graphHandlers.js";
|
|
33
|
+
export { sessionSearchMemoryHandler, knowledgeSearchHandler, sessionIntuitiveRecallHandler, knowledgeUpvoteHandler, knowledgeDownvoteHandler, knowledgeForgetHandler, knowledgeSyncRulesHandler, sessionSynthesizeEdgesHandler, sessionCognitiveRouteHandler } from "./graphHandlers.js";
|
|
34
34
|
// 3. Hygiene (Maintenance & Integrity)
|
|
35
35
|
export { deepStoragePurgeHandler, maintenanceVacuumHandler, sessionHealthCheckHandler, backfillEmbeddingsHandler, sessionBackfillLinksHandler, knowledgeSetRetentionHandler } from "./hygieneHandlers.js";
|
|
36
36
|
// ββ Compaction Handler (v0.4.0 β Enhancement #2) ββ
|
|
@@ -1238,3 +1238,67 @@ export function isSessionSynthesizeEdgesArgs(args) {
|
|
|
1238
1238
|
return false;
|
|
1239
1239
|
return true;
|
|
1240
1240
|
}
|
|
1241
|
+
export const SESSION_COGNITIVE_ROUTE_TOOL = {
|
|
1242
|
+
name: "session_cognitive_route",
|
|
1243
|
+
description: "Resolve an HDC compositional state into a nearest semantic concept with policy-gated routing. " +
|
|
1244
|
+
"Returns concept, confidence, distance, ambiguity, convergence steps, and route outcome. " +
|
|
1245
|
+
"Use this for explainable cognitive recall decisions in v6.5.",
|
|
1246
|
+
inputSchema: {
|
|
1247
|
+
type: "object",
|
|
1248
|
+
properties: {
|
|
1249
|
+
project: {
|
|
1250
|
+
type: "string",
|
|
1251
|
+
description: "Project identifier.",
|
|
1252
|
+
},
|
|
1253
|
+
state: {
|
|
1254
|
+
type: "string",
|
|
1255
|
+
description: "Current state concept key (e.g. 'State:ActiveSession').",
|
|
1256
|
+
},
|
|
1257
|
+
role: {
|
|
1258
|
+
type: "string",
|
|
1259
|
+
description: "Role concept key used for transition binding.",
|
|
1260
|
+
},
|
|
1261
|
+
action: {
|
|
1262
|
+
type: "string",
|
|
1263
|
+
description: "Action concept key used for transition binding.",
|
|
1264
|
+
},
|
|
1265
|
+
fallback_threshold: {
|
|
1266
|
+
type: "number",
|
|
1267
|
+
description: "Optional route fallback threshold override (0 <= fallback < clarify <= 1).",
|
|
1268
|
+
},
|
|
1269
|
+
clarify_threshold: {
|
|
1270
|
+
type: "number",
|
|
1271
|
+
description: "Optional route clarify threshold override (0 <= fallback < clarify <= 1).",
|
|
1272
|
+
},
|
|
1273
|
+
explain: {
|
|
1274
|
+
type: "boolean",
|
|
1275
|
+
description: "If true, include expanded explainability details in the response. Default: true.",
|
|
1276
|
+
},
|
|
1277
|
+
},
|
|
1278
|
+
required: ["project", "state", "role", "action"],
|
|
1279
|
+
},
|
|
1280
|
+
};
|
|
1281
|
+
export function isSessionCognitiveRouteArgs(args) {
|
|
1282
|
+
if (typeof args !== "object" || args === null)
|
|
1283
|
+
return false;
|
|
1284
|
+
const a = args;
|
|
1285
|
+
if (typeof a.project !== "string")
|
|
1286
|
+
return false;
|
|
1287
|
+
if (typeof a.state !== "string")
|
|
1288
|
+
return false;
|
|
1289
|
+
if (typeof a.role !== "string")
|
|
1290
|
+
return false;
|
|
1291
|
+
if (typeof a.action !== "string")
|
|
1292
|
+
return false;
|
|
1293
|
+
if (a.fallback_threshold !== undefined && typeof a.fallback_threshold !== "number")
|
|
1294
|
+
return false;
|
|
1295
|
+
if (a.clarify_threshold !== undefined && typeof a.clarify_threshold !== "number")
|
|
1296
|
+
return false;
|
|
1297
|
+
if (a.explain !== undefined && typeof a.explain !== "boolean")
|
|
1298
|
+
return false;
|
|
1299
|
+
if (typeof a.fallback_threshold === "number" &&
|
|
1300
|
+
typeof a.clarify_threshold === "number" &&
|
|
1301
|
+
!(a.fallback_threshold >= 0 && a.fallback_threshold < a.clarify_threshold && a.clarify_threshold <= 1))
|
|
1302
|
+
return false;
|
|
1303
|
+
return true;
|
|
1304
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prism-mcp-server",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.5.1",
|
|
4
4
|
"mcpName": "io.github.dcostenco/prism-mcp",
|
|
5
5
|
"description": "The Mind Palace for AI Agents β persistent memory (SQLite/Supabase), behavioral learning & IDE rules sync, multimodal VLM image captioning, pluggable LLM providers (OpenAI/Anthropic/Gemini/Ollama), OpenTelemetry distributed tracing, GDPR export, multi-agent Hivemind sync, time travel, visual Mind Palace dashboard. Zero-config local mode.",
|
|
6
6
|
"module": "index.ts",
|