prism-mcp-server 2.5.2 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  ## Table of Contents
16
16
 
17
- - [What's New (v2.5.0)](#whats-new-in-v250---enterprise-memory-)
17
+ - [What's New (v3.0.1)](#whats-new-in-v301---agent-identity--brain-clean-up-)
18
18
  - [How Prism Compares](#how-prism-compares)
19
19
  - [Quick Start](#quick-start-zero-config--local-mode)
20
20
  - [Mind Palace Dashboard](#-the-mind-palace-dashboard)
@@ -22,8 +22,10 @@
22
22
  - [Use Cases](#use-cases)
23
23
  - [Architecture](#architecture)
24
24
  - [Tool Reference](#tool-reference)
25
+ - [Agent Hivemind — Role Usage](#agent-hivemind--role-usage)
25
26
  - [LangChain / LangGraph Integration](#langchain--langgraph-integration)
26
27
  - [Environment Variables](#environment-variables)
28
+ - [Boot Settings (Restart Required)](#-boot-settings-restart-required)
27
29
  - [Progressive Context Loading](#progressive-context-loading)
28
30
  - [Time Travel](#time-travel-version-history)
29
31
  - [Agent Telepathy](#agent-telepathy-multi-client-sync)
@@ -37,7 +39,33 @@
37
39
 
38
40
  ---
39
41
 
40
- ## What's New in v2.5.0Enterprise Memory 🏗️
42
+ ## What's New in v3.0.1Agent Identity & Brain Clean-up 🧹
43
+
44
+ | Feature | Description |
45
+ |---|---|
46
+ | 🧹 **Brain Health Clean-up** | New **Fix Issues** button in the Mind Palace Dashboard's Brain Health card — detects orphaned handoffs, missing embeddings, and stale rollups, then cleans them up in one click without needing the MCP tool. |
47
+ | 👤 **Agent Identity Settings** | Dashboard Settings → Agent Identity panel lets you set a **Default Role** (`dev`, `qa`, `pm`…) and **Agent Name** (e.g. `Dmitri`). Both values auto-apply as fallbacks in all memory and Hivemind tools — no need to pass them per call. |
48
+ | 📜 **Role-Scoped Skills** | Each agent role can have its own persistent skill/rules document stored in the dashboard (⚙️ Settings → Skills). It is automatically injected into every `session_load_context` response so the agent boots with its rules pre-loaded. |
49
+ | 🔤 **Resource Formatting Fix** | `memory://{project}/handoff` resources now render as formatted plain text (Last Summary, TODOs, Keywords) instead of a raw JSON blob — readable in Claude Desktop's paperclip attach panel. |
50
+
51
+ <details>
52
+ <summary><strong>What's in v3.0.0 — Agent Hivemind 🐝</strong></summary>
53
+
54
+ | Feature | Description |
55
+ |---|---|
56
+ | 🐝 **Role-Scoped Memory** | Optional `role` parameter on ledger, handoff, and context loading — each agent role (dev, qa, pm, lead, security, ux) gets its own isolated memory lane within a project. Defaults to `'global'` for full backward compatibility. |
57
+ | 👥 **Agent Registry** | New `agent_register`, `agent_heartbeat`, `agent_list_team` tools — agents announce their presence, pulse their status, and discover who else is working on the team. Stale agents are auto-pruned after 30 minutes. |
58
+ | 🎯 **Team Roster Injection** | When loading context with a role, Prism automatically injects a "Team Roster" showing active teammates, their roles, current tasks, and last heartbeat — true multi-agent awareness without extra tool calls. |
59
+ | ⚙️ **Dashboard Settings** | New Settings modal with runtime toggles (auto-capture, theme, context depth) backed by a persistent `system_settings` key-value store. Environment variables override DB settings for safety. |
60
+ | 📡 **Hivemind Radar** | New dashboard widget showing active agents, their roles (with icons), current tasks, and heartbeat timestamps — a real-time team coordination dashboard. |
61
+ | 🔒 **Conditional Tool Registration** | `PRISM_ENABLE_HIVEMIND` env var gates Hivemind tools — users who don't need multi-agent features keep the same lean tool count as v2.x. |
62
+ | ✅ **Test Suite** | 58 tests across 4 suites (storage, tools, dashboard, load) with Vitest — includes concurrent write stress tests, role isolation verification, and 0.2ms/write performance benchmarks. |
63
+
64
+ </details>
65
+
66
+
67
+ <details>
68
+ <summary><strong>What's in v2.5.0 — Enterprise Memory 🏗️</strong></summary>
41
69
 
42
70
  | Feature | Description |
43
71
  |---|---|
@@ -46,6 +74,8 @@
46
74
  | 🔗 **LangChain Integration (Phase 3)** | `PrismMemoryRetriever` and `PrismKnowledgeRetriever` — async-first `BaseRetriever` subclasses that wrap Prism MCP's traced search endpoints. Trace metadata flows automatically into `Document.metadata["trace"]` for LangSmith visibility. |
47
75
  | 🧩 **LangGraph Research Agent** | Full example in `examples/langgraph-agent/` — a 5-node agentic research loop with MCP bridge, persistent memory, and `EnsembleRetriever` hybrid search. |
48
76
 
77
+ </details>
78
+
49
79
  <details>
50
80
  <summary><strong>What's in v2.5.1 — Version Sync & Embedding Safety</strong></summary>
51
81
 
@@ -86,7 +116,7 @@
86
116
  | Feature | Description |
87
117
  |---|---|
88
118
  | 🩺 **Brain Health Check** | `session_health_check` — like Unix `fsck` for your agent's memory. Detects missing embeddings, duplicate entries, orphaned handoffs, and stale rollups. Use `auto_fix: true` to repair automatically. |
89
- | 📊 **Mind Palace Health** | Brain health indicator on the Mind Palace Dashboard — see your memory integrity at a glance. |
119
+ | 📊 **Mind Palace Health** | Brain health indicator on the Mind Palace Dashboard — see your memory integrity at a glance. **🧹 Fix Issues** button auto-deletes orphaned handoffs in one click. |
90
120
 
91
121
  </details>
92
122
 
@@ -221,11 +251,15 @@ Open **`http://localhost:3000`** in your browser to see exactly what your AI age
221
251
  ![Mind Palace Dashboard](docs/mind-palace-dashboard.png)
222
252
 
223
253
  - **Current State & TODOs** — See the exact context injected into the LLM's prompt
254
+ - **Agent Identity Chip** — Header shows your active role + name (e.g. `🛠️ dev · Antigravity`); click to open Settings
255
+ - **Brain Health 🩺** — Memory integrity status at a glance; **🧹 Fix Issues** button auto-cleans orphaned handoffs in one click
224
256
  - **Git Drift Detection** — Alerts you if you've modified code outside the agent's view
225
257
  - **Morning Briefing** — AI-synthesized action plan from your last sessions
226
258
  - **Time Travel Timeline** — Browse historical handoff states and revert any version
227
259
  - **Visual Memory Vault** — Browse UI screenshots and auto-captured HTML states
228
260
  - **Session Ledger** — Full audit trail of every decision your agent has made
261
+ - **Neural Graph** — Force-directed visualization of project ↔ keyword associations
262
+ - **Hivemind Radar** — Real-time active agent roster with role, task, and heartbeat
229
263
 
230
264
  The dashboard auto-discovers all your projects and updates in real time.
231
265
 
@@ -447,7 +481,15 @@ graph TB
447
481
 
448
482
  | Tool | Purpose | Key Args | Returns |
449
483
  |------|---------|----------|---------|
450
- | `session_health_check` | Scan brain for integrity issues (`fsck`) | `auto_fix` (boolean) | Health report & auto-repairs |
484
+ | `session_health_check` | Scan brain for integrity issues (`fsck`) | `project`, `auto_fix` (boolean) | Health report & auto-repairs |
485
+
486
+ The **Mind Palace Dashboard** also shows a live **Brain Health 🩺** card for every project:
487
+
488
+ - **Status indicator** — `✅ Healthy` or `⚠️ Issues detected` with entry/handoff/rollup counts
489
+ - **🧹 Fix Issues button** — appears automatically when issues are detected; click to clean up orphaned handoffs and stale rollups in one click, no MCP tool call required
490
+ - **No issues found** — shown in green when memory integrity is confirmed
491
+
492
+ The tool and dashboard button both call the same repair logic — the dashboard button is simply a zero-friction shortcut for common maintenance.
451
493
 
452
494
  ### v2.5 Enterprise Memory Tools
453
495
 
@@ -476,6 +518,110 @@ Instead of writing custom JavaScript, pass a `template` name for instant extract
476
518
 
477
519
  ---
478
520
 
521
+ ## Agent Hivemind — Role Usage
522
+
523
+ Role-scoped memory lets multiple agents work on the same project without stepping on each other's memory. Each role gets its own isolated memory lane. Defaults to `global` for full backward compatibility.
524
+
525
+ ### Available Roles
526
+
527
+ | Role | Use for |
528
+ |------|---------|
529
+ | `dev` | Development agent |
530
+ | `qa` | Testing / QA agent |
531
+ | `pm` | Product management |
532
+ | `lead` | Tech lead / orchestrator |
533
+ | `security` | Security review |
534
+ | `ux` | Design / UX |
535
+ | `global` | Default — shared, no isolation |
536
+
537
+ Custom role strings are also supported (e.g. `"docs"`, `"ml"`).
538
+
539
+ ### Using Roles with Memory Tools
540
+
541
+ Just add `"role"` to any of the core memory tools:
542
+
543
+ ```json
544
+ // Save a ledger entry as the "dev" agent
545
+ { "name": "session_save_ledger", "arguments": {
546
+ "project": "my-app",
547
+ "role": "dev",
548
+ "conversation_id": "abc123",
549
+ "summary": "Fixed the auth race condition"
550
+ }}
551
+
552
+ // Load context scoped to your role
553
+ // Also injects a Team Roster showing active teammates
554
+ { "name": "session_load_context", "arguments": {
555
+ "project": "my-app",
556
+ "role": "dev",
557
+ "level": "standard"
558
+ }}
559
+
560
+ // Save handoff as the "qa" agent
561
+ { "name": "session_save_handoff", "arguments": {
562
+ "project": "my-app",
563
+ "role": "qa",
564
+ "last_summary": "Ran regression suite — 2 failures in auth module"
565
+ }}
566
+ ```
567
+
568
+ ### Hivemind Coordination Tools
569
+
570
+ > **Requires:** `PRISM_ENABLE_HIVEMIND=true` (Boot Setting — restart required)
571
+
572
+ ```json
573
+ // Announce yourself to the team at session start
574
+ { "name": "agent_register", "arguments": {
575
+ "project": "my-app",
576
+ "role": "dev",
577
+ "agent_name": "Dev Agent #1",
578
+ "current_task": "Refactoring auth module"
579
+ }}
580
+
581
+ // Pulse every ~5 min to stay visible (agents pruned after 30 min)
582
+ { "name": "agent_heartbeat", "arguments": {
583
+ "project": "my-app",
584
+ "role": "dev",
585
+ "current_task": "Now writing tests"
586
+ }}
587
+
588
+ // See everyone on the team
589
+ { "name": "agent_list_team", "arguments": {
590
+ "project": "my-app"
591
+ }}
592
+ ```
593
+
594
+ ### How Role Isolation Works
595
+
596
+ - `session_load_context` with `role: "dev"` only sees entries saved with `role: "dev"`
597
+ - The `global` role is a shared pool — anything saved without a role goes here
598
+ - When loading *with* a role, Prism auto-injects a **Team Roster** block listing active teammates, roles, and tasks — no extra tool call needed
599
+ - The Hivemind Radar widget in the Mind Palace dashboard shows agent activity in real time
600
+
601
+ ### Setting Your Agent Identity
602
+
603
+ The easiest way to configure your role and name is via the **Mind Palace Dashboard ⚙️ Settings → Agent Identity**:
604
+
605
+ - **Default Role** — dropdown to select `dev`, `qa`, `pm`, `lead`, `security`, `ux`, or `global`
606
+ - **Agent Name** — free text for your display name (e.g. `Dmitri`, `Dev Alex`, `QA Bot`)
607
+
608
+ Once set, **all memory and Hivemind tools automatically use these values** as fallbacks — no need to pass `role` or `agent_name` in every tool call.
609
+
610
+ > **Priority order:** explicit tool arg → dashboard setting → `"global"` (default)
611
+
612
+ **Alternative — hardcode in your startup rules** (if you prefer prompt-level config):
613
+
614
+ ```markdown
615
+ ## Prism MCP Memory Auto-Load (CRITICAL)
616
+ At the start of every new session, call session_load_context with:
617
+ - project: "my-app", role: "dev"
618
+ - project: "my-other-project", role: "dev"
619
+ ```
620
+
621
+ > **Tip:** For true multi-agent setups, each AI instance has its own Mind Palace dashboard — set a different identity per agent there rather than managing it in prompts.
622
+
623
+ ---
624
+
479
625
  ## LangChain / LangGraph Integration
480
626
 
481
627
  Prism MCP includes first-class Python adapters for the LangChain ecosystem, located in `examples/langgraph-agent/`:
@@ -528,7 +674,8 @@ The retrievers use `_aget_relevant_documents` as the primary path with `asyncio.
528
674
  | Variable | Required | Description |
529
675
  |----------|----------|-------------|
530
676
  | `BRAVE_API_KEY` | No | Brave Search Pro API key (enables web/local search tools) |
531
- | `PRISM_STORAGE` | No | `"local"` (default) or `"supabase"` |
677
+ | `PRISM_STORAGE` | No | `"local"` (default) or `"supabase"` — **requires restart** |
678
+ | `PRISM_ENABLE_HIVEMIND` | No | Set `"true"` to enable multi-agent Hivemind tools — **requires restart** |
532
679
  | `GOOGLE_API_KEY` | No | Google AI / Gemini — enables paper analysis, Morning Briefings, compaction |
533
680
  | `BRAVE_ANSWERS_API_KEY` | No | Separate Brave Answers key for AI-grounded answers |
534
681
  | `SUPABASE_URL` | If cloud mode | Supabase project URL |
@@ -540,6 +687,39 @@ The retrievers use `_aget_relevant_documents` as the primary path with `asyncio.
540
687
 
541
688
  ---
542
689
 
690
+ ## ⚡ Boot Settings (Restart Required)
691
+
692
+ Some settings affect how Prism **initializes at startup** and cannot be changed at runtime. Prism stores these in a lightweight, dedicated SQLite database (`~/.prism-mcp/prism-config.db`) that is read **before** the main storage backend is selected — solving the chicken-and-egg problem of needing config before the config store is ready.
693
+
694
+ > **⚠️ You must restart the Prism MCP server after changing any Boot Setting.** The Mind Palace dashboard labels these with a **"Restart Required"** badge.
695
+
696
+ | Setting | Dashboard Control | Environment Override | Description |
697
+ |---------|------------------|---------------------|-------------|
698
+ | `PRISM_STORAGE` | ⚙️ Storage Backend dropdown | `PRISM_STORAGE=supabase` | Switch between `local` (SQLite) and `supabase` (cloud) |
699
+ | `PRISM_ENABLE_HIVEMIND` | ⚙️ Hivemind Mode toggle | `PRISM_ENABLE_HIVEMIND=true` | Enable/disable multi-agent coordination tools |
700
+
701
+ ### How Boot Settings Work
702
+
703
+ 1. **Dashboard saves the setting** → written to `~/.prism-mcp/prism-config.db` immediately
704
+ 2. **You restart the MCP server** → server reads the config DB at startup, selects backend/features
705
+ 3. **Environment variables always win** → if `PRISM_STORAGE` is set in your MCP config JSON, it overrides the dashboard value
706
+
707
+ ```
708
+ Priority: env var in MCP config JSON > Dashboard (prism-config.db) > default (local)
709
+ ```
710
+
711
+ ### Runtime Settings (no restart needed)
712
+
713
+ These settings take effect immediately without a restart:
714
+
715
+ | Setting | Description |
716
+ |---------|-------------|
717
+ | Dashboard Theme | Visual theme for the Mind Palace (`dark`, `midnight`, `purple`) |
718
+ | Context Depth | Default level for `session_load_context` (`quick`, `standard`, `deep`) |
719
+ | Auto-Capture HTML | Snapshot local dev server HTML on every handoff save |
720
+
721
+ ---
722
+
543
723
  ## Progressive Context Loading
544
724
 
545
725
  Load only what you need — saves tokens and speeds up boot:
@@ -880,6 +1060,7 @@ See [`vertex-ai/`](vertex-ai/) for setup and benchmarks.
880
1060
  │ │ ├── interface.ts # StorageBackend abstraction (+ GDPR delete methods)
881
1061
  │ │ ├── sqlite.ts # SQLite local storage (libSQL + F32_BLOB + deleted_at migration)
882
1062
  │ │ ├── supabase.ts # Supabase cloud storage (+ soft/hard delete)
1063
+ │ │ ├── configStorage.ts # Boot config micro-DB (~/.prism-mcp/prism-config.db)
883
1064
  │ │ └── index.ts # Backend factory (auto-selects based on PRISM_STORAGE)
884
1065
  │ ├── sync/
885
1066
  │ │ ├── interface.ts # SyncBus abstraction (Telepathy)
@@ -928,10 +1109,19 @@ See [`vertex-ai/`](vertex-ai/) for setup and benchmarks.
928
1109
 
929
1110
  > **[View the full project board →](https://github.com/users/dcostenco/projects/1/views/1)**
930
1111
 
1112
+ ### ✅ v3.0.1 — Agent Identity & Brain Clean-up (Shipped!)
1113
+
1114
+ See [What's New in v3.0.1](#whats-new-in-v301---agent-identity--brain-clean-up-) above.
1115
+
1116
+ ### ✅ v3.0 — Agent Hivemind (Shipped!)
1117
+
1118
+ See [What's New in v3.0.0 — Agent Hivemind](#whats-new-in-v300---agent-hivemind-) above.
1119
+
931
1120
  ### 🚀 Future Ideas
932
1121
 
933
1122
  | Feature | Issue | Description |
934
1123
  |---------|-------|-------------|
1124
+ | **Role-Scoped Skills & Rules** | — | Each agent role (`dev`, `qa`, `pm`, etc.) gets its own persistent skill/rules document. Preloaded automatically at session start via `session_load_context`. Skills editable and uploadable from the Mind Palace Dashboard (⚙️ → Skills tab per role). Stored in `configStorage` per-role key — backend already exists. |
935
1125
  | OpenTelemetry SDK Integration | [#6](https://github.com/dcostenco/prism-mcp/issues/6) | W3C-compliant tracing with Jaeger/Zipkin export |
936
1126
  | GDPR Right to Portability | [#7](https://github.com/dcostenco/prism-mcp/issues/7) | `session_export_memory` tool for Art. 20 compliance |
937
1127
  | Multi-agent CRDT Conflict Resolution | [#9](https://github.com/dcostenco/prism-mcp/issues/9) | Conflict-free replicated data types for concurrent agent edits |
package/dist/config.js CHANGED
@@ -106,6 +106,14 @@ export const PRISM_CAPTURE_PORTS = (process.env.PRISM_CAPTURE_PORTS || "3000,300
106
106
  // Optionally enable verbose output (stderr) for Prism initialization,
107
107
  // memory indexing, and background tasks.
108
108
  export const PRISM_DEBUG_LOGGING = process.env.PRISM_DEBUG_LOGGING === "true";
109
+ // ─── v3.0: Agent Hivemind Feature Flag ───────────────────────
110
+ // When enabled, registers 3 additional MCP tools for multi-agent
111
+ // coordination: agent_register, agent_heartbeat, agent_list_team.
112
+ // The role parameter on existing tools (session_save_ledger, etc.)
113
+ // is always available regardless of this flag — adding a parameter
114
+ // doesn't increase tool count.
115
+ // Set PRISM_ENABLE_HIVEMIND=true to unlock the Agent Registry tools.
116
+ export const PRISM_ENABLE_HIVEMIND = process.env.PRISM_ENABLE_HIVEMIND === "true";
109
117
  if (PRISM_AUTO_CAPTURE) {
110
118
  // Use console.error instead of debugLog here to prevent circular dependency
111
119
  if (PRISM_DEBUG_LOGGING) {
@@ -21,7 +21,17 @@ import { exec } from "child_process";
21
21
  import { getStorage } from "../storage/index.js";
22
22
  import { PRISM_USER_ID, SERVER_CONFIG } from "../config.js";
23
23
  import { renderDashboardHTML } from "./ui.js";
24
+ import { getAllSettings, setSetting } from "../storage/configStorage.js";
24
25
  const PORT = parseInt(process.env.PRISM_DASHBOARD_PORT || "3000", 10);
26
+ /** Read HTTP request body as string */
27
+ function readBody(req) {
28
+ return new Promise((resolve, reject) => {
29
+ let data = "";
30
+ req.on("data", chunk => { data += chunk; });
31
+ req.on("end", () => resolve(data));
32
+ req.on("error", reject);
33
+ });
34
+ }
25
35
  /**
26
36
  * Kill any existing process holding the dashboard port.
27
37
  * This prevents zombie dashboard processes from surviving IDE restarts
@@ -65,12 +75,12 @@ async function killPortHolder(port) {
65
75
  }
66
76
  export async function startDashboardServer() {
67
77
  // Clean up any zombie dashboard process from a previous session
68
- killPortHolder(PORT);
78
+ await killPortHolder(PORT);
69
79
  const storage = await getStorage();
70
80
  const httpServer = http.createServer(async (req, res) => {
71
81
  // CORS headers for local dev
72
82
  res.setHeader("Access-Control-Allow-Origin", "*");
73
- res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
83
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
74
84
  res.setHeader("Access-Control-Allow-Headers", "Content-Type");
75
85
  if (req.method === "OPTIONS") {
76
86
  res.writeHead(204);
@@ -116,7 +126,7 @@ export async function startDashboardServer() {
116
126
  return res.end(JSON.stringify({ context, ledger, history }));
117
127
  }
118
128
  // ─── API: Brain Health Check (v2.2.0) ───
119
- if (url.pathname === "/api/health") {
129
+ if (url.pathname === "/api/health" && req.method === "GET") {
120
130
  try {
121
131
  const { runHealthCheck } = await import("../utils/healthCheck.js");
122
132
  const stats = await storage.getHealthStats(PRISM_USER_ID);
@@ -137,6 +147,78 @@ export async function startDashboardServer() {
137
147
  }));
138
148
  }
139
149
  }
150
+ // ─── API: Brain Health Cleanup (v3.1) ───
151
+ // Deletes orphaned handoffs (handoffs with no backing ledger entries).
152
+ if (url.pathname === "/api/health/cleanup" && req.method === "POST") {
153
+ try {
154
+ const { runHealthCheck } = await import("../utils/healthCheck.js");
155
+ const stats = await storage.getHealthStats(PRISM_USER_ID);
156
+ const report = runHealthCheck(stats);
157
+ // Collect orphaned handoff projects from the health issues
158
+ const orphaned = stats.orphanedHandoffs || [];
159
+ const cleaned = [];
160
+ for (const { project } of orphaned) {
161
+ try {
162
+ await storage.deleteHandoff(project, PRISM_USER_ID);
163
+ cleaned.push(project);
164
+ console.error(`[Dashboard] Cleaned up orphaned handoff: ${project}`);
165
+ }
166
+ catch (delErr) {
167
+ console.error(`[Dashboard] Failed to delete handoff for ${project}:`, delErr);
168
+ }
169
+ }
170
+ res.writeHead(200, { "Content-Type": "application/json" });
171
+ return res.end(JSON.stringify({
172
+ ok: true,
173
+ cleaned,
174
+ count: cleaned.length,
175
+ message: cleaned.length > 0
176
+ ? `Cleaned up ${cleaned.length} orphaned handoff(s): ${cleaned.join(", ")}`
177
+ : "No orphaned handoffs to clean up.",
178
+ }));
179
+ }
180
+ catch (err) {
181
+ console.error("[Dashboard] Health cleanup error:", err);
182
+ res.writeHead(500, { "Content-Type": "application/json" });
183
+ return res.end(JSON.stringify({ ok: false, error: "Cleanup failed" }));
184
+ }
185
+ }
186
+ // ─── API: Role-Scoped Skills (v3.1) ───
187
+ // GET /api/skills → { skills: { dev: "...", qa: "..." } }
188
+ if (url.pathname === "/api/skills" && req.method === "GET") {
189
+ const all = await getAllSettings();
190
+ const skills = {};
191
+ for (const [k, v] of Object.entries(all)) {
192
+ if (k.startsWith("skill:") && v) {
193
+ skills[k.replace("skill:", "")] = v;
194
+ }
195
+ }
196
+ res.writeHead(200, { "Content-Type": "application/json" });
197
+ return res.end(JSON.stringify({ skills }));
198
+ }
199
+ // POST /api/skills → { role, content } saves skill:<role>
200
+ if (url.pathname === "/api/skills" && req.method === "POST") {
201
+ const body = await new Promise(resolve => {
202
+ let data = "";
203
+ req.on("data", c => data += c);
204
+ req.on("end", () => resolve(data));
205
+ });
206
+ const { role, content } = JSON.parse(body || "{}");
207
+ if (!role) {
208
+ res.writeHead(400);
209
+ return res.end(JSON.stringify({ error: "role required" }));
210
+ }
211
+ await setSetting(`skill:${role}`, content || "");
212
+ res.writeHead(200, { "Content-Type": "application/json" });
213
+ return res.end(JSON.stringify({ ok: true, role }));
214
+ }
215
+ // DELETE /api/skills/:role → clears skill:<role>
216
+ if (url.pathname.startsWith("/api/skills/") && req.method === "DELETE") {
217
+ const role = url.pathname.replace("/api/skills/", "");
218
+ await setSetting(`skill:${role}`, "");
219
+ res.writeHead(200, { "Content-Type": "application/json" });
220
+ return res.end(JSON.stringify({ ok: true, role }));
221
+ }
140
222
  // ─── API: Knowledge Graph Data (v2.3.0) ───
141
223
  if (url.pathname === "/api/graph") {
142
224
  // Fetch recent ledger entries to build the graph
@@ -199,6 +281,55 @@ export async function startDashboardServer() {
199
281
  res.writeHead(200, { "Content-Type": "application/json" });
200
282
  return res.end(JSON.stringify({ nodes, edges }));
201
283
  }
284
+ // ─── API: Hivemind Team Roster (v3.0) ───
285
+ if (url.pathname === "/api/team") {
286
+ const projectName = url.searchParams.get("project");
287
+ if (!projectName) {
288
+ res.writeHead(400, { "Content-Type": "application/json" });
289
+ return res.end(JSON.stringify({ error: "Missing ?project= parameter" }));
290
+ }
291
+ try {
292
+ const team = await storage.listTeam(projectName, PRISM_USER_ID);
293
+ res.writeHead(200, { "Content-Type": "application/json" });
294
+ return res.end(JSON.stringify({ team }));
295
+ }
296
+ catch {
297
+ res.writeHead(200, { "Content-Type": "application/json" });
298
+ return res.end(JSON.stringify({ team: [] }));
299
+ }
300
+ }
301
+ // ─── API: Settings — GET (v3.0 Dashboard Settings) ───
302
+ if (url.pathname === "/api/settings" && req.method === "GET") {
303
+ try {
304
+ const { getAllSettings } = await import("../storage/configStorage.js");
305
+ const settings = await getAllSettings();
306
+ res.writeHead(200, { "Content-Type": "application/json" });
307
+ return res.end(JSON.stringify({ settings }));
308
+ }
309
+ catch {
310
+ res.writeHead(200, { "Content-Type": "application/json" });
311
+ return res.end(JSON.stringify({ settings: {} }));
312
+ }
313
+ }
314
+ // ─── API: Settings — POST (v3.0 Dashboard Settings) ───
315
+ if (url.pathname === "/api/settings" && req.method === "POST") {
316
+ try {
317
+ const body = await readBody(req);
318
+ const parsed = JSON.parse(body);
319
+ if (parsed.key && parsed.value !== undefined) {
320
+ const { setSetting } = await import("../storage/configStorage.js");
321
+ await setSetting(parsed.key, String(parsed.value));
322
+ res.writeHead(200, { "Content-Type": "application/json" });
323
+ return res.end(JSON.stringify({ ok: true, key: parsed.key, value: parsed.value }));
324
+ }
325
+ res.writeHead(400, { "Content-Type": "application/json" });
326
+ return res.end(JSON.stringify({ error: "Missing key or value" }));
327
+ }
328
+ catch (err) {
329
+ res.writeHead(400, { "Content-Type": "application/json" });
330
+ return res.end(JSON.stringify({ error: "Invalid JSON body" }));
331
+ }
332
+ }
202
333
  // ─── 404 ───
203
334
  res.writeHead(404, { "Content-Type": "text/plain" });
204
335
  res.end("Not found");