import {
  buildCitationGuidance
} from "./chunk-IQT3XTKW.js";
import {
  EngramAccessInputError
} from "./chunk-DR7MCMPS.js";
import {
  expandTildePath
} from "./chunk-IXEJRKCZ.js";
import {
  validateBriefingFormat
} from "./chunk-SS253RXF.js";
import {
  readEnvVar
} from "./chunk-MARWOCVP.js";
import {
  validateRequest
} from "./chunk-RILIVK4O.js";

// src/access-mcp.ts
import { readFile } from "fs/promises";
import { randomUUID } from "crypto";
var MCP_PROTOCOL_VERSION = "2024-11-05";
var LEGACY_MCP_PREFIX = "engram.";
var CANONICAL_MCP_PREFIX = "remnic.";
function toCanonicalToolName(name) {
  return name.startsWith(LEGACY_MCP_PREFIX) ? `${CANONICAL_MCP_PREFIX}${name.slice(LEGACY_MCP_PREFIX.length)}` : name;
}
function toLegacyToolName(name) {
  return name.startsWith(CANONICAL_MCP_PREFIX) ? `${LEGACY_MCP_PREFIX}${name.slice(CANONICAL_MCP_PREFIX.length)}` : name;
}
function withToolAliases(tool) {
  const canonicalName = toCanonicalToolName(tool.name);
  const canonicalTool = canonicalName === tool.name ? tool : { ...tool, name: canonicalName };
  if (canonicalName === tool.name) return [canonicalTool];
  return [canonicalTool, tool];
}
var STRICT_MCP_SCHEMA_KEYS = {
  capsuleExport: [
    "name",
    "namespace",
    "since",
    "includeKinds",
    "peerIds",
    "includeTranscripts",
    "encrypt"
  ],
  capsuleImport: ["archivePath", "namespace", "mode"],
  capsuleList: ["namespace"]
};
function parseMcpRequest(schemaName, args) {
  const allowedKeys = STRICT_MCP_SCHEMA_KEYS[schemaName];
  if (allowedKeys) {
    const allowed = new Set(allowedKeys);
    const unexpected = Object.keys(args).filter((key) => !allowed.has(key));
    if (unexpected.length > 0) {
      throw new EngramAccessInputError(
        `request validation failed: (root): Unrecognized key(s) in object: ${unexpected.join(", ")}`
      );
    }
  }
  const validation = validateRequest(schemaName, args);
  if (validation.success) return validation.data;
  const details = validation.error.details.map((detail) => `${detail.field}: ${detail.message}`).join("; ");
  throw new EngramAccessInputError(
    details.length > 0 ? `${validation.error.error}: ${details}` : validation.error.error
  );
}
async function getMcpServerVersion() {
  const envVersion = readEnvVar("OPENCLAW_ENGRAM_VERSION")?.trim() || readEnvVar("npm_package_version")?.trim();
  if (envVersion) return envVersion;
  try {
    const pkgPath = new URL("../package.json", import.meta.url);
    const raw = await readFile(pkgPath, "utf-8");
    const parsed = JSON.parse(raw);
    return parsed.version?.trim() || "unknown";
  } catch {
    return "unknown";
  }
}
var EngramMcpServer = class {
  constructor(service, options = {}) {
    this.service = service;
    this.citationsEnabled = options.citationsEnabled === true;
    this.citationsAutoDetect = options.citationsAutoDetect !== false;
    this.authenticatedPrincipal = options.principal?.trim() || readEnvVar("OPENCLAW_ENGRAM_ACCESS_PRINCIPAL")?.trim() || void 0;
    this.tools = [
      {
        name: "engram.recall",
        description: "Recall Engram context for a query.",
        inputSchema: {
          type: "object",
          properties: {
            query: { type: "string" },
            sessionKey: { type: "string" },
            namespace: { type: "string" },
            topK: { type: "number" },
            mode: { type: "string", enum: ["auto", "no_recall", "minimal", "full", "graph_mode"] },
            includeDebug: { type: "boolean" },
            // Recall disclosure depth (issue #677).  Default `chunk` when
            // omitted.  Section/raw payload shaping ships in PR 2; this PR
            // wires the field end-to-end so clients can already pass it
            // without it being silently dropped.
            disclosure: { type: "string", enum: ["chunk", "section", "raw"] },
            cwd: { type: "string", description: "Working directory for auto git-context resolution." },
            projectTag: { type: "string", description: "Project tag for non-git project scoping (e.g. 'blend-supply')." },
            asOf: {
              type: "string",
              description: "Historical recall pin (issue #680). ISO 8601 timestamp; when set, the recall returns the corpus as it existed at this instant."
            },
            tags: {
              type: "array",
              items: { type: "string" },
              description: "Filter recall results to memories whose frontmatter tags match (issue #689)."
            },
            tagMatch: {
              type: "string",
              enum: ["any", "all"],
              description: "Tag-filter match mode. 'any' (default) admits results with at least one filter tag; 'all' requires every filter tag."
            }
          },
          required: ["query"],
          additionalProperties: false
        }
      },
      {
        name: "engram.recall_explain",
        description: "Return the last recall snapshot for a session or the most recent one.",
        inputSchema: {
          type: "object",
          properties: {
            sessionKey: { type: "string" },
            namespace: { type: "string" }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.set_coding_context",
        description: "Attach a coding-agent context (project / branch) to a session so recall routes to a project- / branch-scoped namespace (issue #569). For MCP clients that do not ship cwd automatically (Cursor, generic agents, etc.). Also aliased as remnic.set_coding_context. Pass codingContext: null to clear. Alternatively, pass just a projectTag for non-git project scoping (e.g. OpenClaw channels).",
        inputSchema: {
          type: "object",
          properties: {
            sessionKey: {
              type: "string",
              description: "Session identifier the context should attach to."
            },
            codingContext: {
              anyOf: [
                { type: "null" },
                {
                  type: "object",
                  properties: {
                    projectId: { type: "string", description: "Stable project id (origin:<hex> or root:<hex>)." },
                    branch: { type: ["string", "null"], description: "Current branch, or null in detached HEAD." },
                    rootPath: { type: "string", description: "Absolute path to the repo root." },
                    defaultBranch: { type: ["string", "null"], description: "Default branch (usually main/master), or null when unknown." }
                  },
                  required: ["projectId", "branch", "rootPath", "defaultBranch"],
                  additionalProperties: false
                }
              ],
              description: "The context to attach, or null to clear. Omit when using projectTag instead."
            },
            projectTag: {
              type: "string",
              description: "Arbitrary project tag for non-git project scoping (e.g. 'blend-supply'). Creates a coding context with projectId 'tag:<projectTag>'. Use instead of codingContext when the session isn't tied to a specific git repo."
            }
          },
          required: ["sessionKey"],
          additionalProperties: false
        }
      },
      {
        name: "engram.recall_tier_explain",
        description: "Return a structured tier-explain payload for the last direct-answer-eligible recall (issue #518). Orthogonal to engram.recall_explain, which returns a graph-path explanation.",
        inputSchema: {
          type: "object",
          properties: {
            sessionKey: {
              type: "string",
              description: "Optional session key. Omit to read the most recent snapshot."
            },
            namespace: {
              type: "string",
              description: "Optional namespace to scope the returned snapshot."
            }
          },
          additionalProperties: false
        }
      },
      {
        // Registered as `engram.recall_xray`; `withToolAliases` below
        // emits the canonical `remnic.recall_xray` alias automatically
        // (dual-naming invariant for every new MCP tool).
        name: "engram.recall_xray",
        description: "Run a recall with X-ray capture enabled and return the unified per-result attribution snapshot (tier + audit + MMR + filters in one view). Issue #570.",
        inputSchema: {
          type: "object",
          properties: {
            query: {
              type: "string",
              description: "Query to recall against. Required; non-empty."
            },
            sessionKey: {
              type: "string",
              description: "Optional session key to scope the recall."
            },
            namespace: {
              type: "string",
              description: "Optional namespace. Enforced against the caller's principal; a mismatch yields snapshotFound:false."
            },
            budget: {
              type: "integer",
              minimum: 1,
              description: "Optional positive-integer override for the recall character budget."
            },
            disclosure: {
              type: "string",
              enum: ["chunk", "section", "raw"],
              description: "Optional disclosure depth for X-ray telemetry (issue #677). When set, populates the per-disclosure token-spend summary on each result."
            }
          },
          required: ["query"],
          additionalProperties: false
        }
      },
      {
        name: "engram.day_summary",
        description: "Generate a structured end-of-day summary. When memories is omitted or empty, auto-gathers today's facts and hourly summaries from storage.",
        inputSchema: {
          type: "object",
          properties: {
            memories: { type: "string" },
            sessionKey: { type: "string" },
            namespace: { type: "string" }
          },
          required: [],
          additionalProperties: false
        }
      },
      {
        name: "engram.capsule_export",
        description: "Export a portable Remnic capsule archive from the namespace-scoped memory store.",
        inputSchema: {
          type: "object",
          properties: {
            name: {
              type: "string",
              description: "Capsule id (alphanumeric with single dashes, max 64 characters)."
            },
            namespace: { type: "string" },
            since: {
              type: "string",
              description: "Only include files modified on or after this ISO 8601 timestamp."
            },
            includeKinds: {
              type: "array",
              items: { type: "string" },
              description: "Optional top-level directory allow-list."
            },
            peerIds: {
              type: "array",
              items: { type: "string" },
              description: "Optional peer id allow-list for the peers/ subtree."
            },
            includeTranscripts: { type: "boolean" },
            encrypt: { type: "boolean" }
          },
          required: ["name"],
          additionalProperties: false
        }
      },
      {
        name: "engram.capsule_import",
        description: "Import a Remnic capsule archive into the namespace-scoped memory store.",
        inputSchema: {
          type: "object",
          properties: {
            archivePath: {
              type: "string",
              description: "Path to a .capsule.json.gz or .capsule.json.gz.enc archive."
            },
            namespace: { type: "string" },
            mode: {
              type: "string",
              enum: ["skip", "overwrite", "fork"],
              description: "Conflict handling mode. Defaults to skip."
            }
          },
          required: ["archivePath"],
          additionalProperties: false
        }
      },
      {
        name: "engram.capsule_list",
        description: "List capsule archives in the namespace-scoped capsule store.",
        inputSchema: {
          type: "object",
          properties: {
            namespace: { type: "string" }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_governance_run",
        description: "Run Remnic memory governance in a bounded shadow/apply pass.",
        inputSchema: {
          type: "object",
          properties: {
            namespace: { type: "string" },
            mode: { type: "string", enum: ["shadow", "apply"] },
            recentDays: { type: "number" },
            maxMemories: { type: "number" },
            batchSize: { type: "number" }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.procedure_mining_run",
        description: "Run procedural memory mining from causal trajectories (issue #519). Respects procedural.enabled; writes under procedures/ when clusters qualify.",
        inputSchema: {
          type: "object",
          properties: {
            namespace: { type: "string" }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.pattern_reinforcement_run",
        description: "Run the pattern-reinforcement maintenance job (issue #687 PR 2/4). Clusters duplicate non-procedural memories by normalized content, promotes the most-recent member to canonical, and supersedes the older duplicates. Gated on patternReinforcementEnabled and the patternReinforcementCadenceMs floor \u2014 pass force=true to bypass the cadence for an ad-hoc operator run.",
        inputSchema: {
          type: "object",
          properties: {
            namespace: { type: "string" },
            force: { type: "boolean" }
          },
          additionalProperties: false
        }
      },
      {
        // The canonical `remnic.procedural_stats` alias is added automatically
        // by `withToolAliases` — the dual-naming invariant keeps both names
        // alive for the legacy surface.
        name: "engram.procedural_stats",
        description: "Procedural memory stats (issue #567): counts by status, recent write activity, and the active procedural.* config. Read-only, namespace-scoped.",
        inputSchema: {
          type: "object",
          properties: {
            namespace: { type: "string" }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_get",
        description: "Fetch one Remnic memory by id.",
        inputSchema: {
          type: "object",
          properties: {
            memoryId: { type: "string" },
            namespace: { type: "string" }
          },
          required: ["memoryId"],
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_timeline",
        description: "Fetch one Remnic memory timeline by id.",
        inputSchema: {
          type: "object",
          properties: {
            memoryId: { type: "string" },
            namespace: { type: "string" },
            limit: { type: "number" }
          },
          required: ["memoryId"],
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_store",
        description: "Store an explicit Remnic memory through the access layer.",
        inputSchema: {
          type: "object",
          properties: {
            schemaVersion: { type: "number" },
            idempotencyKey: { type: "string" },
            dryRun: { type: "boolean" },
            sessionKey: { type: "string" },
            content: { type: "string" },
            category: { type: "string" },
            confidence: { type: "number" },
            namespace: { type: "string" },
            tags: { type: "array", items: { type: "string" } },
            entityRef: { type: "string" },
            ttl: { type: "string" },
            sourceReason: { type: "string" }
          },
          required: ["content"],
          additionalProperties: false
        }
      },
      {
        name: "engram.suggestion_submit",
        description: "Queue a suggested Remnic memory for review.",
        inputSchema: {
          type: "object",
          properties: {
            schemaVersion: { type: "number" },
            idempotencyKey: { type: "string" },
            dryRun: { type: "boolean" },
            sessionKey: { type: "string" },
            content: { type: "string" },
            category: { type: "string" },
            confidence: { type: "number" },
            namespace: { type: "string" },
            tags: { type: "array", items: { type: "string" } },
            entityRef: { type: "string" },
            ttl: { type: "string" },
            sourceReason: { type: "string" }
          },
          required: ["content"],
          additionalProperties: false
        }
      },
      {
        name: "engram.entity_get",
        description: "Fetch one Engram entity by name.",
        inputSchema: {
          type: "object",
          properties: {
            name: { type: "string" },
            namespace: { type: "string" }
          },
          required: ["name"],
          additionalProperties: false
        }
      },
      {
        name: "engram.review_queue_list",
        description: "Fetch the latest Engram review queue artifact bundle.",
        inputSchema: {
          type: "object",
          properties: {
            runId: { type: "string" },
            namespace: { type: "string" }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.observe",
        description: "Feed conversation messages into Engram's memory pipeline (LCM archive + extraction).",
        inputSchema: {
          type: "object",
          properties: {
            sessionKey: { type: "string", description: "Conversation session identifier" },
            messages: {
              type: "array",
              items: {
                type: "object",
                properties: {
                  role: { type: "string", enum: ["user", "assistant"] },
                  content: { type: "string" }
                },
                required: ["role", "content"]
              },
              description: "Conversation messages to observe"
            },
            namespace: { type: "string" },
            skipExtraction: { type: "boolean" },
            cwd: { type: "string", description: "Working directory for auto git-context resolution." },
            projectTag: { type: "string", description: "Project tag for non-git project scoping (e.g. 'blend-supply')." }
          },
          required: ["sessionKey", "messages"],
          additionalProperties: false
        }
      },
      {
        name: "engram.lcm_search",
        description: "Search the LCM conversation archive for matching content.",
        inputSchema: {
          type: "object",
          properties: {
            query: { type: "string", description: "Search query" },
            sessionKey: { type: "string", description: "Optional session filter" },
            namespace: { type: "string" },
            limit: { type: "number", description: "Max results to return" }
          },
          required: ["query"],
          additionalProperties: false
        }
      },
      // ── Continuity / Identity tools ─────────────────────────────────────
      {
        name: "engram.continuity_audit_generate",
        description: "Generate a deterministic identity continuity audit report (weekly/monthly).",
        inputSchema: {
          type: "object",
          properties: {
            period: { type: "string", enum: ["weekly", "monthly"] },
            key: { type: "string", description: "Period key (weekly: YYYY-Www, monthly: YYYY-MM). Defaults to current." }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.continuity_incident_open",
        description: "Create a new continuity incident record in append-only storage.",
        inputSchema: {
          type: "object",
          properties: {
            symptom: { type: "string", description: "Observed continuity failure symptom." },
            namespace: { type: "string" },
            triggerWindow: { type: "string", description: "Time window when incident occurred." },
            suspectedCause: { type: "string" }
          },
          required: ["symptom"],
          additionalProperties: false
        }
      },
      {
        name: "engram.continuity_incident_close",
        description: "Close an open continuity incident with verification details.",
        inputSchema: {
          type: "object",
          properties: {
            id: { type: "string", description: "Incident ID to close." },
            namespace: { type: "string" },
            fixApplied: { type: "string", description: "What fix was applied." },
            verificationResult: { type: "string", description: "How closure was verified." },
            preventiveRule: { type: "string", description: "Optional preventive follow-up rule." }
          },
          required: ["id", "fixApplied", "verificationResult"],
          additionalProperties: false
        }
      },
      {
        name: "engram.continuity_incident_list",
        description: "List continuity incidents, optionally filtered by state.",
        inputSchema: {
          type: "object",
          properties: {
            state: { type: "string", enum: ["open", "closed", "all"] },
            namespace: { type: "string" },
            limit: { type: "number", description: "Max incidents (default 25, max 200)." }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.continuity_loop_add_or_update",
        description: "Add or update a continuity improvement loop entry.",
        inputSchema: {
          type: "object",
          properties: {
            id: { type: "string", description: "Stable loop identifier." },
            cadence: { type: "string", enum: ["daily", "weekly", "monthly", "quarterly"] },
            purpose: { type: "string", description: "What this recurring loop improves." },
            status: { type: "string", enum: ["active", "paused", "retired"] },
            killCondition: { type: "string", description: "Clear condition for retiring this loop." },
            namespace: { type: "string" },
            lastReviewed: { type: "string", description: "ISO timestamp for last review." },
            notes: { type: "string" }
          },
          required: ["id", "cadence", "purpose", "status", "killCondition"],
          additionalProperties: false
        }
      },
      {
        name: "engram.continuity_loop_review",
        description: "Update review metadata for an existing continuity improvement loop.",
        inputSchema: {
          type: "object",
          properties: {
            id: { type: "string", description: "Loop ID to review." },
            namespace: { type: "string" },
            status: { type: "string", enum: ["active", "paused", "retired"] },
            notes: { type: "string" },
            reviewedAt: { type: "string", description: "ISO timestamp for review event." }
          },
          required: ["id"],
          additionalProperties: false
        }
      },
      {
        name: "engram.identity_anchor_get",
        description: "Read the identity continuity anchor document (recovery-safe identity context).",
        inputSchema: {
          type: "object",
          properties: {
            namespace: { type: "string" }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.identity_anchor_update",
        description: "Conservatively merge identity anchor sections without overwriting existing material.",
        inputSchema: {
          type: "object",
          properties: {
            namespace: { type: "string" },
            identityTraits: { type: "string", description: "Updates for 'Identity Traits' section." },
            communicationPreferences: { type: "string", description: "Updates for 'Communication Preferences' section." },
            operatingPrinciples: { type: "string", description: "Updates for 'Operating Principles' section." },
            continuityNotes: { type: "string", description: "Updates for 'Continuity Notes' section." }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_identity",
        description: "Read the agent's identity reflections from the workspace IDENTITY.md file.",
        inputSchema: {
          type: "object",
          properties: {
            namespace: { type: "string" }
          },
          additionalProperties: false
        }
      },
      // ── Work Layer tools ─────────────────────────────────────────────────
      {
        name: "engram.work_task",
        description: "Manage work-layer tasks (create, get, list, update, transition, delete). Excluded from memory extraction.",
        inputSchema: {
          type: "object",
          properties: {
            action: { type: "string", enum: ["create", "get", "list", "update", "transition", "delete"] },
            id: { type: "string" },
            title: { type: "string" },
            description: { type: "string" },
            status: { type: "string", enum: ["todo", "in_progress", "blocked", "done", "cancelled"] },
            priority: { type: "string", enum: ["low", "medium", "high"] },
            owner: { type: "string" },
            assignee: { type: "string" },
            projectId: { type: "string" },
            tags: { type: "array", items: { type: "string" } },
            dueAt: { type: "string" }
          },
          required: ["action"],
          additionalProperties: false
        }
      },
      {
        name: "engram.work_project",
        description: "Manage work-layer projects (create, get, list, update, delete, link_task). Excluded from memory extraction.",
        inputSchema: {
          type: "object",
          properties: {
            action: { type: "string", enum: ["create", "get", "list", "update", "delete", "link_task"] },
            id: { type: "string" },
            name: { type: "string" },
            description: { type: "string" },
            status: { type: "string", enum: ["active", "on_hold", "completed", "archived"] },
            owner: { type: "string" },
            tags: { type: "array", items: { type: "string" } },
            taskId: { type: "string", description: "Task ID for link_task." },
            projectId: { type: "string", description: "Project ID for link_task." }
          },
          required: ["action"],
          additionalProperties: false
        }
      },
      {
        name: "engram.work_board",
        description: "Export/import work-layer board snapshots and markdown.",
        inputSchema: {
          type: "object",
          properties: {
            action: { type: "string", enum: ["export_markdown", "export_snapshot", "import_snapshot"] },
            projectId: { type: "string" },
            snapshotJson: { type: "string", description: "Snapshot JSON for import_snapshot." },
            linkToMemory: { type: "boolean", description: "If true, output can be retained as long-term memory." }
          },
          required: ["action"],
          additionalProperties: false
        }
      },
      // ── Shared Context / Compounding tools ────────────────────────────
      {
        name: "engram.shared_context_write_output",
        description: "Write agent work product into shared-context directory for cross-agent coordination.",
        inputSchema: {
          type: "object",
          properties: {
            agentId: { type: "string", description: "Agent ID producing this output." },
            title: { type: "string", description: "Short title for the output." },
            content: { type: "string", description: "Markdown content to write." }
          },
          required: ["agentId", "title", "content"],
          additionalProperties: false
        }
      },
      {
        name: "engram.shared_feedback_record",
        description: "Append approval/rejection decision into shared-context feedback inbox for compounding learning.",
        inputSchema: {
          type: "object",
          properties: {
            agent: { type: "string", description: "Agent name that produced the output." },
            decision: { type: "string", enum: ["approved", "approved_with_feedback", "rejected"] },
            reason: { type: "string" },
            date: { type: "string", description: "ISO timestamp. Defaults to now." },
            learning: { type: "string" },
            outcome: { type: "string" },
            severity: { type: "string", enum: ["low", "medium", "high"] },
            confidence: { type: "number", description: "Confidence 0-1." },
            workflow: { type: "string" },
            tags: { type: "array", items: { type: "string" } },
            evidenceWindowStart: { type: "string" },
            evidenceWindowEnd: { type: "string" },
            refs: { type: "array", items: { type: "string" } }
          },
          required: ["agent", "decision", "reason"],
          additionalProperties: false
        }
      },
      {
        name: "engram.shared_priorities_append",
        description: "Append priorities text into shared-context inbox for curator merge.",
        inputSchema: {
          type: "object",
          properties: {
            agentId: { type: "string" },
            text: { type: "string", description: "Priority notes (markdown)." }
          },
          required: ["agentId", "text"],
          additionalProperties: false
        }
      },
      {
        name: "engram.shared_context_cross_signals_run",
        description: "Generate cross-signal markdown + JSON artifacts from agent outputs and feedback.",
        inputSchema: {
          type: "object",
          properties: {
            date: { type: "string", description: "YYYY-MM-DD. Defaults to today." }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.shared_context_curate_daily",
        description: "Generate daily roundtable summary (deterministic baseline aggregation).",
        inputSchema: {
          type: "object",
          properties: {
            date: { type: "string", description: "YYYY-MM-DD. Defaults to today." }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.compounding_weekly_synthesize",
        description: "Generate weekly compounding outputs: reports, mistake registry, rubrics, and promotion candidates.",
        inputSchema: {
          type: "object",
          properties: {
            weekId: { type: "string", description: "ISO week ID (YYYY-Www). Defaults to current week." }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.compounding_promote_candidate",
        description: "Promote a compounding candidate from weekly report into durable rule/principle memory.",
        inputSchema: {
          type: "object",
          properties: {
            weekId: { type: "string" },
            candidateId: { type: "string" },
            dryRun: { type: "boolean", description: "Preview without writing." }
          },
          required: ["weekId", "candidateId"],
          additionalProperties: false
        }
      },
      // ── Compression Guidelines tools ────────────────────────────────────
      {
        name: "engram.compression_guidelines_optimize",
        description: "Run compression guideline optimizer, optionally persisting new guidelines.",
        inputSchema: {
          type: "object",
          properties: {
            dryRun: { type: "boolean" },
            eventLimit: { type: "number" }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.compression_guidelines_activate",
        description: "Promote staged compression guideline draft to active (after review).",
        inputSchema: {
          type: "object",
          properties: {
            expectedContentHash: { type: "string" },
            expectedGuidelineVersion: { type: "number" }
          },
          additionalProperties: false
        }
      },
      // ── Memory search & debug tools ────────────────────────────────────
      {
        name: "engram.memory_search",
        description: "Direct semantic search over memory files using the QMD index. Returns matching memories with relevance scores.",
        inputSchema: {
          type: "object",
          properties: {
            query: { type: "string" },
            namespace: { type: "string" },
            maxResults: { type: "number" },
            collection: { type: "string", description: "QMD collection (omit for memory, 'global' for all)" }
          },
          required: ["query"],
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_profile",
        description: "Read the user's behavioral profile \u2014 a living document of their preferences, habits, and personality.",
        inputSchema: {
          type: "object",
          properties: { namespace: { type: "string" } },
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_entities_list",
        description: "List all tracked entities (people, projects, tools, companies).",
        inputSchema: {
          type: "object",
          properties: { namespace: { type: "string" } },
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_questions",
        description: "List open questions the system is curious about from past conversations.",
        inputSchema: {
          type: "object",
          properties: { namespace: { type: "string" } },
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_last_recall",
        description: "Return the last recall snapshot for a session (debug introspection).",
        inputSchema: {
          type: "object",
          properties: { sessionKey: { type: "string" } },
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_intent_debug",
        description: "Return the last intent classification debug snapshot.",
        inputSchema: {
          type: "object",
          properties: { namespace: { type: "string" } },
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_qmd_debug",
        description: "Return QMD search index debug information from the last recall.",
        inputSchema: {
          type: "object",
          properties: { namespace: { type: "string" } },
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_graph_explain",
        description: "Explain the last entity graph recall \u2014 which entities were activated and why.",
        inputSchema: {
          type: "object",
          properties: { namespace: { type: "string" } },
          additionalProperties: false
        }
      },
      {
        // Graph snapshot for the admin pane (issue #691 PR 2/5).  Returns
        // a read-only `{ nodes, edges, generatedAt }` view of the
        // multi-graph adjacency, with the same filter knobs as the HTTP
        // surface so connectors / CLI clients can hit either endpoint
        // interchangeably.
        name: "engram.graph_snapshot",
        description: "Return a read-only graph snapshot (nodes + edges) for the admin pane. Filters: limit (default 500, max 5000), since (ISO timestamp), focusNodeId (restricts to neighborhood), categories (allow-list of memory categories).",
        inputSchema: {
          type: "object",
          properties: {
            namespace: { type: "string" },
            limit: { type: "number", description: "Maximum number of edges to return (default 500, max 5000)." },
            since: { type: "string", description: "Inclusive lower bound on edge timestamp (ISO-8601)." },
            focusNodeId: { type: "string", description: "When set, restrict the snapshot to the focus node and its neighbors." },
            categories: {
              type: "array",
              items: { type: "string" },
              description: "Optional category allow-list (e.g. ['fact', 'decision'])."
            }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_feedback",
        description: "Record relevance feedback (thumbs up/down) for a specific memory.",
        inputSchema: {
          type: "object",
          properties: {
            memoryId: { type: "string" },
            vote: { type: "string", enum: ["up", "down"] },
            note: { type: "string" }
          },
          required: ["memoryId", "vote"],
          additionalProperties: false
        }
      },
      {
        name: "engram.memory_promote",
        description: "Promote a memory's lifecycle state (e.g. from draft to active).",
        inputSchema: {
          type: "object",
          properties: {
            memoryId: { type: "string" },
            namespace: { type: "string" },
            sessionKey: { type: "string" }
          },
          required: ["memoryId"],
          additionalProperties: false
        }
      },
      // Memory Worth outcome signal (issue #560 PR 3). Callers record whether
      // a session that used a given memory ultimately succeeded or failed;
      // the counter is persisted in the memory's frontmatter (mw_success /
      // mw_fail) and will feed the recall-time filter added in PR 4.
      {
        name: "engram.memory_outcome",
        description: "Record a Memory Worth outcome (success/failure) for a memory. Increments mw_success or mw_fail in the memory's frontmatter for use by the recall filter.",
        inputSchema: {
          type: "object",
          properties: {
            memoryId: { type: "string" },
            outcome: { type: "string", enum: ["success", "failure"] },
            namespace: { type: "string" },
            sessionKey: { type: "string" },
            timestamp: { type: "string", description: "Optional ISO-8601 timestamp of the observation." }
          },
          required: ["memoryId", "outcome"],
          additionalProperties: false
        }
      },
      {
        name: "engram.context_checkpoint",
        description: "Save a structured context checkpoint for a session (preserves conversation state to disk).",
        inputSchema: {
          type: "object",
          properties: {
            sessionKey: { type: "string" },
            context: { type: "string", description: "Context content to checkpoint" },
            namespace: { type: "string" }
          },
          required: ["sessionKey", "context"],
          additionalProperties: false
        }
      },
      // ── Daily Context Briefing (#370) ───────────────────────────────────
      // Uses the legacy "engram.*" prefix like every other tool in this array;
      // withToolAliases (applied via .flatMap below) generates the canonical
      // "remnic.briefing" alias automatically.
      ...service.briefingEnabled ? [{
        name: "engram.briefing",
        description: "Generate a daily context briefing by cross-referencing active entities, recent facts, open commitments, and optional calendar events.",
        inputSchema: {
          type: "object",
          properties: {
            since: { type: "string", description: "Lookback window (e.g. 'yesterday', '3d', '1w', '24h')." },
            focus: { type: "string", description: "Optional focus filter (e.g. 'person:Jane Doe', 'project:remnic-core', 'topic:retrieval')." },
            namespace: { type: "string" },
            format: { type: "string", enum: ["markdown", "json"] },
            maxFollowups: { type: "number", description: "Maximum LLM-suggested follow-ups (0 disables that section)." }
          },
          additionalProperties: false
        }
      }] : [],
      // ── Contradiction Review (issue #520) ────────────────────────────────
      {
        name: "engram.review_list",
        description: "List contradiction review items pending user resolution.",
        inputSchema: {
          type: "object",
          properties: {
            filter: { type: "string", enum: ["all", "unresolved", "contradicts", "independent", "duplicates", "needs-user"], description: "Filter by verdict type. Default: unresolved." },
            namespace: { type: "string" },
            limit: { type: "number", description: "Max items to return (default 50)." }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.review_resolve",
        description: "Resolve a contradiction pair with a chosen verb.",
        inputSchema: {
          type: "object",
          properties: {
            pairId: { type: "string", description: "The contradiction pair ID to resolve." },
            verb: { type: "string", enum: ["keep-a", "keep-b", "merge", "both-valid", "needs-more-context"], description: "Resolution action." }
          },
          required: ["pairId", "verb"],
          additionalProperties: false
        }
      },
      {
        name: "engram.contradiction_scan_run",
        description: "Run an on-demand contradiction scan over the memory corpus.",
        inputSchema: {
          type: "object",
          properties: {
            namespace: { type: "string" }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.graph_edge_decay_run",
        description: "Run the graph-edge-confidence decay maintenance pass (issue #681 PR 2/3). Respects graphEdgeDecayEnabled; writes a structured telemetry record to state/graph-edge-decay-status.json.",
        inputSchema: {
          type: "object",
          properties: {
            dryRun: { type: "boolean" }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.live_connectors_run",
        description: "Run due live connectors once. Used by the live-connector cron and available for operator-triggered sync checks.",
        inputSchema: {
          type: "object",
          properties: {
            force: {
              type: "boolean",
              description: "When true, run enabled connectors even if their poll interval has not elapsed."
            }
          },
          additionalProperties: false
        }
      },
      // ── Peer Registry tools (issue #679 PR 4/5) ─────────────────────────
      {
        name: "engram.peer_list",
        description: "List all registered peers in the peer registry (issue #679). Returns an array of peer identity records sorted alphabetically by id.",
        inputSchema: {
          type: "object",
          properties: {},
          additionalProperties: false
        }
      },
      {
        name: "engram.peer_get",
        description: "Get a single peer by id. Returns the peer's identity record or { found: false } when not found (issue #679).",
        inputSchema: {
          type: "object",
          properties: {
            id: { type: "string", description: "Peer id to look up." }
          },
          required: ["id"],
          additionalProperties: false
        }
      },
      {
        name: "engram.peer_set",
        description: "Create or update a peer identity record (issue #679). On first write, creates the peer with the given kind (default 'human'). On subsequent writes, updates displayName and/or notes; kind and createdAt are immutable.",
        inputSchema: {
          type: "object",
          properties: {
            id: { type: "string", description: "Peer id \u2014 must match PEER_ID_PATTERN." },
            kind: {
              type: "string",
              enum: ["self", "human", "agent", "integration"],
              description: "Kind of peer. Required on first write; ignored on updates."
            },
            displayName: { type: "string", description: "Human-readable display name." },
            notes: { type: "string", description: "Optional free-form markdown notes." }
          },
          required: ["id"],
          additionalProperties: false
        }
      },
      {
        name: "engram.peer_delete",
        description: "Delete a peer's identity record (issue #679). Idempotent \u2014 succeeds even if the peer does not exist. The peer directory is preserved so profile and interaction-log data are not destroyed.",
        inputSchema: {
          type: "object",
          properties: {
            id: { type: "string", description: "Peer id to delete." }
          },
          required: ["id"],
          additionalProperties: false
        }
      },
      {
        name: "engram.peer_profile_get",
        description: "Get the evolving cognitive profile for a peer (issue #679). Returns the profile written by the async reasoner (PR 2/5), or { found: false } if no profile has been generated yet.",
        inputSchema: {
          type: "object",
          properties: {
            id: { type: "string", description: "Peer id whose profile to retrieve." }
          },
          required: ["id"],
          additionalProperties: false
        }
      },
      {
        name: "engram.peer_forget",
        description: "DESTRUCTIVELY purge the entire peer directory (identity.md + profile.md + interactions.log.md and any companion files). Requires confirm: 'yes'. Idempotent \u2014 safe to call twice. Use engram.peer_delete when you only want to remove the identity record and preserve profile data.",
        inputSchema: {
          type: "object",
          properties: {
            id: { type: "string", description: "Peer id to purge." },
            confirm: {
              type: "string",
              enum: ["yes"],
              description: "Must be exactly 'yes' to proceed. Guard against accidental invocation."
            }
          },
          required: ["id", "confirm"],
          additionalProperties: false
        }
      },
      // ── Operator Console state (issue #688 PR 2/3) ─────────────────────────
      {
        name: "engram.console_state",
        description: "Return a point-in-time ConsoleStateSnapshot of the engine's runtime state \u2014 buffer, extraction queue, dedup decisions, maintenance ledger tail, QMD probe, and daemon info (issue #688). Read-only; never mutates state.",
        inputSchema: {
          type: "object",
          properties: {
            namespace: {
              type: "string",
              description: "Optional namespace to scope the snapshot."
            }
          },
          additionalProperties: false
        }
      },
      // ── Dreams telemetry (issue #678 PR 3+4) ─────────────────────────────
      {
        name: "engram.dreams_status",
        description: "Return per-phase Dreams pipeline telemetry for the last N hours (default 24). Reports run count, total duration, and items processed for each phase: lightSleep, rem, deepSleep.",
        inputSchema: {
          type: "object",
          properties: {
            windowHours: {
              type: "number",
              description: "How many hours to look back (default 24, minimum 1)."
            },
            namespace: {
              type: "string",
              description: "Optional namespace to read Dreams telemetry from."
            }
          },
          additionalProperties: false
        }
      },
      {
        name: "engram.dreams_run",
        description: "Manually invoke a single Dreams pipeline phase (lightSleep, rem, or deepSleep). Returns the same telemetry shape as a scheduled run. Pass dryRun: true to preview without committing writes.",
        inputSchema: {
          type: "object",
          properties: {
            phase: {
              type: "string",
              enum: ["lightSleep", "rem", "deepSleep"],
              description: "Which phase to run."
            },
            dryRun: {
              type: "boolean",
              description: "When true, report what would change without committing writes (default false)."
            },
            namespace: {
              type: "string",
              description: "Optional namespace to run the phase in."
            }
          },
          required: ["phase"],
          additionalProperties: false
        }
      }
    ].flatMap((tool) => withToolAliases(tool));
  }
  service;
  buffer = Buffer.alloc(0);
  flushTask = null;
  tools;
  authenticatedPrincipal;
  /**
   * MCP client info keyed by server-assigned session ID. On each `initialize`
   * handshake the server generates a UUID, stores the client's clientInfo
   * against it, and returns the ID as `Mcp-Session-Id` in the response
   * metadata. Subsequent requests from the same client include this header,
   * allowing per-session clientInfo lookup without cross-session leaks.
   */
  clientInfoBySession = /* @__PURE__ */ new Map();
  /**
   * Session IDs generated during initialize, keyed by caller-supplied correlation
   * ID (unique per HTTP request) to avoid collisions when multiple clients send
   * initialize with the same JSON-RPC id concurrently.
   */
  initSessionIds = /* @__PURE__ */ new Map();
  /** Whether oai-mem-citation guidance is explicitly enabled via config. */
  citationsEnabled;
  /** Whether to auto-enable citations for Codex adapter connections. */
  citationsAutoDetect;
  /** Get clientInfo for a specific MCP session. Returns undefined for non-MCP requests. */
  getClientInfo(sessionId) {
    if (sessionId) {
      return this.clientInfoBySession.get(sessionId);
    }
    return void 0;
  }
  /** Pop the session ID generated during an initialize handshake, keyed by correlation ID. */
  popInitSessionId(correlationId) {
    const sid = this.initSessionIds.get(correlationId);
    if (sid !== void 0) this.initSessionIds.delete(correlationId);
    return sid;
  }
  async handleRequest(request, options) {
    const id = request.id ?? null;
    const method = request.method ?? "";
    if (method === "notifications/initialized") return null;
    if (method === "ping") {
      return { jsonrpc: "2.0", id, result: {} };
    }
    if (method === "initialize") {
      const params = request.params ?? {};
      const rawClientInfo = params.clientInfo;
      const newSessionId = randomUUID();
      if (rawClientInfo && typeof rawClientInfo.name === "string") {
        const info = { name: rawClientInfo.name, version: rawClientInfo.version };
        this.clientInfoBySession.set(newSessionId, info);
        if (this.clientInfoBySession.size > 1e3) {
          const firstKey = this.clientInfoBySession.keys().next().value;
          if (firstKey) this.clientInfoBySession.delete(firstKey);
        }
      }
      const version = await getMcpServerVersion();
      const corrId = options?.correlationId;
      if (corrId) this.initSessionIds.set(corrId, newSessionId);
      return {
        jsonrpc: "2.0",
        id,
        result: {
          protocolVersion: MCP_PROTOCOL_VERSION,
          capabilities: {
            tools: {}
          },
          serverInfo: {
            name: "remnic",
            version
          }
        }
      };
    }
    if (method === "tools/list") {
      return {
        jsonrpc: "2.0",
        id,
        result: {
          tools: this.tools
        }
      };
    }
    if (method === "tools/call") {
      const params = request.params ?? {};
      const name = typeof params.name === "string" ? params.name : "";
      try {
        let argumentsObject = {};
        if ("arguments" in params && params.arguments !== void 0) {
          if (params.arguments === null || typeof params.arguments !== "object" || Array.isArray(params.arguments)) {
            throw new EngramAccessInputError("tools/call arguments must be an object when provided");
          }
          argumentsObject = params.arguments;
        }
        const effectivePrincipal = options?.principalOverride ?? this.authenticatedPrincipal;
        const result = await this.callTool(name, argumentsObject, effectivePrincipal, options?.sessionId);
        return {
          jsonrpc: "2.0",
          id,
          result: {
            content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
            structuredContent: result,
            isError: false
          }
        };
      } catch (err) {
        const message = err instanceof Error ? err.message : String(err);
        return {
          jsonrpc: "2.0",
          id,
          result: {
            content: [{ type: "text", text: message }],
            isError: true
          }
        };
      }
    }
    return {
      jsonrpc: "2.0",
      id,
      error: {
        code: -32601,
        message: `Method not found: ${method}`
      }
    };
  }
  async runStdio(input, output) {
    input.on("data", (chunk) => {
      this.buffer = Buffer.concat([this.buffer, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)]);
      this.scheduleFlush(output);
    });
    await new Promise((resolve, reject) => {
      input.on("end", resolve);
      input.on("error", reject);
    });
    while (this.flushTask) {
      await this.flushTask;
    }
  }
  scheduleFlush(output) {
    if (this.flushTask) return;
    const task = this.flushBuffer(output).catch((err) => {
      this.writeMessage(output, {
        jsonrpc: "2.0",
        id: null,
        error: {
          code: -32700,
          message: err instanceof Error ? err.message : String(err)
        }
      });
    }).finally(() => {
      if (this.flushTask === task) {
        this.flushTask = null;
      }
      if (this.buffer.length > 0) {
        this.scheduleFlush(output);
      }
    });
    this.flushTask = task;
  }
  async flushBuffer(output) {
    while (true) {
      const headerEnd = this.buffer.indexOf("\r\n\r\n");
      if (headerEnd < 0) return;
      const headerText = this.buffer.slice(0, headerEnd).toString("utf-8");
      const headers = headerText.split("\r\n");
      const contentLengthHeader = headers.find((line) => line.toLowerCase().startsWith("content-length:"));
      if (!contentLengthHeader) {
        this.buffer = Buffer.alloc(0);
        return;
      }
      const contentLength = parseInt(contentLengthHeader.split(":")[1]?.trim() ?? "0", 10);
      if (!Number.isFinite(contentLength) || contentLength < 0) {
        this.buffer = Buffer.alloc(0);
        return;
      }
      const messageStart = headerEnd + 4;
      const messageEnd = messageStart + contentLength;
      if (this.buffer.length < messageEnd) return;
      const body = this.buffer.slice(messageStart, messageEnd).toString("utf-8");
      this.buffer = this.buffer.slice(messageEnd);
      let parsed;
      try {
        parsed = JSON.parse(body);
      } catch {
        this.writeMessage(output, {
          jsonrpc: "2.0",
          id: null,
          error: {
            code: -32700,
            message: "Parse error"
          }
        });
        continue;
      }
      const response = await this.handleRequest(parsed);
      if (response) {
        this.writeMessage(output, response);
      }
    }
  }
  writeMessage(output, payload) {
    const body = JSON.stringify(payload);
    const message = `Content-Length: ${Buffer.byteLength(body, "utf-8")}\r
\r
${body}`;
    output.write(message);
  }
  /**
   * Determine whether oai-mem-citation guidance should be appended to recall.
   * Returns true when explicitly enabled via config OR when auto-detect is
   * active and the current MCP session belongs to a Codex adapter client.
   *
   * When no sessionId is provided (e.g., stdio transport where there are no
   * HTTP headers carrying mcp-session-id), fall back to checking if there is
   * exactly one known session whose clientInfo matches the Codex pattern.
   * This covers the common stdio case where a single client connection exists.
   */
  shouldEmitCitations(mcpSessionId) {
    if (this.citationsEnabled) return true;
    if (!this.citationsAutoDetect) return false;
    if (mcpSessionId) {
      const info = this.clientInfoBySession.get(mcpSessionId);
      if (!info) return false;
      return this.isCodexClient(info);
    }
    if (this.clientInfoBySession.size === 1) {
      const [info] = [...this.clientInfoBySession.values()];
      if (info) return this.isCodexClient(info);
    }
    return false;
  }
  /** Check whether a clientInfo record identifies a Codex adapter client. */
  isCodexClient(info) {
    const lowerName = info.name.toLowerCase();
    return lowerName === "codex-mcp-client" || lowerName.includes("codex");
  }
  /**
   * Build citation metadata for each recall result that has a path.
   * Line range defaults to 1-1 when not determinable from the summary.
   */
  buildRecallCitations(response) {
    return response.results.filter((r) => r.path && r.path.length > 0).map((r) => ({
      memoryId: r.id,
      path: r.path,
      lineStart: 1,
      lineEnd: 1,
      noteDefault: r.preview?.slice(0, 60) || r.id
    }));
  }
  async callTool(name, args, effectivePrincipal, mcpSessionId) {
    switch (toLegacyToolName(name)) {
      case "engram.recall": {
        let disclosure;
        if ("disclosure" in args && args.disclosure !== void 0 && args.disclosure !== null) {
          if (typeof args.disclosure !== "string") {
            throw new EngramAccessInputError(
              "disclosure must be a string (one of: chunk, section, raw)"
            );
          }
          disclosure = args.disclosure;
        }
        if ("cwd" in args && args.cwd !== void 0 && args.cwd !== null && typeof args.cwd !== "string") {
          throw new EngramAccessInputError("cwd must be a string");
        }
        if ("projectTag" in args && args.projectTag !== void 0 && args.projectTag !== null && typeof args.projectTag !== "string") {
          throw new EngramAccessInputError("projectTag must be a string");
        }
        if ("asOf" in args && args.asOf !== void 0 && args.asOf !== null && typeof args.asOf !== "string") {
          throw new EngramAccessInputError("asOf must be a string (ISO 8601 timestamp)");
        }
        let tags;
        if ("tags" in args && args.tags !== void 0 && args.tags !== null) {
          if (!Array.isArray(args.tags) || !args.tags.every((t) => typeof t === "string")) {
            throw new EngramAccessInputError("tags must be an array of strings");
          }
          tags = args.tags;
        }
        let tagMatch;
        if ("tagMatch" in args && args.tagMatch !== void 0 && args.tagMatch !== null) {
          if (typeof args.tagMatch !== "string" || args.tagMatch !== "any" && args.tagMatch !== "all") {
            throw new EngramAccessInputError(
              `tagMatch must be one of: any, all (got: ${String(args.tagMatch)})`
            );
          }
          tagMatch = args.tagMatch;
        }
        const response = await this.service.recall({
          query: typeof args.query === "string" ? args.query : "",
          sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          topK: typeof args.topK === "number" && Number.isFinite(args.topK) ? args.topK : void 0,
          mode: typeof args.mode === "string" ? args.mode : void 0,
          includeDebug: args.includeDebug === true,
          disclosure,
          cwd: typeof args.cwd === "string" ? args.cwd : void 0,
          projectTag: typeof args.projectTag === "string" ? args.projectTag : void 0,
          asOf: typeof args.asOf === "string" ? args.asOf : void 0,
          ...tags !== void 0 ? { tags } : {},
          ...tagMatch !== void 0 ? { tagMatch } : {}
        });
        if (this.shouldEmitCitations(mcpSessionId)) {
          const citations = this.buildRecallCitations(response);
          const guidance = buildCitationGuidance(citations);
          if (guidance.length > 0) {
            return {
              ...response,
              context: response.context + guidance,
              citations
            };
          }
        }
        return response;
      }
      case "engram.recall_explain":
        return this.service.recallExplain({
          sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
          namespace: typeof args.namespace === "string" ? args.namespace : void 0
        });
      case "engram.set_coding_context": {
        const sessionKey = typeof args.sessionKey === "string" ? args.sessionKey : "";
        const hasProjectTag = typeof args.projectTag === "string" && args.projectTag.trim().length > 0;
        const hasCodingContext = "codingContext" in args;
        if (!hasCodingContext && hasProjectTag) {
          const tag = args.projectTag.trim();
          this.service.setCodingContext({
            sessionKey,
            codingContext: {
              projectId: `tag:${tag}`,
              branch: null,
              rootPath: `tag:${tag}`,
              defaultBranch: null
            }
          });
          return { ok: true };
        }
        if (!hasCodingContext && !hasProjectTag) {
          throw new EngramAccessInputError(
            "set_coding_context requires either codingContext or projectTag"
          );
        }
        const rawCtx = args.codingContext;
        let codingContext = null;
        if (rawCtx !== null) {
          if (typeof rawCtx !== "object" || rawCtx === void 0) {
            throw new EngramAccessInputError("codingContext must be an object or null");
          }
          const obj = rawCtx;
          const projectId = typeof obj.projectId === "string" ? obj.projectId : "";
          const rootPath = typeof obj.rootPath === "string" ? obj.rootPath : "";
          const branch = obj.branch === null ? null : typeof obj.branch === "string" ? obj.branch : void 0;
          const defaultBranch = obj.defaultBranch === null ? null : typeof obj.defaultBranch === "string" ? obj.defaultBranch : void 0;
          if (branch === void 0) {
            throw new EngramAccessInputError("codingContext.branch must be a string or null");
          }
          if (defaultBranch === void 0) {
            throw new EngramAccessInputError("codingContext.defaultBranch must be a string or null");
          }
          codingContext = { projectId, branch, rootPath, defaultBranch };
        }
        this.service.setCodingContext({ sessionKey, codingContext });
        return { ok: true };
      }
      case "engram.recall_tier_explain":
        return this.service.recallTierExplain(
          typeof args.sessionKey === "string" && args.sessionKey.length > 0 ? args.sessionKey : void 0,
          typeof args.namespace === "string" && args.namespace.length > 0 ? args.namespace : void 0,
          effectivePrincipal
        );
      case "engram.recall_xray": {
        const query = typeof args.query === "string" ? args.query : "";
        const sessionKey = typeof args.sessionKey === "string" && args.sessionKey.length > 0 ? args.sessionKey : void 0;
        const namespace = typeof args.namespace === "string" && args.namespace.length > 0 ? args.namespace : void 0;
        let budget;
        if (args.budget !== void 0 && args.budget !== null) {
          if (typeof args.budget !== "number" && typeof args.budget !== "string") {
            throw new Error(
              `engram.recall_xray: budget expects a positive integer; got ${JSON.stringify(args.budget)}`
            );
          }
          const parsed = typeof args.budget === "number" ? args.budget : Number(args.budget);
          if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
            throw new Error(
              `engram.recall_xray: budget expects a positive integer; got ${JSON.stringify(args.budget)}`
            );
          }
          budget = parsed;
        }
        let disclosure;
        if ("disclosure" in args && args.disclosure !== void 0 && args.disclosure !== null && args.disclosure !== "") {
          if (typeof args.disclosure !== "string") {
            throw new Error(
              "engram.recall_xray: disclosure must be a string (one of: chunk, section, raw)"
            );
          }
          disclosure = args.disclosure;
        }
        return this.service.recallXray({
          query,
          sessionKey,
          namespace,
          budget,
          authenticatedPrincipal: effectivePrincipal,
          ...disclosure !== void 0 ? { disclosure } : {}
        });
      }
      case "engram.day_summary":
        return this.service.daySummary({
          memories: typeof args.memories === "string" ? args.memories : "",
          sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
          namespace: typeof args.namespace === "string" ? args.namespace : void 0
        });
      case "engram.capsule_export": {
        const body = parseMcpRequest("capsuleExport", args);
        return this.service.capsuleExport({
          name: body.name,
          namespace: body.namespace,
          principal: effectivePrincipal,
          since: body.since,
          includeKinds: body.includeKinds,
          peerIds: body.peerIds,
          includeTranscripts: body.includeTranscripts,
          encrypt: body.encrypt
        });
      }
      case "engram.capsule_import": {
        const body = parseMcpRequest("capsuleImport", args);
        return this.service.capsuleImport({
          archivePath: expandTildePath(body.archivePath),
          namespace: body.namespace,
          principal: effectivePrincipal,
          mode: body.mode
        });
      }
      case "engram.capsule_list": {
        const body = parseMcpRequest("capsuleList", args);
        return this.service.capsuleList({
          namespace: body.namespace,
          principal: effectivePrincipal
        });
      }
      case "engram.memory_governance_run":
        return this.service.governanceRun({
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          mode: args.mode === "apply" ? "apply" : "shadow",
          recentDays: typeof args.recentDays === "number" && Number.isFinite(args.recentDays) ? args.recentDays : void 0,
          maxMemories: typeof args.maxMemories === "number" && Number.isFinite(args.maxMemories) ? args.maxMemories : void 0,
          batchSize: typeof args.batchSize === "number" && Number.isFinite(args.batchSize) ? args.batchSize : void 0,
          authenticatedPrincipal: effectivePrincipal
        }, effectivePrincipal);
      case "engram.procedure_mining_run":
        return this.service.procedureMiningRun(
          {
            namespace: typeof args.namespace === "string" ? args.namespace : void 0,
            authenticatedPrincipal: effectivePrincipal
          },
          effectivePrincipal
        );
      case "engram.pattern_reinforcement_run":
        return this.service.patternReinforcementRun(
          {
            namespace: typeof args.namespace === "string" ? args.namespace : void 0,
            authenticatedPrincipal: effectivePrincipal,
            force: args.force === true
          },
          effectivePrincipal
        );
      case "remnic.procedural_stats":
      case "engram.procedural_stats":
        return this.service.procedureStats(
          {
            namespace: typeof args.namespace === "string" ? args.namespace : void 0
          },
          effectivePrincipal
        );
      case "engram.memory_get":
        return this.service.memoryGet(
          typeof args.memoryId === "string" ? args.memoryId : "",
          typeof args.namespace === "string" ? args.namespace : void 0,
          effectivePrincipal
        );
      case "engram.memory_timeline": {
        const limit = typeof args.limit === "number" && Number.isFinite(args.limit) ? args.limit : 200;
        return this.service.memoryTimeline(
          typeof args.memoryId === "string" ? args.memoryId : "",
          typeof args.namespace === "string" ? args.namespace : void 0,
          limit,
          effectivePrincipal
        );
      }
      case "engram.memory_store":
        return this.service.memoryStore({
          schemaVersion: typeof args.schemaVersion === "number" ? args.schemaVersion : void 0,
          idempotencyKey: typeof args.idempotencyKey === "string" ? args.idempotencyKey : void 0,
          dryRun: args.dryRun === true,
          sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
          authenticatedPrincipal: effectivePrincipal,
          content: typeof args.content === "string" ? args.content : "",
          category: typeof args.category === "string" ? args.category : void 0,
          confidence: typeof args.confidence === "number" ? args.confidence : void 0,
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          tags: Array.isArray(args.tags) ? args.tags.filter((tag) => typeof tag === "string") : void 0,
          entityRef: typeof args.entityRef === "string" ? args.entityRef : void 0,
          ttl: typeof args.ttl === "string" ? args.ttl : void 0,
          sourceReason: typeof args.sourceReason === "string" ? args.sourceReason : void 0
        });
      case "engram.suggestion_submit":
        return this.service.suggestionSubmit({
          schemaVersion: typeof args.schemaVersion === "number" ? args.schemaVersion : void 0,
          idempotencyKey: typeof args.idempotencyKey === "string" ? args.idempotencyKey : void 0,
          dryRun: args.dryRun === true,
          sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
          authenticatedPrincipal: effectivePrincipal,
          content: typeof args.content === "string" ? args.content : "",
          category: typeof args.category === "string" ? args.category : void 0,
          confidence: typeof args.confidence === "number" ? args.confidence : void 0,
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          tags: Array.isArray(args.tags) ? args.tags.filter((tag) => typeof tag === "string") : void 0,
          entityRef: typeof args.entityRef === "string" ? args.entityRef : void 0,
          ttl: typeof args.ttl === "string" ? args.ttl : void 0,
          sourceReason: typeof args.sourceReason === "string" ? args.sourceReason : void 0
        });
      case "engram.entity_get":
        return this.service.entityGet(
          typeof args.name === "string" ? args.name : "",
          typeof args.namespace === "string" ? args.namespace : void 0
        );
      case "engram.review_queue_list":
        return this.service.reviewQueue(
          typeof args.runId === "string" ? args.runId : void 0,
          typeof args.namespace === "string" ? args.namespace : void 0,
          effectivePrincipal
        );
      case "engram.observe": {
        if ("cwd" in args && args.cwd !== void 0 && args.cwd !== null && typeof args.cwd !== "string") {
          throw new EngramAccessInputError("cwd must be a string");
        }
        if ("projectTag" in args && args.projectTag !== void 0 && args.projectTag !== null && typeof args.projectTag !== "string") {
          throw new EngramAccessInputError("projectTag must be a string");
        }
        return this.service.observe({
          sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : "",
          messages: Array.isArray(args.messages) ? args.messages : [],
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          authenticatedPrincipal: effectivePrincipal,
          skipExtraction: args.skipExtraction === true,
          cwd: typeof args.cwd === "string" ? args.cwd : void 0,
          projectTag: typeof args.projectTag === "string" ? args.projectTag : void 0
        });
      }
      case "engram.lcm_search":
        return this.service.lcmSearch({
          query: typeof args.query === "string" ? args.query : "",
          sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          limit: typeof args.limit === "number" && Number.isFinite(args.limit) ? args.limit : void 0,
          authenticatedPrincipal: effectivePrincipal
        });
      // ── Continuity / Identity tools ───────────────────────────────────
      case "engram.continuity_audit_generate":
        return this.service.continuityAuditGenerate({
          period: args.period === "monthly" ? "monthly" : args.period === "weekly" ? "weekly" : void 0,
          key: typeof args.key === "string" ? args.key : void 0
        });
      case "engram.continuity_incident_open":
        return this.service.continuityIncidentOpen({
          symptom: typeof args.symptom === "string" ? args.symptom : "",
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal,
          triggerWindow: typeof args.triggerWindow === "string" ? args.triggerWindow : void 0,
          suspectedCause: typeof args.suspectedCause === "string" ? args.suspectedCause : void 0
        });
      case "engram.continuity_incident_close":
        return this.service.continuityIncidentClose({
          id: typeof args.id === "string" ? args.id : "",
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal,
          fixApplied: typeof args.fixApplied === "string" ? args.fixApplied : "",
          verificationResult: typeof args.verificationResult === "string" ? args.verificationResult : "",
          preventiveRule: typeof args.preventiveRule === "string" ? args.preventiveRule : void 0
        });
      case "engram.continuity_incident_list":
        return this.service.continuityIncidentList({
          state: args.state === "closed" ? "closed" : args.state === "all" ? "all" : args.state === "open" ? "open" : void 0,
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal,
          limit: typeof args.limit === "number" ? args.limit : void 0
        });
      case "engram.continuity_loop_add_or_update":
        return this.service.continuityLoopAddOrUpdate({
          id: typeof args.id === "string" ? args.id : "",
          cadence: args.cadence ?? "weekly",
          purpose: typeof args.purpose === "string" ? args.purpose : "",
          status: args.status ?? "active",
          killCondition: typeof args.killCondition === "string" ? args.killCondition : "",
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal,
          lastReviewed: typeof args.lastReviewed === "string" ? args.lastReviewed : void 0,
          notes: typeof args.notes === "string" ? args.notes : void 0
        });
      case "engram.continuity_loop_review":
        return this.service.continuityLoopReview({
          id: typeof args.id === "string" ? args.id : "",
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal,
          status: args.status === "active" || args.status === "paused" || args.status === "retired" ? args.status : void 0,
          notes: typeof args.notes === "string" ? args.notes : void 0,
          reviewedAt: typeof args.reviewedAt === "string" ? args.reviewedAt : void 0
        });
      case "engram.identity_anchor_get":
        return this.service.identityAnchorGet({
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal
        });
      case "engram.identity_anchor_update":
        return this.service.identityAnchorUpdate({
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal,
          identityTraits: typeof args.identityTraits === "string" ? args.identityTraits : void 0,
          communicationPreferences: typeof args.communicationPreferences === "string" ? args.communicationPreferences : void 0,
          operatingPrinciples: typeof args.operatingPrinciples === "string" ? args.operatingPrinciples : void 0,
          continuityNotes: typeof args.continuityNotes === "string" ? args.continuityNotes : void 0
        });
      case "engram.memory_identity":
        return this.service.memoryIdentity({
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal
        });
      // ── Work Layer tools ──────────────────────────────────────────────
      case "engram.work_task":
        return this.service.workTask({
          action: args.action ?? "list",
          id: typeof args.id === "string" ? args.id : void 0,
          title: typeof args.title === "string" ? args.title : void 0,
          description: typeof args.description === "string" ? args.description : void 0,
          status: typeof args.status === "string" ? args.status : void 0,
          priority: typeof args.priority === "string" ? args.priority : void 0,
          owner: typeof args.owner === "string" ? args.owner : void 0,
          assignee: typeof args.assignee === "string" ? args.assignee : void 0,
          projectId: typeof args.projectId === "string" ? args.projectId : void 0,
          tags: Array.isArray(args.tags) ? args.tags.filter((x) => typeof x === "string") : void 0,
          dueAt: typeof args.dueAt === "string" ? args.dueAt : void 0
        });
      case "engram.work_project":
        return this.service.workProject({
          action: args.action ?? "list",
          id: typeof args.id === "string" ? args.id : void 0,
          name: typeof args.name === "string" ? args.name : void 0,
          description: typeof args.description === "string" ? args.description : void 0,
          status: typeof args.status === "string" ? args.status : void 0,
          owner: typeof args.owner === "string" ? args.owner : void 0,
          tags: Array.isArray(args.tags) ? args.tags.filter((x) => typeof x === "string") : void 0,
          taskId: typeof args.taskId === "string" ? args.taskId : void 0,
          projectId: typeof args.projectId === "string" ? args.projectId : void 0
        });
      case "engram.work_board":
        return this.service.workBoard({
          action: args.action ?? "export_markdown",
          projectId: typeof args.projectId === "string" ? args.projectId : void 0,
          snapshotJson: typeof args.snapshotJson === "string" ? args.snapshotJson : void 0,
          linkToMemory: args.linkToMemory === true
        });
      // ── Shared Context / Compounding tools ─────────────────────────
      case "engram.shared_context_write_output":
        return this.service.sharedContextWriteOutput({
          agentId: typeof args.agentId === "string" ? args.agentId : "",
          title: typeof args.title === "string" ? args.title : "",
          content: typeof args.content === "string" ? args.content : ""
        });
      case "engram.shared_feedback_record":
        return this.service.sharedFeedbackRecord({
          agent: typeof args.agent === "string" ? args.agent : "",
          decision: args.decision ?? "approved",
          reason: typeof args.reason === "string" ? args.reason : "",
          date: typeof args.date === "string" ? args.date : void 0,
          learning: typeof args.learning === "string" ? args.learning : void 0,
          outcome: typeof args.outcome === "string" ? args.outcome : void 0,
          severity: args.severity === "low" || args.severity === "medium" || args.severity === "high" ? args.severity : void 0,
          confidence: typeof args.confidence === "number" ? args.confidence : void 0,
          workflow: typeof args.workflow === "string" ? args.workflow : void 0,
          tags: Array.isArray(args.tags) ? args.tags.filter((x) => typeof x === "string") : void 0,
          evidenceWindowStart: typeof args.evidenceWindowStart === "string" ? args.evidenceWindowStart : void 0,
          evidenceWindowEnd: typeof args.evidenceWindowEnd === "string" ? args.evidenceWindowEnd : void 0,
          refs: Array.isArray(args.refs) ? args.refs.filter((x) => typeof x === "string") : void 0
        });
      case "engram.shared_priorities_append":
        return this.service.sharedPrioritiesAppend({
          agentId: typeof args.agentId === "string" ? args.agentId : "",
          text: typeof args.text === "string" ? args.text : ""
        });
      case "engram.shared_context_cross_signals_run":
        return this.service.sharedContextCrossSignalsRun({
          date: typeof args.date === "string" ? args.date : void 0
        });
      case "engram.shared_context_curate_daily":
        return this.service.sharedContextCurateDaily({
          date: typeof args.date === "string" ? args.date : void 0
        });
      case "engram.compounding_weekly_synthesize":
        return this.service.compoundingWeeklySynthesize({
          weekId: typeof args.weekId === "string" ? args.weekId : void 0
        });
      case "engram.compounding_promote_candidate":
        return this.service.compoundingPromoteCandidate({
          weekId: typeof args.weekId === "string" ? args.weekId : "",
          candidateId: typeof args.candidateId === "string" ? args.candidateId : "",
          dryRun: args.dryRun === true
        });
      // ── Compression Guidelines tools ───────────────────────────────────
      case "engram.compression_guidelines_optimize":
        return this.service.compressionGuidelinesOptimize({
          dryRun: args.dryRun === true,
          eventLimit: typeof args.eventLimit === "number" ? args.eventLimit : void 0
        });
      case "engram.compression_guidelines_activate":
        return this.service.compressionGuidelinesActivate({
          expectedContentHash: typeof args.expectedContentHash === "string" ? args.expectedContentHash : void 0,
          expectedGuidelineVersion: typeof args.expectedGuidelineVersion === "number" ? args.expectedGuidelineVersion : void 0
        });
      // ── Memory search & debug tools ──────────────────────────────────
      case "engram.memory_search":
        return this.service.memorySearch({
          query: typeof args.query === "string" ? args.query : "",
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          maxResults: typeof args.maxResults === "number" && Number.isFinite(args.maxResults) ? args.maxResults : void 0,
          collection: typeof args.collection === "string" ? args.collection : void 0,
          principal: effectivePrincipal
        });
      case "engram.memory_profile":
        return this.service.memoryProfile(
          typeof args.namespace === "string" ? args.namespace : void 0,
          effectivePrincipal
        );
      case "engram.memory_entities_list":
        return this.service.memoryEntitiesList(
          typeof args.namespace === "string" ? args.namespace : void 0,
          effectivePrincipal
        );
      case "engram.memory_questions":
        return this.service.memoryQuestions(
          typeof args.namespace === "string" ? args.namespace : void 0,
          effectivePrincipal
        );
      case "engram.memory_last_recall":
        return this.service.lastRecallSnapshot(
          typeof args.sessionKey === "string" ? args.sessionKey : void 0
        );
      case "engram.memory_intent_debug":
        return this.service.intentDebug(
          typeof args.namespace === "string" ? args.namespace : void 0
        );
      case "engram.memory_qmd_debug":
        return this.service.qmdDebug(
          typeof args.namespace === "string" ? args.namespace : void 0
        );
      case "engram.memory_graph_explain":
        return this.service.graphExplainLastRecall(
          typeof args.namespace === "string" ? args.namespace : void 0
        );
      case "engram.graph_snapshot": {
        if (args.limit !== void 0 && typeof args.limit !== "number") {
          throw new Error("engram.graph_snapshot: limit must be a number");
        }
        if (args.since !== void 0 && typeof args.since !== "string") {
          throw new Error("engram.graph_snapshot: since must be a string");
        }
        if (args.focusNodeId !== void 0 && typeof args.focusNodeId !== "string") {
          throw new Error("engram.graph_snapshot: focusNodeId must be a string");
        }
        let categories;
        if (args.categories !== void 0) {
          if (!Array.isArray(args.categories)) {
            throw new Error(
              "engram.graph_snapshot: categories must be an array of strings"
            );
          }
          categories = args.categories.map((value, index) => {
            if (typeof value !== "string") {
              throw new Error(
                `engram.graph_snapshot: categories[${index}] must be a string`
              );
            }
            return value;
          });
        }
        return this.service.graphSnapshot(
          {
            namespace: typeof args.namespace === "string" ? args.namespace : void 0,
            limit: typeof args.limit === "number" ? args.limit : void 0,
            since: typeof args.since === "string" ? args.since : void 0,
            focusNodeId: typeof args.focusNodeId === "string" ? args.focusNodeId : void 0,
            ...categories !== void 0 ? { categories } : {}
          },
          effectivePrincipal
        );
      }
      case "engram.memory_feedback":
        return this.service.memoryFeedback({
          memoryId: typeof args.memoryId === "string" ? args.memoryId : "",
          vote: args.vote === "down" ? "down" : "up",
          note: typeof args.note === "string" ? args.note : void 0
        });
      case "engram.memory_promote":
        return this.service.memoryPromote({
          memoryId: typeof args.memoryId === "string" ? args.memoryId : "",
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal,
          sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0
        });
      case "engram.memory_outcome": {
        const outcome = args.outcome;
        if (outcome !== "success" && outcome !== "failure") {
          throw new Error(
            `engram.memory_outcome: outcome must be "success" or "failure"; got ${JSON.stringify(outcome)}`
          );
        }
        return this.service.memoryOutcome({
          memoryId: typeof args.memoryId === "string" ? args.memoryId : "",
          outcome,
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal,
          sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : void 0,
          timestamp: typeof args.timestamp === "string" ? args.timestamp : void 0
        });
      }
      case "engram.context_checkpoint":
        return this.service.contextCheckpoint({
          sessionKey: typeof args.sessionKey === "string" ? args.sessionKey : "",
          context: typeof args.context === "string" ? args.context : "",
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          principal: effectivePrincipal
        });
      // ── Daily Context Briefing (#370) ───────────────────────────────────
      case "engram.briefing": {
        const rawFormat = typeof args.format === "string" ? args.format : void 0;
        const formatErr = validateBriefingFormat(rawFormat);
        if (formatErr) throw new Error(formatErr);
        return this.service.briefing({
          since: typeof args.since === "string" ? args.since : void 0,
          focus: typeof args.focus === "string" ? args.focus : void 0,
          namespace: typeof args.namespace === "string" ? args.namespace : void 0,
          format: rawFormat,
          maxFollowups: typeof args.maxFollowups === "number" ? args.maxFollowups : void 0,
          principal: effectivePrincipal
        });
      }
      // ── Contradiction Review (issue #520) ──────────────────────────────────
      case "engram.review_list":
      case "remnic.review_list": {
        const { listPairs } = await import("./contradiction-review-5LTTVDQV.js");
        const VALID_REVIEW_FILTERS = /* @__PURE__ */ new Set(["all", "unresolved", "contradicts", "independent", "duplicates", "needs-user"]);
        const rawFilter = typeof args.filter === "string" ? args.filter : "unresolved";
        if (!VALID_REVIEW_FILTERS.has(rawFilter)) {
          throw new Error(`Invalid filter '${rawFilter}'. Valid: ${[...VALID_REVIEW_FILTERS].join(", ")}`);
        }
        const filter = rawFilter;
        const ns = typeof args.namespace === "string" ? args.namespace : void 0;
        const limit = typeof args.limit === "number" ? args.limit : 50;
        return listPairs(this.service.memoryDir, { filter, namespace: ns, limit });
      }
      case "engram.review_resolve":
      case "remnic.review_resolve": {
        const pairId = typeof args.pairId === "string" ? args.pairId : "";
        const verb = typeof args.verb === "string" ? args.verb : "";
        if (!pairId) throw new Error("pairId is required");
        if (!verb) throw new Error("verb is required");
        const { isValidResolutionVerb } = await import("./resolution-YGIBORXI.js");
        if (!isValidResolutionVerb(verb)) throw new Error(`Invalid verb: ${verb}. Must be one of: keep-a, keep-b, merge, both-valid, needs-more-context`);
        const { executeResolution } = await import("./resolution-YGIBORXI.js");
        return executeResolution(this.service.memoryDir, this.service.storageRef, pairId, verb);
      }
      case "engram.contradiction_scan_run":
      case "remnic.contradiction_scan_run": {
        const { runContradictionScan } = await import("./contradiction-scan-3Z6YW7YA.js");
        return runContradictionScan({
          storage: this.service.storageRef,
          config: this.service.configRef,
          memoryDir: this.service.memoryDir,
          embeddingLookupFactory: this.service.embeddingLookupFactoryRef,
          localLlm: this.service.localLlmRef,
          fallbackLlm: this.service.fallbackLlmRef,
          namespace: typeof args.namespace === "string" ? args.namespace : void 0
        });
      }
      case "engram.graph_edge_decay_run":
      case "remnic.graph_edge_decay_run": {
        const cfg = this.service.configRef;
        if (!cfg.graphEdgeDecayEnabled) {
          return {
            ranAt: (/* @__PURE__ */ new Date()).toISOString(),
            disabled: true,
            reason: "graphEdgeDecayEnabled is false"
          };
        }
        const { runGraphEdgeDecayMaintenanceAcrossNamespaces } = await import("./graph-edge-decay-PWB63GRE.js");
        const dryRun = args.dryRun === true;
        const results = await runGraphEdgeDecayMaintenanceAcrossNamespaces(
          this.service.memoryDir,
          {
            windowMs: cfg.graphEdgeDecayWindowMs,
            perWindow: cfg.graphEdgeDecayPerWindow,
            floor: cfg.graphEdgeDecayFloor,
            visibilityThreshold: cfg.graphEdgeDecayVisibilityThreshold,
            dryRun,
            namespacesEnabled: cfg.namespacesEnabled === true,
            defaultNamespace: cfg.defaultNamespace
          }
        );
        return { results };
      }
      case "engram.live_connectors_run":
      case "remnic.live_connectors_run":
        return this.service.liveConnectorsRun(
          {
            authenticatedPrincipal: effectivePrincipal,
            force: args.force === true
          },
          effectivePrincipal
        );
      // ── Peer Registry dispatchers (issue #679 PR 4/5) ─────────────────
      case "engram.peer_list":
      case "remnic.peer_list":
        return this.service.peerList();
      case "engram.peer_get":
      case "remnic.peer_get": {
        const id = typeof args.id === "string" ? args.id : "";
        if (!id) throw new Error("engram.peer_get: id is required");
        return this.service.peerGet(id);
      }
      case "engram.peer_set":
      case "remnic.peer_set": {
        const id = typeof args.id === "string" ? args.id : "";
        if (!id) throw new Error("engram.peer_set: id is required");
        if (args.kind !== void 0 && typeof args.kind !== "string") {
          throw new Error("engram.peer_set: kind must be a string when provided");
        }
        if (args.displayName !== void 0 && typeof args.displayName !== "string") {
          throw new Error("engram.peer_set: displayName must be a string when provided");
        }
        if (args.notes !== void 0 && typeof args.notes !== "string") {
          throw new Error("engram.peer_set: notes must be a string when provided");
        }
        return this.service.peerSet({
          id,
          kind: typeof args.kind === "string" ? args.kind : void 0,
          displayName: typeof args.displayName === "string" ? args.displayName : void 0,
          notes: typeof args.notes === "string" ? args.notes : void 0
        });
      }
      case "engram.peer_delete":
      case "remnic.peer_delete": {
        const id = typeof args.id === "string" ? args.id : "";
        if (!id) throw new Error("engram.peer_delete: id is required");
        return this.service.peerDelete(id);
      }
      case "engram.peer_profile_get":
      case "remnic.peer_profile_get": {
        const id = typeof args.id === "string" ? args.id : "";
        if (!id) throw new Error("engram.peer_profile_get: id is required");
        return this.service.peerProfileGet(id);
      }
      case "engram.peer_forget":
      case "remnic.peer_forget": {
        const id = typeof args.id === "string" ? args.id : "";
        if (!id) throw new Error("engram.peer_forget: id is required");
        const confirm = typeof args.confirm === "string" ? args.confirm : "";
        if (confirm !== "yes") {
          throw new Error(
            "engram.peer_forget: confirm must be 'yes' to prevent accidental data loss"
          );
        }
        return this.service.peerForget(id, { confirm: "yes" });
      }
      // ── Operator Console state (issue #688 PR 2/3) ──────────────────────────
      case "engram.console_state":
      case "remnic.console_state":
        return this.service.consoleState(
          typeof args.namespace === "string" ? args.namespace : void 0,
          effectivePrincipal
        );
      // ── Dreams telemetry (issue #678 PR 3+4) ──────────────────────────────
      case "engram.dreams_status":
      case "remnic.dreams_status": {
        const { normalizeDreamsStatusWindowHours } = await import("./dreams-ledger-LR2NBAZE.js");
        let windowHours = 24;
        try {
          windowHours = normalizeDreamsStatusWindowHours(args.windowHours);
        } catch {
          throw new Error(
            `engram.dreams_status: windowHours must be a positive integer (e.g. 24). Got: ${String(args.windowHours)}`
          );
        }
        if ("namespace" in args && args.namespace !== void 0 && typeof args.namespace !== "string") {
          throw new Error("engram.dreams_status: namespace must be a string when provided");
        }
        const namespace = typeof args.namespace === "string" ? args.namespace : void 0;
        return this.service.dreamsStatus({
          windowHours,
          namespace,
          principal: effectivePrincipal
        });
      }
      case "engram.dreams_run":
      case "remnic.dreams_run": {
        const VALID_PHASES = ["lightSleep", "rem", "deepSleep"];
        const phase = typeof args.phase === "string" ? args.phase : "";
        if (!phase || !VALID_PHASES.includes(phase)) {
          throw new Error(
            `engram.dreams_run: phase is required and must be one of: ${VALID_PHASES.join(", ")}`
          );
        }
        if ("dryRun" in args && args.dryRun !== void 0 && typeof args.dryRun !== "boolean") {
          throw new Error("engram.dreams_run: dryRun must be a boolean when provided");
        }
        if ("namespace" in args && args.namespace !== void 0 && typeof args.namespace !== "string") {
          throw new Error("engram.dreams_run: namespace must be a string when provided");
        }
        const namespace = typeof args.namespace === "string" ? args.namespace : void 0;
        const dryRun = args.dryRun === true;
        return this.service.dreamsRun({
          phase,
          dryRun,
          namespace,
          authenticatedPrincipal: effectivePrincipal
        });
      }
      default:
        throw new Error(`unknown tool: ${name}`);
    }
  }
};

export {
  EngramMcpServer
};
//# sourceMappingURL=chunk-4PLGJRBV.js.map