{"version":3,"file":"src-B1FeW6Q-.mjs","names":["DEFAULT_MODEL","API_URL","API_URL","extractFiles","truncate","truncate","VALID_TYPES","estimateTokens","MS_PER_DAY","DEFAULTS","findObservation","r","asNonEmptyString"],"sources":["../src/providers/agent-sdk.ts","../src/providers/anthropic.ts","../src/providers/_fetch.ts","../src/providers/minimax.ts","../src/providers/noop.ts","../src/providers/_openai-shared.ts","../src/providers/openai.ts","../src/providers/openrouter.ts","../src/providers/circuit-breaker.ts","../src/providers/resilient.ts","../src/providers/fallback-chain.ts","../src/providers/embedding/gemini.ts","../src/providers/embedding/openai.ts","../src/providers/embedding/voyage.ts","../src/providers/embedding/cohere.ts","../src/providers/embedding/openrouter.ts","../src/providers/embedding/local.ts","../src/providers/embedding/clip.ts","../src/providers/embedding/index.ts","../src/providers/index.ts","../src/state/kv.ts","../src/state/vector-index.ts","../src/state/memory-utils.ts","../src/functions/graph-retrieval.ts","../src/functions/query-expansion.ts","../src/state/reranker.ts","../src/state/hybrid-search.ts","../src/state/stemmer.ts","../src/state/synonyms.ts","../src/state/cjk-segmenter.ts","../src/state/search-index.ts","../src/functions/audit.ts","../src/state/index-persistence.ts","../src/functions/privacy.ts","../src/functions/compress-synthetic.ts","../src/functions/access-tracker.ts","../src/functions/search.ts","../src/functions/observe.ts","../src/functions/image-quota-cleanup.ts","../src/functions/vision-search.ts","../src/functions/slots.ts","../src/functions/disk-size-manager.ts","../src/prompts/compression.ts","../src/prompts/vision.ts","../src/prompts/xml.ts","../src/eval/schemas.ts","../src/eval/validator.ts","../src/eval/quality.ts","../src/eval/self-correct.ts","../src/functions/compress.ts","../src/functions/context.ts","../src/prompts/summary.ts","../src/functions/summarize.ts","../src/functions/migrate.ts","../src/functions/file-index.ts","../src/functions/consolidate.ts","../src/functions/patterns.ts","../src/functions/remember.ts","../src/functions/evict.ts","../src/functions/relations.ts","../src/functions/timeline.ts","../src/telemetry/setup.ts","../src/functions/smart-search.ts","../src/functions/recent-searches-sweep.ts","../src/functions/profile.ts","../src/functions/auto-forget.ts","../src/functions/export-import.ts","../src/functions/enrich.ts","../src/functions/claude-bridge.ts","../src/prompts/graph-extraction.ts","../src/functions/graph.ts","../src/prompts/consolidation.ts","../src/functions/consolidation-pipeline.ts","../src/functions/team.ts","../src/functions/governance.ts","../src/functions/snapshot.ts","../src/functions/actions.ts","../src/functions/frontier.ts","../src/functions/leases.ts","../src/functions/routines.ts","../src/functions/signals.ts","../src/functions/checkpoints.ts","../src/functions/flow-compress.ts","../src/functions/mesh.ts","../src/functions/branch-aware.ts","../src/functions/sentinels.ts","../src/functions/sketches.ts","../src/functions/crystallize.ts","../src/functions/diagnostics.ts","../src/functions/facets.ts","../src/functions/verify.ts","../src/functions/cascade.ts","../src/functions/lessons.ts","../src/functions/obsidian-export.ts","../src/prompts/reflect.ts","../src/functions/reflect.ts","../src/functions/working-memory.ts","../src/functions/skill-extract.ts","../src/functions/sliding-window.ts","../src/functions/temporal-graph.ts","../src/functions/retention.ts","../src/functions/compress-file.ts","../src/replay/jsonl-parser.ts","../src/replay/timeline.ts","../src/functions/replay.ts","../src/health/thresholds.ts","../src/health/monitor.ts","../src/auth.ts","../src/viewer/document.ts","../src/viewer/server.ts","../src/triggers/api.ts","../src/triggers/events.ts","../src/mcp/server.ts","../src/eval/metrics-store.ts","../src/functions/dedup.ts","../src/index.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { MemoryProvider } from '../types.js'\n\n// #781: the recursion guard used to live on `process.env.AGENTMEMORY_SDK_CHILD`\n// (#181). #472 then introduced chunked summarize that runs chunks\n// concurrently in the same process via Promise.all. The first chunk\n// flipped the global env to \"1\" synchronously before its `await`, and\n// every sibling chunk in the same batch immediately bailed out as a\n// \"child\" — returning \"\" — so half-plus of the chunks failed to parse\n// and the summarize threw `too_many_chunks_skipped: N/N`.\n//\n// Split the guard so each concern uses the right primitive:\n//\n//   - **In-process** recursion guard: AsyncLocalStorage. Scoped to the\n//     async call tree of the SDK query, so concurrent siblings on the\n//     same provider instance no longer see each other's marker.\n//   - **Cross-process** recursion guard for hooks: still\n//     `process.env.AGENTMEMORY_SDK_CHILD = \"1\"` around the SDK call.\n//     Subprocesses spawned by `@anthropic-ai/claude-agent-sdk` inherit\n//     `process.env` at spawn time, so the hook scripts (which run as\n//     separate processes) still see the marker and skip their REST\n//     callback to /summarize. ALS does not cross process boundaries.\nconst sdkChildContext = new AsyncLocalStorage<true>()\n\n// Module-level refcount for the process.env marker. A per-call snapshot\n// races across overlapping calls: A saves prev=undef, B saves prev=\"1\",\n// A's finally restores undef while B is still mid-flight (so any child\n// process B spawns won't inherit the marker), and B's finally restores\n// \"1\" — leaking the marker into the global env after the last caller.\n// Reference-count instead so only the first entrant snapshots the\n// original value and only the last exit restores it.\nlet sdkActiveCount = 0\nlet sdkOriginalEnv: string | undefined\n\ntype ClaudeAgentSdkModule = typeof import('@anthropic-ai/claude-agent-sdk')\n\nexport class AgentSDKProvider implements MemoryProvider {\n  name = 'agent-sdk'\n\n  // Memoize the dynamic import so concurrent callers share one resolution\n  // instead of racing to resolve the specifier independently. Keeps the\n  // SDK out of the cold-start path for users on other providers.\n  private sdkPromise: Promise<ClaudeAgentSdkModule> | null = null\n\n  private loadSdk(): Promise<ClaudeAgentSdkModule> {\n    if (!this.sdkPromise) {\n      this.sdkPromise = import('@anthropic-ai/claude-agent-sdk')\n    }\n    return this.sdkPromise\n  }\n\n  async compress(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.query(systemPrompt, userPrompt)\n  }\n\n  async summarize(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.query(systemPrompt, userPrompt)\n  }\n\n  private async query(systemPrompt: string, userPrompt: string): Promise<string> {\n    // In-process recursion guard. Concurrent sibling calls (chunked\n    // summarize via Promise.all) each have their own ALS frame, so they\n    // do not poison each other.\n    if (sdkChildContext.getStore()) {\n      // We are already inside a Claude Agent SDK-spawned async call\n      // tree. Spawning another one would let its plugin-hook-driven\n      // Stop loop re-enter /agentmemory/summarize and cause unbounded\n      // recursion (#149 follow-up). Degrade to empty string so callers\n      // short-circuit. The chunk retry path in src/functions/summarize.ts\n      // treats \"\" as a parse failure but only the in-process re-entry\n      // path can reach this branch — legitimate concurrent siblings now\n      // run with their own ALS frames.\n      return ''\n    }\n\n    return sdkChildContext.run(true, async () => {\n      // Mark spawned subprocesses (the SDK's underlying Claude session\n      // + its hook scripts) as SDK children via process.env. Hook scripts\n      // run in separate processes and read process.env to short-circuit\n      // their REST callbacks. Reference-counted so overlapping calls\n      // don't race each other into restoring stale values.\n      if (sdkActiveCount === 0) {\n        sdkOriginalEnv = process.env.AGENTMEMORY_SDK_CHILD\n        process.env.AGENTMEMORY_SDK_CHILD = '1'\n      }\n      sdkActiveCount++\n\n      try {\n        const { query } = await this.loadSdk()\n\n        const messages = query({\n          prompt: userPrompt,\n          options: {\n            systemPrompt,\n            maxTurns: 1,\n            allowedTools: [],\n          },\n        })\n\n        let result = ''\n        for await (const msg of messages) {\n          if (msg.type === 'result') {\n            result = (msg as any).result ?? ''\n          }\n        }\n        return result\n      } finally {\n        sdkActiveCount--\n        if (sdkActiveCount === 0) {\n          if (sdkOriginalEnv === undefined) {\n            delete process.env.AGENTMEMORY_SDK_CHILD\n          } else {\n            process.env.AGENTMEMORY_SDK_CHILD = sdkOriginalEnv\n          }\n          sdkOriginalEnv = undefined\n        }\n      }\n    })\n  }\n}\n","import Anthropic from '@anthropic-ai/sdk'\nimport type { MemoryProvider } from '../types.js'\n\nexport class AnthropicProvider implements MemoryProvider {\n  name = 'anthropic'\n  private client: Anthropic\n  private model: string\n  private maxTokens: number\n\n  constructor(apiKey: string, model: string, maxTokens: number, baseURL?: string) {\n    this.client = new Anthropic({ apiKey, ...(baseURL ? { baseURL } : {}) })\n    this.model = model\n    this.maxTokens = maxTokens\n  }\n\n  async compress(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(systemPrompt, userPrompt)\n  }\n\n  async summarize(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(systemPrompt, userPrompt)\n  }\n\n  async describeImage(imageData: string, mimeType: string, prompt: string): Promise<string> {\n    const response = await this.client.messages.create({\n      model: this.model,\n      max_tokens: this.maxTokens,\n      messages: [{\n        role: 'user',\n        content: [\n          {\n            type: 'image',\n            source: { type: 'base64', media_type: mimeType as 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp', data: imageData },\n          },\n          { type: 'text', text: prompt },\n        ],\n      }],\n    })\n\n    const textBlock = response.content.find((b) => b.type === 'text')\n    return textBlock?.text ?? ''\n  }\n\n  private async call(systemPrompt: string, userPrompt: string): Promise<string> {\n    const response = await this.client.messages.create({\n      model: this.model,\n      max_tokens: this.maxTokens,\n      system: systemPrompt,\n      messages: [{ role: 'user', content: userPrompt }],\n    })\n\n    const textBlock = response.content.find((b) => b.type === 'text')\n    return textBlock?.text ?? ''\n  }\n}\n","import { getEnvVar } from \"../config.js\";\n\nexport function fetchWithTimeout(\n  url: string,\n  init: RequestInit,\n  timeoutMs?: number,\n): Promise<Response> {\n  const parsed =\n    timeoutMs ??\n    Number.parseInt(getEnvVar(\"AGENTMEMORY_LLM_TIMEOUT_MS\") ?? \"60000\", 10);\n  const ms = Number.isFinite(parsed) && parsed > 0 ? parsed : 60000;\n\n  const ctl = new AbortController();\n  const signal = init.signal\n    ? AbortSignal.any([init.signal, ctl.signal])\n    : ctl.signal;\n  const t = setTimeout(() => ctl.abort(), ms);\n  return fetch(url, { ...init, signal }).finally(() => clearTimeout(t));\n}\n","import type { MemoryProvider } from '../types.js'\nimport { getEnvVar } from '../config.js'\nimport { fetchWithTimeout } from './_fetch.js'\n\n/**\n * MiniMax provider using raw fetch to call MiniMax's Anthropic-compatible API.\n *\n * The Anthropic SDK automatically injects `x-stainless-*` headers that MiniMax\n * rejects with 403. This provider bypasses the SDK and calls the API directly.\n *\n * Required env vars (loaded from ~/.agentmemory/.env or process.env):\n *   MINIMAX_API_KEY  — your MiniMax API key\n *   MINIMAX_MODEL    — model name (default: MiniMax-M2.7)\n *   MAX_TOKENS       — max output tokens (default: 800; MiniMax-M2.7 needs ≤800)\n *\n * Optional:\n *   MINIMAX_BASE_URL — base URL without path (default: https://api.minimax.io/anthropic)\n */\nexport class MinimaxProvider implements MemoryProvider {\n  name = 'minimax'\n  private apiKey: string\n  private model: string\n  private maxTokens: number\n  private baseUrl: string\n\n  constructor(apiKey: string, model: string, maxTokens: number) {\n    this.apiKey = apiKey\n    this.model = model\n    this.maxTokens = maxTokens\n    this.baseUrl =\n      getEnvVar('MINIMAX_BASE_URL') || 'https://api.minimax.io/anthropic'\n  }\n\n  async compress(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(systemPrompt, userPrompt)\n  }\n\n  async summarize(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(systemPrompt, userPrompt)\n  }\n\n  private async call(systemPrompt: string, userPrompt: string): Promise<string> {\n    const url = `${this.baseUrl}/v1/messages`\n    const response = await fetchWithTimeout(url, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        'x-api-key': this.apiKey,\n        'anthropic-version': '2023-06-01',\n      },\n      body: JSON.stringify({\n        model: this.model,\n        max_tokens: this.maxTokens,\n        system: systemPrompt,\n        messages: [{ role: 'user', content: userPrompt }],\n      }),\n    })\n\n    if (!response.ok) {\n      const text = await response.text()\n      throw new Error(`MiniMax API error ${response.status}: ${text}`)\n    }\n\n    const data = (await response.json()) as {\n      content?: Array<{ type: string; text?: string }>\n    }\n    const textBlock = data.content?.find((b) => b.type === 'text')\n    return textBlock?.text ?? ''\n  }\n}\n","import type { MemoryProvider } from \"../types.js\";\n\n/**\n * Returns empty strings for every call. Used when no LLM API key is set\n * AND the user has not opted into the agent-sdk fallback via\n * AGENTMEMORY_ALLOW_AGENT_SDK=true. Callers (compress, summarize) must\n * detect the empty result and short-circuit instead of spawning a\n * provider session (#149 / Stop-hook recursion loop fix).\n */\nexport class NoopProvider implements MemoryProvider {\n  name = \"noop\";\n\n  async compress(): Promise<string> {\n    return \"\";\n  }\n\n  async summarize(): Promise<string> {\n    return \"\";\n  }\n}\n","// Shared transport helpers for the OpenAI-compatible LLM + embedding\n// providers. Both surfaces (chat completions, embeddings) speak the\n// same wire shape on the standard OpenAI path. Azure OpenAI ships\n// two URL styles and we support both:\n//\n//   - Legacy/stable: `/openai/deployments/<deployment>/chat/completions`\n//     with mandatory `api-version=<date>` query param. The deployment\n//     name lives in the URL path. Required api-version moves with\n//     every Azure date-stamped revision; we keep the\n//     `OPENAI_API_VERSION` env knob + `DEFAULT_AZURE_API_VERSION`\n//     fallback so existing configs don't break on upgrade.\n//\n//   - v1 (GA Apr-2025): `/openai/v1/chat/completions`. No\n//     api-version query param, no `/deployments/` segment. Deployment\n//     name is passed in the request body as `model`. This matches\n//     the OpenAI wire shape one-for-one which is the whole point of\n//     v1 — drop-in compatibility.\n//\n// Auto-detection runs off the URL shape, not a flag: if the path\n// already carries `/deployments/`, we route through the legacy\n// builder; otherwise v1. Users opt into v1 by stripping the\n// `/openai/deployments/<deployment>` suffix from their\n// OPENAI_BASE_URL (or never adding it). See azureStyleOf().\n\nexport const DEFAULT_OPENAI_BASE_URL = \"https://api.openai.com\";\n\n// Default api-version for the legacy Azure URL pattern. Only used\n// when the configured base URL carries `/deployments/` AND\n// OPENAI_API_VERSION is unset. The v1 path ignores this entirely.\nexport const DEFAULT_AZURE_API_VERSION = \"2024-08-01-preview\";\n\ntype AzureStyle = \"legacy\" | \"v1\";\n\n// Azure resource URLs land at <resource>.openai.azure.com.\nexport function detectAzure(baseUrl: string): boolean {\n  try {\n    const u = new URL(baseUrl);\n    return u.hostname.endsWith(\".openai.azure.com\");\n  } catch {\n    return false;\n  }\n}\n\n// Pick the Azure URL style off the base URL's path shape. We only\n// consult this when detectAzure(baseUrl) has already returned true.\nfunction azureStyleOf(baseUrl: string): AzureStyle {\n  try {\n    const u = new URL(baseUrl);\n    // `/openai/deployments/<deployment>` (with or without a trailing\n    // segment) signals the legacy URL pattern. Anything else — a\n    // bare resource host, an `/openai/v1` prefix, an empty path —\n    // routes through v1.\n    if (/\\/openai\\/deployments\\//.test(u.pathname)) return \"legacy\";\n    return \"v1\";\n  } catch {\n    return \"v1\";\n  }\n}\n\n// Legacy Azure: append the route to the existing deployment path,\n// set api-version via searchParams. URL-API composition keeps any\n// pre-existing query params on the base URL intact.\nfunction legacyAzureUrl(\n  baseUrl: string,\n  path: string,\n  apiVersion: string,\n): string {\n  const url = new URL(baseUrl);\n  const existing = url.pathname.replace(/\\/+$/, \"\");\n  const route = path.startsWith(\"/\") ? path : `/${path}`;\n  url.pathname = `${existing}${route}`;\n  url.searchParams.set(\"api-version\", apiVersion);\n  return url.toString();\n}\n\n// v1 Azure: route through `/openai/v1/<path>`. Preserve any existing\n// query params on the base URL (corporate proxy, diagnostics tokens)\n// but never append api-version — v1 doesn't accept it.\nfunction v1AzureUrl(baseUrl: string, path: string): string {\n  const url = new URL(baseUrl);\n  const route = path.startsWith(\"/\") ? path.slice(1) : path;\n  // Strip any trailing `/openai`, `/openai/`, or `/openai/v1` so a\n  // user who configures OPENAI_BASE_URL with a partial prefix still\n  // gets a single, correct path.\n  const base = url.pathname.replace(/\\/?openai(?:\\/v1)?\\/?$/, \"\");\n  url.pathname = `${base.replace(/\\/+$/, \"\")}/openai/v1/${route}`;\n  return url.toString();\n}\n\n// Append an OpenAI-compatible route to the base URL without producing\n// a doubled version segment. Three cases:\n//\n//   1. Empty path (just a hostname) — OpenAI default: prepend `/v1/`.\n//        https://api.openai.com → https://api.openai.com/v1/chat/completions\n//   2. Path already ends with `/v1` — provider-documented base, treat\n//      it as the version anchor and append the route directly.\n//        https://api.deepseek.com/v1 → https://api.deepseek.com/v1/chat/completions\n//        (without this, we'd produce /v1/v1/chat/completions and 404. #628)\n//   3. Path ends with any other versioned or path segment — provider\n//      uses a non-OpenAI version scheme (Zhipu /api/paas/v4, others) —\n//      append the route directly, no `/v1/` injected.\n//        https://open.bigmodel.cn/api/paas/v4 → .../v4/chat/completions  (#646)\nfunction appendOpenAIRoute(baseUrl: string, route: string): string {\n  const trimmedBase = baseUrl.replace(/\\/+$/, \"\");\n  const cleanRoute = route.startsWith(\"/\") ? route : `/${route}`;\n  let pathname: string;\n  try {\n    pathname = new URL(trimmedBase).pathname.replace(/\\/+$/, \"\");\n  } catch {\n    return `${trimmedBase}/v1${cleanRoute}`;\n  }\n  if (pathname === \"\" || pathname === \"/\") {\n    return `${trimmedBase}/v1${cleanRoute}`;\n  }\n  return `${trimmedBase}${cleanRoute}`;\n}\n\nexport function buildChatUrl(\n  baseUrl: string,\n  isAzure: boolean,\n  azureApiVersion: string,\n): string {\n  if (isAzure) {\n    return azureStyleOf(baseUrl) === \"legacy\"\n      ? legacyAzureUrl(baseUrl, \"/chat/completions\", azureApiVersion)\n      : v1AzureUrl(baseUrl, \"/chat/completions\");\n  }\n  return appendOpenAIRoute(baseUrl, \"/chat/completions\");\n}\n\nexport function buildEmbeddingUrl(\n  baseUrl: string,\n  isAzure: boolean,\n  azureApiVersion: string,\n): string {\n  if (isAzure) {\n    return azureStyleOf(baseUrl) === \"legacy\"\n      ? legacyAzureUrl(baseUrl, \"/embeddings\", azureApiVersion)\n      : v1AzureUrl(baseUrl, \"/embeddings\");\n  }\n  return appendOpenAIRoute(baseUrl, \"/embeddings\");\n}\n\n// Azure key-auth uses `api-key: <KEY>`; standard OpenAI-compatible\n// endpoints use `Authorization: Bearer <KEY>`. Azure also accepts\n// Bearer when AAD-auth is configured upstream, but the api-key path\n// is the default and what our config block documents.\nexport function buildAuthHeaders(\n  apiKey: string,\n  isAzure: boolean,\n): Record<string, string> {\n  if (isAzure) {\n    return {\n      \"Content-Type\": \"application/json\",\n      \"api-key\": apiKey,\n    };\n  }\n  return {\n    \"Content-Type\": \"application/json\",\n    Authorization: `Bearer ${apiKey}`,\n  };\n}\n\nexport function normalizeBaseUrl(raw: string | undefined): string {\n  return (raw || DEFAULT_OPENAI_BASE_URL).replace(/\\/+$/, \"\");\n}\n","import type { MemoryProvider } from \"../types.js\";\nimport { getEnvVar } from \"../config.js\";\nimport { fetchWithTimeout } from \"./_fetch.js\";\nimport {\n  DEFAULT_AZURE_API_VERSION,\n  buildAuthHeaders,\n  buildChatUrl,\n  detectAzure,\n  normalizeBaseUrl,\n} from \"./_openai-shared.js\";\n\nconst DEFAULT_MODEL = \"gpt-4o-mini\";\nconst DEFAULT_TIMEOUT_MS = 60_000;\n\n/**\n * OpenAI-compatible LLM provider.\n *\n * Uses raw fetch (no SDK) to support any OpenAI-compatible endpoint:\n *   - OpenAI official\n *   - Azure OpenAI (auto-detected from .openai.azure.com host)\n *   - DeepSeek\n *   - 硅基流动 (SiliconFlow)\n *   - vLLM / LM Studio / Ollama (with OpenAI compatibility layer)\n *   - Any other proxy implementing /v1/chat/completions\n *\n * Required env vars:\n *   OPENAI_API_KEY  — API key\n *\n * Optional:\n *   OPENAI_BASE_URL          — base URL without path (default: https://api.openai.com).\n *                              Azure: https://<resource>.openai.azure.com/openai/deployments/<deployment>\n *   OPENAI_MODEL             — model name (default: gpt-4o-mini)\n *   OPENAI_API_VERSION       — Azure api-version query param (default: 2024-08-01-preview)\n *   OPENAI_TIMEOUT_MS        — outbound fetch timeout in ms (OpenAI-scoped alias,\n *                              takes precedence over AGENTMEMORY_LLM_TIMEOUT_MS\n *                              for back-compat with the v0.9.17 shipping name).\n *   AGENTMEMORY_LLM_TIMEOUT_MS — outbound fetch timeout in ms shared across all\n *                              raw-fetch LLM + embedding providers. Used when\n *                              OPENAI_TIMEOUT_MS is not set. Default: 60000.\n *   MAX_TOKENS               — max output tokens (default: from config or 4096)\n *   OPENAI_REASONING_EFFORT  — \"low\" | \"medium\" | \"high\" | \"none\"\n *                              Passthrough for reasoning models (e.g. Ollama Cloud\n *                              thinking models). Set to \"none\" to ensure\n *                              message.content is populated instead of only\n *                              message.reasoning.\n */\nexport class OpenAIProvider implements MemoryProvider {\n  name = \"openai\";\n  private apiKey: string;\n  private model: string;\n  private maxTokens: number;\n  private baseUrl: string;\n  private reasoningEffort?: string;\n  private timeoutMs: number;\n  private isAzure: boolean;\n  private azureApiVersion: string;\n\n  constructor(apiKey: string, model: string, maxTokens: number, baseURL?: string) {\n    this.apiKey = apiKey;\n    this.model = model;\n    this.maxTokens = maxTokens;\n    this.baseUrl = normalizeBaseUrl(baseURL || getEnvVar(\"OPENAI_BASE_URL\"));\n    this.reasoningEffort = getEnvVar(\"OPENAI_REASONING_EFFORT\") || undefined;\n    this.timeoutMs = resolveTimeout();\n    this.azureApiVersion =\n      getEnvVar(\"OPENAI_API_VERSION\") || DEFAULT_AZURE_API_VERSION;\n    this.isAzure = detectAzure(this.baseUrl);\n  }\n\n  async compress(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(systemPrompt, userPrompt);\n  }\n\n  async summarize(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(systemPrompt, userPrompt);\n  }\n\n  private async call(systemPrompt: string, userPrompt: string): Promise<string> {\n    const url = buildChatUrl(this.baseUrl, this.isAzure, this.azureApiVersion);\n    const body: Record<string, unknown> = {\n      model: this.model,\n      max_tokens: this.maxTokens,\n      // OpenAI API spec defines `stream` as defaulting to false, so omitting\n      // it should yield a JSON response. Some OpenAI-compatible proxies\n      // (notably 9Router < 0.4.56 — see decolua/9router#1260) default to\n      // text/event-stream when `stream` is absent, which crashes the\n      // `response.json()` call below with `Unexpected token 'd', \"data: {\"id\"...`.\n      // Send it explicitly so non-spec endpoints route to non-streaming too.\n      stream: false,\n      messages: [\n        { role: \"system\", content: systemPrompt },\n        { role: \"user\", content: userPrompt },\n      ],\n    };\n    if (this.reasoningEffort) {\n      body.reasoning_effort = this.reasoningEffort;\n    }\n\n    // Bound the request via the shared fetchWithTimeout helper, which\n    // owns the AbortController + clearTimeout cleanup for every raw-fetch\n    // provider (minimax, openrouter, gemini, openrouter-embed, etc.).\n    // OPENAI_TIMEOUT_MS keeps its v0.9.17 meaning (OpenAI-scoped alias,\n    // takes precedence); when unset we fall through to\n    // AGENTMEMORY_LLM_TIMEOUT_MS and finally the 60s default. See #446.\n    let response: Response;\n    try {\n      response = await fetchWithTimeout(\n        url,\n        {\n          method: \"POST\",\n          headers: buildAuthHeaders(this.apiKey, this.isAzure),\n          body: JSON.stringify(body),\n        },\n        this.timeoutMs,\n      );\n    } catch (err) {\n      const aborted = err instanceof Error && err.name === \"AbortError\";\n      if (aborted) {\n        throw new Error(\n          `OpenAI API request timed out after ${this.timeoutMs}ms — set OPENAI_TIMEOUT_MS (or AGENTMEMORY_LLM_TIMEOUT_MS) to raise the bound or check the provider status.`,\n        );\n      }\n      throw err;\n    }\n\n    if (!response.ok) {\n      const text = await response.text();\n      throw new Error(`OpenAI API error (${response.status}): ${text}`);\n    }\n\n    const data = (await response.json()) as {\n      choices?: Array<{\n        message?: { content?: string; reasoning?: string; reasoning_content?: string };\n      }>;\n    };\n    const message = data.choices?.[0]?.message;\n    const content = message?.content;\n    if (content) {\n      return content;\n    }\n    // Fallback: some thinking models return reasoning but no content.\n    // DeepSeek V4 / Qwen3 / GLM / Kimi return `reasoning_content`;\n    // older OpenAI o-series + some compatibles return `reasoning`. #627\n    const reasoning = message?.reasoning ?? message?.reasoning_content;\n    if (reasoning) {\n      return reasoning;\n    }\n    throw new Error(\n      `OpenAI returned unexpected response: ${JSON.stringify(data).slice(0, 200)}`,\n    );\n  }\n}\n\n// Resolves the outbound-fetch timeout for the OpenAI LLM path.\n// Precedence (preserving v0.9.17 behaviour):\n//   1. OPENAI_TIMEOUT_MS       — OpenAI-scoped alias (back-compat)\n//   2. AGENTMEMORY_LLM_TIMEOUT_MS — global LLM/embedding timeout (#446)\n//   3. 60 000 ms default\nfunction resolveTimeout(): number {\n  const openaiRaw = getEnvVar(\"OPENAI_TIMEOUT_MS\");\n  const openai = parsePositiveInt(openaiRaw);\n  if (openai !== undefined) return openai;\n\n  const globalRaw = getEnvVar(\"AGENTMEMORY_LLM_TIMEOUT_MS\");\n  const globalMs = parsePositiveInt(globalRaw);\n  if (globalMs !== undefined) return globalMs;\n\n  return DEFAULT_TIMEOUT_MS;\n}\n\nfunction parsePositiveInt(raw: string | null | undefined): number | undefined {\n  if (!raw) return undefined;\n  const trimmed = raw.trim();\n  // Reject malformed values like \"30ms\" or \"1_000\" — parseInt would\n  // silently return 30 / 1, swallowing user typos as valid timeouts.\n  // The regex enforces pure digits (no sign, no trailing units, no\n  // separators) before we hand off to Number.\n  if (!/^\\d+$/.test(trimmed)) return undefined;\n  const n = Number(trimmed);\n  return Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\n","import type { MemoryProvider } from \"../types.js\";\nimport { fetchWithTimeout } from \"./_fetch.js\";\n\nexport class OpenRouterProvider implements MemoryProvider {\n  name: string;\n  private apiKey: string;\n  private model: string;\n  private maxTokens: number;\n  private baseUrl: string;\n\n  constructor(\n    apiKey: string,\n    model: string,\n    maxTokens: number,\n    baseUrl: string,\n  ) {\n    this.apiKey = apiKey;\n    this.model = model;\n    this.maxTokens = maxTokens;\n    this.baseUrl = baseUrl;\n    this.name = baseUrl.includes(\"openrouter\") ? \"openrouter\" : \"gemini\";\n  }\n\n  async compress(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(systemPrompt, userPrompt);\n  }\n\n  async summarize(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(systemPrompt, userPrompt);\n  }\n\n  private async call(\n    systemPrompt: string,\n    userPrompt: string,\n  ): Promise<string> {\n    const response = await fetchWithTimeout(this.baseUrl, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        Authorization: `Bearer ${this.apiKey}`,\n        ...(this.baseUrl.includes(\"openrouter\")\n          ? { \"HTTP-Referer\": \"https://github.com/rohitg00/agentmemory\" }\n          : {}),\n      },\n      body: JSON.stringify({\n        model: this.model,\n        max_tokens: this.maxTokens,\n        messages: [\n          { role: \"system\", content: systemPrompt },\n          { role: \"user\", content: userPrompt },\n        ],\n      }),\n    });\n\n    if (!response.ok) {\n      const text = await response.text();\n      throw new Error(`${this.name} API error (${response.status}): ${text}`);\n    }\n\n    const data = (await response.json()) as Record<string, unknown>;\n    const choices = data.choices as\n      | Array<{ message: { content: string } }>\n      | undefined;\n    const content = choices?.[0]?.message?.content;\n    if (!content) {\n      throw new Error(\n        `${this.name} returned unexpected response: ${JSON.stringify(data).slice(0, 200)}`,\n      );\n    }\n    return content;\n  }\n}\n","import type { CircuitBreakerState } from \"../types.js\";\n\ninterface CircuitBreakerOptions {\n  failureThreshold?: number;\n  failureWindowMs?: number;\n  recoveryTimeoutMs?: number;\n}\n\nfunction positiveFinite(val: number | undefined, fallback: number): number {\n  return Number.isFinite(val) && val! > 0 ? val! : fallback;\n}\n\nexport class CircuitBreaker {\n  private state: \"closed\" | \"open\" | \"half-open\" = \"closed\";\n  private failures = 0;\n  private lastFailureAt: number | null = null;\n  private openedAt: number | null = null;\n\n  private readonly failureThreshold: number;\n  private readonly failureWindowMs: number;\n  private readonly recoveryTimeoutMs: number;\n\n  constructor(opts?: CircuitBreakerOptions) {\n    this.failureThreshold = Math.max(\n      1,\n      Math.floor(positiveFinite(opts?.failureThreshold, 3)),\n    );\n    this.failureWindowMs = positiveFinite(opts?.failureWindowMs, 60_000);\n    this.recoveryTimeoutMs = positiveFinite(opts?.recoveryTimeoutMs, 30_000);\n  }\n\n  get isAllowed(): boolean {\n    if (this.state === \"closed\") return true;\n    if (this.state === \"open\") {\n      if (\n        this.openedAt &&\n        Date.now() - this.openedAt >= this.recoveryTimeoutMs\n      ) {\n        this.state = \"half-open\";\n        return true;\n      }\n      return false;\n    }\n    return true;\n  }\n\n  recordSuccess(): void {\n    if (this.state === \"half-open\") {\n      this.state = \"closed\";\n      this.failures = 0;\n      this.lastFailureAt = null;\n      this.openedAt = null;\n    }\n  }\n\n  recordFailure(): void {\n    const now = Date.now();\n    if (this.state === \"half-open\") {\n      this.state = \"open\";\n      this.openedAt = now;\n      return;\n    }\n    if (this.lastFailureAt && now - this.lastFailureAt > this.failureWindowMs) {\n      this.failures = 0;\n    }\n    this.failures += 1;\n    this.lastFailureAt = now;\n    if (this.failures >= this.failureThreshold) {\n      this.state = \"open\";\n      this.openedAt = now;\n    }\n  }\n\n  getState(): CircuitBreakerState {\n    return {\n      state: this.state,\n      failures: this.failures,\n      lastFailureAt: this.lastFailureAt,\n      openedAt: this.openedAt,\n    };\n  }\n}\n","import type { MemoryProvider, CircuitBreakerState } from \"../types.js\";\nimport { CircuitBreaker } from \"./circuit-breaker.js\";\n\nexport class ResilientProvider implements MemoryProvider {\n  private breaker = new CircuitBreaker();\n  name: string;\n\n  constructor(private inner: MemoryProvider) {\n    this.name = `resilient(${inner.name})`;\n  }\n\n  private async call(fn: () => Promise<string>): Promise<string> {\n    if (!this.breaker.isAllowed) {\n      throw new Error(\"circuit_breaker_open\");\n    }\n    try {\n      const result = await fn();\n      this.breaker.recordSuccess();\n      return result;\n    } catch (err) {\n      this.breaker.recordFailure();\n      throw err;\n    }\n  }\n\n  async compress(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(() => this.inner.compress(systemPrompt, userPrompt));\n  }\n\n  async summarize(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(() => this.inner.summarize(systemPrompt, userPrompt));\n  }\n\n  get circuitState(): CircuitBreakerState {\n    return this.breaker.getState();\n  }\n}\n","import type { MemoryProvider } from \"../types.js\";\n\nexport class FallbackChainProvider implements MemoryProvider {\n  name: string;\n\n  constructor(private providers: MemoryProvider[]) {\n    this.name = `fallback(${providers.map((p) => p.name).join(\" -> \")})`;\n  }\n\n  async compress(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.tryAll((p) => p.compress(systemPrompt, userPrompt));\n  }\n\n  async summarize(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.tryAll((p) => p.summarize(systemPrompt, userPrompt));\n  }\n\n  private async tryAll(\n    fn: (p: MemoryProvider) => Promise<string>,\n  ): Promise<string> {\n    let lastError: Error | null = null;\n    for (const provider of this.providers) {\n      try {\n        return await fn(provider);\n      } catch (err) {\n        lastError = err instanceof Error ? err : new Error(String(err));\n      }\n    }\n    throw lastError || new Error(\"No providers available\");\n  }\n}\n","import type { EmbeddingProvider } from \"../../types.js\";\nimport { getEnvVar } from \"../../config.js\";\nimport { fetchWithTimeout } from \"../_fetch.js\";\n\nconst BATCH_LIMIT = 100;\nconst MODEL = \"models/gemini-embedding-001\";\nconst API_BASE = `https://generativelanguage.googleapis.com/v1beta/${MODEL}:batchEmbedContents`;\n\nexport class GeminiEmbeddingProvider implements EmbeddingProvider {\n  readonly name = \"gemini\";\n  readonly dimensions = 768;\n  private apiKey: string;\n\n  constructor(apiKey?: string) {\n    this.apiKey = apiKey || getEnvVar(\"GEMINI_API_KEY\") || \"\";\n    if (!this.apiKey) throw new Error(\"GEMINI_API_KEY is required\");\n  }\n\n  async embed(text: string): Promise<Float32Array> {\n    const [result] = await this.embedBatch([text]);\n    return result;\n  }\n\n  async embedBatch(texts: string[]): Promise<Float32Array[]> {\n    const results: Float32Array[] = [];\n\n    for (let i = 0; i < texts.length; i += BATCH_LIMIT) {\n      const chunk = texts.slice(i, i + BATCH_LIMIT);\n      const response = await fetchWithTimeout(`${API_BASE}?key=${this.apiKey}`, {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({\n          requests: chunk.map((t) => ({\n            model: MODEL,\n            content: { parts: [{ text: t }] },\n            outputDimensionality: this.dimensions,\n          })),\n        }),\n      });\n\n      if (!response.ok) {\n        const err = await response.text();\n        throw new Error(`Gemini embedding failed (${response.status}): ${err}`);\n      }\n\n      const data = (await response.json()) as {\n        embeddings: Array<{ values: number[] }>;\n      };\n\n      for (const emb of data.embeddings) {\n        results.push(l2Normalize(new Float32Array(emb.values)));\n      }\n    }\n\n    return results;\n  }\n}\n\nlet zeroNormWarned = false;\n\nfunction l2Normalize(vec: Float32Array): Float32Array {\n  let sum = 0;\n  for (let i = 0; i < vec.length; i++) sum += vec[i]! * vec[i]!;\n  const norm = Math.sqrt(sum);\n  if (norm === 0) {\n    if (!zeroNormWarned) {\n      zeroNormWarned = true;\n      process.stderr.write(\n        `[agentmemory] warn: gemini-embedding-001 returned a zero-norm ` +\n          `embedding (length=${vec.length}); leaving it un-normalized. ` +\n          `Subsequent zero-norm vectors will not be reported.\\n`,\n      );\n    }\n    return vec;\n  }\n  for (let i = 0; i < vec.length; i++) vec[i] = vec[i]! / norm;\n  return vec;\n}\n","import type { EmbeddingProvider } from \"../../types.js\";\nimport { getEnvVar } from \"../../config.js\";\nimport { fetchWithTimeout } from \"../_fetch.js\";\nimport {\n  DEFAULT_AZURE_API_VERSION,\n  buildAuthHeaders,\n  buildEmbeddingUrl,\n  detectAzure,\n  normalizeBaseUrl,\n} from \"../_openai-shared.js\";\n\nconst DEFAULT_MODEL = \"text-embedding-3-small\";\n\n/**\n * Known OpenAI embedding model dimensions. Extend as new models ship.\n * Override in any case via OPENAI_EMBEDDING_DIMENSIONS for custom or\n * self-hosted OpenAI-compatible endpoints returning non-standard sizes.\n */\nconst MODEL_DIMENSIONS: Record<string, number> = {\n  \"text-embedding-3-small\": 1536,\n  \"text-embedding-3-large\": 3072,\n  \"text-embedding-ada-002\": 1536,\n};\n\nconst DEFAULT_DIMENSIONS = MODEL_DIMENSIONS[DEFAULT_MODEL] ?? 1536;\n\nfunction resolveDimensions(model: string, override: string | undefined): number {\n  if (override !== undefined && override.trim().length > 0) {\n    const parsed = parseInt(override, 10);\n    if (!Number.isFinite(parsed) || parsed <= 0) {\n      throw new Error(\n        `OPENAI_EMBEDDING_DIMENSIONS must be a positive integer, got: ${override}`,\n      );\n    }\n    return parsed;\n  }\n  return MODEL_DIMENSIONS[model] ?? DEFAULT_DIMENSIONS;\n}\n\n/**\n * OpenAI-compatible embedding provider.\n *\n * Shares transport (URL builder, auth header, Azure detection) with\n * the OpenAI LLM provider via `_openai-shared` (#371). Same env knobs\n * pick up automatically: when `OPENAI_BASE_URL` points at an Azure\n * resource (`.openai.azure.com` hostname) the embedding request uses\n * Azure's `/embeddings` path with the `api-version` query param and\n * `api-key` header instead of `Authorization: Bearer`.\n *\n * Required env vars:\n *   OPENAI_API_KEY               — API key (fallback for OPENAI_EMBEDDING_API_KEY)\n *\n * Optional:\n *   OPENAI_BASE_URL              — base URL without path (default: https://api.openai.com).\n *                                  Azure: https://<resource>.openai.azure.com/openai/deployments/<deployment>\n *   OPENAI_EMBEDDING_BASE_URL    — embedding-specific base URL override (defaults\n *                                  to OPENAI_BASE_URL). Lets operators run\n *                                  embeddings on a separate endpoint from chat —\n *                                  e.g. local Ollama / LM Studio / llama.cpp /\n *                                  vLLM at http://localhost:1234 for unlimited\n *                                  free embeddings, while keeping chat\n *                                  completions on a rate-limited but high-quality\n *                                  hosted provider. Azure detection runs on\n *                                  whichever URL ends up selected.\n *   OPENAI_EMBEDDING_API_KEY     — separate API key for the embedding endpoint\n *                                  (defaults to OPENAI_API_KEY). Useful when the\n *                                  embedding endpoint requires a different key\n *                                  or no key at all (set to e.g. \"local\" for\n *                                  endpoints that ignore Authorization).\n *   OPENAI_API_VERSION           — Azure api-version query param (default: 2024-08-01-preview)\n *   OPENAI_EMBEDDING_MODEL       — model name (default: text-embedding-3-small)\n *   OPENAI_EMBEDDING_DIMENSIONS  — override reported dimensions (required for\n *                                  custom / self-hosted models not in the\n *                                  MODEL_DIMENSIONS table above)\n */\nexport class OpenAIEmbeddingProvider implements EmbeddingProvider {\n  readonly name = \"openai\";\n  readonly dimensions: number;\n  private apiKey: string;\n  private baseUrl: string;\n  private model: string;\n  private isAzure: boolean;\n  private azureApiVersion: string;\n\n  constructor(apiKey?: string) {\n    // Separate API key path: caller-passed wins, then OPENAI_EMBEDDING_API_KEY,\n    // then fall back to OPENAI_API_KEY. Allows e.g. a placeholder key for\n    // local endpoints that ignore Authorization (most do).\n    this.apiKey =\n      apiKey ||\n      getEnvVar(\"OPENAI_EMBEDDING_API_KEY\") ||\n      getEnvVar(\"OPENAI_API_KEY\") ||\n      \"\";\n    if (!this.apiKey) {\n      throw new Error(\n        \"API key is required (via constructor, OPENAI_EMBEDDING_API_KEY, or OPENAI_API_KEY)\",\n      );\n    }\n    // Embedding-specific base URL override; falls back to OPENAI_BASE_URL,\n    // then normalizeBaseUrl's default. The chat-LLM path (src/providers/openai.ts)\n    // still reads only OPENAI_BASE_URL, so setting OPENAI_EMBEDDING_BASE_URL\n    // alone moves embeddings to the new endpoint without affecting chat.\n    this.baseUrl = normalizeBaseUrl(\n      getEnvVar(\"OPENAI_EMBEDDING_BASE_URL\") || getEnvVar(\"OPENAI_BASE_URL\"),\n    );\n    this.model = getEnvVar(\"OPENAI_EMBEDDING_MODEL\") || DEFAULT_MODEL;\n    this.dimensions = resolveDimensions(\n      this.model,\n      getEnvVar(\"OPENAI_EMBEDDING_DIMENSIONS\"),\n    );\n    this.isAzure = detectAzure(this.baseUrl);\n    this.azureApiVersion =\n      getEnvVar(\"OPENAI_API_VERSION\") || DEFAULT_AZURE_API_VERSION;\n  }\n\n  async embed(text: string): Promise<Float32Array> {\n    const [result] = await this.embedBatch([text]);\n    return result;\n  }\n\n  async embedBatch(texts: string[]): Promise<Float32Array[]> {\n    const url = buildEmbeddingUrl(\n      this.baseUrl,\n      this.isAzure,\n      this.azureApiVersion,\n    );\n    const response = await fetchWithTimeout(url, {\n      method: \"POST\",\n      headers: buildAuthHeaders(this.apiKey, this.isAzure),\n      body: JSON.stringify({\n        model: this.model,\n        input: texts,\n      }),\n    });\n\n    if (!response.ok) {\n      const err = await response.text();\n      throw new Error(`OpenAI embedding failed (${response.status}): ${err}`);\n    }\n\n    const data = (await response.json()) as {\n      data: Array<{ embedding: number[] }>;\n    };\n\n    return data.data.map((d) => new Float32Array(d.embedding));\n  }\n}\n","import type { EmbeddingProvider } from \"../../types.js\";\nimport { getEnvVar } from \"../../config.js\";\nimport { fetchWithTimeout } from \"../_fetch.js\";\n\nconst API_URL = \"https://api.voyageai.com/v1/embeddings\";\n\nexport class VoyageEmbeddingProvider implements EmbeddingProvider {\n  readonly name = \"voyage\";\n  readonly dimensions = 1024;\n  private apiKey: string;\n\n  constructor(apiKey?: string) {\n    this.apiKey = apiKey || getEnvVar(\"VOYAGE_API_KEY\") || \"\";\n    if (!this.apiKey) throw new Error(\"VOYAGE_API_KEY is required\");\n  }\n\n  async embed(text: string): Promise<Float32Array> {\n    const [result] = await this.embedBatch([text]);\n    return result;\n  }\n\n  async embedBatch(texts: string[]): Promise<Float32Array[]> {\n    const response = await fetchWithTimeout(API_URL, {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${this.apiKey}`,\n        \"Content-Type\": \"application/json\",\n      },\n      body: JSON.stringify({\n        model: \"voyage-code-3\",\n        input: texts,\n        input_type: \"document\",\n      }),\n    });\n\n    if (!response.ok) {\n      const err = await response.text();\n      throw new Error(`Voyage embedding failed (${response.status}): ${err}`);\n    }\n\n    const data = (await response.json()) as {\n      data: Array<{ embedding: number[] }>;\n    };\n\n    return data.data.map((d) => new Float32Array(d.embedding));\n  }\n}\n","import type { EmbeddingProvider } from \"../../types.js\";\nimport { getEnvVar } from \"../../config.js\";\nimport { fetchWithTimeout } from \"../_fetch.js\";\n\nconst API_URL = \"https://api.cohere.ai/v1/embed\";\n\nexport class CohereEmbeddingProvider implements EmbeddingProvider {\n  readonly name = \"cohere\";\n  readonly dimensions = 1024;\n  private apiKey: string;\n\n  constructor(apiKey?: string) {\n    this.apiKey = apiKey || getEnvVar(\"COHERE_API_KEY\") || \"\";\n    if (!this.apiKey) throw new Error(\"COHERE_API_KEY is required\");\n  }\n\n  async embed(text: string): Promise<Float32Array> {\n    const [result] = await this.embedBatch([text]);\n    return result;\n  }\n\n  async embedBatch(texts: string[]): Promise<Float32Array[]> {\n    const response = await fetchWithTimeout(API_URL, {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${this.apiKey}`,\n        \"Content-Type\": \"application/json\",\n      },\n      body: JSON.stringify({\n        model: \"embed-english-v3.0\",\n        texts,\n        input_type: \"search_document\",\n      }),\n    });\n\n    if (!response.ok) {\n      const err = await response.text();\n      throw new Error(`Cohere embedding failed (${response.status}): ${err}`);\n    }\n\n    const data = (await response.json()) as {\n      embeddings: number[][];\n    };\n\n    return data.embeddings.map((e) => new Float32Array(e));\n  }\n}\n","import type { EmbeddingProvider } from \"../../types.js\";\nimport { getEnvVar } from \"../../config.js\";\nimport { fetchWithTimeout } from \"../_fetch.js\";\n\nconst API_URL = \"https://openrouter.ai/api/v1/embeddings\";\n\nexport class OpenRouterEmbeddingProvider implements EmbeddingProvider {\n  readonly name = \"openrouter\";\n  readonly dimensions = 1536;\n  private apiKey: string;\n  private model: string;\n\n  constructor(apiKey?: string) {\n    this.apiKey = apiKey || getEnvVar(\"OPENROUTER_API_KEY\") || \"\";\n    if (!this.apiKey) throw new Error(\"OPENROUTER_API_KEY is required\");\n    this.model =\n      getEnvVar(\"OPENROUTER_EMBEDDING_MODEL\") ||\n      \"openai/text-embedding-3-small\";\n  }\n\n  async embed(text: string): Promise<Float32Array> {\n    const [result] = await this.embedBatch([text]);\n    return result;\n  }\n\n  async embedBatch(texts: string[]): Promise<Float32Array[]> {\n    const response = await fetchWithTimeout(API_URL, {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${this.apiKey}`,\n        \"Content-Type\": \"application/json\",\n      },\n      body: JSON.stringify({\n        model: this.model,\n        input: texts,\n      }),\n    });\n\n    if (!response.ok) {\n      const err = await response.text();\n      throw new Error(\n        `OpenRouter embedding failed (${response.status}): ${err}`,\n      );\n    }\n\n    const data = (await response.json()) as {\n      data: Array<{ embedding: number[] }>;\n    };\n\n    return data.data.map((d) => new Float32Array(d.embedding));\n  }\n}\n","import type { EmbeddingProvider } from \"../../types.js\";\n\ntype Pipeline = (\n  task: string,\n  model: string,\n) => Promise<\n  (\n    texts: string[],\n    options: { pooling: string; normalize: boolean },\n  ) => Promise<{ tolist: () => number[][] }>\n>;\n\nexport class LocalEmbeddingProvider implements EmbeddingProvider {\n  readonly name = \"local\";\n  readonly dimensions = 384;\n  private extractor: Awaited<ReturnType<Pipeline>> | null = null;\n\n  async embed(text: string): Promise<Float32Array> {\n    const [result] = await this.embedBatch([text]);\n    return result;\n  }\n\n  async embedBatch(texts: string[]): Promise<Float32Array[]> {\n    const extractor = await this.getExtractor();\n    const output = await extractor(texts, {\n      pooling: \"mean\",\n      normalize: true,\n    });\n    const vectors = output.tolist();\n    return vectors.map((v: number[]) => new Float32Array(v));\n  }\n\n  private async getExtractor() {\n    if (this.extractor) return this.extractor;\n\n    let transformers: { pipeline: Pipeline };\n    try {\n      // @ts-ignore - optional peer dependency\n      transformers = await import(\"@xenova/transformers\");\n    } catch {\n      throw new Error(\n        \"Install @xenova/transformers for local embeddings: npm install @xenova/transformers\",\n      );\n    }\n\n    this.extractor = await transformers.pipeline(\n      \"feature-extraction\",\n      \"Xenova/all-MiniLM-L6-v2\",\n    );\n    return this.extractor;\n  }\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { EmbeddingProvider } from \"../../types.js\";\n\ntype TransformersModule = {\n  pipeline: (\n    task: string,\n    model: string,\n  ) => Promise<ClipPipeline>;\n  RawImage: {\n    fromBlob: (blob: Blob) => Promise<RawImageInstance>;\n  };\n};\n\ntype RawImageInstance = unknown;\n\ntype ClipPipeline = (\n  input: string[] | RawImageInstance | RawImageInstance[],\n  options?: { pooling?: string; normalize?: boolean },\n) => Promise<{ tolist: () => number[][]; data: Float32Array }>;\n\nconst DEFAULT_MODEL = \"Xenova/clip-vit-base-patch32\";\nconst DIMENSIONS = 512;\n\nexport class ClipEmbeddingProvider implements EmbeddingProvider {\n  readonly name = \"clip\";\n  readonly dimensions = DIMENSIONS;\n  private textExtractor: ClipPipeline | null = null;\n  private imageExtractor: ClipPipeline | null = null;\n  private transformers: TransformersModule | null = null;\n  private readonly modelId: string;\n\n  constructor(modelId: string = DEFAULT_MODEL) {\n    this.modelId = modelId;\n  }\n\n  async embed(text: string): Promise<Float32Array> {\n    const [vec] = await this.embedBatch([text]);\n    return vec;\n  }\n\n  async embedBatch(texts: string[]): Promise<Float32Array[]> {\n    const extractor = await this.getTextExtractor();\n    const output = await extractor(texts, { pooling: \"mean\", normalize: true });\n    return output.tolist().map((v) => new Float32Array(v));\n  }\n\n  async embedImage(src: string): Promise<Float32Array> {\n    const t = await this.getTransformers();\n    const image = await loadImage(t, src);\n    const extractor = await this.getImageExtractor();\n    const output = await extractor(image);\n    const vec = output.data ?? new Float32Array(output.tolist()[0] || []);\n    return normalize(vec);\n  }\n\n  private async getTransformers(): Promise<TransformersModule> {\n    if (this.transformers) return this.transformers;\n    try {\n      this.transformers = (await import(\"@xenova/transformers\")) as unknown as TransformersModule;\n    } catch {\n      throw new Error(\n        \"Install @xenova/transformers for CLIP image embeddings: npm install @xenova/transformers\",\n      );\n    }\n    return this.transformers;\n  }\n\n  private async getTextExtractor(): Promise<ClipPipeline> {\n    if (this.textExtractor) return this.textExtractor;\n    const t = await this.getTransformers();\n    this.textExtractor = await t.pipeline(\"feature-extraction\", this.modelId);\n    return this.textExtractor;\n  }\n\n  private async getImageExtractor(): Promise<ClipPipeline> {\n    if (this.imageExtractor) return this.imageExtractor;\n    const t = await this.getTransformers();\n    this.imageExtractor = await t.pipeline(\"image-feature-extraction\", this.modelId);\n    return this.imageExtractor;\n  }\n}\n\nasync function loadImage(\n  t: TransformersModule,\n  src: string,\n): Promise<RawImageInstance> {\n  if (src.startsWith(\"data:\")) {\n    const comma = src.indexOf(\",\");\n    const b64 = comma >= 0 ? src.slice(comma + 1) : src;\n    const buf = Buffer.from(b64, \"base64\");\n    const blob = new Blob([buf]);\n    return t.RawImage.fromBlob(blob);\n  }\n  const data = await readFile(src);\n  const blob = new Blob([data]);\n  return t.RawImage.fromBlob(blob);\n}\n\nfunction normalize(vec: Float32Array): Float32Array {\n  let sum = 0;\n  for (let i = 0; i < vec.length; i++) sum += vec[i] * vec[i];\n  const norm = Math.sqrt(sum);\n  if (norm === 0) return vec;\n  const out = new Float32Array(vec.length);\n  for (let i = 0; i < vec.length; i++) out[i] = vec[i] / norm;\n  return out;\n}\n","import type { EmbeddingProvider } from \"../../types.js\";\nimport { detectEmbeddingProvider, getEnvVar } from \"../../config.js\";\nimport { GeminiEmbeddingProvider } from \"./gemini.js\";\nimport { OpenAIEmbeddingProvider } from \"./openai.js\";\nimport { VoyageEmbeddingProvider } from \"./voyage.js\";\nimport { CohereEmbeddingProvider } from \"./cohere.js\";\nimport { OpenRouterEmbeddingProvider } from \"./openrouter.js\";\nimport { LocalEmbeddingProvider } from \"./local.js\";\nimport { ClipEmbeddingProvider } from \"./clip.js\";\n\nexport {\n  GeminiEmbeddingProvider,\n  OpenAIEmbeddingProvider,\n  VoyageEmbeddingProvider,\n  CohereEmbeddingProvider,\n  OpenRouterEmbeddingProvider,\n  LocalEmbeddingProvider,\n  ClipEmbeddingProvider,\n};\n\nlet imageEmbeddingProvider: EmbeddingProvider | null = null;\n\nexport function createImageEmbeddingProvider(): EmbeddingProvider | null {\n  if (process.env[\"AGENTMEMORY_IMAGE_EMBEDDINGS\"] !== \"true\") return null;\n  if (imageEmbeddingProvider) return imageEmbeddingProvider;\n  imageEmbeddingProvider = withDimensionGuard(new ClipEmbeddingProvider());\n  return imageEmbeddingProvider;\n}\n\nexport function createEmbeddingProvider(): EmbeddingProvider | null {\n  const detected = detectEmbeddingProvider();\n  if (!detected) return null;\n\n  switch (detected) {\n    case \"gemini\":\n      return withDimensionGuard(new GeminiEmbeddingProvider(getEnvVar(\"GEMINI_API_KEY\")!));\n    case \"openai\":\n      return withDimensionGuard(new OpenAIEmbeddingProvider(getEnvVar(\"OPENAI_API_KEY\")!));\n    case \"voyage\":\n      return withDimensionGuard(new VoyageEmbeddingProvider(getEnvVar(\"VOYAGE_API_KEY\")!));\n    case \"cohere\":\n      return withDimensionGuard(new CohereEmbeddingProvider(getEnvVar(\"COHERE_API_KEY\")!));\n    case \"openrouter\":\n      return withDimensionGuard(new OpenRouterEmbeddingProvider(getEnvVar(\"OPENROUTER_API_KEY\")!));\n    case \"local\":\n      return withDimensionGuard(new LocalEmbeddingProvider());\n    default:\n      return null;\n  }\n}\n\n// Wrong-dimension vectors corrupt the index silently: vector-index.ts\n// returns 0 from cosineSimilarity on length mismatch instead of throwing,\n// so a bad vector is stored, never matches anything, and the memory\n// becomes invisible without an error. Catch it at the boundary.\nexport function withDimensionGuard(provider: EmbeddingProvider): EmbeddingProvider {\n  const expected = provider.dimensions;\n  const check = (v: Float32Array, where: string): Float32Array => {\n    if (v.length !== expected) {\n      throw new Error(\n        `Embedding dimension mismatch in ${provider.name}.${where}: expected ${expected}, got ${v.length}`,\n      );\n    }\n    return v;\n  };\n  // Preserve the provider's prototype chain so `instanceof` checks\n  // against concrete classes (e.g. GeminiEmbeddingProvider) keep working.\n  const wrapped = Object.create(provider) as EmbeddingProvider;\n  wrapped.embed = async (t) => check(await provider.embed(t), \"embed\");\n  wrapped.embedBatch = async (ts) => {\n    const out = await provider.embedBatch(ts);\n    out.forEach((v, i) => check(v, `embedBatch[${i}]`));\n    return out;\n  };\n  if (provider.embedImage) {\n    wrapped.embedImage = async (s: string) =>\n      check(await provider.embedImage!(s), \"embedImage\");\n  }\n  return wrapped;\n}\n","import type {\n  MemoryProvider,\n  ProviderConfig,\n  FallbackConfig,\n} from \"../types.js\";\nimport { AgentSDKProvider } from \"./agent-sdk.js\";\nimport { AnthropicProvider } from \"./anthropic.js\";\nimport { MinimaxProvider } from \"./minimax.js\";\nimport { NoopProvider } from \"./noop.js\";\nimport { OpenAIProvider } from \"./openai.js\";\nimport { OpenRouterProvider } from \"./openrouter.js\";\nimport { ResilientProvider } from \"./resilient.js\";\nimport { FallbackChainProvider } from \"./fallback-chain.js\";\nimport { getEnvVar } from \"../config.js\";\n\nexport { createEmbeddingProvider, createImageEmbeddingProvider } from \"./embedding/index.js\";\n\nfunction requireEnvVar(key: string): string {\n  const value = getEnvVar(key);\n  if (!value) {\n    throw new Error(\n      `Missing required environment variable: ${key}. Set it in ~/.agentmemory/.env or as an environment variable.`,\n    );\n  }\n  return value;\n}\n\n// #778: fallback providers used to inherit the primary provider's\n// model name (e.g. fallback Gemini was called with `gpt-4o-mini`),\n// 404'd every call, and tripped the circuit breaker — making\n// FALLBACK_PROVIDERS actively worse than no fallback. Each provider\n// must resolve its OWN env-driven default model. Mirrors the resolution\n// in detectProvider() so primary + fallback agree on what each\n// provider's default model is.\nfunction defaultModelFor(providerType: ProviderConfig[\"provider\"]): string {\n  switch (providerType) {\n    case \"openai\":\n      return getEnvVar(\"OPENAI_MODEL\") || \"gpt-4o-mini\";\n    case \"anthropic\":\n      return getEnvVar(\"ANTHROPIC_MODEL\") || \"claude-sonnet-4-20250514\";\n    case \"gemini\":\n      return getEnvVar(\"GEMINI_MODEL\") || \"gemini-2.5-flash\";\n    case \"openrouter\":\n      return (\n        getEnvVar(\"OPENROUTER_MODEL\") || \"anthropic/claude-sonnet-4-20250514\"\n      );\n    case \"minimax\":\n      return getEnvVar(\"MINIMAX_MODEL\") || \"MiniMax-M2.7\";\n    case \"agent-sdk\":\n      return \"claude-sonnet-4-20250514\";\n    case \"noop\":\n    default:\n      return \"noop\";\n  }\n}\n\nexport function createProvider(config: ProviderConfig): ResilientProvider {\n  return new ResilientProvider(createBaseProvider(config));\n}\n\nexport function createFallbackProvider(\n  config: ProviderConfig,\n  fallbackConfig: FallbackConfig,\n): ResilientProvider {\n  if (fallbackConfig.providers.length === 0) {\n    return createProvider(config);\n  }\n\n  const providers: MemoryProvider[] = [createBaseProvider(config)];\n  for (const providerType of fallbackConfig.providers) {\n    if (providerType === config.provider) continue;\n    try {\n      // #778: resolve the fallback's OWN default model (or its env\n      // override) rather than copying config.model from the primary.\n      // Without this, FALLBACK_PROVIDERS=gemini on an OpenAI primary\n      // would call Gemini with `gpt-4o-mini`, get a 404 every time,\n      // and trip the circuit breaker.\n      const fbConfig: ProviderConfig = {\n        provider: providerType,\n        model: defaultModelFor(providerType),\n        maxTokens: config.maxTokens,\n      };\n      providers.push(createBaseProvider(fbConfig));\n    } catch {\n      // skip unavailable fallback providers\n    }\n  }\n\n  if (providers.length > 1) {\n    return new ResilientProvider(new FallbackChainProvider(providers));\n  }\n  return new ResilientProvider(providers[0]);\n}\n\nfunction createBaseProvider(config: ProviderConfig): MemoryProvider {\n  switch (config.provider) {\n    case \"minimax\":\n      return new MinimaxProvider(\n        requireEnvVar(\"MINIMAX_API_KEY\"),\n        config.model,\n        config.maxTokens,\n      );\n    case \"anthropic\":\n      return new AnthropicProvider(\n        requireEnvVar(\"ANTHROPIC_API_KEY\"),\n        config.model,\n        config.maxTokens,\n        config.baseURL,\n      );\n    case \"gemini\": {\n      const geminiKey =\n        getEnvVar(\"GEMINI_API_KEY\") || getEnvVar(\"GOOGLE_API_KEY\");\n      if (!geminiKey) {\n        throw new Error(\n          \"GEMINI_API_KEY (or GOOGLE_API_KEY) is required for the gemini provider\",\n        );\n      }\n      return new OpenRouterProvider(\n        geminiKey,\n        config.model,\n        config.maxTokens,\n        \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n      );\n    }\n    case \"openrouter\":\n      return new OpenRouterProvider(\n        requireEnvVar(\"OPENROUTER_API_KEY\"),\n        config.model,\n        config.maxTokens,\n        \"https://openrouter.ai/api/v1/chat/completions\",\n      );\n    case \"openai\": {\n      const openaiKey = getEnvVar(\"OPENAI_API_KEY\");\n      if (!openaiKey) {\n        throw new Error(\n          \"OPENAI_API_KEY is required for the openai provider\",\n        );\n      }\n      return new OpenAIProvider(\n        openaiKey,\n        config.model,\n        config.maxTokens,\n        config.baseURL,\n      );\n    }\n    case \"noop\":\n      return new NoopProvider();\n    case \"agent-sdk\":\n    default:\n      return new AgentSDKProvider();\n  }\n}\n","import type { ISdk } from 'iii-sdk'\n\nexport class StateKV {\n  constructor(private sdk: ISdk) {}\n\n  async get<T = unknown>(scope: string, key: string): Promise<T | null> {\n    return this.sdk.trigger<{ scope: string; key: string }, T | null>({\n      function_id: 'state::get',\n      payload: { scope, key },\n    })\n  }\n\n  async set<T = unknown>(scope: string, key: string, value: T): Promise<T> {\n    return this.sdk.trigger<{ scope: string; key: string; value: T }, T>({\n      function_id: 'state::set',\n      payload: { scope, key, value },\n    })\n  }\n\n  async update<T = unknown>(\n    scope: string,\n    key: string,\n    ops: Array<{ type: string; path: string; value?: unknown }>,\n  ): Promise<T> {\n    return this.sdk.trigger<\n      { scope: string; key: string; ops: Array<{ type: string; path: string; value?: unknown }> },\n      T\n    >({\n      function_id: 'state::update',\n      payload: { scope, key, ops },\n    })\n  }\n\n  async delete(scope: string, key: string): Promise<void> {\n    return this.sdk.trigger<{ scope: string; key: string }, void>({\n      function_id: 'state::delete',\n      payload: { scope, key },\n    })\n  }\n\n  async list<T = unknown>(scope: string): Promise<T[]> {\n    return this.sdk.trigger<{ scope: string }, T[]>({\n      function_id: 'state::list',\n      payload: { scope },\n    })\n  }\n}\n","// Pass byteOffset + byteLength explicitly so the round-trip survives\n// Node's Buffer pool. Buffer.from(b64, \"base64\") returns a slice of a\n// shared 8KB pool (poolSize), and `new Float32Array(buf.buffer)` ignores\n// the slice metadata — it would mint a 2048-element view over the whole\n// pool. Same risk on the encode side if the input Float32Array is itself\n// a sliced view. Reported as a phantom \"2048 dimensions on disk\" crash\n// in #455 / #469 / #584 / #587.\nfunction float32ToBase64(arr: Float32Array): string {\n  return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength).toString(\n    \"base64\",\n  );\n}\n\nfunction base64ToFloat32(b64: string): Float32Array {\n  const buf = Buffer.from(b64, \"base64\");\n  return new Float32Array(\n    buf.buffer,\n    buf.byteOffset,\n    buf.byteLength / Float32Array.BYTES_PER_ELEMENT,\n  );\n}\n\nfunction cosineSimilarity(a: Float32Array, b: Float32Array): number {\n  if (a.length !== b.length) return 0;\n  let dot = 0;\n  let normA = 0;\n  let normB = 0;\n  for (let i = 0; i < a.length; i++) {\n    dot += a[i] * b[i];\n    normA += a[i] * a[i];\n    normB += b[i] * b[i];\n  }\n  const denom = Math.sqrt(normA) * Math.sqrt(normB);\n  return denom === 0 ? 0 : dot / denom;\n}\n\nexport class VectorIndex {\n  private vectors: Map<string, { embedding: Float32Array; sessionId: string }> =\n    new Map();\n\n  add(obsId: string, sessionId: string, embedding: Float32Array): void {\n    this.vectors.set(obsId, { embedding, sessionId });\n  }\n\n  remove(obsId: string): void {\n    this.vectors.delete(obsId);\n  }\n\n  search(\n    query: Float32Array,\n    limit = 20,\n  ): Array<{ obsId: string; sessionId: string; score: number }> {\n    const results: Array<{\n      obsId: string;\n      sessionId: string;\n      score: number;\n    }> = [];\n    let minScore = -Infinity;\n\n    for (const [obsId, entry] of this.vectors) {\n      const score = cosineSimilarity(query, entry.embedding);\n      if (results.length < limit) {\n        results.push({ obsId, sessionId: entry.sessionId, score });\n        if (results.length === limit) {\n          results.sort((a, b) => a.score - b.score);\n          minScore = results[0].score;\n        }\n      } else if (score > minScore) {\n        results[0] = { obsId, sessionId: entry.sessionId, score };\n        results.sort((a, b) => a.score - b.score);\n        minScore = results[0].score;\n      }\n    }\n\n    results.sort((a, b) => b.score - a.score);\n    return results;\n  }\n\n  get size(): number {\n    return this.vectors.size;\n  }\n\n  // Walks every stored vector and returns the obsIds whose dimension\n  // doesn't match `expected`, plus the set of distinct dimensions seen.\n  // Used by the persistence-restore guard in src/index.ts to refuse\n  // loading any index containing wrong-dimension vectors — including\n  // legacy on-disk indexes written before the live-API dimension guard\n  // existed (where a mid-session provider swap could mix dimensions\n  // inside a single index). Empty `mismatches` plus a single-entry\n  // `seenDimensions` matching `expected` is the only clean state.\n  validateDimensions(\n    expected: number,\n  ): { mismatches: Array<{ obsId: string; dim: number }>; seenDimensions: Set<number> } {\n    const mismatches: Array<{ obsId: string; dim: number }> = [];\n    const seenDimensions = new Set<number>();\n    for (const [obsId, entry] of this.vectors) {\n      const dim = entry.embedding.length;\n      seenDimensions.add(dim);\n      if (dim !== expected) {\n        mismatches.push({ obsId, dim });\n      }\n    }\n    return { mismatches, seenDimensions };\n  }\n\n  clear(): void {\n    this.vectors.clear();\n  }\n\n  restoreFrom(other: VectorIndex): void {\n    const src = (other as any).vectors as Map<\n      string,\n      { embedding: Float32Array; sessionId: string }\n    >;\n    this.vectors = new Map();\n    for (const [obsId, entry] of src) {\n      this.vectors.set(obsId, {\n        embedding: new Float32Array(entry.embedding),\n        sessionId: entry.sessionId,\n      });\n    }\n  }\n\n  serialize(): string {\n    const data: Array<[string, { embedding: string; sessionId: string }]> = [];\n    for (const [obsId, entry] of this.vectors) {\n      data.push([\n        obsId,\n        {\n          embedding: float32ToBase64(entry.embedding),\n          sessionId: entry.sessionId,\n        },\n      ]);\n    }\n    return JSON.stringify(data);\n  }\n\n  static deserialize(json: string): VectorIndex {\n    const idx = new VectorIndex();\n    let data: unknown;\n    try {\n      data = JSON.parse(json);\n    } catch {\n      return idx;\n    }\n    if (!Array.isArray(data)) return idx;\n    for (const row of data) {\n      try {\n        if (!Array.isArray(row) || row.length < 2) continue;\n        const [obsId, entry] = row;\n        if (\n          typeof obsId !== \"string\" ||\n          typeof entry?.embedding !== \"string\" ||\n          typeof entry?.sessionId !== \"string\"\n        )\n          continue;\n        idx.vectors.set(obsId, {\n          embedding: base64ToFloat32(entry.embedding),\n          sessionId: entry.sessionId,\n        });\n      } catch {\n        continue;\n      }\n    }\n    return idx;\n  }\n}\n","import type { CompressedObservation, Memory } from \"../types.js\";\n\n// Wraps a Memory record in the CompressedObservation shape that\n// SearchIndex / VectorIndex / enrichment paths consume. Memories share\n// the same searchable fields as observations (title + content +\n// concepts + files); type is normalized to \"decision\" so memories stay\n// distinguishable in result metadata without colliding with observation\n// enums (file_read, command_run, …). The synthetic sessionId\n// (\"memory\" or memory.sessionIds[0]) is what enrich-side fallbacks key\n// off of when looking up the source record in KV.memories.\nexport function memoryToObservation(memory: Memory): CompressedObservation {\n  return {\n    id: memory.id,\n    sessionId: memory.sessionIds?.[0] ?? \"memory\",\n    timestamp: memory.createdAt,\n    type: \"decision\",\n    title: memory.title,\n    facts: [memory.content],\n    narrative: memory.content,\n    concepts: memory.concepts,\n    files: memory.files,\n    importance: memory.strength,\n  };\n}\n","import type {\n  GraphNode,\n  GraphEdge,\n} from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\n\nexport interface GraphRetrievalResult {\n  obsId: string;\n  sessionId: string;\n  score: number;\n  graphContext: string;\n  pathLength: number;\n}\n\nfunction buildGraphContext(\n  path: Array<{ node: GraphNode; edge?: GraphEdge }>,\n): string {\n  const parts: string[] = [];\n  for (const step of path) {\n    const props = Object.entries(step.node.properties)\n      .slice(0, 3)\n      .map(([k, v]) => `${k}=${v}`)\n      .join(\", \");\n    let line = `[${step.node.type}] ${step.node.name}`;\n    if (props) line += ` (${props})`;\n    if (step.edge) {\n      line += ` --${step.edge.type}-->`;\n      if (step.edge.context?.reasoning) {\n        line += ` [${step.edge.context.reasoning}]`;\n      }\n      if (step.edge.tvalid) {\n        line += ` @${step.edge.tvalid}`;\n      }\n    }\n    parts.push(line);\n  }\n  return parts.join(\" \");\n}\n\nexport class GraphRetrieval {\n  constructor(private kv: StateKV) {}\n\n  async searchByEntities(\n    entityNames: string[],\n    maxDepth = 2,\n    maxResults = 20,\n  ): Promise<GraphRetrievalResult[]> {\n    const allNodes = (await this.kv.list<GraphNode>(KV.graphNodes)).filter((n) => !n.stale);\n    const allEdges = (await this.kv.list<GraphEdge>(KV.graphEdges)).filter((e) => !e.stale);\n\n    const matchingNodes = allNodes.filter((n) => {\n      const nameLower = n.name.toLowerCase();\n      return entityNames.some(\n        (e) =>\n          nameLower.includes(e.toLowerCase()) ||\n          e.toLowerCase().includes(nameLower),\n      );\n    });\n\n    if (matchingNodes.length === 0) return [];\n\n    const results: GraphRetrievalResult[] = [];\n    const visitedObs = new Set<string>();\n\n    for (const startNode of matchingNodes) {\n      const paths = this.dijkstraTraversal(\n        startNode,\n        allNodes,\n        allEdges,\n        maxDepth,\n      );\n\n      for (const path of paths) {\n        const lastNode = path[path.length - 1].node;\n        for (const obsId of lastNode.sourceObservationIds) {\n          if (visitedObs.has(obsId)) continue;\n          visitedObs.add(obsId);\n\n          const pathLength = path.length;\n          const edgeWeights = path\n            .filter((s) => s.edge)\n            .map((s) => s.edge!.weight);\n          const avgWeight =\n            edgeWeights.length > 0\n              ? edgeWeights.reduce((a, b) => a + b, 0) / edgeWeights.length\n              : 0.5;\n          const score = avgWeight * (1 / pathLength);\n\n          results.push({\n            obsId,\n            sessionId: \"\",\n            score,\n            graphContext: buildGraphContext(path),\n            pathLength,\n          });\n        }\n      }\n\n      for (const obsId of startNode.sourceObservationIds) {\n        if (visitedObs.has(obsId)) continue;\n        visitedObs.add(obsId);\n        results.push({\n          obsId,\n          sessionId: \"\",\n          score: 1.0,\n          graphContext: `[${startNode.type}] ${startNode.name}`,\n          pathLength: 0,\n        });\n      }\n    }\n\n    results.sort((a, b) => b.score - a.score);\n    return results.slice(0, maxResults);\n  }\n\n  async expandFromChunks(\n    obsIds: string[],\n    maxDepth = 1,\n    maxResults = 10,\n  ): Promise<GraphRetrievalResult[]> {\n    const allNodes = (await this.kv.list<GraphNode>(KV.graphNodes)).filter((n) => !n.stale);\n    const allEdges = (await this.kv.list<GraphEdge>(KV.graphEdges)).filter((e) => !e.stale);\n\n    const linkedNodes = allNodes.filter((n) =>\n      n.sourceObservationIds.some((id) => obsIds.includes(id)),\n    );\n\n    const results: GraphRetrievalResult[] = [];\n    const visitedObs = new Set<string>(obsIds);\n\n    for (const node of linkedNodes) {\n      const paths = this.dijkstraTraversal(node, allNodes, allEdges, maxDepth);\n      for (const path of paths) {\n        const lastNode = path[path.length - 1].node;\n        for (const obsId of lastNode.sourceObservationIds) {\n          if (visitedObs.has(obsId)) continue;\n          visitedObs.add(obsId);\n\n          const pathLength = path.length;\n          const score = 0.5 * (1 / (pathLength + 1));\n\n          results.push({\n            obsId,\n            sessionId: \"\",\n            score,\n            graphContext: buildGraphContext(path),\n            pathLength,\n          });\n        }\n      }\n    }\n\n    results.sort((a, b) => b.score - a.score);\n    return results.slice(0, maxResults);\n  }\n\n  async temporalQuery(\n    entityName: string,\n    asOf?: string,\n  ): Promise<{\n    entity: GraphNode | null;\n    currentState: GraphEdge[];\n    history: GraphEdge[];\n  }> {\n    const allNodes = (await this.kv.list<GraphNode>(KV.graphNodes)).filter((n) => !n.stale);\n    const allEdges = (await this.kv.list<GraphEdge>(KV.graphEdges)).filter((e) => !e.stale);\n\n    const entity = allNodes.find(\n      (n) => n.name.toLowerCase() === entityName.toLowerCase(),\n    );\n    if (!entity) return { entity: null, currentState: [], history: [] };\n\n    const relatedEdges = allEdges.filter(\n      (e) => e.sourceNodeId === entity.id || e.targetNodeId === entity.id,\n    );\n\n    if (!asOf) {\n      const latestEdges = this.getLatestEdges(relatedEdges);\n      const historicalEdges = relatedEdges.filter(\n        (e) => !latestEdges.some((le) => le.id === e.id),\n      );\n      return { entity, currentState: latestEdges, history: historicalEdges };\n    }\n\n    const asOfDate = new Date(asOf).getTime();\n    const validEdges = relatedEdges.filter((e) => {\n      const commitDate = new Date(e.tcommit || e.createdAt).getTime();\n      if (commitDate > asOfDate) return false;\n      if (e.tvalid) {\n        const validDate = new Date(e.tvalid).getTime();\n        if (validDate > asOfDate) return false;\n      }\n      if (e.tvalidEnd) {\n        const endDate = new Date(e.tvalidEnd).getTime();\n        if (endDate < asOfDate) return false;\n      }\n      return true;\n    });\n\n    return {\n      entity,\n      currentState: this.getLatestEdges(validEdges),\n      history: validEdges,\n    };\n  }\n\n  private getLatestEdges(edges: GraphEdge[]): GraphEdge[] {\n    const byKey = new Map<string, GraphEdge[]>();\n    for (const e of edges) {\n      const key = `${e.sourceNodeId}|${e.targetNodeId}|${e.type}`;\n      if (!byKey.has(key)) byKey.set(key, []);\n      byKey.get(key)!.push(e);\n    }\n\n    const latest: GraphEdge[] = [];\n    for (const group of byKey.values()) {\n      if (group.length === 0) continue;\n      group.sort(\n        (a, b) =>\n          new Date(b.tcommit || b.createdAt).getTime() -\n          new Date(a.tcommit || a.createdAt).getTime(),\n      );\n      const newest = group.find((e) => e.isLatest !== false) || group[0];\n      latest.push(newest);\n    }\n    return latest;\n  }\n\n  // Weighted shortest-path traversal (#328). Replaces the prior BFS,\n  // which fell back to edge-count order and ignored the 0.1-1.0 weight\n  // attached to every graph edge. Dijkstra over `cost = 1/weight`\n  // (cheaper edges = stronger relationships) returns the\n  // highest-weighted path to each reachable node within maxDepth. Also\n  // tightens the perf profile:\n  //   - Adjacency built once in O(V+E) (previous BFS re-filtered\n  //     allEdges per visited node, O(V·E) overall).\n  //   - Min-heap dequeue is O(log V) per pop (previous queue.shift()\n  //     was O(n) — the dominant cost on graphs above ~200 nodes per\n  //     the contributor's benchmark in #328).\n  private dijkstraTraversal(\n    startNode: GraphNode,\n    allNodes: GraphNode[],\n    allEdges: GraphEdge[],\n    maxDepth: number,\n  ): Array<Array<{ node: GraphNode; edge?: GraphEdge }>> {\n    const nodeIndex = new Map<string, GraphNode>();\n    for (const n of allNodes) nodeIndex.set(n.id, n);\n\n    const adjacency = new Map<string, Array<{ neighborId: string; edge: GraphEdge }>>();\n    for (const edge of allEdges) {\n      const a = edge.sourceNodeId;\n      const b = edge.targetNodeId;\n      if (!adjacency.has(a)) adjacency.set(a, []);\n      if (!adjacency.has(b)) adjacency.set(b, []);\n      adjacency.get(a)!.push({ neighborId: b, edge });\n      adjacency.get(b)!.push({ neighborId: a, edge });\n    }\n\n    const dist = new Map<string, number>();\n    const pathTo = new Map<string, Array<{ node: GraphNode; edge?: GraphEdge }>>();\n    dist.set(startNode.id, 0);\n    pathTo.set(startNode.id, [{ node: startNode }]);\n\n    const heap = new MinHeap<{ nodeId: string; depth: number; cost: number }>(\n      (a, b) => a.cost - b.cost,\n    );\n    heap.push({ nodeId: startNode.id, depth: 0, cost: 0 });\n\n    while (heap.size() > 0) {\n      const { nodeId, depth, cost } = heap.pop()!;\n      // Skip stale heap entries (cost beaten by a later push).\n      if (cost > (dist.get(nodeId) ?? Infinity)) continue;\n      if (depth >= maxDepth) continue;\n\n      const neighbors = adjacency.get(nodeId) ?? [];\n      for (const { neighborId, edge } of neighbors) {\n        const nextNode = nodeIndex.get(neighborId);\n        if (!nextNode) continue;\n        // Clamp weight to avoid division-by-zero on malformed edges;\n        // 0.01 is below the documented 0.1 floor.\n        const edgeCost = 1 / Math.max(edge.weight, 0.01);\n        const newCost = cost + edgeCost;\n        if (newCost < (dist.get(neighborId) ?? Infinity)) {\n          dist.set(neighborId, newCost);\n          pathTo.set(neighborId, [\n            ...pathTo.get(nodeId)!,\n            { node: nextNode, edge },\n          ]);\n          heap.push({ nodeId: neighborId, depth: depth + 1, cost: newCost });\n        }\n      }\n    }\n\n    // Drop the startNode's own entry before returning: callers\n    // (searchByEntities, expandFromChunks) score start-node\n    // observations via a dedicated fallback loop with score=1.0. If\n    // we leave it in here, the start-path (length 1, no edges) goes\n    // through the generic path-scoring loop first — pathLength=1 +\n    // empty edgeWeights makes avgWeight fall to 0.5, the obs get\n    // marked visited, and the score=1.0 fallback becomes dead code.\n    pathTo.delete(startNode.id);\n    return Array.from(pathTo.values());\n  }\n}\n\n// Minimal binary min-heap. Pulled inline so graph-retrieval doesn't\n// take a new dependency for the perf-critical inner loop of #328.\n// Comparator returns negative when `a` should pop before `b`.\nclass MinHeap<T> {\n  private heap: T[] = [];\n\n  constructor(private compare: (a: T, b: T) => number) {}\n\n  size(): number {\n    return this.heap.length;\n  }\n\n  push(value: T): void {\n    this.heap.push(value);\n    this.bubbleUp(this.heap.length - 1);\n  }\n\n  pop(): T | undefined {\n    if (this.heap.length === 0) return undefined;\n    const top = this.heap[0];\n    const last = this.heap.pop()!;\n    if (this.heap.length > 0) {\n      this.heap[0] = last;\n      this.sinkDown(0);\n    }\n    return top;\n  }\n\n  private bubbleUp(i: number): void {\n    while (i > 0) {\n      const parent = (i - 1) >> 1;\n      if (this.compare(this.heap[i], this.heap[parent]) < 0) {\n        [this.heap[i], this.heap[parent]] = [this.heap[parent], this.heap[i]];\n        i = parent;\n      } else break;\n    }\n  }\n\n  private sinkDown(i: number): void {\n    const n = this.heap.length;\n    while (true) {\n      const left = 2 * i + 1;\n      const right = 2 * i + 2;\n      let smallest = i;\n      if (left < n && this.compare(this.heap[left], this.heap[smallest]) < 0) {\n        smallest = left;\n      }\n      if (right < n && this.compare(this.heap[right], this.heap[smallest]) < 0) {\n        smallest = right;\n      }\n      if (smallest === i) break;\n      [this.heap[i], this.heap[smallest]] = [this.heap[smallest], this.heap[i]];\n      i = smallest;\n    }\n  }\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { MemoryProvider, QueryExpansion } from \"../types.js\";\nimport { logger } from \"../logger.js\";\n\nconst QUERY_EXPANSION_SYSTEM = `You are a query expansion engine for a memory retrieval system. Given a user query, generate diverse reformulations to maximize recall.\n\nOutput EXACTLY this XML:\n<expansion>\n  <reformulations>\n    <query>semantically diverse rephrasing 1</query>\n    <query>semantically diverse rephrasing 2</query>\n    <query>semantically diverse rephrasing 3</query>\n  </reformulations>\n  <temporal>\n    <query>time-concretized version if applicable</query>\n  </temporal>\n  <entities>\n    <entity>extracted entity name 1</entity>\n    <entity>extracted entity name 2</entity>\n  </entities>\n</expansion>\n\nRules:\n- Generate 3-5 reformulations capturing different interpretations\n- Include paraphrases, domain-specific restatements, and abstract/concrete variants\n- Extract any named entities (people, files, projects, libraries, concepts)\n- If the query mentions time (\"last week\", \"recently\"), generate temporal concretizations\n- Each reformulation should capture a distinct facet of intent\n- Keep reformulations concise (under 100 chars each)`;\n\nfunction parseExpansionXml(xml: string): QueryExpansion | null {\n  const reformulations: string[] = [];\n  const queryRegex =\n    /<reformulations>[\\s\\S]*?<\\/reformulations>/;\n  const reformBlock = xml.match(queryRegex);\n  if (reformBlock) {\n    const qRegex = /<query>([^<]+)<\\/query>/g;\n    let match;\n    while ((match = qRegex.exec(reformBlock[0])) !== null) {\n      reformulations.push(match[1].trim());\n    }\n  }\n\n  const temporalConcretizations: string[] = [];\n  const tempBlock = xml.match(/<temporal>[\\s\\S]*?<\\/temporal>/);\n  if (tempBlock) {\n    const qRegex = /<query>([^<]+)<\\/query>/g;\n    let match;\n    while ((match = qRegex.exec(tempBlock[0])) !== null) {\n      temporalConcretizations.push(match[1].trim());\n    }\n  }\n\n  const entityExtractions: string[] = [];\n  const entityRegex = /<entity>([^<]+)<\\/entity>/g;\n  let match;\n  while ((match = entityRegex.exec(xml)) !== null) {\n    entityExtractions.push(match[1].trim());\n  }\n\n  return {\n    original: \"\",\n    reformulations,\n    temporalConcretizations,\n    entityExtractions,\n  };\n}\n\nexport function registerQueryExpansionFunction(\n  sdk: ISdk,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\"mem::expand-query\", \n    async (data: { query: string; maxReformulations?: number } | undefined) => {\n      if (!data || typeof data.query !== \"string\" || !data.query.trim()) {\n        logger.warn(\"Invalid expand-query payload\");\n        return { success: false, error: \"query must be a non-empty string\" };\n      }\n      const rawMaxR = Number(data.maxReformulations);\n      const maxR = Number.isFinite(rawMaxR)\n        ? Math.max(1, Math.min(10, Math.floor(rawMaxR)))\n        : 5;\n      const query = data.query.trim();\n\n      try {\n        const response = await provider.compress(\n          QUERY_EXPANSION_SYSTEM,\n          `Expand this query for memory retrieval:\\n\\n\"${query}\"`,\n        );\n\n        const parsed = parseExpansionXml(response);\n        if (!parsed) {\n          logger.warn(\"Failed to parse query expansion\");\n          return {\n            success: true,\n            expansion: {\n              original: query,\n              reformulations: [],\n              temporalConcretizations: [],\n              entityExtractions: [],\n            },\n          };\n        }\n\n        parsed.original = query;\n        parsed.reformulations = parsed.reformulations.slice(0, maxR);\n\n        logger.info(\"Query expanded\", {\n          original: query,\n          reformulations: parsed.reformulations.length,\n          entities: parsed.entityExtractions.length,\n        });\n\n        return { success: true, expansion: parsed };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.error(\"Query expansion failed\", { error: msg });\n        return {\n          success: true,\n          expansion: {\n            original: query,\n            reformulations: [],\n            temporalConcretizations: [],\n            entityExtractions: [],\n          },\n        };\n      }\n    },\n  );\n}\n\nexport function extractEntitiesFromQuery(query: string): string[] {\n  const entities: string[] = [];\n  const quoted = query.match(/\"([^\"]+)\"/g);\n  if (quoted) {\n    for (const q of quoted) {\n      entities.push(q.replace(/\"/g, \"\"));\n    }\n  }\n  const capitalized = query.match(/\\b[A-Z][a-zA-Z0-9_.-]+\\b/g);\n  if (capitalized) {\n    const stopWords = new Set([\n      \"The\",\n      \"This\",\n      \"That\",\n      \"What\",\n      \"When\",\n      \"Where\",\n      \"How\",\n      \"Why\",\n      \"Who\",\n      \"Which\",\n      \"Did\",\n      \"Does\",\n      \"Do\",\n      \"Is\",\n      \"Are\",\n      \"Was\",\n      \"Were\",\n      \"Has\",\n      \"Have\",\n      \"Had\",\n      \"Can\",\n      \"Could\",\n      \"Would\",\n      \"Should\",\n      \"Will\",\n      \"May\",\n      \"Might\",\n      \"If\",\n      \"And\",\n      \"But\",\n      \"Or\",\n      \"Not\",\n      \"For\",\n      \"From\",\n      \"With\",\n      \"About\",\n      \"After\",\n      \"Before\",\n      \"Between\",\n    ]);\n    for (const c of capitalized) {\n      if (!stopWords.has(c)) entities.push(c);\n    }\n  }\n  return [...new Set(entities)];\n}\n","import type { HybridSearchResult } from \"../types.js\";\n\nlet pipeline: any = null;\nlet pipelineLoading: Promise<any> | null = null;\nlet pipelineUnavailable = false;\n\nasync function loadPipeline(): Promise<any> {\n  if (pipelineUnavailable) return null;\n  if (pipeline) return pipeline;\n  if (pipelineLoading) return pipelineLoading;\n\n  pipelineLoading = (async () => {\n    try {\n      const { pipeline: createPipeline } = await import(\n        \"@xenova/transformers\"\n      );\n      pipeline = await createPipeline(\n        \"text-classification\",\n        \"Xenova/ms-marco-MiniLM-L-6-v2\",\n        { quantized: true },\n      );\n      return pipeline;\n    } catch {\n      pipeline = null;\n      pipelineUnavailable = true;\n      return null;\n    } finally {\n      pipelineLoading = null;\n    }\n  })();\n  return pipelineLoading;\n}\n\nexport async function rerank(\n  query: string,\n  results: HybridSearchResult[],\n  topK = 20,\n): Promise<HybridSearchResult[]> {\n  if (results.length <= 1) return results;\n\n  const reranker = await loadPipeline();\n  if (!reranker) return results;\n\n  const candidates = results.slice(0, Math.min(results.length, topK));\n\n  const pairs = candidates.map((r) => ({\n    text: `${query} [SEP] ${r.observation.title || \"\"} ${r.observation.narrative || \"\"}`.slice(0, 512),\n    result: r,\n  }));\n\n  const scores: Array<{ result: HybridSearchResult; rerankScore: number }> = [];\n\n  for (const pair of pairs) {\n    try {\n      const output = await reranker(pair.text);\n      const score = Array.isArray(output) ? output[0]?.score ?? 0 : 0;\n      scores.push({ result: pair.result, rerankScore: score });\n    } catch {\n      scores.push({ result: pair.result, rerankScore: pair.result.combinedScore });\n    }\n  }\n\n  scores.sort((a, b) => b.rerankScore - a.rerankScore);\n\n  return scores.map((s, i) => ({\n    ...s.result,\n    combinedScore: s.rerankScore,\n    rerankPosition: i + 1,\n  }));\n}\n\nexport function isRerankerAvailable(): boolean {\n  return pipeline !== null;\n}\n","import { SearchIndex } from \"./search-index.js\";\nimport { VectorIndex } from \"./vector-index.js\";\nimport type {\n  EmbeddingProvider,\n  HybridSearchResult,\n  CompressedObservation,\n  Memory,\n  QueryExpansion,\n} from \"../types.js\";\nimport { memoryToObservation } from \"./memory-utils.js\";\nimport type { StateKV } from \"./kv.js\";\nimport { KV } from \"./schema.js\";\nimport {\n  GraphRetrieval,\n  type GraphRetrievalResult,\n} from \"../functions/graph-retrieval.js\";\nimport { extractEntitiesFromQuery } from \"../functions/query-expansion.js\";\nimport { rerank } from \"./reranker.js\";\n\nconst RRF_K = 60;\n\nexport class HybridSearch {\n  private graphRetrieval: GraphRetrieval;\n\n  constructor(\n    private bm25: SearchIndex,\n    private vector: VectorIndex | null,\n    private embeddingProvider: EmbeddingProvider | null,\n    private kv: StateKV,\n    private bm25Weight = 0.4,\n    private vectorWeight = 0.6,\n    private graphWeight = 0.3,\n    private rerankEnabled = process.env.RERANK_ENABLED === \"true\",\n  ) {\n    this.graphRetrieval = new GraphRetrieval(kv);\n  }\n\n  async search(query: string, limit = 20): Promise<HybridSearchResult[]> {\n    return this.tripleStreamSearch(query, limit);\n  }\n\n  async searchWithExpansion(\n    query: string,\n    limit: number,\n    expansion: QueryExpansion,\n  ): Promise<HybridSearchResult[]> {\n    const allQueries = [\n      query,\n      ...expansion.reformulations,\n      ...expansion.temporalConcretizations,\n    ];\n\n    const allEntities = [\n      ...expansion.entityExtractions,\n      ...extractEntitiesFromQuery(query),\n    ];\n\n    const resultSets = await Promise.all(\n      allQueries.map((q) => this.tripleStreamSearch(q, limit, allEntities)),\n    );\n\n    const merged = new Map<string, HybridSearchResult>();\n    for (const results of resultSets) {\n      for (const r of results) {\n        const existing = merged.get(r.observation.id);\n        if (!existing || r.combinedScore > existing.combinedScore) {\n          merged.set(r.observation.id, r);\n        }\n      }\n    }\n\n    return Array.from(merged.values())\n      .sort((a, b) => b.combinedScore - a.combinedScore)\n      .slice(0, limit);\n  }\n\n  private async tripleStreamSearch(\n    query: string,\n    limit: number,\n    entityHints?: string[],\n  ): Promise<HybridSearchResult[]> {\n    const bm25Results = this.bm25.search(query, limit * 2);\n\n    let vectorResults: Array<{\n      obsId: string;\n      sessionId: string;\n      score: number;\n    }> = [];\n    let queryEmbedding: Float32Array | null = null;\n\n    if (this.vector && this.embeddingProvider && this.vector.size > 0) {\n      try {\n        queryEmbedding = await this.embeddingProvider.embed(query);\n        vectorResults = this.vector.search(queryEmbedding, limit * 2);\n      } catch {\n        // fall through to BM25-only\n      }\n    }\n\n    const entities =\n      entityHints && entityHints.length > 0\n        ? entityHints\n        : extractEntitiesFromQuery(query);\n    let graphResults: GraphRetrievalResult[] = [];\n    if (entities.length > 0) {\n      try {\n        graphResults = await this.graphRetrieval.searchByEntities(\n          entities,\n          2,\n          limit,\n        );\n      } catch {\n        // graph search is best-effort\n      }\n    }\n\n    const topVectorObs = vectorResults.slice(0, 5).map((r) => r.obsId);\n    if (topVectorObs.length > 0) {\n      try {\n        const expansionResults =\n          await this.graphRetrieval.expandFromChunks(topVectorObs, 1, 5);\n        graphResults = [...graphResults, ...expansionResults];\n      } catch {\n        // expansion is best-effort\n      }\n    }\n\n    const scores = new Map<\n      string,\n      {\n        bm25Rank: number;\n        vectorRank: number;\n        graphRank: number;\n        sessionId: string;\n        bm25Score: number;\n        vectorScore: number;\n        graphScore: number;\n        graphContext?: string;\n      }\n    >();\n\n    bm25Results.forEach((r, i) => {\n      scores.set(r.obsId, {\n        bm25Rank: i + 1,\n        vectorRank: Infinity,\n        graphRank: Infinity,\n        sessionId: r.sessionId,\n        bm25Score: r.score,\n        vectorScore: 0,\n        graphScore: 0,\n      });\n    });\n\n    vectorResults.forEach((r, i) => {\n      const existing = scores.get(r.obsId);\n      if (existing) {\n        existing.vectorRank = i + 1;\n        existing.vectorScore = r.score;\n      } else {\n        scores.set(r.obsId, {\n          bm25Rank: Infinity,\n          vectorRank: i + 1,\n          graphRank: Infinity,\n          sessionId: r.sessionId,\n          bm25Score: 0,\n          vectorScore: r.score,\n          graphScore: 0,\n        });\n      }\n    });\n\n    graphResults.forEach((r, i) => {\n      const existing = scores.get(r.obsId);\n      if (existing) {\n        existing.graphRank = Math.min(existing.graphRank, i + 1);\n        existing.graphScore = Math.max(existing.graphScore, r.score);\n        if (r.graphContext && !existing.graphContext) {\n          existing.graphContext = r.graphContext;\n        }\n      } else {\n        scores.set(r.obsId, {\n          bm25Rank: Infinity,\n          vectorRank: Infinity,\n          graphRank: i + 1,\n          sessionId: r.sessionId,\n          bm25Score: 0,\n          vectorScore: 0,\n          graphScore: r.score,\n          graphContext: r.graphContext,\n        });\n      }\n    });\n\n    const hasVector = vectorResults.length > 0;\n    const hasGraph = graphResults.length > 0;\n\n    let effectiveBm25W = this.bm25Weight;\n    let effectiveVectorW = hasVector ? this.vectorWeight : 0;\n    let effectiveGraphW = hasGraph ? this.graphWeight : 0;\n\n    const totalW = effectiveBm25W + effectiveVectorW + effectiveGraphW;\n    if (totalW > 0) {\n      effectiveBm25W /= totalW;\n      effectiveVectorW /= totalW;\n      effectiveGraphW /= totalW;\n    }\n\n    const combined = Array.from(scores.entries()).map(([obsId, s]) => ({\n      obsId,\n      sessionId: s.sessionId,\n      bm25Score: s.bm25Score,\n      vectorScore: s.vectorScore,\n      graphScore: s.graphScore,\n      graphContext: s.graphContext,\n      combinedScore:\n        effectiveBm25W * (1 / (RRF_K + s.bm25Rank)) +\n        effectiveVectorW * (1 / (RRF_K + s.vectorRank)) +\n        effectiveGraphW * (1 / (RRF_K + s.graphRank)),\n    }));\n\n    combined.sort((a, b) => b.combinedScore - a.combinedScore);\n\n    const retrievalDepth = Math.max(limit, 20);\n    const rerankWindow = 20;\n    const diversified = this.diversifyBySession(combined, retrievalDepth);\n    const enriched = await this.enrichResults(diversified, retrievalDepth);\n\n    if (this.rerankEnabled && enriched.length > 1) {\n      try {\n        const head = enriched.slice(0, rerankWindow);\n        const tail = enriched.slice(rerankWindow);\n        const reranked = await rerank(query, head, rerankWindow);\n        return reranked.concat(tail).slice(0, limit);\n      } catch {\n        return enriched.slice(0, limit);\n      }\n    }\n\n    return enriched.slice(0, limit);\n  }\n\n  private diversifyBySession(\n    results: Array<{\n      obsId: string;\n      sessionId: string;\n      bm25Score: number;\n      vectorScore: number;\n      graphScore: number;\n      combinedScore: number;\n      graphContext?: string;\n    }>,\n    limit: number,\n    maxPerSession = 3,\n  ): typeof results {\n    const selected: typeof results = [];\n    const sessionCounts = new Map<string, number>();\n\n    for (const r of results) {\n      const count = sessionCounts.get(r.sessionId) || 0;\n      if (count >= maxPerSession) continue;\n      selected.push(r);\n      sessionCounts.set(r.sessionId, count + 1);\n      if (selected.length >= limit) break;\n    }\n\n    if (selected.length < limit) {\n      for (const r of results) {\n        if (selected.length >= limit) break;\n        if (!selected.some(s => s.obsId === r.obsId)) {\n          selected.push(r);\n        }\n      }\n    }\n\n    return selected;\n  }\n\n  private async enrichResults(\n    results: Array<{\n      obsId: string;\n      sessionId: string;\n      bm25Score: number;\n      vectorScore: number;\n      graphScore: number;\n      combinedScore: number;\n      graphContext?: string;\n    }>,\n    limit: number,\n  ): Promise<HybridSearchResult[]> {\n    const sliced = results.slice(0, limit);\n    const observations = await Promise.all(\n      sliced.map(async (r) => {\n        const obs = await this.kv\n          .get<CompressedObservation>(KV.observations(r.sessionId), r.obsId)\n          .catch(() => null);\n        if (obs) return obs;\n        // Fallback: indexed entry may originate from mem::remember, which\n        // writes to KV.memories with a synthetic sessionId (\"memory\" or the\n        // memory's first associated session). Coerce the Memory record into\n        // a CompressedObservation so search/recall surface saved memories.\n        const mem = await this.kv\n          .get<Memory>(KV.memories, r.obsId)\n          .catch(() => null);\n        return mem ? memoryToObservation(mem) : null;\n      }),\n    );\n    const enriched: HybridSearchResult[] = [];\n    for (let i = 0; i < sliced.length; i++) {\n      const obs = observations[i];\n      if (obs) {\n        enriched.push({\n          observation: obs,\n          bm25Score: sliced[i].bm25Score,\n          vectorScore: sliced[i].vectorScore,\n          graphScore: sliced[i].graphScore,\n          combinedScore: sliced[i].combinedScore,\n          sessionId: sliced[i].sessionId,\n          graphContext: sliced[i].graphContext,\n        });\n      }\n    }\n    return enriched;\n  }\n}\n","const step2map: Record<string, string> = {\n  ational: \"ate\", tional: \"tion\", enci: \"ence\", anci: \"ance\",\n  izer: \"ize\", iser: \"ise\", abli: \"able\", alli: \"al\",\n  entli: \"ent\", eli: \"e\", ousli: \"ous\", ization: \"ize\",\n  isation: \"ise\", ation: \"ate\", ator: \"ate\", alism: \"al\",\n  iveness: \"ive\", fulness: \"ful\", ousness: \"ous\", aliti: \"al\",\n  iviti: \"ive\", biliti: \"ble\",\n};\n\nconst step3map: Record<string, string> = {\n  icate: \"ic\", ative: \"\", alize: \"al\", alise: \"al\",\n  iciti: \"ic\", ical: \"ic\", ful: \"\", ness: \"\",\n};\n\nfunction hasVowel(s: string): boolean {\n  return /[aeiou]/.test(s);\n}\n\nfunction measure(s: string): number {\n  const reduced = s.replace(/[^aeiouy]+/g, \"C\").replace(/[aeiouy]+/g, \"V\");\n  const m = reduced.match(/VC/g);\n  return m ? m.length : 0;\n}\n\nfunction endsDoubleConsonant(s: string): boolean {\n  return s.length >= 2 && s[s.length - 1] === s[s.length - 2] && !/[aeiou]/.test(s[s.length - 1]);\n}\n\nfunction endsCVC(s: string): boolean {\n  if (s.length < 3) return false;\n  const c1 = s[s.length - 3], v = s[s.length - 2], c2 = s[s.length - 1];\n  return !/[aeiou]/.test(c1) && /[aeiou]/.test(v) && !/[aeiouwxy]/.test(c2);\n}\n\nexport function stem(word: string): string {\n  if (word.length <= 2) return word;\n\n  let w = word;\n\n  if (w.endsWith(\"sses\")) w = w.slice(0, -2);\n  else if (w.endsWith(\"ies\")) w = w.slice(0, -2);\n  else if (!w.endsWith(\"ss\") && w.endsWith(\"s\")) w = w.slice(0, -1);\n\n  if (w.endsWith(\"eed\")) {\n    if (measure(w.slice(0, -3)) > 0) w = w.slice(0, -1);\n  } else if (w.endsWith(\"ed\") && hasVowel(w.slice(0, -2))) {\n    w = w.slice(0, -2);\n    if (w.endsWith(\"at\") || w.endsWith(\"bl\") || w.endsWith(\"iz\")) w += \"e\";\n    else if (endsDoubleConsonant(w) && !/[lsz]$/.test(w)) w = w.slice(0, -1);\n    else if (measure(w) === 1 && endsCVC(w)) w += \"e\";\n  } else if (w.endsWith(\"ing\") && hasVowel(w.slice(0, -3))) {\n    w = w.slice(0, -3);\n    if (w.endsWith(\"at\") || w.endsWith(\"bl\") || w.endsWith(\"iz\")) w += \"e\";\n    else if (endsDoubleConsonant(w) && !/[lsz]$/.test(w)) w = w.slice(0, -1);\n    else if (measure(w) === 1 && endsCVC(w)) w += \"e\";\n  }\n\n  if (w.endsWith(\"y\") && hasVowel(w.slice(0, -1))) {\n    w = w.slice(0, -1) + \"i\";\n  }\n\n  for (const [suffix, replacement] of Object.entries(step2map)) {\n    if (w.endsWith(suffix)) {\n      const base = w.slice(0, -suffix.length);\n      if (measure(base) > 0) w = base + replacement;\n      break;\n    }\n  }\n\n  for (const [suffix, replacement] of Object.entries(step3map)) {\n    if (w.endsWith(suffix)) {\n      const base = w.slice(0, -suffix.length);\n      if (measure(base) > 0) w = base + replacement;\n      break;\n    }\n  }\n\n  if (w.endsWith(\"al\") || w.endsWith(\"ance\") || w.endsWith(\"ence\") ||\n      w.endsWith(\"er\") || w.endsWith(\"ic\") || w.endsWith(\"able\") ||\n      w.endsWith(\"ible\") || w.endsWith(\"ant\") || w.endsWith(\"ement\") ||\n      w.endsWith(\"ment\") || w.endsWith(\"ent\") || w.endsWith(\"tion\") ||\n      w.endsWith(\"sion\") || w.endsWith(\"ou\") || w.endsWith(\"ism\") ||\n      w.endsWith(\"ate\") || w.endsWith(\"iti\") || w.endsWith(\"ous\") ||\n      w.endsWith(\"ive\") || w.endsWith(\"ize\") || w.endsWith(\"ise\")) {\n    const suffixLen = w.match(/(ement|ment|tion|sion|ance|ence|able|ible|ism|ate|iti|ous|ive|ize|ise|ant|ent|al|er|ic|ou)$/)?.[0]?.length ?? 0;\n    if (suffixLen > 0) {\n      const base = w.slice(0, -suffixLen);\n      if (measure(base) > 1) w = base;\n    }\n  }\n\n  if (w.endsWith(\"e\")) {\n    const base = w.slice(0, -1);\n    if (measure(base) > 1 || (measure(base) === 1 && !endsCVC(base))) {\n      w = base;\n    }\n  }\n\n  if (endsDoubleConsonant(w) && w.endsWith(\"l\") && measure(w.slice(0, -1)) > 1) {\n    w = w.slice(0, -1);\n  }\n\n  return w;\n}\n","import { stem } from \"./stemmer.js\";\n\nconst SYNONYM_GROUPS: string[][] = [\n  [\"auth\", \"authentication\", \"authn\", \"authenticating\"],\n  [\"authz\", \"authorization\", \"authorizing\"],\n  [\"db\", \"database\", \"datastore\"],\n  [\"perf\", \"performance\", \"latency\", \"throughput\", \"slow\", \"bottleneck\"],\n  [\"optim\", \"optimization\", \"optimizing\", \"optimise\", \"query-optimization\"],\n  [\"k8s\", \"kubernetes\", \"kube\"],\n  [\"config\", \"configuration\", \"configuring\", \"setup\"],\n  [\"deps\", \"dependencies\", \"dependency\"],\n  [\"env\", \"environment\"],\n  [\"fn\", \"function\"],\n  [\"impl\", \"implementation\", \"implementing\"],\n  [\"msg\", \"message\", \"messaging\"],\n  [\"repo\", \"repository\"],\n  [\"req\", \"request\"],\n  [\"res\", \"response\"],\n  [\"ts\", \"typescript\"],\n  [\"js\", \"javascript\"],\n  [\"pg\", \"postgres\", \"postgresql\"],\n  [\"err\", \"error\", \"errors\"],\n  [\"api\", \"endpoint\", \"endpoints\"],\n  [\"ci\", \"continuous-integration\"],\n  [\"cd\", \"continuous-deployment\"],\n  [\"test\", \"testing\", \"tests\"],\n  [\"doc\", \"documentation\", \"docs\"],\n  [\"infra\", \"infrastructure\"],\n  [\"deploy\", \"deployment\", \"deploying\"],\n  [\"cache\", \"caching\", \"cached\"],\n  [\"log\", \"logging\", \"logs\"],\n  [\"monitor\", \"monitoring\"],\n  [\"observe\", \"observability\"],\n  [\"sec\", \"security\", \"secure\"],\n  [\"validate\", \"validation\", \"validating\"],\n  [\"migrate\", \"migration\", \"migrations\"],\n  [\"debug\", \"debugging\"],\n  [\"container\", \"containerization\", \"docker\"],\n  [\"crash\", \"crashloop\", \"crashloopbackoff\"],\n  [\"webhook\", \"webhooks\", \"callback\"],\n  [\"middleware\", \"mw\"],\n  [\"paginate\", \"pagination\"],\n  [\"serialize\", \"serialization\"],\n  [\"encrypt\", \"encryption\"],\n  [\"hash\", \"hashing\"],\n];\n\nconst synonymMap = new Map<string, Set<string>>();\n\nfor (const group of SYNONYM_GROUPS) {\n  const stemmed = group.map(t => stem(t.toLowerCase()));\n  for (const s of stemmed) {\n    if (!synonymMap.has(s)) synonymMap.set(s, new Set());\n    for (const other of stemmed) {\n      if (other !== s) synonymMap.get(s)!.add(other);\n    }\n  }\n}\n\nexport function getSynonyms(stemmedTerm: string): string[] {\n  const syns = synonymMap.get(stemmedTerm);\n  return syns ? [...syns] : [];\n}\n","import { createRequire } from \"node:module\";\n\nconst cjkRequire = createRequire(import.meta.url);\n\nconst CJK_RE = /[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]/u;\nconst HAN_RE = /\\p{Script=Han}/u;\nconst KANA_RE = /[\\p{Script=Hiragana}\\p{Script=Katakana}]/u;\nconst HANGUL_RE = /\\p{Script=Hangul}/u;\nconst CJK_RUN_RE = /[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]+/gu;\nconst HANGUL_BLOCK_RE = /[가-힯]+/g;\n\ntype Script = \"han\" | \"kana\" | \"hangul\" | \"other\";\n\nconst hintShown = new Set<string>();\n\nexport function hasCjk(text: string): boolean {\n  return CJK_RE.test(text);\n}\n\nexport function detectScript(text: string): Script {\n  if (HAN_RE.test(text)) return \"han\";\n  if (KANA_RE.test(text)) return \"kana\";\n  if (HANGUL_RE.test(text)) return \"hangul\";\n  return \"other\";\n}\n\nfunction showHintOnce(key: string, message: string): void {\n  if (hintShown.has(key)) return;\n  hintShown.add(key);\n  if (typeof process !== \"undefined\" && process.stderr?.write) {\n    process.stderr.write(`agentmemory: ${message}\\n`);\n  }\n}\n\ninterface JiebaInstance {\n  cut(text: string, hmm?: boolean): string[];\n}\n\nlet jiebaInstance: JiebaInstance | null = null;\nlet jiebaLoaded = false;\n\nfunction getJieba(): JiebaInstance | null {\n  if (jiebaLoaded) return jiebaInstance;\n  jiebaLoaded = true;\n  try {\n    const mod = cjkRequire(\"@node-rs/jieba\") as {\n      Jieba: {\n        new (): JiebaInstance;\n        withDict(dict: Uint8Array): JiebaInstance;\n      };\n    };\n    try {\n      const dictMod = cjkRequire(\"@node-rs/jieba/dict\") as { dict: Uint8Array };\n      jiebaInstance = mod.Jieba.withDict(dictMod.dict);\n    } catch {\n      jiebaInstance = new mod.Jieba();\n    }\n    return jiebaInstance;\n  } catch {\n    showHintOnce(\n      \"jieba\",\n      \"install @node-rs/jieba to improve Chinese search; falling back to whole-string tokenization\",\n    );\n    return null;\n  }\n}\n\ninterface JaSegmenter {\n  segment(text: string): string[];\n}\n\nlet jaSegmenterInstance: JaSegmenter | null = null;\nlet jaSegmenterLoaded = false;\n\nfunction getJaSegmenter(): JaSegmenter | null {\n  if (jaSegmenterLoaded) return jaSegmenterInstance;\n  jaSegmenterLoaded = true;\n  try {\n    const Ctor = cjkRequire(\"tiny-segmenter\") as new () => JaSegmenter;\n    jaSegmenterInstance = new Ctor();\n    return jaSegmenterInstance;\n  } catch {\n    showHintOnce(\n      \"tiny-segmenter\",\n      \"install tiny-segmenter to improve Japanese search; falling back to whole-string tokenization\",\n    );\n    return null;\n  }\n}\n\nfunction cleanTokens(tokens: string[]): string[] {\n  const out: string[] = [];\n  for (const t of tokens) {\n    const trimmed = t.trim();\n    if (trimmed) out.push(trimmed);\n  }\n  return out;\n}\n\nfunction segmentHan(text: string): string[] {\n  const j = getJieba();\n  if (!j) return [text];\n  try {\n    return cleanTokens(j.cut(text, true));\n  } catch {\n    return [text];\n  }\n}\n\nfunction segmentKana(text: string): string[] {\n  const s = getJaSegmenter();\n  if (!s) return [text];\n  try {\n    return cleanTokens(s.segment(text));\n  } catch {\n    return [text];\n  }\n}\n\nfunction segmentHangul(text: string): string[] {\n  const out: string[] = [];\n  for (const m of text.matchAll(HANGUL_BLOCK_RE)) {\n    if (m[0]) out.push(m[0]);\n  }\n  return out;\n}\n\nexport function segmentCjk(text: string): string[] {\n  if (!hasCjk(text)) return [text];\n\n  const out: string[] = [];\n  let cursor = 0;\n\n  for (const m of text.matchAll(CJK_RUN_RE)) {\n    const start = m.index ?? 0;\n    const run = m[0];\n    const end = start + run.length;\n\n    if (start > cursor) {\n      const piece = text.slice(cursor, start).trim();\n      if (piece) out.push(piece);\n    }\n\n    if (HANGUL_RE.test(run)) {\n      out.push(...segmentHangul(run));\n    } else if (KANA_RE.test(run)) {\n      out.push(...segmentKana(run));\n    } else {\n      out.push(...segmentHan(run));\n    }\n\n    cursor = end;\n  }\n\n  if (cursor < text.length) {\n    const trailing = text.slice(cursor).trim();\n    if (trailing) out.push(trailing);\n  }\n\n  return out;\n}\n\nexport function __resetCjkSegmenterStateForTests(): void {\n  hintShown.clear();\n  jiebaInstance = null;\n  jiebaLoaded = false;\n  jaSegmenterInstance = null;\n  jaSegmenterLoaded = false;\n}\n","import type { CompressedObservation } from \"../types.js\";\nimport { stem } from \"./stemmer.js\";\nimport { getSynonyms } from \"./synonyms.js\";\nimport { segmentCjk, hasCjk } from \"./cjk-segmenter.js\";\n\ninterface IndexEntry {\n  obsId: string;\n  sessionId: string;\n  termCount: number;\n}\n\nexport class SearchIndex {\n  private entries: Map<string, IndexEntry> = new Map();\n  private invertedIndex: Map<string, Set<string>> = new Map();\n  private docTermCounts: Map<string, Map<string, number>> = new Map();\n  private totalDocLength = 0;\n  private sortedTerms: string[] | null = null;\n\n  private readonly k1 = 1.2;\n  private readonly b = 0.75;\n\n  add(obs: CompressedObservation): void {\n    const terms = this.extractTerms(obs);\n    const termFreq = new Map<string, number>();\n    let termCount = 0;\n\n    for (const term of terms) {\n      termFreq.set(term, (termFreq.get(term) || 0) + 1);\n      termCount++;\n    }\n\n    this.entries.set(obs.id, {\n      obsId: obs.id,\n      sessionId: obs.sessionId,\n      termCount,\n    });\n    this.docTermCounts.set(obs.id, termFreq);\n    this.totalDocLength += termCount;\n\n    for (const term of termFreq.keys()) {\n      if (!this.invertedIndex.has(term)) {\n        this.invertedIndex.set(term, new Set());\n      }\n      this.invertedIndex.get(term)!.add(obs.id);\n    }\n\n    this.sortedTerms = null;\n  }\n\n  has(id: string): boolean {\n    return this.entries.has(id);\n  }\n\n  remove(id: string): void {\n    const entry = this.entries.get(id);\n    if (!entry) return;\n\n    const termFreq = this.docTermCounts.get(id);\n    if (termFreq) {\n      for (const term of termFreq.keys()) {\n        const postingList = this.invertedIndex.get(term);\n        if (postingList) {\n          postingList.delete(id);\n          if (postingList.size === 0) {\n            this.invertedIndex.delete(term);\n          }\n        }\n      }\n      this.docTermCounts.delete(id);\n    }\n\n    this.totalDocLength = Math.max(0, this.totalDocLength - entry.termCount);\n    this.entries.delete(id);\n    this.sortedTerms = null;\n  }\n\n  search(\n    query: string,\n    limit = 20,\n  ): Array<{ obsId: string; sessionId: string; score: number }> {\n    const rawTerms = this.tokenize(query.toLowerCase());\n    if (rawTerms.length === 0) return [];\n\n    const N = this.entries.size;\n    if (N === 0) return [];\n    const avgDocLen = this.totalDocLength / N;\n\n    const queryTerms: Array<{ term: string; weight: number }> = [];\n    const seen = new Set<string>();\n    for (const term of rawTerms) {\n      if (!seen.has(term)) {\n        seen.add(term);\n        queryTerms.push({ term, weight: 1.0 });\n      }\n      for (const syn of getSynonyms(term)) {\n        if (!seen.has(syn)) {\n          seen.add(syn);\n          queryTerms.push({ term: syn, weight: 0.7 });\n        }\n      }\n    }\n\n    const scores = new Map<string, number>();\n    const sorted = this.getSortedTerms();\n\n    for (const { term, weight } of queryTerms) {\n      const matchingDocs = this.invertedIndex.get(term);\n      if (matchingDocs) {\n        const df = matchingDocs.size;\n        const idf = Math.log((N - df + 0.5) / (df + 0.5) + 1);\n\n        for (const obsId of matchingDocs) {\n          const entry = this.entries.get(obsId)!;\n          const docTerms = this.docTermCounts.get(obsId);\n          const tf = docTerms?.get(term) || 0;\n          const docLen = entry.termCount;\n\n          const numerator = tf * (this.k1 + 1);\n          const denominator =\n            tf + this.k1 * (1 - this.b + this.b * (docLen / avgDocLen));\n          const bm25Score = idf * (numerator / denominator) * weight;\n\n          scores.set(obsId, (scores.get(obsId) || 0) + bm25Score);\n        }\n      }\n\n      const startIdx = this.lowerBound(sorted, term);\n      for (let si = startIdx; si < sorted.length; si++) {\n        const indexTerm = sorted[si];\n        if (!indexTerm.startsWith(term)) break;\n        if (indexTerm === term) continue;\n\n        const obsIds = this.invertedIndex.get(indexTerm)!;\n        const prefixDf = obsIds.size;\n        const prefixIdf =\n          Math.log((N - prefixDf + 0.5) / (prefixDf + 0.5) + 1) * 0.5;\n        for (const obsId of obsIds) {\n          const entry = this.entries.get(obsId)!;\n          const docTerms = this.docTermCounts.get(obsId);\n          const tf = docTerms?.get(indexTerm) || 0;\n          const docLen = entry.termCount;\n          const numerator = tf * (this.k1 + 1);\n          const denominator =\n            tf + this.k1 * (1 - this.b + this.b * (docLen / avgDocLen));\n          scores.set(\n            obsId,\n            (scores.get(obsId) || 0) + prefixIdf * (numerator / denominator) * weight,\n          );\n        }\n      }\n    }\n\n    return Array.from(scores.entries())\n      .map(([obsId, score]) => {\n        const entry = this.entries.get(obsId)!;\n        return { obsId, sessionId: entry.sessionId, score };\n      })\n      .sort((a, b) => b.score - a.score)\n      .slice(0, limit);\n  }\n\n  get size(): number {\n    return this.entries.size;\n  }\n\n  clear(): void {\n    this.entries.clear();\n    this.invertedIndex.clear();\n    this.docTermCounts.clear();\n    this.totalDocLength = 0;\n    this.sortedTerms = null;\n  }\n\n  restoreFrom(other: SearchIndex): void {\n    this.entries = new Map(\n      Array.from(other.entries.entries()).map(([k, v]) => [k, { ...v }]),\n    );\n    this.invertedIndex = new Map(\n      Array.from(other.invertedIndex.entries()).map(([k, v]) => [\n        k,\n        new Set(v),\n      ]),\n    );\n    this.docTermCounts = new Map(\n      Array.from(other.docTermCounts.entries()).map(([k, v]) => [\n        k,\n        new Map(v),\n      ]),\n    );\n    this.totalDocLength = other.totalDocLength;\n    this.sortedTerms = null;\n  }\n\n  serialize(): string {\n    const entries = Array.from(this.entries.entries());\n    const inverted = Array.from(this.invertedIndex.entries()).map(\n      ([term, ids]) => [term, Array.from(ids)] as [string, string[]],\n    );\n    const docTerms = Array.from(this.docTermCounts.entries()).map(\n      ([id, counts]) =>\n        [id, Array.from(counts.entries())] as [string, [string, number][]],\n    );\n    return JSON.stringify({\n      v: 2,\n      entries,\n      inverted,\n      docTerms,\n      totalDocLength: this.totalDocLength,\n    });\n  }\n\n  static deserialize(json: string): SearchIndex {\n    try {\n      const idx = new SearchIndex();\n      const data = JSON.parse(json);\n      if (!data?.entries || !data?.inverted || !data?.docTerms) return idx;\n      for (const [key, val] of data.entries) {\n        idx.entries.set(key, val);\n      }\n      for (const [term, ids] of data.inverted) {\n        idx.invertedIndex.set(term, new Set(ids));\n      }\n      for (const [id, counts] of data.docTerms) {\n        idx.docTermCounts.set(id, new Map(counts));\n      }\n      const rawLen = Number(data.totalDocLength);\n      idx.totalDocLength =\n        Number.isFinite(rawLen) && rawLen >= 0 ? Math.floor(rawLen) : 0;\n      return idx;\n    } catch {\n      return new SearchIndex();\n    }\n  }\n\n  private extractTerms(obs: CompressedObservation): string[] {\n    const parts = [\n      obs.title,\n      obs.subtitle || \"\",\n      obs.narrative,\n      ...obs.facts,\n      ...obs.concepts,\n      ...obs.files,\n      obs.type,\n    ];\n    return this.tokenize(parts.join(\" \").toLowerCase());\n  }\n\n  private tokenize(text: string): string[] {\n    const cleaned = text.replace(/[^\\p{L}\\p{N}\\s/.\\\\-_]/gu, \" \");\n    const out: string[] = [];\n    for (const raw of cleaned.split(/\\s+/)) {\n      if (raw.length < 2) continue;\n      if (hasCjk(raw)) {\n        for (const seg of segmentCjk(raw)) {\n          if (seg.length >= 1) out.push(seg);\n        }\n      } else {\n        out.push(stem(raw));\n      }\n    }\n    return out;\n  }\n\n  private getSortedTerms(): string[] {\n    if (!this.sortedTerms) {\n      this.sortedTerms = Array.from(this.invertedIndex.keys()).sort();\n    }\n    return this.sortedTerms;\n  }\n\n  private lowerBound(arr: string[], target: string): number {\n    let lo = 0;\n    let hi = arr.length;\n    while (lo < hi) {\n      const mid = (lo + hi) >>> 1;\n      if (arr[mid] < target) lo = mid + 1;\n      else hi = mid;\n    }\n    return lo;\n  }\n}\n","import type { AuditEntry } from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { logger } from \"../logger.js\";\n\n// Audit coverage policy (issue #125).\n//\n// Every structural deletion of a memory, observation, session, or\n// semantic row MUST call recordAudit. Two shapes are allowed, keyed to\n// whether the caller is scoped or bulk:\n//\n//   Scoped deletions — a user-visible, per-call action removing a\n//   bounded set of items. Emit ONE audit row per call with targetIds\n//   populated. Examples: mem::governance-delete, mem::forget.\n//\n//   Bulk deletions — automatic sweeps (retention, TTL eviction,\n//   auto-forget) that can remove hundreds of rows per invocation.\n//   Emit ONE batched audit row per invocation with targetIds listing\n//   every removed id and details.evicted holding the count. Per-item\n//   audit rows would flood the audit log during routine sweeps.\n//\n//   Either shape is required; silent deletes are not acceptable.\n//\n// operation field:\n//   - \"delete\"          — permanent removal (governance, retention sweep, evict).\n//   - \"forget\"          — forget/removal flows. Scoped when emitted by\n//                         mem::forget (user-initiated); bulk-batched when\n//                         emitted by mem::auto-forget (automatic sweep).\n//   - everything else   — see AuditEntry[\"operation\"] union in src/types.ts.\n//\n// When adding a new deletion path, add an explicit recordAudit call\n// BEFORE kv.delete(...) and match one of the two shapes above.\n\nexport async function recordAudit(\n  kv: StateKV,\n  operation: AuditEntry[\"operation\"],\n  functionId: string,\n  targetIds: string[],\n  details: Record<string, unknown> = {},\n  qualityScore?: number,\n  userId?: string,\n): Promise<AuditEntry> {\n  const entry: AuditEntry = {\n    id: generateId(\"aud\"),\n    timestamp: new Date().toISOString(),\n    operation,\n    userId,\n    functionId,\n    targetIds,\n    details,\n    qualityScore,\n  };\n  await kv.set(KV.audit, entry.id, entry);\n  return entry;\n}\n\nexport async function safeAudit(\n  kv: StateKV,\n  operation: AuditEntry[\"operation\"],\n  functionId: string,\n  targetIds: string[],\n  details: Record<string, unknown> = {},\n  qualityScore?: number,\n  userId?: string,\n): Promise<void> {\n  try {\n    await recordAudit(kv, operation, functionId, targetIds, details, qualityScore, userId);\n  } catch (err) {\n    try {\n      logger.warn(\"audit write failed\", {\n        functionId,\n        operation,\n        targetIds,\n        error: err instanceof Error ? err.message : String(err),\n      });\n    } catch {}\n  }\n}\n\nexport async function queryAudit(\n  kv: StateKV,\n  filter?: {\n    operation?: AuditEntry[\"operation\"];\n    dateFrom?: string;\n    dateTo?: string;\n    limit?: number;\n  },\n): Promise<AuditEntry[]> {\n  const all = await kv.list<AuditEntry>(KV.audit);\n  let entries = [...all].sort(\n    (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n  );\n\n  if (filter?.operation) {\n    entries = entries.filter((e) => e.operation === filter.operation);\n  }\n  if (filter?.dateFrom) {\n    const from = new Date(filter.dateFrom).getTime();\n    if (Number.isNaN(from)) {\n      throw new Error(`Invalid dateFrom: ${filter.dateFrom}`);\n    }\n    entries = entries.filter((e) => new Date(e.timestamp).getTime() >= from);\n  }\n  if (filter?.dateTo) {\n    const to = new Date(filter.dateTo).getTime();\n    if (Number.isNaN(to)) {\n      throw new Error(`Invalid dateTo: ${filter.dateTo}`);\n    }\n    entries = entries.filter((e) => new Date(e.timestamp).getTime() <= to);\n  }\n\n  return entries.slice(0, filter?.limit || 100);\n}\n","import { SearchIndex } from \"./search-index.js\";\nimport { VectorIndex } from \"./vector-index.js\";\nimport type { StateKV } from \"./kv.js\";\nimport { KV, generateId } from \"./schema.js\";\nimport { logger } from \"../logger.js\";\nimport { safeAudit } from \"../functions/audit.js\";\n\nconst DEBOUNCE_MS = 5000;\nconst FAILURE_LOG_THROTTLE_MS = 60_000;\nconst INDEX_PERSISTENCE_FUNCTION_ID = \"mem::index-persistence\";\nconst BM25_KEY = \"data\";\nconst BM25_MANIFEST_KEY = \"data:manifest\";\nconst BM25_SHARD_SCOPE_PREFIX = `${KV.bm25Index}:bm25:`;\nconst VECTOR_KEY = \"vectors\";\nconst VECTOR_MANIFEST_KEY = \"vectors:manifest\";\nconst VECTOR_SHARD_SCOPE_PREFIX = `${KV.bm25Index}:vectors:`;\nconst INDEX_SHARD_KEY = \"data\";\nconst DEFAULT_INDEX_SHARD_CHARS = 2_000_000;\n\ntype IndexShardManifest = {\n  v: 1;\n  generation?: string;\n  shards: Array<{ scope: string; key: string; chars: number }>;\n  chars: number;\n};\n\ntype IndexPersistenceOptions = {\n  shardChars?: number;\n  createGeneration?: () => string;\n};\n\nfunction shardChars(options: IndexPersistenceOptions): number {\n  const configured = options.shardChars;\n  if (typeof configured !== \"number\" || !Number.isFinite(configured)) {\n    return DEFAULT_INDEX_SHARD_CHARS;\n  }\n  const wholeChars = Math.floor(configured);\n  return wholeChars >= 1 ? wholeChars : DEFAULT_INDEX_SHARD_CHARS;\n}\n\nfunction createIndexGeneration(): string {\n  return generateId(\"idx\");\n}\n\nfunction statePath(scope: string, key: string): string {\n  return `${scope}/${key}`;\n}\n\nfunction errorMessage(err: unknown): string {\n  return err instanceof Error ? err.message : String(err);\n}\n\nfunction isValidShardDescriptor(\n  shard: unknown,\n): shard is IndexShardManifest[\"shards\"][number] {\n  if (!shard || typeof shard !== \"object\") return false;\n  const candidate = shard as { scope?: unknown; key?: unknown; chars?: unknown };\n  return (\n    typeof candidate.scope === \"string\" &&\n    candidate.scope.length > 0 &&\n    typeof candidate.key === \"string\" &&\n    candidate.key.length > 0 &&\n    Number.isInteger(candidate.chars) &&\n    candidate.chars >= 0\n  );\n}\n\nexport class IndexPersistence {\n  private timer: ReturnType<typeof setTimeout> | null = null;\n  private lastFailureLogAt = 0;\n\n  constructor(\n    private kv: StateKV,\n    private bm25: SearchIndex,\n    private vector: VectorIndex | null,\n    private options: IndexPersistenceOptions = {},\n  ) {}\n\n  scheduleSave(): void {\n    if (this.timer) clearTimeout(this.timer);\n    // setTimeout discards the returned promise, so any rejection inside\n    // save() would surface as unhandledRejection and crash the process\n    // under sustained iii-engine write timeouts (issue #204). Funnel\n    // rejections through logFailure() instead.\n    this.timer = setTimeout(() => {\n      this.save().catch((err) => this.logFailure(err));\n    }, DEBOUNCE_MS);\n  }\n\n  async save(): Promise<void> {\n    if (this.timer) {\n      clearTimeout(this.timer);\n      this.timer = null;\n    }\n    try {\n      await this.saveBm25Index(this.bm25.serialize());\n      if (this.vector) {\n        await this.saveVectorIndex(this.vector.serialize());\n      }\n    } catch (err) {\n      this.logFailure(err);\n    }\n  }\n\n  async load(): Promise<{\n    bm25: SearchIndex | null;\n    vector: VectorIndex | null;\n  }> {\n    let bm25: SearchIndex | null = null;\n    let vector: VectorIndex | null = null;\n\n    const bm25Data = await this.loadBm25Data();\n    if (bm25Data && typeof bm25Data === \"string\") {\n      bm25 = SearchIndex.deserialize(bm25Data);\n    }\n\n    const vecData = await this.loadVectorData();\n    if (vecData && typeof vecData === \"string\") {\n      vector = VectorIndex.deserialize(vecData);\n    }\n\n    return { bm25, vector };\n  }\n\n  stop(): void {\n    if (this.timer) {\n      clearTimeout(this.timer);\n      this.timer = null;\n    }\n  }\n\n  private logFailure(err: unknown): void {\n    const now = Date.now();\n    // Throttle: persistence failures under load arrive in bursts\n    // (iii-engine queue pressure). Logging every debounce flush adds\n    // noise without information.\n    if (now - this.lastFailureLogAt < FAILURE_LOG_THROTTLE_MS) return;\n    this.lastFailureLogAt = now;\n    const code = (err as { code?: string })?.code;\n    const message = err instanceof Error ? err.message : String(err);\n    logger.warn(\"index persistence: failed to save BM25/vector index\", {\n      code,\n      message,\n      hint:\n        code === \"TIMEOUT\"\n          ? \"iii-engine state::set timed out; recent index updates remain in memory and will retry on the next debounce flush\"\n          : undefined,\n    });\n  }\n\n  private async saveBm25Index(serialized: string): Promise<void> {\n    await this.saveShardedIndex(\n      serialized,\n      BM25_MANIFEST_KEY,\n      BM25_KEY,\n      BM25_SHARD_SCOPE_PREFIX,\n    );\n  }\n\n  private async saveVectorIndex(serialized: string): Promise<void> {\n    await this.saveShardedIndex(\n      serialized,\n      VECTOR_MANIFEST_KEY,\n      VECTOR_KEY,\n      VECTOR_SHARD_SCOPE_PREFIX,\n    );\n  }\n\n  private async saveShardedIndex(\n    serialized: string,\n    manifestKey: string,\n    legacyKey: string,\n    scopePrefix: string,\n  ): Promise<void> {\n    const previous = await this.kv\n      .get<IndexShardManifest>(KV.bm25Index, manifestKey)\n      .catch(() => null);\n    const generation =\n      this.options.createGeneration?.() ?? createIndexGeneration();\n    const chunkChars = shardChars(this.options);\n    const shards: IndexShardManifest[\"shards\"] = [];\n    const chunks: string[] = [];\n\n    for (let offset = 0; offset < serialized.length; offset += chunkChars) {\n      const shardIndex = shards.length;\n      const scope = `${scopePrefix}${generation}:${String(shardIndex).padStart(\n        5,\n        \"0\",\n      )}`;\n      const chunk = serialized.slice(offset, offset + chunkChars);\n      shards.push({ scope, key: INDEX_SHARD_KEY, chars: chunk.length });\n      chunks.push(chunk);\n    }\n\n    const writeResults = await Promise.allSettled(\n      shards.map(async (shard, index) => {\n        const chunk = chunks[index] ?? \"\";\n        await this.kv.set(shard.scope, shard.key, chunk);\n        await this.auditIndexPersistence(\"shard_write\", [\n          statePath(shard.scope, shard.key),\n        ], {\n          scope: shard.scope,\n          key: shard.key,\n          manifestKey,\n          generation,\n          chars: chunk.length,\n        });\n      }),\n    );\n    const failedWrite = writeResults.find(\n      (result): result is PromiseRejectedResult => result.status === \"rejected\",\n    );\n    if (failedWrite) {\n      await this.deleteShards(shards, \"shard_write_rollback\");\n      throw failedWrite.reason;\n    }\n\n    const nextManifest: IndexShardManifest = {\n      v: 1,\n      generation,\n      shards,\n      chars: serialized.length,\n    };\n    try {\n      await this.kv.set<IndexShardManifest>(\n        KV.bm25Index,\n        manifestKey,\n        nextManifest,\n      );\n      await this.auditIndexPersistence(\"manifest_publish\", [\n        statePath(KV.bm25Index, manifestKey),\n      ], {\n        manifestKey,\n        generation,\n        chars: serialized.length,\n        shards: shards.length,\n        result: \"committed\",\n      });\n    } catch (err) {\n      if (await this.isManifestPublished(manifestKey, nextManifest)) {\n        await this.auditIndexPersistence(\"manifest_publish\", [\n          statePath(KV.bm25Index, manifestKey),\n        ], {\n          manifestKey,\n          generation,\n          chars: serialized.length,\n          shards: shards.length,\n          result: \"committed_after_error\",\n          error: errorMessage(err),\n        });\n      } else {\n        await this.deleteShards(shards, \"manifest_publish_rollback\");\n      }\n      throw err;\n    }\n\n    await this.deleteKey(KV.bm25Index, legacyKey, \"legacy_cleanup\");\n    if (previous?.v === 1 && Array.isArray(previous.shards)) {\n      const currentShardIds = new Set(\n        shards.map((shard) => `${shard.scope}\\0${shard.key}`),\n      );\n      for (const shard of previous.shards) {\n        if (currentShardIds.has(`${shard.scope}\\0${shard.key}`)) continue;\n        await this.deleteShards([shard], \"previous_generation_cleanup\");\n      }\n    }\n  }\n\n  private async auditIndexPersistence(\n    action: string,\n    targetIds: string[],\n    details: Record<string, unknown>,\n  ): Promise<void> {\n    await safeAudit(\n      this.kv,\n      \"index_persist\",\n      INDEX_PERSISTENCE_FUNCTION_ID,\n      targetIds,\n      { action, ...details },\n    );\n  }\n\n  private async deleteKey(\n    scope: string,\n    key: string,\n    reason: string,\n  ): Promise<void> {\n    let result = \"deleted\";\n    let error: string | undefined;\n    try {\n      await this.kv.delete(scope, key);\n    } catch (err) {\n      result = \"failed\";\n      error = errorMessage(err);\n    }\n    await this.auditIndexPersistence(\"delete\", [statePath(scope, key)], {\n      scope,\n      key,\n      reason,\n      result,\n      error,\n    });\n  }\n\n  private async deleteShards(\n    shards: IndexShardManifest[\"shards\"],\n    reason: string,\n  ): Promise<void> {\n    for (const shard of shards) {\n      await this.deleteKey(shard.scope, shard.key, reason);\n    }\n  }\n\n  private async isManifestPublished(\n    manifestKey: string,\n    expected: IndexShardManifest,\n  ): Promise<boolean> {\n    const published = await this.kv\n      .get<IndexShardManifest>(KV.bm25Index, manifestKey)\n      .catch(() => null);\n    if (\n      published?.v !== 1 ||\n      published.generation !== expected.generation ||\n      published.chars !== expected.chars ||\n      !Array.isArray(published.shards) ||\n      published.shards.length !== expected.shards.length\n    ) {\n      return false;\n    }\n    return published.shards.every((shard, index) => {\n      const expectedShard = expected.shards[index];\n      if (!expectedShard) return false;\n      return (\n        shard.scope === expectedShard.scope &&\n        shard.key === expectedShard.key &&\n        shard.chars === expectedShard.chars\n      );\n    });\n  }\n\n  private async loadBm25Data(): Promise<string | null> {\n    return this.loadShardedData(BM25_KEY, BM25_MANIFEST_KEY, \"BM25\");\n  }\n\n  private async loadVectorData(): Promise<string | null> {\n    return this.loadShardedData(VECTOR_KEY, VECTOR_MANIFEST_KEY, \"vector\");\n  }\n\n  private async loadShardedData(\n    legacyKey: string,\n    manifestKey: string,\n    label: string,\n  ): Promise<string | null> {\n    const manifest = await this.readIndexValue<IndexShardManifest>(\n      KV.bm25Index,\n      manifestKey,\n      label,\n      \"manifest\",\n    );\n    if (!manifest.ok) return null;\n    // #797: some iii-state adapters return `undefined` (not `null`) for\n    // a missing key. The previous `value !== null` check passed\n    // undefined through to loadManifestData, which then crashed on\n    // `manifest.v` with TypeError. Treat both null and undefined as\n    // \"no manifest\" and fall through to the legacy path. The shape\n    // check stays so a malformed-but-present row still fails closed.\n    if (\n      manifest.value != null &&\n      typeof manifest.value === \"object\"\n    ) {\n      return this.loadManifestData(manifest.value, label);\n    }\n\n    const legacy = await this.readIndexValue<string>(\n      KV.bm25Index,\n      legacyKey,\n      label,\n      \"legacy\",\n    );\n    if (!legacy.ok) return null;\n    if (legacy.value && typeof legacy.value === \"string\") return legacy.value;\n    return null;\n  }\n\n  private async readIndexValue<T>(\n    scope: string,\n    key: string,\n    label: string,\n    source: \"manifest\" | \"legacy\",\n  ): Promise<{ ok: true; value: T | null } | { ok: false }> {\n    try {\n      return { ok: true, value: await this.kv.get<T>(scope, key) };\n    } catch (err) {\n      logger.warn(`index persistence: ${label} ${source} read failed`, {\n        scope,\n        key,\n        message: errorMessage(err),\n      });\n      return { ok: false };\n    }\n  }\n\n  private async loadManifestData(\n    manifest: IndexShardManifest,\n    label: string,\n  ): Promise<string | null> {\n    if (\n      manifest.v !== 1 ||\n      !Array.isArray(manifest.shards) ||\n      manifest.shards.length === 0 ||\n      !Number.isInteger(manifest.chars) ||\n      manifest.chars < 0\n    ) {\n      logger.warn(`index persistence: ${label} shard manifest invalid`);\n      return null;\n    }\n    for (const shard of manifest.shards) {\n      if (!isValidShardDescriptor(shard)) {\n        logger.warn(`index persistence: ${label} shard manifest invalid`);\n        return null;\n      }\n    }\n    const loadedShards = await Promise.all(\n      manifest.shards.map(async (shard) => ({\n        shard,\n        chunk: await this.kv.get<string>(shard.scope, shard.key).catch(() => null),\n      })),\n    );\n    const chunks: string[] = [];\n    let chars = 0;\n    for (const { shard, chunk } of loadedShards) {\n      if (typeof chunk !== \"string\") {\n        logger.warn(`index persistence: ${label} shard missing`, {\n          scope: shard.scope,\n          key: shard.key,\n        });\n        return null;\n      }\n      if (chunk.length !== shard.chars) {\n        logger.warn(`index persistence: ${label} shard length mismatch`, {\n          scope: shard.scope,\n          key: shard.key,\n          expected: shard.chars,\n          actual: chunk.length,\n        });\n        return null;\n      }\n      chunks.push(chunk);\n      chars += chunk.length;\n    }\n    if (chars !== manifest.chars) {\n      logger.warn(`index persistence: ${label} total length mismatch`, {\n        expected: manifest.chars,\n        actual: chars,\n      });\n      return null;\n    }\n    return chunks.join(\"\");\n  }\n}\n","import type { ISdk } from \"iii-sdk\";\n\nconst PRIVATE_TAG_RE = /<private>[\\s\\S]*?<\\/private>/gi;\n\nconst SECRET_PATTERN_SOURCES = [\n  /(?:api[_-]?key|secret|token|password|credential|auth)[\\s]*[=:]\\s*[\"']?[A-Za-z0-9_\\-/.+]{20,}[\"']?/gi,\n  /Bearer\\s+[A-Za-z0-9._\\-+/=]{20,}/gi,\n  /sk-proj-[A-Za-z0-9\\-_]{20,}/g,\n  /(?:sk|pk|rk|ak)-[A-Za-z0-9][A-Za-z0-9\\-_]{19,}/g,\n  /sk-ant-[A-Za-z0-9\\-_]{20,}/g,\n  /gh[pus]_[A-Za-z0-9]{36,}/g,\n  /github_pat_[A-Za-z0-9_]{22,}/g,\n  /xoxb-[A-Za-z0-9\\-]+/g,\n  /AKIA[0-9A-Z]{16}/g,\n  /AIza[A-Za-z0-9\\-_]{35}/g,\n  /eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}/g,\n  /npm_[A-Za-z0-9]{36}/g,\n  /glpat-[A-Za-z0-9\\-_]{20,}/g,\n  /dop_v1_[A-Za-z0-9]{64}/g,\n];\n\nexport function stripPrivateData(input: string): string {\n  let result = input.replace(PRIVATE_TAG_RE, \"[REDACTED]\");\n  for (const source of SECRET_PATTERN_SOURCES) {\n    const pattern = new RegExp(source.source, source.flags);\n    result = result.replace(pattern, \"[REDACTED_SECRET]\");\n  }\n  return result;\n}\n\nexport function registerPrivacyFunction(sdk: ISdk): void {\n  sdk.registerFunction(\"mem::privacy\", \n    async (data: { input?: unknown } | undefined) => {\n      if (!data || typeof data.input !== \"string\") {\n        return { output: \"\", error: \"invalid input: expected string field 'input'\" };\n      }\n      return { output: stripPrivateData(data.input) };\n    },\n  );\n}\n","import type {\n  RawObservation,\n  CompressedObservation,\n  ObservationType,\n} from \"../types.js\";\n\n// Zero-LLM compression path. Converts a RawObservation into a\n// CompressedObservation using only heuristics — no Claude call, no token\n// spend. This is the default as of 0.8.8 (#138); users who want richer\n// LLM-generated summaries set AGENTMEMORY_AUTO_COMPRESS=true.\n\nfunction inferType(\n  toolName: string | undefined,\n  hookType: string,\n): ObservationType {\n  if (hookType === \"post_tool_failure\") return \"error\";\n  if (hookType === \"prompt_submit\") return \"conversation\";\n  if (hookType === \"subagent_stop\" || hookType === \"task_completed\")\n    return \"subagent\";\n  if (hookType === \"notification\") return \"notification\";\n\n  if (!toolName) return \"other\";\n  // Normalize camelCase and kebab-case into word chunks so we can match\n  // substrings like \"WebFetch\" -> \"web\" / \"fetch\".\n  const n = toolName\n    .replace(/([a-z])([A-Z])/g, \"$1_$2\")\n    .replace(/[-\\s]+/g, \"_\")\n    .toLowerCase();\n  const hasWord = (word: string) =>\n    new RegExp(`(^|_)${word}(_|$)`).test(n) ||\n    n === word ||\n    n.endsWith(word) ||\n    n.startsWith(word);\n  if ([\"fetch\", \"http\", \"web\"].some(hasWord)) return \"web_fetch\";\n  if ([\"grep\", \"search\", \"glob\", \"find\"].some(hasWord)) return \"search\";\n  if ([\"bash\", \"shell\", \"exec\", \"run\"].some(hasWord)) return \"command_run\";\n  if ([\"edit\", \"update\", \"patch\", \"replace\"].some(hasWord)) return \"file_edit\";\n  if ([\"write\", \"create\"].some(hasWord)) return \"file_write\";\n  if ([\"read\", \"view\"].some(hasWord)) return \"file_read\";\n  if ([\"task\", \"agent\"].some(hasWord)) return \"subagent\";\n  return \"other\";\n}\n\nfunction extractFiles(input: unknown): string[] {\n  if (!input || typeof input !== \"object\") return [];\n  const o = input as Record<string, unknown>;\n  const out = new Set<string>();\n  for (const key of [\n    \"file_path\",\n    \"filepath\",\n    \"path\",\n    \"filePath\",\n    \"file\",\n    \"pattern\",\n  ]) {\n    const v = o[key];\n    if (typeof v === \"string\" && v.length > 0 && v.length < 512) out.add(v);\n  }\n  return [...out];\n}\n\nfunction stringifyForNarrative(v: unknown): string {\n  if (v == null) return \"\";\n  if (typeof v === \"string\") return v;\n  try {\n    return JSON.stringify(v);\n  } catch {\n    return String(v);\n  }\n}\n\nfunction truncate(s: string, n: number): string {\n  return s.length > n ? s.slice(0, n - 1) + \"\\u2026\" : s;\n}\n\nexport function buildSyntheticCompression(\n  raw: RawObservation,\n): CompressedObservation {\n  const toolName = raw.toolName ?? raw.hookType;\n  const inputStr = stringifyForNarrative(raw.toolInput);\n  const outputStr = stringifyForNarrative(raw.toolOutput);\n  const promptStr = raw.userPrompt ?? \"\";\n\n  const narrativeParts = [promptStr, inputStr, outputStr].filter(\n    (s) => s.length > 0,\n  );\n\n  const result: CompressedObservation = {\n    id: raw.id,\n    sessionId: raw.sessionId,\n    timestamp: raw.timestamp,\n    type: inferType(toolName, raw.hookType),\n    title: truncate(toolName || \"observation\", 80),\n    subtitle: inputStr ? truncate(inputStr, 120) : undefined,\n    facts: [],\n    narrative: truncate(narrativeParts.join(\" | \"), 400),\n    concepts: [],\n    files: extractFiles(raw.toolInput),\n    importance: 5,\n    confidence: 0.3,\n  };\n  if (raw.modality) result.modality = raw.modality;\n  if (raw.imageData) result.imageData = raw.imageData;\n  if (raw.agentId) result.agentId = raw.agentId;\n  return result;\n}\n","import { KV } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { logger } from \"../logger.js\";\n\nconst RECENT_CAP = 20;\n\nexport interface AccessLog {\n  memoryId: string;\n  count: number;\n  lastAt: string;\n  recent: number[];\n}\n\nexport function emptyAccessLog(memoryId: string): AccessLog {\n  return { memoryId, count: 0, lastAt: \"\", recent: [] };\n}\n\nexport function normalizeAccessLog(raw: unknown): AccessLog {\n  const r = (raw ?? {}) as Partial<AccessLog>;\n  const rawCount =\n    typeof r.count === \"number\" && Number.isFinite(r.count) ? r.count : 0;\n  const count = Math.max(0, Math.floor(rawCount));\n  const rawRecent = Array.isArray(r.recent)\n    ? r.recent.filter(\n        (x): x is number => typeof x === \"number\" && Number.isFinite(x),\n      )\n    : [];\n  const recent =\n    rawRecent.length > RECENT_CAP ? rawRecent.slice(-RECENT_CAP) : rawRecent;\n  return {\n    memoryId: typeof r.memoryId === \"string\" ? r.memoryId : \"\",\n    count: Math.max(count, recent.length),\n    lastAt: typeof r.lastAt === \"string\" ? r.lastAt : \"\",\n    recent,\n  };\n}\n\nexport async function getAccessLog(\n  kv: StateKV,\n  memoryId: string,\n): Promise<AccessLog> {\n  try {\n    const raw = await kv.get<AccessLog>(KV.accessLog, memoryId);\n    if (!raw) return emptyAccessLog(memoryId);\n    const normalized = normalizeAccessLog(raw);\n    if (!normalized.memoryId) normalized.memoryId = memoryId;\n    return normalized;\n  } catch {\n    return emptyAccessLog(memoryId);\n  }\n}\n\nexport async function recordAccess(\n  kv: StateKV,\n  memoryId: string,\n  timestampMs?: number,\n): Promise<void> {\n  if (!memoryId) return;\n  const ts = timestampMs ?? Date.now();\n  try {\n    await withKeyedLock(`mem:access:${memoryId}`, async () => {\n      const existing = await getAccessLog(kv, memoryId);\n      existing.count += 1;\n      existing.lastAt = new Date(ts).toISOString();\n      existing.recent.push(ts);\n      if (existing.recent.length > RECENT_CAP) {\n        existing.recent = existing.recent.slice(-RECENT_CAP);\n      }\n      await kv.set(KV.accessLog, memoryId, existing);\n    });\n  } catch (err) {\n    try {\n      logger.warn(\"recordAccess failed\", {\n        memoryId,\n        error: err instanceof Error ? err.message : String(err),\n      });\n    } catch {}\n  }\n}\n\nexport async function recordAccessBatch(\n  kv: StateKV,\n  memoryIds: string[],\n  timestampMs?: number,\n): Promise<void> {\n  if (!memoryIds || memoryIds.length === 0) return;\n  const ts = timestampMs ?? Date.now();\n  const unique = Array.from(new Set(memoryIds.filter(Boolean)));\n  await Promise.allSettled(unique.map((id) => recordAccess(kv, id, ts)));\n}\n\nexport async function deleteAccessLog(\n  kv: StateKV,\n  memoryId: string,\n): Promise<void> {\n  if (!memoryId) return;\n  try {\n    await withKeyedLock(`mem:access:${memoryId}`, async () => {\n      await kv.delete(KV.accessLog, memoryId);\n    });\n  } catch {}\n}\n\n","import type { ISdk } from 'iii-sdk'\nimport type { CompactSearchResult, CompressedObservation, Memory, SearchResult, Session } from '../types.js'\nimport { KV } from '../state/schema.js'\nimport { StateKV } from '../state/kv.js'\nimport { SearchIndex } from '../state/search-index.js'\nimport { VectorIndex } from '../state/vector-index.js'\nimport type { EmbeddingProvider } from '../types.js'\nimport { memoryToObservation } from '../state/memory-utils.js'\nimport { recordAccessBatch } from './access-tracker.js'\nimport { logger } from \"../logger.js\";\nimport { getAgentId, isAgentScopeIsolated } from \"../config.js\";\n\nlet index: SearchIndex | null = null\nlet vectorIndex: VectorIndex | null = null\nlet currentEmbeddingProvider: EmbeddingProvider | null = null\n\nexport function getSearchIndex(): SearchIndex {\n  if (!index) index = new SearchIndex()\n  return index\n}\n\nexport function setVectorIndex(idx: VectorIndex | null): void {\n  vectorIndex = idx\n}\n\nexport function getVectorIndex(): VectorIndex | null {\n  return vectorIndex\n}\n\nexport function setEmbeddingProvider(provider: EmbeddingProvider | null): void {\n  currentEmbeddingProvider = provider\n}\n\nexport function getEmbeddingProvider(): EmbeddingProvider | null {\n  return currentEmbeddingProvider\n}\n\nexport function vectorIndexRemove(id: string): void {\n  vectorIndex?.remove(id);\n}\n\n// Persistence sync hook. Without this, index removals only live in\n// memory; a crash/SIGKILL before graceful shutdown reloads a stale\n// snapshot at boot and the deleted entry resurrects in the index.\n// Wired by src/index.ts after IndexPersistence is constructed; no-op\n// until then so unit tests that exercise the delete paths in\n// isolation don't need to wire persistence.\nlet indexPersistence: {\n  scheduleSave: () => void;\n  save: () => Promise<void>;\n} | null = null;\n\nexport function setIndexPersistence(\n  p: { scheduleSave: () => void; save: () => Promise<void> } | null,\n): void {\n  indexPersistence = p;\n}\n\nexport function scheduleIndexSave(): void {\n  indexPersistence?.scheduleSave();\n}\n\n// Synchronous flush variant for delete paths. The debounced\n// scheduleSave is fine for adds (chatty), but a hard process exit\n// inside the 5s debounce window would lose deletes and resurrect\n// removed entries on next boot. Deletes are infrequent enough that\n// awaiting a single write per operation is acceptable. save() catches\n// its own errors via IndexPersistence.logFailure, so this resolves\n// even when persistence fails — callers must not treat a failed\n// flush as a fatal error on the delete itself (the KV delete already\n// committed before this is invoked).\nexport async function flushIndexSave(): Promise<void> {\n  await indexPersistence?.save();\n}\n\n// Hard cap on embedding input length. Most providers cap input around\n// 8k tokens (~32k chars at ~4 chars/token). Truncate defensively so a\n// huge memory.content can't 400 the embed call or blow context budget\n// on a single doc. 16k chars ≈ 4k tokens, safely under every provider.\nconst EMBED_MAX_CHARS = 16_000\n\nexport function clipEmbedInput(text: string): string {\n  if (text.length <= EMBED_MAX_CHARS) return text\n  return text.slice(0, EMBED_MAX_CHARS)\n}\n\n// Single guarded vector-index write. Returns true on success. Logs and\n// no-ops on:\n//   - dimension mismatch (mis-configured provider would silently corrupt\n//     the index per #248 otherwise — guarded at persistence load there;\n//     this is the symmetric guard at the write site)\n//   - embed throwing (network, rate limit, provider down)\n// Always soft-fails so a downed embedder doesn't break the upstream save.\nexport async function vectorIndexAddGuarded(\n  id: string,\n  sessionId: string,\n  text: string,\n  context: { kind: \"memory\" | \"observation\" | \"synthetic\"; logId: string },\n): Promise<boolean> {\n  const vi = vectorIndex\n  const ep = currentEmbeddingProvider\n  if (!vi || !ep) return false\n  try {\n    const embedding = await ep.embed(clipEmbedInput(text))\n    if (embedding.length !== ep.dimensions) {\n      logger.warn(\"vector-index add: dimension mismatch — skipping\", {\n        kind: context.kind,\n        id: context.logId,\n        provider: ep.name,\n        expected: ep.dimensions,\n        received: embedding.length,\n      })\n      return false\n    }\n    vi.add(id, sessionId, embedding)\n    return true\n  } catch (err) {\n    logger.warn(\"vector-index add: embed failed — skipping\", {\n      kind: context.kind,\n      id: context.logId,\n      provider: ep.name,\n      error: err instanceof Error ? err.message : String(err),\n    })\n    return false\n  }\n}\n\n// Batched variant: calls EmbeddingProvider.embedBatch ONCE for the whole\n// batch, then writes each resulting vector. Use this for bulk paths\n// (rebuildIndex, future bulk-add APIs) where per-item serial awaits\n// dominate wallclock. A batch of N has roughly the latency of a single\n// embed (network + GPU setup amortized), so backfilling a 500k-obs\n// corpus drops from days to hours on a per-batch endpoint like vLLM.\n//\n// Per-item failure shape:\n//   - whole-batch network/provider error → all skipped, single warn line\n//   - per-item dimension mismatch → that item skipped, others continue\nexport async function vectorIndexAddBatchGuarded(\n  items: Array<{\n    id: string\n    sessionId: string\n    text: string\n    context: { kind: \"memory\" | \"observation\" | \"synthetic\"; logId: string }\n  }>,\n): Promise<{ ok: number; fail: number }> {\n  const vi = vectorIndex\n  const ep = currentEmbeddingProvider\n  if (!vi || !ep || items.length === 0) return { ok: 0, fail: 0 }\n\n  let embeddings: Float32Array[]\n  try {\n    embeddings = await ep.embedBatch(items.map((i) => clipEmbedInput(i.text)))\n  } catch (err) {\n    logger.warn(\"vector-index add batch: embed failed — skipping batch\", {\n      batchSize: items.length,\n      provider: ep.name,\n      error: err instanceof Error ? err.message : String(err),\n    })\n    return { ok: 0, fail: items.length }\n  }\n\n  if (embeddings.length !== items.length) {\n    logger.warn(\n      \"vector-index add batch: provider returned wrong length — skipping batch\",\n      {\n        batchSize: items.length,\n        returned: embeddings.length,\n        provider: ep.name,\n      },\n    )\n    return { ok: 0, fail: items.length }\n  }\n\n  let ok = 0\n  let fail = 0\n  for (let i = 0; i < items.length; i++) {\n    const item = items[i]\n    const embedding = embeddings[i]\n    if (embedding.length !== ep.dimensions) {\n      logger.warn(\"vector-index add batch: dimension mismatch — skipping item\", {\n        kind: item.context.kind,\n        id: item.context.logId,\n        provider: ep.name,\n        expected: ep.dimensions,\n        received: embedding.length,\n      })\n      fail++\n      continue\n    }\n    try {\n      vi.add(item.id, item.sessionId, embedding)\n      ok++\n    } catch (err) {\n      logger.warn(\"vector-index add batch: index write failed — skipping item\", {\n        kind: item.context.kind,\n        id: item.context.logId,\n        error: err instanceof Error ? err.message : String(err),\n      })\n      fail++\n    }\n  }\n  return { ok, fail }\n}\n\n// Embed-batch size for rebuild. Each item is one /v1/embeddings call's\n// `input` array element; the provider sees the whole batch as one HTTP\n// round-trip. 32 fits comfortably under typical per-request token budgets\n// (32 × ~110 tok/item ≈ 3.5k tokens) and gets close to per-call\n// throughput for GPU-backed endpoints (vLLM, Triton, etc.). Override via\n// REBUILD_EMBED_BATCH_SIZE for endpoints that prefer smaller/larger\n// batches. Set to 1 to fall back to the legacy per-item path.\nconst DEFAULT_REBUILD_EMBED_BATCH = 32\n\nfunction getRebuildEmbedBatchSize(): number {\n  const raw = process.env.REBUILD_EMBED_BATCH_SIZE\n  if (!raw) return DEFAULT_REBUILD_EMBED_BATCH\n  const n = parseInt(raw, 10)\n  return Number.isFinite(n) && n > 0 ? n : DEFAULT_REBUILD_EMBED_BATCH\n}\n\nexport async function rebuildIndex(kv: StateKV): Promise<number> {\n  const idx = getSearchIndex()\n  idx.clear()\n\n  // BM25 clear above wipes stale doc entries; the vector index has the\n  // symmetric concern — memories/observations deleted between runs\n  // would leave orphan embeddings here forever. Clear both before the\n  // repopulation loops run, so BM25 and vector stay in sync.\n  vectorIndex?.clear()\n\n  const batchSize = getRebuildEmbedBatchSize()\n  // Accumulator for the batched embed flush. BM25 add is synchronous and\n  // doesn't need batching — only the vector path benefits.\n  type EmbedJob = {\n    id: string\n    sessionId: string\n    text: string\n    context: { kind: \"memory\" | \"observation\" | \"synthetic\"; logId: string }\n  }\n  const pending: EmbedJob[] = []\n  let count = 0\n\n  const flush = async (): Promise<void> => {\n    if (pending.length === 0) return\n    await vectorIndexAddBatchGuarded(pending)\n    pending.length = 0\n  }\n  const enqueue = async (job: EmbedJob): Promise<void> => {\n    pending.push(job)\n    if (pending.length >= batchSize) await flush()\n  }\n\n  // Memories live in their own KV scope outside per-session observation\n  // scopes, so they need a separate walk. Without this, mem::remember\n  // entries vanish from BM25 on every restart even after the live-write\n  // fix in remember.ts (#257).\n  try {\n    const memories = await kv.list<Memory>(KV.memories)\n    for (const memory of memories) {\n      if (memory.isLatest === false) continue\n      if (!memory.title || !memory.content) continue\n      idx.add(memoryToObservation(memory))\n      await enqueue({\n        id: memory.id,\n        sessionId: memory.sessionIds?.[0] ?? 'memory',\n        text: memory.title + ' ' + memory.content,\n        context: { kind: \"memory\", logId: memory.id },\n      })\n      count++\n    }\n  } catch (err) {\n    logger.warn('rebuildIndex: failed to load memories', {\n      error: err instanceof Error ? err.message : String(err),\n    })\n  }\n\n  const sessions = await kv.list<Session>(KV.sessions)\n  if (!sessions.length) {\n    await flush()\n    return count\n  }\n\n  const obsPerSession: CompressedObservation[][] = []\n  const failedSessions: string[] = []\n  for (let batch = 0; batch < sessions.length; batch += 10) {\n    const chunk = sessions.slice(batch, batch + 10)\n    const results = await Promise.all(\n      chunk.map(async (s) => {\n        try {\n          return await kv.list<CompressedObservation>(KV.observations(s.id))\n        } catch {\n          failedSessions.push(s.id)\n          return [] as CompressedObservation[]\n        }\n      })\n    )\n    obsPerSession.push(...results)\n  }\n  if (failedSessions.length > 0) {\n    logger.warn('rebuildIndex: failed to load observations for sessions', { failedSessions })\n  }\n  for (const observations of obsPerSession) {\n    for (const obs of observations) {\n      if (obs.title && obs.narrative) {\n        idx.add(obs)\n        await enqueue({\n          id: obs.id,\n          sessionId: obs.sessionId,\n          text: obs.title + ' ' + obs.narrative,\n          context: { kind: \"observation\", logId: obs.id },\n        })\n        count++\n      }\n    }\n  }\n\n  // Drain the last partial batch.\n  await flush()\n  return count\n}\n\nexport function registerSearchFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\n    'mem::search',\n    async (data: {\n      query: string\n      limit?: number\n      project?: string\n      cwd?: string\n      format?: string\n      token_budget?: number\n      agentId?: string\n    }) => {\n      const idx = getSearchIndex()\n\n      // Input validation / normalization.\n      if (typeof data?.query !== 'string' || !data.query.trim()) {\n        throw new Error('mem::search: query must be a non-empty string')\n      }\n      const query = data.query.trim()\n      const MAX_LIMIT = 100\n      let effectiveLimit = 20\n      if (data.limit !== undefined) {\n        if (!Number.isInteger(data.limit) || data.limit < 1) {\n          throw new Error('mem::search: limit must be a positive integer')\n        }\n        effectiveLimit = Math.min(data.limit, MAX_LIMIT)\n      }\n      const projectFilter = typeof data.project === 'string' && data.project.trim().length > 0 ? data.project.trim() : undefined\n      const cwdFilter = typeof data.cwd === 'string' && data.cwd.trim().length > 0 ? data.cwd.trim() : undefined\n      // #817: agent-scope isolation. mem::search backs REST /search,\n      // memory_recall and recall_context. Without filtering here a\n      // worker booted with AGENT_ID=B + AGENTMEMORY_AGENT_SCOPE=isolated\n      // could read A's memories — the cross-agent leak the issue\n      // documented. Mirrors the smart-search pattern: wildcard \"*\"\n      // bypasses, explicit agentId pins, isolated mode falls back to\n      // the worker's own AGENT_ID.\n      //\n      // Fail-closed: if isolated mode is on AND no explicit agentId\n      // is given AND env AGENT_ID is unset, refuse the call rather\n      // than silently dropping the filter. Allowing the call through\n      // with filterAgentId=undefined is the same leak this fix is\n      // supposed to close.\n      const isolated = isAgentScopeIsolated();\n      const explicitAgentId =\n        typeof data.agentId === \"string\" && data.agentId.trim().length > 0\n          ? data.agentId.trim()\n          : undefined;\n      const wildcardAgent = explicitAgentId === \"*\";\n      const envAgentId = isolated ? getAgentId() : undefined;\n      const filterAgentId = wildcardAgent\n        ? undefined\n        : explicitAgentId ?? envAgentId;\n      if (\n        isolated &&\n        !wildcardAgent &&\n        !explicitAgentId &&\n        !envAgentId\n      ) {\n        throw new Error(\n          \"mem::search: AGENTMEMORY_AGENT_SCOPE=isolated is set but no \" +\n            \"agent id is available (env AGENT_ID unset and no explicit \" +\n            \"agentId in the call). Refusing to read cross-agent rows. \" +\n            'Pass agentId: \"*\" to opt in to a wildcard read.',\n        );\n      }\n      const format = typeof data.format === 'string' ? data.format : 'full'\n      if (!['full', 'compact', 'narrative'].includes(format)) {\n        throw new Error(\"mem::search: format must be one of 'full', 'compact', or 'narrative'\")\n      }\n      let tokenBudget: number | undefined\n      if (data.token_budget !== undefined) {\n        if (!Number.isInteger(data.token_budget) || data.token_budget < 1) {\n          throw new Error('mem::search: token_budget must be a positive integer')\n        }\n        tokenBudget = data.token_budget\n      }\n\n      if (idx.size === 0) {\n        const count = await rebuildIndex(kv)\n        logger.info('Search index rebuilt', { entries: count })\n      }\n\n      // When filtering by project/cwd, over-fetch from the index so the\n      // post-filter still has a chance of returning `effectiveLimit` results.\n      // Over-fetch whenever ANY post-index filter is active. agentId\n      // is dropped after the observation/memory is loaded (BM25 index\n      // doesn't carry it), so without the over-fetch isolated-mode\n      // queries return underfilled pages when same-agent matches\n      // rank lower than cross-agent ones in the hybrid score.\n      const filtering = !!(projectFilter || cwdFilter || filterAgentId)\n      const fetchLimit = filtering ? Math.max(effectiveLimit * 10, 100) : effectiveLimit\n      const results = idx.search(query, fetchLimit)\n\n      // Resolve session -> project/cwd once per sessionId we touch.\n      const sessionCache = new Map<string, Session | null>()\n      const loadSession = async (sessionId: string): Promise<Session | null> => {\n        if (sessionCache.has(sessionId)) return sessionCache.get(sessionId)!\n        const s = await kv.get<Session>(KV.sessions, sessionId)\n        sessionCache.set(sessionId, s ?? null)\n        return s ?? null\n      }\n\n      // Cache for memory project lookups. Memories indexed via mem::remember\n      // use a synthetic sessionId ('memory' or the first real sessionId) that\n      // either has no KV.sessions entry or belongs to a different project.\n      // When loadSession returns null we fall through to a KV.memories probe\n      // so project-filtered search can include or exclude them correctly.\n      const memoryProjectCache = new Map<string, string | null>()\n      const loadMemoryProject = async (obsId: string): Promise<string | null> => {\n        if (memoryProjectCache.has(obsId)) return memoryProjectCache.get(obsId)!\n        const mem = await kv.get<Memory>(KV.memories, obsId).catch(() => null)\n        const proj = mem?.project ?? null\n        memoryProjectCache.set(obsId, proj)\n        return proj\n      }\n\n      // First pass: filter by session (sequential — benefits from session cache).\n      // Memory entries with a synthetic sessionId take a secondary KV.memories\n      // path so project filtering works correctly for them too.\n      //\n      // When agentId filtering is active we can't cap at effectiveLimit\n      // here — the second pass (post-load) is what drops cross-agent\n      // rows, and capping early would underfill the result page. Use\n      // fetchLimit as the upper bound in that case; the final\n      // truncation lives at the end of the second pass.\n      const earlyCap = filterAgentId ? fetchLimit : effectiveLimit\n      const candidates: typeof results = []\n      for (const r of results) {\n        if (candidates.length >= earlyCap) break\n        if (filtering) {\n          const s = await loadSession(r.sessionId)\n          if (s) {\n            if (projectFilter && s.project !== projectFilter) continue\n            if (cwdFilter && s.cwd !== cwdFilter) continue\n          } else {\n            // Session not found. Two cases arrive here:\n            //   1. Synthetic sessionId — memories indexed via mem::remember use\n            //      sessionIds[0] ?? 'memory'. The string 'memory' has no session\n            //      entry; neither does a real sessionId when sessionIds[0] happens\n            //      to be a session from a different lifecycle. Probe KV.memories\n            //      directly to get the memory's own project field.\n            //   2. Deleted session — the session existed when the entry was indexed\n            //      but was since evicted. The KV.memories probe returns null for\n            //      these (they are observations, not memories), so memProject is\n            //      null and the entry passes through as unscoped. This is the safe\n            //      fallback: we lose the ability to filter but never incorrectly\n            //      block a result whose session we can no longer verify.\n            // In both cases, a null memProject means \"project unknown — treat as\n            // unscoped and let it through\" to preserve backward-compatibility.\n            if (projectFilter) {\n              const memProject = await loadMemoryProject(r.obsId)\n              if (memProject !== null && memProject !== projectFilter) continue\n            }\n            // cwd filter does not apply to unbound entries.\n          }\n        }\n        candidates.push(r)\n      }\n\n      // Second pass: load observations in parallel. Fall back to\n      // KV.memories when the observation lookup misses — entries indexed\n      // via mem::remember live in the memories scope under a synthetic\n      // sessionId, so the observation key never exists (#265).\n      const obsResults = await Promise.all(\n        candidates.map(async (r) => {\n          const obs = await kv\n            .get<CompressedObservation>(KV.observations(r.sessionId), r.obsId)\n            .catch(() => null)\n          if (obs) return obs\n          const mem = await kv\n            .get<Memory>(KV.memories, r.obsId)\n            .catch(() => null)\n          return mem ? memoryToObservation(mem) : null\n        })\n      )\n      const enriched: SearchResult[] = []\n      for (let i = 0; i < candidates.length; i++) {\n        const obs = obsResults[i]\n        if (!obs) continue\n        // #817: enforce agent-scope after the observation/memory is\n        // loaded. The BM25 index doesn't carry agentId so the filter\n        // happens post-lookup. Wildcard (\"*\") and no-isolation paths\n        // resolved filterAgentId=undefined upstream and pass through.\n        if (filterAgentId !== undefined && obs.agentId !== filterAgentId) continue\n        if (enriched.length >= effectiveLimit) break\n        enriched.push({\n          observation: obs,\n          score: candidates[i].score,\n          sessionId: candidates[i].sessionId,\n        })\n      }\n\n      void recordAccessBatch(\n        kv,\n        enriched.map((r) => r.observation.id),\n      )\n\n      const estimateTokens = (value: unknown): number =>\n        Math.max(1, Math.ceil(JSON.stringify(value).length / 3))\n\n      const applyTokenBudget = <T>(items: T[]): {\n        items: T[]\n        used: number\n        truncated: boolean\n      } => {\n        if (!tokenBudget) return { items, used: items.reduce((sum, item) => sum + estimateTokens(item), 0), truncated: false }\n        const selected: T[] = []\n        let used = 0\n        for (const item of items) {\n          const itemTokens = estimateTokens(item)\n          if (used + itemTokens > tokenBudget) {\n            return { items: selected, used, truncated: selected.length < items.length }\n          }\n          selected.push(item)\n          used += itemTokens\n        }\n        return { items: selected, used, truncated: false }\n      }\n\n      if (format === 'compact') {\n        const compactResults: CompactSearchResult[] = enriched.map((r) => ({\n          obsId: r.observation.id,\n          sessionId: r.sessionId,\n          title: r.observation.title,\n          type: r.observation.type,\n          score: r.score,\n          timestamp: r.observation.timestamp,\n        }))\n        const packed = applyTokenBudget(compactResults)\n        return {\n          format,\n          results: packed.items,\n          tokens_used: packed.used,\n          tokens_budget: tokenBudget,\n          truncated: packed.truncated,\n        }\n      }\n\n      if (format === 'narrative') {\n        const narrativeResults = enriched.map((r) => ({\n          obsId: r.observation.id,\n          sessionId: r.sessionId,\n          title: r.observation.title,\n          narrative: r.observation.narrative,\n          score: r.score,\n          timestamp: r.observation.timestamp,\n        }))\n        const packed = applyTokenBudget(narrativeResults)\n        const text = packed.items\n          .map((r, index) => `${index + 1}. ${r.title}\\n${r.narrative}`)\n          .join('\\n\\n')\n        return {\n          format,\n          results: packed.items,\n          text,\n          tokens_used: packed.used,\n          tokens_budget: tokenBudget,\n          truncated: packed.truncated,\n        }\n      }\n\n      const packed = applyTokenBudget(enriched)\n\n      // Avoid logging raw cwd/project (host paths). Log only that filters were active.\n      logger.info('Search completed', {\n        query,\n        results: packed.items.length,\n        hasProjectFilter: !!projectFilter,\n        hasCwdFilter: !!cwdFilter,\n      })\n      return {\n        format,\n        results: packed.items,\n        tokens_used: packed.used,\n        tokens_budget: tokenBudget,\n        truncated: packed.truncated,\n      }\n    }\n  )\n}\n","import { TriggerAction, type ISdk } from \"iii-sdk\";\nimport type { RawObservation, HookPayload } from \"../types.js\";\nimport { KV, STREAM, generateId } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { stripPrivateData } from \"./privacy.js\";\nimport { DedupMap } from \"./dedup.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { isAutoCompressEnabled } from \"../config.js\";\nimport { buildSyntheticCompression } from \"./compress-synthetic.js\";\nimport { getSearchIndex, vectorIndexAddGuarded } from \"./search.js\";\nimport { getAgentId } from \"../config.js\";\nimport { logger } from \"../logger.js\";\nimport { saveImageToDisk } from \"../utils/image-store.js\";\n\nexport function extractImage(d: unknown): string | undefined {\n  if (!d) return undefined;\n  if (typeof d === \"string\") {\n    if (d.startsWith(\"data:image/\") || d.startsWith(\"iVBORw0KGgo\") || d.startsWith(\"/9j/\")) {\n      return d;\n    }\n    return undefined;\n  }\n  if (typeof d === \"object\" && d !== null) {\n    const obj = d as Record<string, unknown>;\n    if (typeof obj[\"image_data\"] === \"string\") return obj[\"image_data\"];\n    if (typeof obj[\"image_path\"] === \"string\") return obj[\"image_path\"];\n    if (typeof obj[\"imageBase64\"] === \"string\") return obj[\"imageBase64\"];\n    if (typeof obj[\"imagePath\"] === \"string\") return obj[\"imagePath\"];\n\n    for (const key of Object.keys(obj)) {\n      const match = extractImage(obj[key]);\n      if (match) return match;\n    }\n  }\n  return undefined;\n}\n\nexport function registerObserveFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  dedupMap?: DedupMap,\n  maxObservationsPerSession?: number,\n): void {\n  sdk.registerFunction(\"mem::observe\", \n    async (payload: HookPayload) => {\n\n      if (\n        !payload?.sessionId ||\n        typeof payload.sessionId !== \"string\" ||\n        !payload.hookType ||\n        typeof payload.hookType !== \"string\" ||\n        !payload.timestamp ||\n        typeof payload.timestamp !== \"string\"\n      ) {\n        return {\n          success: false,\n          error:\n            \"Invalid payload: sessionId, hookType, and timestamp are required\",\n        };\n      }\n\n      const obsId = generateId(\"obs\");\n\n      let dedupHash: string | undefined;\n      if (dedupMap) {\n        const d =\n          typeof payload.data === \"object\" && payload.data !== null\n            ? (payload.data as Record<string, unknown>)\n            : {};\n        const toolName = (d[\"tool_name\"] as string) || payload.hookType;\n        dedupHash = dedupMap.computeHash(\n          payload.sessionId,\n          toolName,\n          d[\"tool_input\"],\n        );\n        if (dedupMap.isDuplicate(dedupHash)) {\n          return { deduplicated: true, sessionId: payload.sessionId };\n        }\n      }\n\n      let sanitizedRaw: unknown = payload.data;\n      try {\n        const jsonStr = JSON.stringify(payload.data);\n        const sanitized = stripPrivateData(jsonStr);\n        sanitizedRaw = JSON.parse(sanitized);\n      } catch {\n        sanitizedRaw = stripPrivateData(String(payload.data));\n      }\n\n      const raw: RawObservation = {\n        id: obsId,\n        sessionId: payload.sessionId,\n        timestamp: payload.timestamp,\n        hookType: payload.hookType,\n        raw: sanitizedRaw,\n      };\n\n      let extractedImage: string | undefined;\n\n      if (typeof sanitizedRaw === \"object\" && sanitizedRaw !== null) {\n        const d = sanitizedRaw as Record<string, unknown>;\n        if (\n          payload.hookType === \"post_tool_use\" ||\n          payload.hookType === \"post_tool_failure\"\n        ) {\n          raw.toolName = d[\"tool_name\"] as string | undefined;\n          raw.toolInput = d[\"tool_input\"];\n          raw.toolOutput = d[\"tool_output\"] || d[\"error\"];\n        }\n        if (payload.hookType === \"prompt_submit\") {\n          raw.userPrompt = d[\"prompt\"] as string | undefined;\n        }\n\n        extractedImage = extractImage(sanitizedRaw);\n        if (extractedImage) {\n          raw.modality = (raw.toolInput || raw.toolOutput || raw.userPrompt) ? \"mixed\" : \"image\";\n        }\n      } else if (typeof sanitizedRaw === \"string\") {\n        extractedImage = extractImage(sanitizedRaw);\n        if (extractedImage) {\n          raw.modality = \"image\";\n        }\n      }\n\n      const pendingImageData = extractedImage;\n\n      return withKeyedLock(`obs:${payload.sessionId}`, async () => {\n        if (maxObservationsPerSession && maxObservationsPerSession > 0) {\n          const existing = await kv.list(KV.observations(payload.sessionId));\n          if (existing.length >= maxObservationsPerSession) {\n            return {\n              success: false,\n              error: `Session observation limit reached (${maxObservationsPerSession})`,\n            };\n          }\n        }\n\n        // Existing session is the source of truth for agentId (even\n        // undefined). Env AGENT_ID only fires when no session row\n        // exists yet — otherwise an unscoped session would get\n        // retroactively scoped by a later AGENT_ID export.\n        const existingSession = await kv.get<{\n          agentId?: string;\n          observationCount?: number;\n          firstPrompt?: string;\n        }>(KV.sessions, payload.sessionId);\n        const inheritedAgentId = existingSession\n          ? existingSession.agentId\n          : getAgentId();\n        if (inheritedAgentId) {\n          raw.agentId = inheritedAgentId;\n        }\n\n        if (pendingImageData && (pendingImageData.startsWith(\"data:image/\") || pendingImageData.startsWith(\"iVBORw0KGgo\") || pendingImageData.startsWith(\"/9j/\"))) {\n          const { filePath, bytesWritten } = await saveImageToDisk(pendingImageData);\n          raw.imageData = filePath;\n          const { incrementImageRef } = await import(\"./image-refs.js\");\n          await incrementImageRef(kv, filePath);\n          sdk.trigger({\n            function_id: \"mem::disk-size-delta\",\n            payload: { deltaBytes: bytesWritten },\n            action: TriggerAction.Void(),\n          });\n          if (process.env[\"AGENTMEMORY_IMAGE_EMBEDDINGS\"] === \"true\") {\n            sdk.trigger({\n              function_id: \"mem::vision-embed\",\n              payload: {\n                imageRef: filePath,\n                sessionId: payload.sessionId,\n                observationId: obsId,\n              },\n              action: TriggerAction.Void(),\n            });\n          }\n        }\n\n        try {\n\n          await kv.set(KV.observations(payload.sessionId), obsId, raw);\n\n        } catch (error) {\n          if (raw.imageData) {\n            // Roll back the ref taken above. decrementImageRef deletes the file\n            // only when no other observation still references it (deduped images\n            // survive) and emits the disk-size delta itself — deleting the file\n            // directly here would orphan shared images and leave a stale ref.\n            // If the rollback itself fails, log it but still surface the\n            // original write error (the more useful failure to diagnose).\n            try {\n              const { decrementImageRef } = await import(\"./image-refs.js\");\n              await decrementImageRef(kv, sdk, raw.imageData);\n            } catch (rollbackError) {\n              logger.error(\"Failed to roll back image ref after observation write failure\", {\n                imageRef: raw.imageData,\n                error: rollbackError instanceof Error ? rollbackError.message : String(rollbackError),\n              });\n            }\n          }\n          throw error;\n        }\n\n        if (dedupMap && dedupHash) {\n          dedupMap.record(dedupHash);\n        }\n\n        await sdk.trigger({\n          function_id: \"stream::set\",\n          payload: {\n          stream_name: STREAM.name,\n          group_id: STREAM.group(payload.sessionId),\n          item_id: obsId,\n          data: { type: \"raw\", observation: raw },\n          },\n        });\n\n        await sdk.trigger({\n          function_id: \"stream::send\",\n          payload: {\n            stream_name: STREAM.name,\n            group_id: STREAM.viewerGroup,\n            id: `raw-${obsId}`,\n            type: \"raw_observation\",\n            data: { type: \"raw\", observation: raw, sessionId: payload.sessionId },\n          },\n          action: TriggerAction.Void(),\n        });\n\n        const session = existingSession;\n        if (session) {\n          const updates: Array<{ type: \"set\"; path: string; value: unknown }> = [\n            { type: \"set\", path: \"updatedAt\", value: new Date().toISOString() },\n            {\n              type: \"set\",\n              path: \"observationCount\",\n              value: (session.observationCount || 0) + 1,\n            },\n          ];\n          if (!session.firstPrompt && typeof raw.userPrompt === \"string\") {\n            const trimmed = raw.userPrompt.replace(/\\s+/g, \" \").trim();\n            if (trimmed.length > 0) {\n              updates.push({\n                type: \"set\",\n                path: \"firstPrompt\",\n                value: trimmed.slice(0, 200),\n              });\n            }\n          }\n          await kv.update(KV.sessions, payload.sessionId, updates);\n        } else if (\n          typeof payload.project === \"string\" &&\n          payload.project.trim().length > 0 &&\n          typeof payload.cwd === \"string\" &&\n          payload.cwd.trim().length > 0\n        ) {\n          // OpenCode (and any plugin that skips POST /session/start)\n          // can fire observations before the session record exists. Without\n          // an implicit create, those observations stack up but\n          // `memory_sessions` never lists them, and summarize bails with\n          // \"Session not found for summarize\". Create the session now from\n          // the observation payload — but only when project + cwd are\n          // present (HookPayload contract). Older test payloads without\n          // those fields keep their original no-op behaviour.\n          const trimmedPrompt =\n            typeof raw.userPrompt === \"string\"\n              ? raw.userPrompt.replace(/\\s+/g, \" \").trim().slice(0, 200)\n              : undefined;\n          const ts = new Date().toISOString();\n          await kv.set(KV.sessions, payload.sessionId, {\n            id: payload.sessionId,\n            project: payload.project,\n            cwd: payload.cwd,\n            startedAt: payload.timestamp ?? ts,\n            updatedAt: ts,\n            status: \"active\",\n            observationCount: 1,\n            ...(inheritedAgentId ? { agentId: inheritedAgentId } : {}),\n            ...(trimmedPrompt && trimmedPrompt.length > 0\n              ? { firstPrompt: trimmedPrompt }\n              : {}),\n          });\n        }\n\n        // Per-observation LLM compression is opt-in as of 0.8.8.\n        // Default path: build a zero-LLM synthetic compression so recall\n        // and BM25 search still work without burning the user's Claude\n        // token allocation on every tool invocation.\n        if (isAutoCompressEnabled()) {\n          await sdk.trigger({\n            function_id: \"mem::compress\",\n            payload: {\n              observationId: obsId,\n              sessionId: payload.sessionId,\n              raw,\n            },\n            action: TriggerAction.Void(),\n          });\n        } else {\n          const synthetic = buildSyntheticCompression(raw);\n          await kv.set(\n            KV.observations(payload.sessionId),\n            obsId,\n            synthetic,\n          );\n          getSearchIndex().add(synthetic);\n          await vectorIndexAddGuarded(\n            synthetic.id,\n            synthetic.sessionId,\n            synthetic.title + \" \" + (synthetic.narrative || \"\"),\n            { kind: \"synthetic\", logId: synthetic.id },\n          );\n          await sdk.trigger({\n            function_id: \"stream::set\",\n            payload: {\n              stream_name: STREAM.name,\n              group_id: STREAM.group(payload.sessionId),\n              item_id: obsId,\n              data: { type: \"compressed\", observation: synthetic },\n            },\n          });\n          await sdk.trigger({\n            function_id: \"stream::set\",\n            payload: {\n              stream_name: STREAM.name,\n              group_id: STREAM.viewerGroup,\n              item_id: obsId,\n              data: {\n                type: \"compressed\",\n                observation: synthetic,\n                sessionId: payload.sessionId,\n              },\n            },\n          });\n        }\n\n        logger.info(\"Observation captured\", {\n          obsId,\n          sessionId: payload.sessionId,\n          hook: payload.hookType,\n          compress: isAutoCompressEnabled() ? \"llm\" : \"synthetic\",\n        });\n        return { observationId: obsId };\n      });\n    },\n  );\n}\n","import { TriggerAction, type ISdk } from \"iii-sdk\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { IMAGES_DIR, getMaxBytes, deleteImage } from \"../utils/image-store.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { logger } from \"../logger.js\";\n\nconst GRACE_PERIOD_MS = 30_000;\n\nexport function registerImageQuotaCleanup(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\n    \"mem::image-quota-cleanup\",\n    async () => {\n      const now = Date.now();\n\n      return withKeyedLock(\"system:cleanupLock\", async () => {\n        let totalSize = 0;\n        const fileStats: Array<{ filePath: string; size: number; mtimeMs: number }> = [];\n\n        try {\n          const files = await readdir(IMAGES_DIR);\n          for (const file of files) {\n            if (file.startsWith(\".\")) continue;\n            const filePath = join(IMAGES_DIR, file);\n            const s = await stat(filePath);\n            if (s.isFile()) {\n              fileStats.push({ filePath, size: s.size, mtimeMs: s.mtimeMs });\n              totalSize += s.size;\n            }\n          }\n        } catch {\n          return { success: true, evicted: 0, freedBytes: 0 };\n        }\n\n        const limit = getMaxBytes();\n        if (totalSize <= limit) {\n          return { success: true, evicted: 0, freedBytes: 0, underQuota: true };\n        }\n\n        fileStats.sort((a, b) => a.mtimeMs - b.mtimeMs);\n\n        let totalToFree = totalSize - limit;\n        let evicted = 0;\n        let freedBytes = 0;\n\n        for (const f of fileStats) {\n          if (totalToFree <= 0) break;\n\n          if (now - f.mtimeMs < GRACE_PERIOD_MS) {\n            continue;\n          }\n\n          await withKeyedLock(`imgRef:${f.filePath}`, async () => {\n            let refCount: number;\n            try {\n              const { getImageRefCount } = await import(\"./image-refs.js\");\n              refCount = await getImageRefCount(kv, f.filePath);\n            } catch (err) {\n              // Fail-closed: if we cannot determine refCount we must NOT\n              // delete the image. Previously we let refCount fall through\n              // to the default 0 and evicted, which risks deleting\n              // still-referenced images on transient KV errors.\n              logger.error(\"Failed to read refCount; skipping eviction\", {\n                filePath: f.filePath,\n                error: err instanceof Error ? err.message : String(err),\n              });\n              return;\n            }\n\n            if (refCount > 0) {\n              return;\n            }\n\n            const { deletedBytes } = await deleteImage(f.filePath);\n            if (deletedBytes > 0) {\n              sdk.trigger({\n                function_id: \"mem::disk-size-delta\",\n                payload: { deltaBytes: -deletedBytes },\n                action: TriggerAction.Void(),\n              });\n              totalToFree -= deletedBytes;\n              freedBytes += deletedBytes;\n              evicted++;\n            }\n          });\n        }\n\n        if (evicted > 0) {\n          const freedMb = (freedBytes / (1024 * 1024)).toFixed(1);\n          logger.info(\"Image quota cleanup complete\", { evicted, freedMb });\n        }\n\n        return { success: true, evicted, freedBytes };\n      });\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { EmbeddingProvider } from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { isManagedImagePath } from \"../utils/image-store.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { logger } from \"../logger.js\";\n\ninterface StoredEmbedding {\n  imageRef: string;\n  vector: number[];\n  modelName: string;\n  dimensions: number;\n  updatedAt: string;\n  sessionId?: string;\n  observationId?: string;\n}\n\nexport function registerVisionSearchFunctions(\n  sdk: ISdk,\n  kv: StateKV,\n  imageProvider: EmbeddingProvider | null,\n): void {\n  sdk.registerFunction(\n    \"mem::vision-embed\",\n    async (data: {\n      imageRef: string;\n      sessionId?: string;\n      observationId?: string;\n    }) => {\n      if (!imageProvider?.embedImage) {\n        return { success: false, error: \"image embeddings disabled (set AGENTMEMORY_IMAGE_EMBEDDINGS=true)\" };\n      }\n      if (!data?.imageRef || typeof data.imageRef !== \"string\") {\n        return { success: false, error: \"imageRef required\" };\n      }\n      if (!isManagedImagePath(data.imageRef)) {\n        return { success: false, error: \"imageRef must point to a file under the managed image store\" };\n      }\n      const refCount = await kv.get<number>(KV.imageRefs, data.imageRef);\n      if (!refCount || Number(refCount) < 1) {\n        return { success: false, error: \"imageRef not registered in mem:image-refs\" };\n      }\n      try {\n        const vec = await imageProvider.embedImage(data.imageRef);\n        const stored: StoredEmbedding = {\n          imageRef: data.imageRef,\n          vector: Array.from(vec),\n          modelName: imageProvider.name,\n          dimensions: imageProvider.dimensions,\n          updatedAt: new Date().toISOString(),\n          sessionId: data.sessionId,\n          observationId: data.observationId,\n        };\n        await kv.set(KV.imageEmbeddings, data.imageRef, stored);\n        await recordAudit(kv, \"vision_embed\", \"mem::vision-embed\", [data.imageRef], {\n          modelName: imageProvider.name,\n          dimensions: stored.dimensions,\n          sessionId: data.sessionId,\n          observationId: data.observationId,\n        });\n        return { success: true, imageRef: data.imageRef, dimensions: stored.dimensions };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.warn(\"vision-embed failed\", { imageRef: data.imageRef, error: msg });\n        return { success: false, error: msg };\n      }\n    },\n  );\n\n  sdk.registerFunction(\n    \"mem::vision-search\",\n    async (data: {\n      queryText?: string;\n      queryImageRef?: string;\n      queryImageBase64?: string;\n      topK?: number;\n      sessionId?: string;\n    }) => {\n      if (!imageProvider?.embedImage) {\n        return { success: false, error: \"image embeddings disabled (set AGENTMEMORY_IMAGE_EMBEDDINGS=true)\" };\n      }\n      const requestedTopK =\n        typeof data?.topK === \"number\" && Number.isFinite(data.topK)\n          ? Math.trunc(data.topK)\n          : 10;\n      const topK = Math.min(50, Math.max(1, requestedTopK));\n\n      let queryVec: Float32Array | null = null;\n      try {\n        if (data?.queryText) {\n          queryVec = await imageProvider.embed(data.queryText);\n        } else if (data?.queryImageBase64) {\n          const b64 = data.queryImageBase64.startsWith(\"data:\")\n            ? data.queryImageBase64\n            : `data:image/png;base64,${data.queryImageBase64}`;\n          queryVec = await imageProvider.embedImage(b64);\n        } else if (data?.queryImageRef) {\n          if (!isManagedImagePath(data.queryImageRef)) {\n            return { success: false, error: \"queryImageRef must point to a file under the managed image store\" };\n          }\n          const refCount = await kv.get<number>(KV.imageRefs, data.queryImageRef);\n          if (!refCount || Number(refCount) < 1) {\n            return { success: false, error: \"queryImageRef not registered in mem:image-refs\" };\n          }\n          queryVec = await imageProvider.embedImage(data.queryImageRef);\n        } else {\n          return { success: false, error: \"queryText, queryImageRef, or queryImageBase64 required\" };\n        }\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        return { success: false, error: `query embed failed: ${msg}` };\n      }\n\n      if (!queryVec) return { success: false, error: \"failed to build query vector\" };\n\n      const stored = await kv.list<StoredEmbedding>(KV.imageEmbeddings);\n      const filtered = data?.sessionId\n        ? stored.filter((s) => s.sessionId === data.sessionId)\n        : stored;\n\n      const scored = filtered.map((s) => ({\n        imageRef: s.imageRef,\n        score: cosine(queryVec!, s.vector),\n        sessionId: s.sessionId,\n        observationId: s.observationId,\n        updatedAt: s.updatedAt,\n      }));\n      scored.sort((a, b) => b.score - a.score);\n      return { success: true, results: scored.slice(0, topK), total: scored.length };\n    },\n  );\n}\n\nfunction cosine(a: Float32Array, b: number[]): number {\n  if (a.length !== b.length) return 0;\n  let dot = 0;\n  let normA = 0;\n  let normB = 0;\n  for (let i = 0; i < a.length; i++) {\n    dot += a[i] * b[i];\n    normA += a[i] * a[i];\n    normB += b[i] * b[i];\n  }\n  const denom = Math.sqrt(normA) * Math.sqrt(normB);\n  return denom === 0 ? 0 : dot / denom;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { MemorySlot, CompressedObservation } from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { getEnvVar } from \"../config.js\";\nimport { logger } from \"../logger.js\";\n\ntype SlotScope = \"project\" | \"global\";\n\nconst DEFAULT_SIZE_LIMIT = 2000;\n\nexport const DEFAULT_SLOTS: ReadonlyArray<\n  Omit<MemorySlot, \"createdAt\" | \"updatedAt\">\n> = [\n  {\n    label: \"persona\",\n    content: \"\",\n    sizeLimit: 1000,\n    description:\n      \"How the agent should see itself: role, tone, behavioural guidelines.\",\n    pinned: true,\n    readOnly: false,\n    scope: \"global\",\n  },\n  {\n    label: \"user_preferences\",\n    content: \"\",\n    sizeLimit: 2000,\n    description:\n      \"Coding style, tool preferences, naming conventions, and other habits the user wants preserved across sessions.\",\n    pinned: true,\n    readOnly: false,\n    scope: \"global\",\n  },\n  {\n    label: \"tool_guidelines\",\n    content: \"\",\n    sizeLimit: 1500,\n    description:\n      \"Rules the agent should follow when picking or sequencing tools (e.g. prefer X over Y, never run Z without confirmation).\",\n    pinned: true,\n    readOnly: false,\n    scope: \"global\",\n  },\n  {\n    label: \"project_context\",\n    content: \"\",\n    sizeLimit: 3000,\n    description:\n      \"Architecture decisions, codebase conventions, build/test commands, and cross-cutting constraints for the current project.\",\n    pinned: true,\n    readOnly: false,\n    scope: \"project\",\n  },\n  {\n    label: \"guidance\",\n    content: \"\",\n    sizeLimit: 1500,\n    description:\n      \"Active advice for the next session: what to focus on, what to avoid, open risks.\",\n    pinned: true,\n    readOnly: false,\n    scope: \"project\",\n  },\n  {\n    label: \"pending_items\",\n    content: \"\",\n    sizeLimit: 2000,\n    description:\n      \"Unfinished work, explicit TODOs, and promises made but not yet delivered.\",\n    pinned: true,\n    readOnly: false,\n    scope: \"project\",\n  },\n  {\n    label: \"session_patterns\",\n    content: \"\",\n    sizeLimit: 1500,\n    description:\n      \"Recurring behaviours and common struggles observed across recent sessions.\",\n    pinned: false,\n    readOnly: false,\n    scope: \"project\",\n  },\n  {\n    label: \"self_notes\",\n    content: \"\",\n    sizeLimit: 1500,\n    description:\n      \"Free-form notes the agent keeps for itself: hypotheses, dead ends, things to revisit.\",\n    pinned: false,\n    readOnly: false,\n    scope: \"project\",\n  },\n];\n\n// Read merged env so values loaded from ~/.agentmemory/.env are\n// honoured. process.env alone misses .env-only exports (#678).\nexport function isSlotsEnabled(): boolean {\n  return getEnvVar(\"AGENTMEMORY_SLOTS\") === \"true\";\n}\n\nexport function isReflectEnabled(): boolean {\n  return getEnvVar(\"AGENTMEMORY_REFLECT\") === \"true\";\n}\n\nfunction scopeKv(scope: SlotScope): string {\n  return scope === \"global\" ? KV.globalSlots : KV.slots;\n}\n\nfunction nowIso(): string {\n  return new Date().toISOString();\n}\n\nfunction validateLabel(label: unknown): string | null {\n  if (typeof label !== \"string\") return null;\n  const trimmed = label.trim();\n  if (!trimmed || trimmed.length > 64) return null;\n  if (!/^[a-z][a-z0-9_]*$/.test(trimmed)) return null;\n  return trimmed;\n}\n\nasync function readSlot(\n  kv: StateKV,\n  label: string,\n): Promise<{ slot: MemorySlot | null; scope: SlotScope }> {\n  const project = await kv.get<MemorySlot>(KV.slots, label);\n  if (project) return { slot: project, scope: \"project\" };\n  const global = await kv.get<MemorySlot>(KV.globalSlots, label);\n  if (global) return { slot: global, scope: \"global\" };\n  return { slot: null, scope: \"project\" };\n}\n\nasync function readSlotInScope(\n  kv: StateKV,\n  label: string,\n  scope: SlotScope,\n): Promise<MemorySlot | null> {\n  return kv.get<MemorySlot>(scopeKv(scope), label);\n}\n\nfunction validateScope(raw: unknown): SlotScope | null {\n  if (raw === undefined || raw === null) return \"project\";\n  if (raw === \"project\" || raw === \"global\") return raw;\n  return null;\n}\n\nfunction validateSizeLimit(raw: unknown): number | null | undefined {\n  if (raw === undefined || raw === null) return DEFAULT_SIZE_LIMIT;\n  if (typeof raw !== \"number\") return null;\n  if (!Number.isInteger(raw) || raw < 1 || raw > 20000) return null;\n  return raw;\n}\n\nasync function seedDefaults(kv: StateKV): Promise<void> {\n  const ts = nowIso();\n  for (const tmpl of DEFAULT_SLOTS) {\n    const target = scopeKv(tmpl.scope);\n    const existing = await kv.get<MemorySlot>(target, tmpl.label);\n    if (existing) continue;\n    const slot: MemorySlot = {\n      ...tmpl,\n      createdAt: ts,\n      updatedAt: ts,\n    };\n    await kv.set(target, tmpl.label, slot);\n  }\n}\n\nexport async function listPinnedSlots(kv: StateKV): Promise<MemorySlot[]> {\n  const [project, global] = await Promise.all([\n    kv.list<MemorySlot>(KV.slots),\n    kv.list<MemorySlot>(KV.globalSlots),\n  ]);\n  const merged = new Map<string, MemorySlot>();\n  for (const s of global) merged.set(s.label, s);\n  for (const s of project) merged.set(s.label, s);\n  return Array.from(merged.values())\n    .filter((s) => s.pinned && s.content.trim().length > 0)\n    .sort((a, b) => a.label.localeCompare(b.label));\n}\n\nexport function renderPinnedContext(slots: MemorySlot[]): string {\n  if (slots.length === 0) return \"\";\n  const lines: string[] = [\"# agentmemory pinned slots\", \"\"];\n  for (const slot of slots) {\n    lines.push(`## ${slot.label}`);\n    lines.push(slot.content.trim());\n    lines.push(\"\");\n  }\n  return lines.join(\"\\n\");\n}\n\nexport function registerSlotsFunctions(sdk: ISdk, kv: StateKV): void {\n  void seedDefaults(kv).catch((err) => {\n    logger.warn(\"slot defaults seed failed\", {\n      error: err instanceof Error ? err.message : String(err),\n    });\n  });\n\n  sdk.registerFunction(\"mem::slot-list\", async () => {\n    const [project, global] = await Promise.all([\n      kv.list<MemorySlot>(KV.slots),\n      kv.list<MemorySlot>(KV.globalSlots),\n    ]);\n    const merged = new Map<string, MemorySlot>();\n    for (const s of global) merged.set(s.label, s);\n    for (const s of project) merged.set(s.label, s);\n    const slots = Array.from(merged.values()).sort((a, b) =>\n      a.label.localeCompare(b.label),\n    );\n    return { success: true, slots };\n  });\n\n  sdk.registerFunction(\n    \"mem::slot-get\",\n    async (data: { label?: string }) => {\n      const label = validateLabel(data?.label);\n      if (!label) return { success: false, error: \"label required (lowercase, starts with letter, [a-z0-9_])\" };\n      const { slot, scope } = await readSlot(kv, label);\n      if (!slot) return { success: false, error: \"slot not found\" };\n      return { success: true, slot, scope };\n    },\n  );\n\n  sdk.registerFunction(\n    \"mem::slot-create\",\n    async (data: {\n      label?: string;\n      content?: string;\n      sizeLimit?: number;\n      description?: string;\n      pinned?: boolean;\n      scope?: SlotScope;\n    }) => {\n      const label = validateLabel(data?.label);\n      if (!label) return { success: false, error: \"label required (lowercase, starts with letter, [a-z0-9_])\" };\n      const scope = validateScope(data?.scope);\n      if (!scope) return { success: false, error: \"scope must be 'project' or 'global'\" };\n      const sizeLimit = validateSizeLimit(data?.sizeLimit);\n      if (sizeLimit === null) {\n        return { success: false, error: \"sizeLimit must be an integer between 1 and 20000\" };\n      }\n      const content = typeof data?.content === \"string\" ? data.content : \"\";\n      if (content.length > sizeLimit) {\n        return { success: false, error: `content exceeds sizeLimit (${content.length} > ${sizeLimit})` };\n      }\n      const description = typeof data?.description === \"string\" ? data.description : \"\";\n      const pinned = typeof data?.pinned === \"boolean\" ? data.pinned : true;\n      return withKeyedLock(`slot:${label}`, async () => {\n        // Duplicate check is scope-local so a project slot can shadow a\n        // global slot with the same label — matches the read precedence.\n        const existing = await readSlotInScope(kv, label, scope);\n        if (existing) return { success: false, error: `slot already exists in ${scope} scope` };\n        const ts = nowIso();\n        const slot: MemorySlot = {\n          label,\n          content,\n          sizeLimit: sizeLimit as number,\n          description,\n          pinned,\n          readOnly: false,\n          scope,\n          createdAt: ts,\n          updatedAt: ts,\n        };\n        await kv.set(scopeKv(scope), label, slot);\n        await recordAudit(kv, \"slot_create\", \"mem::slot-create\", [label], {\n          scope,\n          sizeLimit: slot.sizeLimit,\n          pinned: slot.pinned,\n        });\n        return { success: true, slot };\n      });\n    },\n  );\n\n  sdk.registerFunction(\n    \"mem::slot-append\",\n    async (data: { label?: string; text?: string }) => {\n      const label = validateLabel(data?.label);\n      if (!label) return { success: false, error: \"label required\" };\n      const text = typeof data?.text === \"string\" ? data.text : \"\";\n      if (!text) return { success: false, error: \"text required\" };\n      return withKeyedLock(`slot:${label}`, async () => {\n        const { slot, scope } = await readSlot(kv, label);\n        if (!slot) return { success: false, error: \"slot not found (use mem::slot-create first)\" };\n        if (slot.readOnly) return { success: false, error: \"slot is read-only\" };\n        const sep = slot.content && !slot.content.endsWith(\"\\n\") ? \"\\n\" : \"\";\n        const next = `${slot.content}${sep}${text}`;\n        if (next.length > slot.sizeLimit) {\n          return {\n            success: false,\n            error: `append would exceed sizeLimit (${next.length} > ${slot.sizeLimit}). Use mem::slot-replace to compact first.`,\n            currentSize: slot.content.length,\n            sizeLimit: slot.sizeLimit,\n          };\n        }\n        const updated: MemorySlot = { ...slot, content: next, updatedAt: nowIso() };\n        await kv.set(scopeKv(scope), label, updated);\n        await recordAudit(kv, \"slot_append\", \"mem::slot-append\", [label], {\n          scope,\n          added: text.length,\n          total: next.length,\n        });\n        return { success: true, slot: updated, size: next.length };\n      });\n    },\n  );\n\n  sdk.registerFunction(\n    \"mem::slot-replace\",\n    async (data: { label?: string; content?: string }) => {\n      const label = validateLabel(data?.label);\n      if (!label) return { success: false, error: \"label required\" };\n      if (typeof data?.content !== \"string\") return { success: false, error: \"content required (string)\" };\n      return withKeyedLock(`slot:${label}`, async () => {\n        const { slot, scope } = await readSlot(kv, label);\n        if (!slot) return { success: false, error: \"slot not found (use mem::slot-create first)\" };\n        if (slot.readOnly) return { success: false, error: \"slot is read-only\" };\n        if (data.content.length > slot.sizeLimit) {\n          return {\n            success: false,\n            error: `content exceeds sizeLimit (${data.content.length} > ${slot.sizeLimit})`,\n            sizeLimit: slot.sizeLimit,\n          };\n        }\n        const updated: MemorySlot = { ...slot, content: data.content, updatedAt: nowIso() };\n        await kv.set(scopeKv(scope), label, updated);\n        await recordAudit(kv, \"slot_replace\", \"mem::slot-replace\", [label], {\n          scope,\n          before: slot.content.length,\n          after: data.content.length,\n        });\n        return { success: true, slot: updated, size: data.content.length };\n      });\n    },\n  );\n\n  sdk.registerFunction(\n    \"mem::slot-delete\",\n    async (data: { label?: string }) => {\n      const label = validateLabel(data?.label);\n      if (!label) return { success: false, error: \"label required\" };\n      return withKeyedLock(`slot:${label}`, async () => {\n        const { slot, scope } = await readSlot(kv, label);\n        if (!slot) return { success: false, error: \"slot not found\" };\n        if (slot.readOnly) return { success: false, error: \"slot is read-only\" };\n        await kv.delete(scopeKv(scope), label);\n        await recordAudit(kv, \"slot_delete\", \"mem::slot-delete\", [label], {\n          scope,\n          size: slot.content.length,\n        });\n        return { success: true };\n      });\n    },\n  );\n\n  sdk.registerFunction(\n    \"mem::slot-reflect\",\n    async (data: { sessionId?: string; maxObservations?: number }) => {\n      if (!data?.sessionId || typeof data.sessionId !== \"string\") {\n        return { success: false, error: \"sessionId required\" };\n      }\n      const max =\n        typeof data.maxObservations === \"number\" &&\n        Number.isInteger(data.maxObservations) &&\n        data.maxObservations > 0\n          ? Math.min(200, data.maxObservations)\n          : 50;\n      const observations = await kv.list<CompressedObservation>(\n        KV.observations(data.sessionId),\n      );\n      if (observations.length === 0) {\n        return { success: true, applied: 0, reason: \"no observations for session\" };\n      }\n      const recent = observations\n        .slice()\n        .sort((a, b) => (b.timestamp || \"\").localeCompare(a.timestamp || \"\"))\n        .slice(0, max);\n\n      const pendingLines: string[] = [];\n      const patternCounts = new Map<string, number>();\n      const files = new Set<string>();\n      for (const obs of recent) {\n        const title = (obs.title || \"\").toLowerCase();\n        const narrative = (obs.narrative || \"\").toLowerCase();\n        if (narrative.includes(\"todo\") || title.includes(\"todo\")) {\n          pendingLines.push(`- ${obs.title || obs.id}`);\n        }\n        if (obs.type === \"error\") {\n          patternCounts.set(\"errors\", (patternCounts.get(\"errors\") ?? 0) + 1);\n        }\n        if (obs.type === \"command_run\") {\n          patternCounts.set(\"commands\", (patternCounts.get(\"commands\") ?? 0) + 1);\n        }\n        if (obs.files) for (const f of obs.files) files.add(f);\n      }\n\n      let applied = 0;\n\n      if (pendingLines.length > 0) {\n        const pendingApplied = await withKeyedLock(`slot:pending_items`, async () => {\n          const { slot, scope } = await readSlot(kv, \"pending_items\");\n          if (!slot) return false;\n          const already = new Set(slot.content.split(\"\\n\"));\n          const fresh = pendingLines.filter((line) => !already.has(line));\n          if (fresh.length === 0) return false;\n          const sep = slot.content && !slot.content.endsWith(\"\\n\") ? \"\\n\" : \"\";\n          const next = `${slot.content}${sep}${fresh.join(\"\\n\")}`;\n          const truncated = next.length > slot.sizeLimit\n            ? next.slice(next.length - slot.sizeLimit)\n            : next;\n          await kv.set(scopeKv(scope), \"pending_items\", {\n            ...slot,\n            content: truncated,\n            updatedAt: nowIso(),\n          });\n          return true;\n        });\n        if (pendingApplied) applied++;\n      }\n\n      if (patternCounts.size > 0) {\n        const patternsApplied = await withKeyedLock(`slot:session_patterns`, async () => {\n          const { slot, scope } = await readSlot(kv, \"session_patterns\");\n          if (!slot) return false;\n          const summary = [\n            `last reflection: ${nowIso()}`,\n            ...Array.from(patternCounts.entries()).map(\n              ([kind, count]) => `- ${kind}: ${count} in last ${recent.length} observations`,\n            ),\n          ].join(\"\\n\");\n          const next =\n            summary.length > slot.sizeLimit ? summary.slice(0, slot.sizeLimit) : summary;\n          await kv.set(scopeKv(scope), \"session_patterns\", {\n            ...slot,\n            content: next,\n            updatedAt: nowIso(),\n          });\n          return true;\n        });\n        if (patternsApplied) applied++;\n      }\n\n      if (files.size > 0) {\n        const ctxApplied = await withKeyedLock(`slot:project_context`, async () => {\n          const { slot, scope } = await readSlot(kv, \"project_context\");\n          if (!slot) return false;\n          const already = slot.content;\n          const fresh = Array.from(files)\n            .filter((f) => !already.includes(f))\n            .slice(0, 20);\n          if (fresh.length === 0) return false;\n          const header =\n            already.length === 0 ? \"Files touched in recent sessions:\" : \"\";\n          const sep = already && !already.endsWith(\"\\n\") ? \"\\n\" : \"\";\n          const nextRaw = `${already}${sep}${header ? header + \"\\n\" : \"\"}${fresh\n            .map((f) => `- ${f}`)\n            .join(\"\\n\")}`;\n          const next =\n            nextRaw.length > slot.sizeLimit\n              ? nextRaw.slice(nextRaw.length - slot.sizeLimit)\n              : nextRaw;\n          await kv.set(scopeKv(scope), \"project_context\", {\n            ...slot,\n            content: next,\n            updatedAt: nowIso(),\n          });\n          return true;\n        });\n        if (ctxApplied) applied++;\n      }\n\n      if (applied > 0) {\n        await recordAudit(kv, \"slot_reflect\", \"mem::slot-reflect\", [data.sessionId], {\n          observationCount: recent.length,\n          slotsUpdated: applied,\n        });\n      }\n\n      return { success: true, applied, observationsReviewed: recent.length };\n    },\n  );\n}\n","import { TriggerAction, type ISdk } from \"iii-sdk\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { getMaxBytes } from \"../utils/image-store.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { logger } from \"../logger.js\";\nimport type { StateScope, StateScopeKey } from \"../types.js\";\n\nconst DISK_SIZE_KEY: StateScopeKey = \"system:currentDiskSize\";\n\nexport function registerDiskSizeManager(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\n    \"mem::disk-size-delta\",\n    async (data: { deltaBytes: number }) => {\n      if (typeof data?.deltaBytes !== \"number\" || !isFinite(data.deltaBytes)) {\n        return { success: false, error: \"deltaBytes must be a finite number\" };\n      }\n\n      return withKeyedLock(DISK_SIZE_KEY, async () => {\n        const currentTotal =\n          (await kv.get<StateScope[typeof DISK_SIZE_KEY]>(KV.state, DISK_SIZE_KEY)) || 0;\n        let newTotal = currentTotal + data.deltaBytes;\n\n        if (newTotal < 0) newTotal = 0;\n\n        await kv.set<StateScope[typeof DISK_SIZE_KEY]>(KV.state, DISK_SIZE_KEY, newTotal);\n\n        if (data.deltaBytes > 0 && newTotal > getMaxBytes()) {\n          sdk.trigger({\n            function_id: \"mem::image-quota-cleanup\",\n            payload: {},\n            action: TriggerAction.Void(),\n          });\n          logger.info(\"Disk quota exceeded, cleanup triggered\", {\n            currentBytes: newTotal,\n            maxBytes: getMaxBytes(),\n          });\n        }\n\n        return { success: true, currentTotal: newTotal };\n      });\n    },\n  );\n}\n","export const COMPRESSION_SYSTEM = `You are a memory compression engine for an AI coding agent. Your job is to extract the essential information from a tool usage observation and compress it into structured data.\n\nOutput EXACTLY this XML format with no additional text:\n\n<observation>\n  <type>one of: file_read, file_write, file_edit, command_run, search, web_fetch, conversation, error, decision, discovery, subagent, notification, task, other</type>\n  <title>Short descriptive title (max 80 chars)</title>\n  <subtitle>One-line context (optional)</subtitle>\n  <facts>\n    <fact>Specific factual detail 1</fact>\n    <fact>Specific factual detail 2</fact>\n  </facts>\n  <narrative>2-3 sentence summary of what happened and why it matters</narrative>\n  <concepts>\n    <concept>technical concept or pattern</concept>\n  </concepts>\n  <files>\n    <file>path/to/file</file>\n  </files>\n  <importance>1-10 scale, 10 being critical architectural decision</importance>\n</observation>\n\nRules:\n- Be concise but preserve ALL technically relevant details\n- File paths must be exact\n- Importance: 1-3 for routine reads, 4-6 for edits/commands, 7-9 for architectural decisions, 10 for breaking changes\n- Concepts should be reusable search terms (e.g., \"React hooks\", \"SQL migration\", \"auth middleware\")\n- Strip any secrets, tokens, or credentials from the output`;\n\nexport function buildCompressionPrompt(observation: {\n  hookType: string;\n  toolName?: string;\n  toolInput?: unknown;\n  toolOutput?: unknown;\n  userPrompt?: string;\n  timestamp: string;\n}): string {\n  const parts = [\n    `Timestamp: ${observation.timestamp}`,\n    `Hook: ${observation.hookType}`,\n  ];\n\n  if (observation.toolName) parts.push(`Tool: ${observation.toolName}`);\n  if (observation.toolInput) {\n    const input =\n      typeof observation.toolInput === \"string\"\n        ? observation.toolInput\n        : JSON.stringify(observation.toolInput, null, 2);\n    parts.push(`Input:\\n${truncate(input, 4000)}`);\n  }\n  if (observation.toolOutput) {\n    const output =\n      typeof observation.toolOutput === \"string\"\n        ? observation.toolOutput\n        : JSON.stringify(observation.toolOutput, null, 2);\n    parts.push(`Output:\\n${truncate(output, 4000)}`);\n  }\n  if (observation.userPrompt) {\n    parts.push(`User prompt:\\n${truncate(observation.userPrompt, 2000)}`);\n  }\n\n  return parts.join(\"\\n\\n\");\n}\n\nfunction truncate(s: string, max: number): string {\n  return s.length > max ? s.slice(0, max) + \"\\n[...truncated]\" : s;\n}\n","export const VISION_DESCRIPTION_PROMPT = `Describe what this image shows in the context of software development. Extract:\n- What type of image this is (screenshot, diagram, mockup, terminal output, error, etc.)\n- Key entities visible (files, components, UI elements, error messages)\n- Relationships or flow shown\n- Any decisions, errors, or state visible\n- Text content visible in the image\n\nBe concise but preserve all technically relevant details. Output plain text, no XML.`;\n","const VALID_TAG = /^[a-zA-Z_][a-zA-Z0-9_-]*$/;\n\nexport function getXmlTag(xml: string, tag: string): string {\n  if (!VALID_TAG.test(tag)) return \"\";\n  const match = xml.match(new RegExp(`<${tag}>([\\\\s\\\\S]*?)</${tag}>`));\n  return match ? match[1].trim() : \"\";\n}\n\nexport function getXmlChildren(\n  xml: string,\n  parentTag: string,\n  childTag: string,\n): string[] {\n  if (!VALID_TAG.test(parentTag) || !VALID_TAG.test(childTag)) return [];\n  const parentMatch = xml.match(\n    new RegExp(`<${parentTag}>([\\\\s\\\\S]*?)</${parentTag}>`),\n  );\n  if (!parentMatch) return [];\n  const items: string[] = [];\n  const re = new RegExp(`<${childTag}>([\\\\s\\\\S]*?)</${childTag}>`, \"g\");\n  let m;\n  while ((m = re.exec(parentMatch[1])) !== null) {\n    items.push(m[1].trim());\n  }\n  return items;\n}\n","import { z } from \"zod\";\n\nconst HookTypeEnum = z.enum([\n  \"session_start\",\n  \"prompt_submit\",\n  \"pre_tool_use\",\n  \"post_tool_use\",\n  \"post_tool_failure\",\n  \"pre_compact\",\n  \"subagent_start\",\n  \"subagent_stop\",\n  \"notification\",\n  \"task_completed\",\n  \"stop\",\n  \"session_end\",\n]);\n\nconst ObservationTypeEnum = z.enum([\n  \"file_read\",\n  \"file_write\",\n  \"file_edit\",\n  \"command_run\",\n  \"search\",\n  \"web_fetch\",\n  \"conversation\",\n  \"error\",\n  \"decision\",\n  \"discovery\",\n  \"subagent\",\n  \"notification\",\n  \"task\",\n  \"other\",\n]);\n\nexport const ObserveInputSchema = z.object({\n  hookType: HookTypeEnum,\n  sessionId: z.string().min(1),\n  project: z.string().min(1),\n  cwd: z.string().min(1),\n  timestamp: z.string().min(1),\n  data: z.unknown(),\n});\n\nexport const CompressOutputSchema = z.object({\n  type: ObservationTypeEnum,\n  title: z.string().min(1).max(120),\n  subtitle: z.string().optional(),\n  facts: z.array(z.string()).min(1),\n  narrative: z.string().min(10),\n  concepts: z.array(z.string()),\n  files: z.array(z.string()),\n  importance: z.number().int().min(1).max(10),\n});\n\nexport const SummaryOutputSchema = z.object({\n  title: z.string().min(1),\n  narrative: z.string().min(20),\n  keyDecisions: z.array(z.string()),\n  filesModified: z.array(z.string()),\n  concepts: z.array(z.string()),\n});\n\nexport const SearchInputSchema = z.object({\n  query: z.string().min(1),\n  limit: z.number().int().positive().optional(),\n});\n\nexport const ContextInputSchema = z.object({\n  sessionId: z.string().min(1),\n  project: z.string().min(1),\n  budget: z.number().positive().optional(),\n});\n\nexport const RememberInputSchema = z.object({\n  content: z.string().min(1),\n  type: z\n    .enum([\"pattern\", \"preference\", \"architecture\", \"bug\", \"workflow\", \"fact\"])\n    .optional(),\n  concepts: z.array(z.string()).optional(),\n  files: z.array(z.string()).optional(),\n});\n\nexport const SmartSearchInputSchema = z.object({\n  query: z.string().optional(),\n  expandIds: z.array(z.string()).optional(),\n  limit: z.number().int().positive().optional(),\n});\n\nexport const TimelineInputSchema = z.object({\n  anchor: z.string().min(1),\n  project: z.string().optional(),\n  before: z.number().int().nonnegative().optional(),\n  after: z.number().int().nonnegative().optional(),\n});\n\nexport const ProfileInputSchema = z.object({\n  project: z.string().min(1),\n  refresh: z.boolean().optional(),\n});\n\nexport const RelateInputSchema = z.object({\n  sourceId: z.string().min(1),\n  targetId: z.string().min(1),\n  type: z.enum([\"supersedes\", \"extends\", \"derives\", \"contradicts\", \"related\"]),\n});\n\nexport const EvolveInputSchema = z.object({\n  memoryId: z.string().min(1),\n  newContent: z.string().min(1),\n  newTitle: z.string().optional(),\n});\n\nexport const ExportImportInputSchema = z.object({\n  exportData: z.object({\n    version: z.union([z.literal(\"0.3.0\"), z.literal(\"0.4.0\")]),\n    exportedAt: z.string(),\n    sessions: z.array(z.unknown()),\n    observations: z.record(z.string(), z.array(z.unknown())),\n    memories: z.array(z.unknown()),\n    summaries: z.array(z.unknown()),\n    profiles: z.array(z.unknown()).optional(),\n  }),\n  strategy: z.enum([\"merge\", \"replace\", \"skip\"]).optional(),\n});\n","import type { z } from \"zod\";\nimport type { EvalResult } from \"../types.js\";\n\nexport function validateInput<T>(\n  schema: z.ZodType<T>,\n  data: unknown,\n  functionId: string,\n): { valid: true; data: T } | { valid: false; result: EvalResult } {\n  const parsed = schema.safeParse(data);\n  if (parsed.success) {\n    return { valid: true, data: parsed.data };\n  }\n  return {\n    valid: false,\n    result: {\n      valid: false,\n      errors: parsed.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`),\n      qualityScore: 0,\n      latencyMs: 0,\n      functionId,\n    },\n  };\n}\n\nexport function validateOutput<T>(\n  schema: z.ZodType<T>,\n  data: unknown,\n  functionId: string,\n): { valid: true; data: T } | { valid: false; result: EvalResult } {\n  return validateInput(schema, data, functionId);\n}\n","export function scoreCompression(obs: {\n  type?: string;\n  title?: string;\n  facts?: string[];\n  narrative?: string;\n  concepts?: string[];\n  importance?: number;\n}): number {\n  let score = 0;\n  if (obs.facts && obs.facts.length > 0) score += 25;\n  if (obs.facts && obs.facts.length >= 3) score += 10;\n  if (obs.narrative && obs.narrative.length >= 20) score += 20;\n  if (obs.narrative && obs.narrative.length >= 50) score += 5;\n  if (obs.title && obs.title.length >= 5 && obs.title.length <= 120) score += 15;\n  if (obs.concepts && obs.concepts.length > 0) score += 15;\n  if (obs.importance && obs.importance >= 1 && obs.importance <= 10) score += 10;\n  return Math.min(100, score);\n}\n\nexport function scoreSummary(summary: {\n  title?: string;\n  narrative?: string;\n  keyDecisions?: string[];\n  filesModified?: string[];\n  concepts?: string[];\n}): number {\n  let score = 0;\n  if (summary.title && summary.title.length >= 5) score += 20;\n  if (summary.narrative && summary.narrative.length >= 20) score += 25;\n  if (summary.narrative && summary.narrative.length >= 100) score += 5;\n  if (summary.keyDecisions && summary.keyDecisions.length > 0) score += 20;\n  if (summary.filesModified && summary.filesModified.length > 0) score += 15;\n  if (summary.concepts && summary.concepts.length > 0) score += 15;\n  return Math.min(100, score);\n}\n\nexport function scoreContextRelevance(\n  context: string,\n  project: string,\n): number {\n  let score = 0;\n  if (context.length > 0) score += 20;\n  if (project && context.toLowerCase().includes(project.toLowerCase())) score += 20;\n  if (context.includes(\"<\")) score += 15;\n  const sectionCount = (context.match(/<\\w+>/g) || []).length;\n  if (sectionCount >= 2) score += 15;\n  if (sectionCount >= 4) score += 10;\n  if (context.length >= 100) score += 10;\n  if (context.length >= 500) score += 10;\n  return Math.min(100, score);\n}\n","import type { MemoryProvider } from \"../types.js\";\n\nconst STRICTER_SUFFIX = `\n\nIMPORTANT: Your previous response was invalid. Please ensure your output strictly follows the required XML format. Every required field must be present with valid values.`;\n\nexport async function compressWithRetry(\n  provider: MemoryProvider,\n  systemPrompt: string,\n  userPrompt: string,\n  validator: (response: string) => { valid: boolean; errors?: string[] },\n  maxRetries = 1,\n): Promise<{ response: string; retried: boolean }> {\n  const first = await provider.compress(systemPrompt, userPrompt);\n  const result = validator(first);\n  if (result.valid) return { response: first, retried: false };\n\n  for (let i = 0; i < maxRetries; i++) {\n    const retry = await provider.compress(\n      systemPrompt + STRICTER_SUFFIX,\n      userPrompt,\n    );\n    const retryResult = validator(retry);\n    if (retryResult.valid) return { response: retry, retried: true };\n  }\n\n  return { response: first, retried: true };\n}\n","import { TriggerAction, type ISdk } from \"iii-sdk\";\nimport { readFileSync } from \"node:fs\";\nimport { isManagedImagePath } from \"../utils/image-store.js\";\nimport type {\n  RawObservation,\n  CompressedObservation,\n  ObservationType,\n  MemoryProvider,\n} from \"../types.js\";\nimport { KV, STREAM } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport {\n  COMPRESSION_SYSTEM,\n  buildCompressionPrompt,\n} from \"../prompts/compression.js\";\nimport { VISION_DESCRIPTION_PROMPT } from \"../prompts/vision.js\";\nimport { getXmlTag, getXmlChildren } from \"../prompts/xml.js\";\nimport { getSearchIndex, vectorIndexAddGuarded } from \"./search.js\";\nimport { CompressOutputSchema } from \"../eval/schemas.js\";\nimport { validateOutput } from \"../eval/validator.js\";\nimport { scoreCompression } from \"../eval/quality.js\";\nimport { compressWithRetry } from \"../eval/self-correct.js\";\nimport type { MetricsStore } from \"../eval/metrics-store.js\";\nimport { logger } from \"../logger.js\";\n\nconst VALID_TYPES = new Set<string>([\n  \"file_read\",\n  \"file_write\",\n  \"file_edit\",\n  \"command_run\",\n  \"search\",\n  \"web_fetch\",\n  \"conversation\",\n  \"error\",\n  \"decision\",\n  \"discovery\",\n  \"subagent\",\n  \"notification\",\n  \"task\",\n  \"image\",\n  \"other\",\n]);\n\nfunction parseCompressionXml(\n  xml: string,\n): Omit<CompressedObservation, \"id\" | \"sessionId\" | \"timestamp\"> | null {\n  const rawType = getXmlTag(xml, \"type\");\n  const title = getXmlTag(xml, \"title\");\n  if (!rawType || !title) return null;\n  const type = VALID_TYPES.has(rawType) ? rawType : \"other\";\n\n  return {\n    type: type as ObservationType,\n    title,\n    subtitle: getXmlTag(xml, \"subtitle\") || undefined,\n    facts: getXmlChildren(xml, \"facts\", \"fact\"),\n    narrative: getXmlTag(xml, \"narrative\"),\n    concepts: getXmlChildren(xml, \"concepts\", \"concept\"),\n    files: getXmlChildren(xml, \"files\", \"file\"),\n    importance: Math.max(\n      1,\n      Math.min(10, parseInt(getXmlTag(xml, \"importance\") || \"5\", 10) || 5),\n    ),\n  };\n}\n\nexport function registerCompressFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n  metricsStore?: MetricsStore,\n): void {\n  sdk.registerFunction(\"mem::compress\", \n    async (data: {\n      observationId: string;\n      sessionId: string;\n      raw: RawObservation;\n    }) => {\n      const startMs = Date.now();\n\n      let imageDescription: string | undefined;\n      const hasImage = data.raw.modality === \"image\" || data.raw.modality === \"mixed\";\n\n      if (hasImage && data.raw.imageData && provider.describeImage) {\n        try {\n          let base64Data = data.raw.imageData;\n          let mimeType = \"image/png\";\n\n          if (!data.raw.imageData.startsWith(\"/9j/\") && !data.raw.imageData.startsWith(\"iVBOR\")) {\n            if (!isManagedImagePath(data.raw.imageData)) {\n              throw new Error(`Refusing to read image outside managed store: ${data.raw.imageData}`);\n            }\n            const fileBuffer = readFileSync(data.raw.imageData);\n            base64Data = fileBuffer.toString(\"base64\");\n            if (data.raw.imageData.endsWith(\".jpg\") || data.raw.imageData.endsWith(\".jpeg\")) mimeType = \"image/jpeg\";\n            else if (data.raw.imageData.endsWith(\".webp\")) mimeType = \"image/webp\";\n            else if (data.raw.imageData.endsWith(\".gif\")) mimeType = \"image/gif\";\n          }\n\n          imageDescription = await provider.describeImage(base64Data, mimeType, VISION_DESCRIPTION_PROMPT);\n          logger.info(\"Image described by vision model\", { obsId: data.observationId });\n        } catch (err) {\n          const msg = err instanceof Error ? err.message : String(err);\n          logger.warn(\"Vision model call failed, falling back to text-only compression\", {\n            obsId: data.observationId,\n            error: msg,\n          });\n        }\n      }\n\n      const prompt = buildCompressionPrompt({\n        hookType: data.raw.hookType,\n        toolName: data.raw.toolName,\n        toolInput: data.raw.toolInput,\n        toolOutput: imageDescription\n          ? `[Image Description]: ${imageDescription}\\n\\n${data.raw.toolOutput ?? \"\"}`\n          : data.raw.toolOutput,\n        userPrompt: data.raw.userPrompt,\n        timestamp: data.raw.timestamp,\n      });\n\n      try {\n        const validator = (response: string) => {\n          const parsed = parseCompressionXml(response);\n          if (!parsed) return { valid: false, errors: [\"xml_parse_failed\"] };\n          const result = validateOutput(\n            CompressOutputSchema,\n            parsed,\n            \"mem::compress\",\n          );\n          return result.valid\n            ? { valid: true }\n            : { valid: false, errors: result.result.errors };\n        };\n\n        const { response, retried } = await compressWithRetry(\n          provider,\n          COMPRESSION_SYSTEM,\n          prompt,\n          validator,\n          1,\n        );\n\n        const parsed = parseCompressionXml(response);\n        if (!parsed) {\n          const latencyMs = Date.now() - startMs;\n          if (metricsStore) {\n            await metricsStore.record(\"mem::compress\", latencyMs, false);\n          }\n          logger.warn(\"Failed to parse compression XML\", {\n            obsId: data.observationId,\n            retried,\n          });\n          return { success: false, error: \"parse_failed\" };\n        }\n\n        const qualityScore = scoreCompression(parsed);\n\n        const compressed: CompressedObservation = {\n          id: data.observationId,\n          sessionId: data.sessionId,\n          timestamp: data.raw.timestamp,\n          ...parsed,\n          confidence: qualityScore / 100,\n          ...(hasImage ? { modality: data.raw.modality } : {}),\n          ...(imageDescription ? { imageDescription } : {}),\n          ...(data.raw.imageData ? { imageRef: data.raw.imageData } : {}),\n          ...(data.raw.agentId ? { agentId: data.raw.agentId } : {}),\n        };\n\n        await kv.set(\n          KV.observations(data.sessionId),\n          data.observationId,\n          compressed,\n        );\n\n        try {\n          getSearchIndex().add(compressed);\n        } catch (err) {\n          logger.warn(\"Failed to index compressed observation into BM25\", {\n            obsId: compressed.id,\n            sessionId: compressed.sessionId,\n            title: compressed.title,\n            error: err instanceof Error ? err.message : String(err),\n          });\n        }\n\n        await vectorIndexAddGuarded(\n          compressed.id,\n          compressed.sessionId,\n          compressed.title + \" \" + (compressed.narrative || \"\"),\n          { kind: \"observation\", logId: compressed.id },\n        );\n\n        const streamResults = await Promise.allSettled([\n          sdk.trigger({\n            function_id: \"stream::set\",\n            payload: {\n              stream_name: STREAM.name,\n              group_id: STREAM.group(data.sessionId),\n              item_id: data.observationId,\n              data: { type: \"compressed\", observation: compressed },\n            },\n          }),\n          sdk.trigger({\n            function_id: \"stream::send\",\n            payload: {\n              stream_name: STREAM.name,\n              group_id: STREAM.viewerGroup,\n              id: `compressed-${data.observationId}`,\n              type: \"compressed_observation\",\n              data: {\n                type: \"compressed\",\n                observation: compressed,\n                sessionId: data.sessionId,\n              },\n            },\n            action: TriggerAction.Void(),\n          }),\n        ]);\n        for (const result of streamResults) {\n          if (result.status === \"rejected\") {\n            logger.warn(\"Non-fatal stream publish failure after compress\", {\n              sessionId: data.sessionId,\n              observationId: data.observationId,\n              error:\n                result.reason instanceof Error\n                  ? result.reason.message\n                  : String(result.reason),\n            });\n          }\n        }\n\n        const latencyMs = Date.now() - startMs;\n        if (metricsStore) {\n          await metricsStore.record(\n            \"mem::compress\",\n            latencyMs,\n            true,\n            qualityScore,\n          );\n        }\n\n        logger.info(\"Observation compressed\", {\n          obsId: data.observationId,\n          type: compressed.type,\n          importance: compressed.importance,\n          qualityScore,\n          retried,\n        });\n\n        return { success: true, compressed, qualityScore };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        const latencyMs = Date.now() - startMs;\n        if (metricsStore) {\n          await metricsStore.record(\"mem::compress\", latencyMs, false);\n        }\n        logger.error(\"Compression failed\", {\n          obsId: data.observationId,\n          error: msg,\n        });\n        return { success: false, error: \"compression_failed\" };\n      }\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  Session,\n  CompressedObservation,\n  SessionSummary,\n  ContextBlock,\n  ProjectProfile,\n  MemorySlot,\n  Lesson,\n} from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { recordAccessBatch } from \"./access-tracker.js\";\nimport { logger } from \"../logger.js\";\nimport {\n  isSlotsEnabled,\n  listPinnedSlots,\n  renderPinnedContext,\n} from \"./slots.js\";\n\nfunction estimateTokens(text: string): number {\n  return Math.ceil(text.length / 3);\n}\n\nfunction escapeXmlAttr(s: string): string {\n  return s\n    .replace(/&/g, \"&amp;\")\n    .replace(/\"/g, \"&quot;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\");\n}\n\nexport function registerContextFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  tokenBudget: number,\n): void {\n  sdk.registerFunction(\"mem::context\", \n    async (data: { sessionId: string; project: string; budget?: number }) => {\n      const budget = data.budget || tokenBudget;\n      const blocks: ContextBlock[] = [];\n\n      const [pinnedSlots, profile, lessons] = await Promise.all([\n        isSlotsEnabled()\n          ? listPinnedSlots(kv).catch(() => [] as MemorySlot[])\n          : Promise.resolve([] as MemorySlot[]),\n        kv\n          .get<ProjectProfile>(KV.profiles, data.project)\n          .catch(() => null),\n        kv.list<Lesson>(KV.lessons).catch(() => [] as Lesson[]),\n      ]);\n\n      const slotContent = renderPinnedContext(pinnedSlots);\n      if (slotContent) {\n        blocks.push({\n          type: \"memory\",\n          content: slotContent,\n          tokens: estimateTokens(slotContent),\n          recency: Date.now(),\n        });\n      }\n      if (profile) {\n        const profileParts = [];\n        if (profile.topConcepts.length > 0) {\n          profileParts.push(\n            `Concepts: ${profile.topConcepts\n              .slice(0, 8)\n              .map((c) => c.concept)\n              .join(\", \")}`,\n          );\n        }\n        if (profile.topFiles.length > 0) {\n          profileParts.push(\n            `Key files: ${profile.topFiles\n              .slice(0, 5)\n              .map((f) => f.file)\n              .join(\", \")}`,\n          );\n        }\n        if (profile.conventions.length > 0) {\n          profileParts.push(`Conventions: ${profile.conventions.join(\"; \")}`);\n        }\n        if (profile.commonErrors.length > 0) {\n          profileParts.push(\n            `Common errors: ${profile.commonErrors.slice(0, 3).join(\"; \")}`,\n          );\n        }\n        if (profileParts.length > 0) {\n          const profileContent = `## Project Profile\\n${profileParts.join(\"\\n\")}`;\n          blocks.push({\n            type: \"memory\",\n            content: profileContent,\n            tokens: estimateTokens(profileContent),\n            recency: new Date(profile.updatedAt).getTime(),\n          });\n        }\n      }\n\n      // Lessons — closes the loop opened by mem::lesson-save / mem::reflect.\n      // Without this block, lessons sit in KV and only surface when the agent\n      // thinks to call memory_lesson_recall. Ranking puts project-scoped\n      // lessons ahead of global ones, then weights by confidence; we cap at\n      // 10 to keep the block bounded since the outer token-budget loop\n      // below will drop the whole block if it doesn't fit. #457.\n      const relevantLessons = lessons\n        .filter((l) => !l.deleted && (!l.project || l.project === data.project))\n        .sort((a, b) => {\n          const scoreA = (a.project === data.project ? 1.5 : 1) * a.confidence;\n          const scoreB = (b.project === data.project ? 1.5 : 1) * b.confidence;\n          return scoreB - scoreA;\n        })\n        .slice(0, 10);\n\n      if (relevantLessons.length > 0) {\n        const items = relevantLessons\n          .map(\n            (l) =>\n              `- (${l.confidence.toFixed(2)}) ${l.content}${l.context ? ` — ${l.context}` : \"\"}`,\n          )\n          .join(\"\\n\");\n        const lessonsContent = `## Lessons Learned\\n${items}`;\n        const mostRecent = relevantLessons.reduce((acc, l) => {\n          const t = new Date(l.lastReinforcedAt || l.updatedAt).getTime();\n          return t > acc ? t : acc;\n        }, 0);\n        blocks.push({\n          type: \"memory\",\n          content: lessonsContent,\n          tokens: estimateTokens(lessonsContent),\n          recency: mostRecent,\n          sourceIds: relevantLessons.map((l) => l.id),\n        });\n      }\n\n      const allSessions = await kv.list<Session>(KV.sessions);\n      const sessions = allSessions\n        .filter((s) => s.project === data.project && s.id !== data.sessionId)\n        .sort(\n          (a, b) =>\n            new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime(),\n        )\n        .slice(0, 10);\n\n      const summariesPerSession = await Promise.all(\n        sessions.map((s) =>\n          kv.get<SessionSummary>(KV.summaries, s.id).catch(() => null),\n        ),\n      );\n\n      const sessionsNeedingObs: number[] = [];\n      for (let i = 0; i < sessions.length; i++) {\n        const summary = summariesPerSession[i];\n        if (summary) {\n          const content = `## ${summary.title}\\n${summary.narrative}\\nDecisions: ${summary.keyDecisions.join(\"; \")}\\nFiles: ${summary.filesModified.join(\", \")}`;\n          blocks.push({\n            type: \"summary\",\n            content,\n            tokens: estimateTokens(content),\n            recency: new Date(summary.createdAt).getTime(),\n          });\n        } else {\n          sessionsNeedingObs.push(i);\n        }\n      }\n\n      const obsResults = await Promise.all(\n        sessionsNeedingObs.map((i) =>\n          kv\n            .list<CompressedObservation>(KV.observations(sessions[i].id))\n            .catch(() => []),\n        ),\n      );\n\n      for (let j = 0; j < sessionsNeedingObs.length; j++) {\n        const i = sessionsNeedingObs[j];\n        const observations = obsResults[j];\n        const important = observations.filter(\n          (o) => o.title && o.importance >= 5,\n        );\n\n        if (important.length > 0) {\n          const top = important\n            .sort((a, b) => b.importance - a.importance)\n            .slice(0, 5);\n          const items = top\n            .map((o) => `- [${o.type}] ${o.title}: ${o.narrative}`)\n            .join(\"\\n\");\n          const content = `## Session ${sessions[i].id.slice(0, 8)} (${sessions[i].startedAt})\\n${items}`;\n          blocks.push({\n            type: \"observation\",\n            content,\n            tokens: estimateTokens(content),\n            recency: new Date(sessions[i].startedAt).getTime(),\n            sourceIds: top.map((o) => o.id),\n          });\n        }\n      }\n\n      blocks.sort((a, b) => b.recency - a.recency);\n\n      let usedTokens = 0;\n      const selected: string[] = [];\n      const accessedIds: string[] = [];\n      const header = `<agentmemory-context project=\"${escapeXmlAttr(data.project)}\">`;\n      const footer = `</agentmemory-context>`;\n      usedTokens += estimateTokens(header) + estimateTokens(footer);\n\n      for (const block of blocks) {\n        if (usedTokens + block.tokens > budget) continue;\n        selected.push(block.content);\n        usedTokens += block.tokens;\n        if (block.sourceIds && block.sourceIds.length > 0) {\n          accessedIds.push(...block.sourceIds);\n        }\n      }\n\n      if (accessedIds.length > 0) {\n        void recordAccessBatch(kv, accessedIds);\n      }\n\n      if (selected.length === 0) {\n        logger.info(\"No context available\", { project: data.project });\n        return { context: \"\", blocks: 0, tokens: 0 };\n      }\n\n      const result = `${header}\\n${selected.join(\"\\n\\n\")}\\n${footer}`;\n      logger.info(\"Context generated\", {\n        blocks: selected.length,\n        tokens: usedTokens,\n      });\n      return { context: result, blocks: selected.length, tokens: usedTokens };\n    },\n  );\n}\n","export const SUMMARY_SYSTEM = `You are a session summarizer for an AI coding agent's memory system. Given all compressed observations from a coding session, produce a concise session summary.\n\nOutput EXACTLY this XML format with no additional text:\n\n<summary>\n  <title>Short session title (max 100 chars)</title>\n  <narrative>3-5 sentence narrative of what was accomplished</narrative>\n  <decisions>\n    <decision>Key technical decision made</decision>\n  </decisions>\n  <files>\n    <file>path/to/modified/file</file>\n  </files>\n  <concepts>\n    <concept>key concept from session</concept>\n  </concepts>\n</summary>\n\nRules:\n- Focus on outcomes, not individual tool calls\n- Highlight decisions and their rationale\n- List all files that were created or modified\n- Concepts should be searchable terms for future context retrieval`\n\nexport function buildSummaryPrompt(observations: Array<{\n  type: string\n  title: string\n  facts: string[]\n  narrative: string\n  files: string[]\n  concepts: string[]\n}>): string {\n  const lines = observations.map((obs, i) => {\n    const facts = obs.facts.map((f) => `  - ${f}`).join('\\n')\n    return `[${i + 1}] ${obs.type}: ${obs.title}\\n${obs.narrative}\\nFacts:\\n${facts}\\nFiles: ${obs.files.join(', ')}`\n  })\n  return `Session observations (${observations.length} total):\\n\\n${lines.join('\\n\\n---\\n\\n')}`\n}\n\nexport const REDUCE_SYSTEM = `You are merging multiple partial summaries of the SAME coding session into one final session summary. The partials are chronological chunks of one continuous session — not separate sessions.\n\nOutput EXACTLY this XML format with no additional text:\n\n<summary>\n  <title>Short session title (max 100 chars)</title>\n  <narrative>3-5 sentence narrative covering the whole session</narrative>\n  <decisions>\n    <decision>Key technical decision made</decision>\n  </decisions>\n  <files>\n    <file>path/to/modified/file</file>\n  </files>\n  <concepts>\n    <concept>key concept from session</concept>\n  </concepts>\n</summary>\n\nRules:\n- Synthesize a single narrative that reflects the whole arc, not a chunk-by-chunk recap\n- Preserve every distinct decision across chunks\n- Union (deduplicate) all files and concepts\n- Title should capture the session's overall outcome`\n\nexport function buildReducePrompt(partials: Array<{\n  title: string\n  narrative: string\n  keyDecisions: string[]\n  filesModified: string[]\n  concepts: string[]\n  obsRangeStart: number\n  obsRangeEnd: number\n}>): string {\n  const sections = partials.map((p, i) => {\n    const decisions = p.keyDecisions.map((d) => `  - ${d}`).join('\\n')\n    const files = p.filesModified.map((f) => `  - ${f}`).join('\\n')\n    const concepts = p.concepts.join(', ')\n    return `[Chunk ${i + 1} of ${partials.length} — obs ${p.obsRangeStart}-${p.obsRangeEnd}]\nTitle: ${p.title}\nNarrative: ${p.narrative}\nDecisions:\n${decisions}\nFiles:\n${files}\nConcepts: ${concepts}`\n  })\n  return `Partial summaries (${partials.length} chunks of one session, chronological):\\n\\n${sections.join('\\n\\n---\\n\\n')}`\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  CompressedObservation,\n  SessionSummary,\n  MemoryProvider,\n  Session,\n} from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport {\n  SUMMARY_SYSTEM,\n  buildSummaryPrompt,\n  REDUCE_SYSTEM,\n  buildReducePrompt,\n} from \"../prompts/summary.js\";\nimport { getXmlTag, getXmlChildren } from \"../prompts/xml.js\";\nimport { SummaryOutputSchema } from \"../eval/schemas.js\";\nimport { validateOutput } from \"../eval/validator.js\";\nimport { scoreSummary } from \"../eval/quality.js\";\nimport type { MetricsStore } from \"../eval/metrics-store.js\";\nimport { safeAudit } from \"./audit.js\";\nimport { logger } from \"../logger.js\";\n\n// Per-chunk observation budget when a session is too large to fit in one\n// LLM call. Default ≈ 50k input tokens per chunk at ~110 tok/obs — fits\n// comfortably in 128k-window models. Override via SUMMARIZE_CHUNK_SIZE.\nconst CHUNK_SIZE_DEFAULT = 400;\n// Concurrent in-flight chunk calls. 6 keeps a 100-chunk session under\n// iii's 180s function-invocation timeout at ~8s/call while staying\n// inside generous-but-not-unlimited provider rate limits (well below\n// OpenAI free tier's 500 RPM). High-throughput providers\n// (Novita / DeepInfra / DeepSeek) typically allow 100+ concurrent — set\n// SUMMARIZE_CHUNK_CONCURRENCY higher to cover ~1000+ chunk sessions.\nconst CHUNK_CONCURRENCY_DEFAULT = 6;\n// Bail on the merged summary if more than this fraction of chunks fail\n// to parse — a half-blind narrative is worse than a clean error.\nconst MAX_SKIP_RATIO = 0.5;\n\nfunction getChunkSize(): number {\n  const raw = process.env.SUMMARIZE_CHUNK_SIZE;\n  if (!raw) return CHUNK_SIZE_DEFAULT;\n  const n = parseInt(raw, 10);\n  return Number.isFinite(n) && n > 0 ? n : CHUNK_SIZE_DEFAULT;\n}\n\nfunction getChunkConcurrency(): number {\n  const raw = process.env.SUMMARIZE_CHUNK_CONCURRENCY;\n  if (!raw) return CHUNK_CONCURRENCY_DEFAULT;\n  const n = parseInt(raw, 10);\n  return Number.isFinite(n) && n > 0 ? n : CHUNK_CONCURRENCY_DEFAULT;\n}\n\n// One chunk call with retry-once. Returns null when both attempts fail —\n// whether by parse failure, provider 4xx (content rejected by upstream\n// filters), or transient network/5xx errors that didn't recover on retry.\n// All failure modes are equivalent at this layer: the chunk is unusable,\n// skip it and let the caller decide via the skip-ratio bailout whether\n// the overall summary is still trustworthy. Errors that affect every\n// chunk (auth, model down) will trip the bailout naturally.\nasync function summarizeChunkWithRetry(\n  provider: MemoryProvider,\n  chunk: CompressedObservation[],\n  sessionId: string,\n  project: string,\n  idx: number,\n  total: number,\n): Promise<SessionSummary | null> {\n  for (let attempt = 1; attempt <= 2; attempt++) {\n    try {\n      const xml = await provider.summarize(\n        SUMMARY_SYSTEM,\n        buildSummaryPrompt(chunk),\n      );\n      const parsed = parseSummaryXml(xml, sessionId, project, chunk.length);\n      if (parsed) return parsed;\n      logger.warn(\"Summarize chunk parse failed\", {\n        sessionId,\n        chunk: `${idx + 1}/${total}`,\n        attempt,\n      });\n    } catch (err) {\n      logger.warn(\"Summarize chunk LLM call failed\", {\n        sessionId,\n        chunk: `${idx + 1}/${total}`,\n        attempt,\n        error: err instanceof Error ? err.message : String(err),\n      });\n    }\n  }\n  return null;\n}\n\n// Returns the final summary XML string. For sessions ≤ chunk size, this is\n// a single LLM call (legacy behavior). For larger sessions, observations\n// are split into chunks processed in parallel batches, each chunk retried\n// once on parse failure, persistently-bad chunks skipped, and remaining\n// partials merged via a reduce call.\nasync function produceSummaryXml(\n  provider: MemoryProvider,\n  compressed: CompressedObservation[],\n  sessionId: string,\n  project: string,\n): Promise<{\n  response: string;\n  mode: \"single\" | \"chunked\";\n  chunks: number;\n  skipped?: number;\n}> {\n  const chunkSize = getChunkSize();\n  if (compressed.length <= chunkSize) {\n    const response = await provider.summarize(\n      SUMMARY_SYSTEM,\n      buildSummaryPrompt(compressed),\n    );\n    return { response, mode: \"single\", chunks: 1 };\n  }\n\n  const chunks: CompressedObservation[][] = [];\n  for (let i = 0; i < compressed.length; i += chunkSize) {\n    chunks.push(compressed.slice(i, i + chunkSize));\n  }\n  const concurrency = getChunkConcurrency();\n  logger.info(\"Summarize chunking session\", {\n    sessionId,\n    chunks: chunks.length,\n    chunkSize,\n    concurrency,\n    totalObservations: compressed.length,\n  });\n\n  // Sparse array preserves chunk → index mapping after parallel resolution,\n  // so the reduce step sees partials in chronological order even when some\n  // were skipped.\n  const partialByIdx: Array<SessionSummary | null> = new Array(chunks.length).fill(null);\n  for (let batchStart = 0; batchStart < chunks.length; batchStart += concurrency) {\n    const batch = chunks.slice(batchStart, batchStart + concurrency);\n    await Promise.all(\n      batch.map(async (chunk, j) => {\n        const idx = batchStart + j;\n        partialByIdx[idx] = await summarizeChunkWithRetry(\n          provider,\n          chunk,\n          sessionId,\n          project,\n          idx,\n          chunks.length,\n        );\n      }),\n    );\n  }\n\n  const skipped = partialByIdx.filter((p) => p === null).length;\n  const partials = partialByIdx.filter((p): p is SessionSummary => p !== null);\n\n  if (skipped > Math.floor(chunks.length * MAX_SKIP_RATIO)) {\n    throw new Error(\n      `too_many_chunks_skipped: ${skipped}/${chunks.length} chunks failed to parse after retry`,\n    );\n  }\n  if (skipped > 0) {\n    logger.warn(\"Summarize chunks partially skipped\", {\n      sessionId,\n      skipped,\n      total: chunks.length,\n    });\n  }\n\n  const reduceInput = partials.map((p) => {\n    const originalIdx = partialByIdx.indexOf(p);\n    return {\n      title: p.title,\n      narrative: p.narrative,\n      keyDecisions: p.keyDecisions,\n      filesModified: p.filesModified,\n      concepts: p.concepts,\n      obsRangeStart: originalIdx * chunkSize + 1,\n      obsRangeEnd: Math.min((originalIdx + 1) * chunkSize, compressed.length),\n    };\n  });\n  const response = await provider.summarize(\n    REDUCE_SYSTEM,\n    buildReducePrompt(reduceInput),\n  );\n  return { response, mode: \"chunked\", chunks: chunks.length, skipped };\n}\n\n// #783: many LLMs (DeepSeek, GPT variants, some Anthropic responses)\n// wrap structured XML in markdown code fences or add conversational\n// text before/after. Strip those wrappers before the tag regex so a\n// well-formed summary doesn't get silently dropped as parse_failed.\nfunction stripXmlWrappers(raw: string): string {\n  if (!raw) return \"\";\n  let cleaned = raw.trim();\n  // ```xml ... ``` or ``` ... ``` fences (anywhere in the payload).\n  cleaned = cleaned.replace(/```\\s*xml\\s*\\n?/gi, \"\");\n  cleaned = cleaned.replace(/```/g, \"\");\n  cleaned = cleaned.trim();\n  // If preamble / postamble surrounds the XML root, peel it off.\n  const rootMatch = cleaned.match(\n    /(<[a-zA-Z_][a-zA-Z0-9_-]*>[\\s\\S]*<\\/[a-zA-Z_][a-zA-Z0-9_-]*>)/,\n  );\n  if (rootMatch && rootMatch[1]) return rootMatch[1].trim();\n  return cleaned;\n}\n\nfunction parseSummaryXml(\n  xml: string,\n  sessionId: string,\n  project: string,\n  obsCount: number,\n): SessionSummary | null {\n  const cleaned = stripXmlWrappers(xml);\n  const title = getXmlTag(cleaned, \"title\");\n  if (!title) return null;\n\n  return {\n    sessionId,\n    project,\n    createdAt: new Date().toISOString(),\n    title,\n    narrative: getXmlTag(cleaned, \"narrative\"),\n    keyDecisions: getXmlChildren(cleaned, \"decisions\", \"decision\"),\n    filesModified: getXmlChildren(cleaned, \"files\", \"file\"),\n    concepts: getXmlChildren(cleaned, \"concepts\", \"concept\"),\n    observationCount: obsCount,\n  };\n}\n\nexport function registerSummarizeFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n  metricsStore?: MetricsStore,\n): void {\n  sdk.registerFunction(\"mem::summarize\", \n    async (data: { sessionId: string } | undefined) => {\n      const startMs = Date.now();\n      if (!data || typeof data.sessionId !== \"string\" || !data.sessionId.trim()) {\n        return { success: false, error: \"sessionId is required\" };\n      }\n      const sessionId = data.sessionId.trim();\n\n      const session = await kv.get<Session>(KV.sessions, sessionId);\n      if (!session) {\n        logger.warn(\"Session not found for summarize\", {\n          sessionId,\n        });\n        return { success: false, error: \"session_not_found\" };\n      }\n\n      const observations = await kv.list<CompressedObservation>(\n        KV.observations(sessionId),\n      );\n      const compressed = observations.filter((o) => o.title);\n\n      if (compressed.length === 0) {\n        logger.info(\"No observations to summarize\", {\n          sessionId,\n        });\n        return { success: false, error: \"no_observations\" };\n      }\n\n      if (provider.name === \"noop\") {\n        logger.info(\"Summarize skipped — no LLM provider configured\", {\n          sessionId,\n        });\n        return {\n          success: false,\n          error: \"no_provider\",\n          reason:\n            \"No LLM provider key set; Summarize is a no-op. Set ANTHROPIC_API_KEY (or GEMINI/OPENROUTER/MINIMAX) in ~/.agentmemory/.env to enable.\",\n        };\n      }\n\n      try {\n        // #783: chunk-level produceSummaryXml retries internally, but\n        // the final merge used to parse once and bail. Wrap the\n        // produce-and-parse pair in the same 2-attempt loop so a\n        // markdown-wrapped or otherwise wrapped response gets a\n        // second roll-of-the-dice instead of dropping the summary.\n        let summary: SessionSummary | null = null;\n        let response = \"\";\n        let mode = \"single\";\n        let chunks = 1;\n        for (let attempt = 1; attempt <= 2; attempt++) {\n          const produced = await produceSummaryXml(\n            provider,\n            compressed,\n            sessionId,\n            session.project,\n          );\n          response = produced.response;\n          mode = produced.mode;\n          chunks = produced.chunks;\n          if (!response || !response.trim()) {\n            logger.warn(\"Empty provider response on summarize\", {\n              sessionId,\n              provider: provider.name,\n              mode,\n              chunks,\n              observationCount: compressed.length,\n              attempt,\n            });\n            continue;\n          }\n          summary = parseSummaryXml(\n            response,\n            sessionId,\n            session.project,\n            compressed.length,\n          );\n          if (summary) break;\n          logger.warn(\"Failed to parse summary XML\", { sessionId, attempt });\n        }\n\n        if (!response || !response.trim()) {\n          const latencyMs = Date.now() - startMs;\n          if (metricsStore) {\n            await metricsStore.record(\"mem::summarize\", latencyMs, false);\n          }\n          return { success: false, error: \"empty_provider_response\" };\n        }\n\n        if (!summary) {\n          const latencyMs = Date.now() - startMs;\n          if (metricsStore) {\n            await metricsStore.record(\"mem::summarize\", latencyMs, false);\n          }\n          return { success: false, error: \"parse_failed\" };\n        }\n\n        const summaryForValidation = {\n          title: summary.title,\n          narrative: summary.narrative,\n          keyDecisions: summary.keyDecisions,\n          filesModified: summary.filesModified,\n          concepts: summary.concepts,\n        };\n        const validation = validateOutput(\n          SummaryOutputSchema,\n          summaryForValidation,\n          \"mem::summarize\",\n        );\n\n        if (!validation.valid) {\n          const latencyMs = Date.now() - startMs;\n          if (metricsStore) {\n            await metricsStore.record(\"mem::summarize\", latencyMs, false);\n          }\n          logger.warn(\"Summary validation failed\", {\n            sessionId,\n            errors: validation.result.errors,\n          });\n          return { success: false, error: \"validation_failed\" };\n        }\n\n        const qualityScore = scoreSummary(summaryForValidation);\n\n        await kv.set(KV.summaries, sessionId, summary);\n        await safeAudit(kv, \"compress\", \"mem::summarize\", [sessionId], {\n          title: summary.title,\n          observationCount: compressed.length,\n        });\n\n        const latencyMs = Date.now() - startMs;\n        if (metricsStore) {\n          await metricsStore.record(\n            \"mem::summarize\",\n            latencyMs,\n            true,\n            qualityScore,\n          );\n        }\n\n        logger.info(\"Session summarized\", {\n          sessionId,\n          title: summary.title,\n          decisions: summary.keyDecisions.length,\n          qualityScore,\n          valid: validation.valid,\n        });\n\n        return { success: true, summary, qualityScore };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        const latencyMs = Date.now() - startMs;\n        if (metricsStore) {\n          await metricsStore.record(\"mem::summarize\", latencyMs, false);\n        }\n        logger.error(\"Summarize failed\", {\n          sessionId,\n          error: msg,\n        });\n        return { success: false, error: msg };\n      }\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport { resolve } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport type {\n  Memory,\n  Session,\n  CompressedObservation,\n  SessionSummary,\n} from \"../types.js\";\nimport { logger } from \"../logger.js\";\n\nconst ALLOWED_DIRS = [resolve(homedir(), \".agentmemory\")];\n\nfunction isAllowedPath(dbPath: string): boolean {\n  const resolved = resolve(dbPath);\n  return ALLOWED_DIRS.some((dir) => resolved.startsWith(dir + \"/\"));\n}\n\n// Infer memory project from the majority project of its associated sessions.\n// Returns { updated, skipped } — safe to run repeatedly (idempotent).\nexport async function inferMemoryProjects(\n  kv: StateKV,\n  dryRun = false,\n): Promise<{ updated: number; skipped: number; ambiguous: number }> {\n  const memories = await kv.list<Memory>(KV.memories);\n  const sessionCache = new Map<string, Session | null>();\n\n  const loadSession = async (sid: string): Promise<Session | null> => {\n    if (sessionCache.has(sid)) return sessionCache.get(sid)!;\n    const s = await kv.get<Session>(KV.sessions, sid).catch(() => null);\n    sessionCache.set(sid, s);\n    return s;\n  };\n\n  let updated = 0;\n  let skipped = 0;\n  let ambiguous = 0;\n\n  for (const memory of memories) {\n    if (memory.project) {\n      skipped++;\n      continue;\n    }\n\n    const sessionIds = memory.sessionIds ?? [];\n    if (sessionIds.length === 0) {\n      ambiguous++;\n      continue;\n    }\n\n    const projects: string[] = [];\n    for (const sid of sessionIds) {\n      const session = await loadSession(sid);\n      if (session?.project) projects.push(session.project);\n    }\n\n    if (projects.length === 0) {\n      ambiguous++;\n      continue;\n    }\n\n    // Majority-vote: count frequency of each project value.\n    const freq = new Map<string, number>();\n    for (const p of projects) freq.set(p, (freq.get(p) ?? 0) + 1);\n    const sorted = [...freq.entries()].sort((a, b) => b[1] - a[1]);\n    const [topProject, topCount] = sorted[0];\n\n    // Require a strict majority (> 50%) to avoid misattributing a memory\n    // that was genuinely built from sessions across multiple projects.\n    if (topCount <= projects.length / 2 && sorted.length > 1) {\n      ambiguous++;\n      continue;\n    }\n\n    if (!dryRun) {\n      memory.project = topProject;\n      await kv.set(KV.memories, memory.id, memory);\n    }\n    updated++;\n  }\n\n  logger.info(\"inferMemoryProjects complete\", { updated, skipped, ambiguous, dryRun });\n  return { updated, skipped, ambiguous };\n}\n\nexport function registerMigrateFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::migrate\",\n    async (data: { dbPath?: string; step?: string; dryRun?: boolean }) => {\n      // In-place KV migration steps (no SQLite dependency).\n      if (data.step === \"infer-memory-projects\") {\n        const dryRun = data.dryRun ?? false;\n        logger.info(\"Migration step: infer-memory-projects\", { dryRun });\n        const result = await inferMemoryProjects(kv, dryRun);\n        return { success: true, step: \"infer-memory-projects\", ...result };\n      }\n\n      if (!data.dbPath) {\n        return {\n          success: false,\n          error: \"Either step or dbPath is required\",\n        };\n      }\n\n      logger.info(\"Migration started\", { dbPath: data.dbPath });\n\n      if (!isAllowedPath(data.dbPath)) {\n        return {\n          success: false,\n          error: `Path not allowed. Must be under: ${ALLOWED_DIRS.join(\", \")}`,\n        };\n      }\n\n      let Database: any;\n      try {\n        // @ts-expect-error optional dependency\n        Database = (await import(\"better-sqlite3\")).default;\n      } catch {\n        return {\n          success: false,\n          error:\n            \"better-sqlite3 not installed. Run: npm install better-sqlite3\",\n        };\n      }\n\n      const fs = await import(\"node:fs\");\n      if (!fs.existsSync(data.dbPath)) {\n        return { success: false, error: `Database not found: ${data.dbPath}` };\n      }\n\n      let db: any;\n      try {\n        db = Database(data.dbPath, { readonly: true });\n        let sessionCount = 0;\n        let obsCount = 0;\n        let summaryCount = 0;\n\n        const sessions = db\n          .prepare(\"SELECT * FROM sessions ORDER BY created_at DESC\")\n          .all() as any[];\n        for (const row of sessions) {\n          const session: Session = {\n            id: row.session_id || row.id,\n            project: row.project_path || row.project || \"unknown\",\n            cwd: row.cwd || row.project_path || \"\",\n            startedAt:\n              row.created_at || row.started_at || new Date().toISOString(),\n            endedAt: row.ended_at || row.updated_at,\n            status: \"completed\",\n            observationCount: 0,\n          };\n          await kv.set(KV.sessions, session.id, session);\n          sessionCount++;\n        }\n\n        let observations: any[] = [];\n        try {\n          observations = db\n            .prepare(\"SELECT * FROM observations ORDER BY created_at ASC\")\n            .all() as any[];\n        } catch {\n          try {\n            observations = db\n              .prepare(\n                \"SELECT * FROM compressed_observations ORDER BY created_at ASC\",\n              )\n              .all() as any[];\n          } catch {\n            logger.warn(\"No observation tables found\");\n          }\n        }\n\n        for (const row of observations) {\n          const sessionId = row.session_id || \"migrated\";\n          const obs: CompressedObservation = {\n            id: row.id || generateId(\"mig\"),\n            sessionId,\n            timestamp: row.created_at || new Date().toISOString(),\n            type: row.type || \"other\",\n            title: row.title || row.summary || \"Migrated observation\",\n            subtitle: row.subtitle,\n            facts: safeJsonParse(row.facts, []),\n            narrative: row.narrative || row.content || \"\",\n            concepts: safeJsonParse(row.concepts, []),\n            files: safeJsonParse(row.files, []),\n            importance: row.importance || 5,\n          };\n          await kv.set(KV.observations(sessionId), obs.id, obs);\n          obsCount++;\n        }\n\n        let summaries: any[] = [];\n        try {\n          summaries = db\n            .prepare(\"SELECT * FROM session_summaries\")\n            .all() as any[];\n        } catch {\n          logger.warn(\"No summaries table found\");\n        }\n\n        for (const row of summaries) {\n          const summary: SessionSummary = {\n            sessionId: row.session_id,\n            project: row.project || \"unknown\",\n            createdAt: row.created_at || new Date().toISOString(),\n            title: row.title || \"Migrated session\",\n            narrative: row.narrative || row.summary || \"\",\n            keyDecisions: safeJsonParse(row.key_decisions, []),\n            filesModified: safeJsonParse(row.files_modified, []),\n            concepts: safeJsonParse(row.concepts, []),\n            observationCount: row.observation_count || 0,\n          };\n          await kv.set(KV.summaries, row.session_id, summary);\n          summaryCount++;\n        }\n\n        logger.info(\"Migration complete\", {\n          sessionCount,\n          obsCount,\n          summaryCount,\n        });\n        return { success: true, sessionCount, obsCount, summaryCount };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.error(\"Migration failed\", { error: msg });\n        return { success: false, error: \"Migration failed\" };\n      } finally {\n        try {\n          if (db) db.close();\n        } catch {}\n      }\n    },\n  );\n}\n\nfunction safeJsonParse<T>(value: unknown, fallback: T): T {\n  if (Array.isArray(value)) return value as T;\n  if (typeof value === \"string\") {\n    try {\n      return JSON.parse(value) as T;\n    } catch {\n      return fallback;\n    }\n  }\n  return fallback;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { CompressedObservation, Session } from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { recordAccessBatch } from \"./access-tracker.js\";\nimport { logger } from \"../logger.js\";\n\ninterface FileHistory {\n  file: string;\n  observations: Array<{\n    sessionId: string;\n    obsId: string;\n    type: string;\n    title: string;\n    narrative: string;\n    importance: number;\n    timestamp: string;\n  }>;\n}\n\nexport function registerFileIndexFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::file-context\", \n    async (\n      data: { sessionId?: string; files?: string[]; project?: string } | undefined,\n    ) => {\n      const sessionId =\n        data && typeof data.sessionId === \"string\" ? data.sessionId.trim() : \"\";\n      const normalizedProject =\n        typeof data?.project === \"string\" ? data.project.trim() : undefined;\n      const files = Array.isArray(data?.files)\n        ? data!.files\n            .map((file) => (typeof file === \"string\" ? file.trim() : \"\"))\n            .filter(Boolean)\n        : [];\n      if (files.length === 0) {\n        await recordAudit(kv, \"observe\", \"mem::file-context\", [sessionId || \"unknown\"], {\n          error: \"invalid_payload\",\n          hasSessionId: !!sessionId,\n          hasProject: !!normalizedProject,\n          fileCount: files.length,\n        });\n        return { context: \"\", files: [] };\n      }\n      const results: FileHistory[] = [];\n\n      const sessions = await kv.list<Session>(KV.sessions);\n      let otherSessions = sessionId\n        ? sessions.filter((s) => s.id !== sessionId)\n        : sessions;\n      if (normalizedProject) {\n        otherSessions = otherSessions.filter((s) => s.project === normalizedProject);\n      }\n      otherSessions = otherSessions\n        .sort(\n          (a, b) =>\n            new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime(),\n        )\n        .slice(0, 15);\n\n      const obsCache = new Map<string, CompressedObservation[]>();\n      for (const session of otherSessions) {\n        obsCache.set(\n          session.id,\n          await kv.list<CompressedObservation>(KV.observations(session.id)),\n        );\n      }\n\n      for (const file of files) {\n        const history: FileHistory = { file, observations: [] };\n        const normalizedFile = file.replace(/^\\.\\//, \"\");\n\n        for (const session of otherSessions) {\n          const observations = obsCache.get(session.id) || [];\n\n          for (const obs of observations) {\n            if (!obs.files || !obs.title) continue;\n            const matches = obs.files.some(\n              (f) =>\n                f === file ||\n                f === normalizedFile ||\n                f.endsWith(`/${normalizedFile}`) ||\n                normalizedFile.endsWith(`/${f}`),\n            );\n            if (matches && obs.importance >= 4) {\n              history.observations.push({\n                sessionId: session.id,\n                obsId: obs.id,\n                type: obs.type,\n                title: obs.title,\n                narrative: obs.narrative,\n                importance: obs.importance,\n                timestamp: obs.timestamp,\n              });\n            }\n          }\n        }\n\n        history.observations.sort((a, b) => b.importance - a.importance);\n        history.observations = history.observations.slice(0, 5);\n\n        if (history.observations.length > 0) {\n          results.push(history);\n        }\n      }\n\n      if (results.length === 0) {\n        return { context: \"\" };\n      }\n\n      const lines: string[] = [\"<agentmemory-file-context>\"];\n      for (const fh of results) {\n        lines.push(`## ${fh.file}`);\n        for (const obs of fh.observations) {\n          lines.push(`- [${obs.type}] ${obs.title}: ${obs.narrative}`);\n        }\n      }\n      lines.push(\"</agentmemory-file-context>\");\n\n      const accessedIds: string[] = [];\n      for (const fh of results) {\n        for (const obs of fh.observations) accessedIds.push(obs.obsId);\n      }\n      void recordAccessBatch(kv, accessedIds);\n\n      const context = lines.join(\"\\n\");\n      logger.info(\"File context generated\", {\n        files: files.length,\n        results: results.length,\n      });\n      return { context };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  CompressedObservation,\n  Memory,\n  Session,\n  MemoryProvider,\n} from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\n\nconst CONSOLIDATION_SYSTEM = `You are a memory consolidation engine. Given a set of related observations from coding sessions, synthesize them into a single long-term memory.\n\nOutput XML:\n<memory>\n  <type>pattern|preference|architecture|bug|workflow|fact</type>\n  <title>Concise memory title (max 80 chars)</title>\n  <content>2-4 sentence description of the learned insight</content>\n  <concepts>\n    <concept>key term</concept>\n  </concepts>\n  <files>\n    <file>relevant/file/path</file>\n  </files>\n  <strength>1-10 how confident/important this memory is</strength>\n</memory>`;\n\nimport { getXmlTag, getXmlChildren } from \"../prompts/xml.js\";\nimport { logger } from \"../logger.js\";\n\nfunction parseMemoryXml(\n  xml: string,\n  sessionIds: string[],\n): Omit<Memory, \"id\" | \"createdAt\" | \"updatedAt\"> | null {\n  const type = getXmlTag(xml, \"type\");\n  const title = getXmlTag(xml, \"title\");\n  const content = getXmlTag(xml, \"content\");\n  if (!type || !title || !content) return null;\n\n  const validTypes = new Set([\n    \"pattern\",\n    \"preference\",\n    \"architecture\",\n    \"bug\",\n    \"workflow\",\n    \"fact\",\n  ]);\n\n  return {\n    type: (validTypes.has(type) ? type : \"fact\") as Memory[\"type\"],\n    title,\n    content,\n    concepts: getXmlChildren(xml, \"concepts\", \"concept\"),\n    files: getXmlChildren(xml, \"files\", \"file\"),\n    sessionIds,\n    strength: Math.max(\n      1,\n      Math.min(10, parseInt(getXmlTag(xml, \"strength\") || \"5\", 10) || 5),\n    ),\n    version: 1,\n    isLatest: true,\n  };\n}\n\nexport function registerConsolidateFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\"mem::consolidate\", \n    async (data: { project?: string; minObservations?: number }) => {\n      const minObs = data.minObservations ?? 10;\n\n      const sessions = await kv.list<Session>(KV.sessions);\n      const filtered = data.project\n        ? sessions.filter((s) => s.project === data.project)\n        : sessions;\n\n      const allObs: Array<CompressedObservation & { sid: string }> = [];\n      const obsPerSession: CompressedObservation[][] = [];\n      for (let batch = 0; batch < filtered.length; batch += 10) {\n        const chunk = filtered.slice(batch, batch + 10);\n        const results = await Promise.all(\n          chunk.map((s) =>\n            kv\n              .list<CompressedObservation>(KV.observations(s.id))\n              .catch(() => [] as CompressedObservation[]),\n          ),\n        );\n        obsPerSession.push(...results);\n      }\n      for (let i = 0; i < filtered.length; i++) {\n        for (const obs of obsPerSession[i]) {\n          if (obs.title && obs.importance >= 5) {\n            allObs.push({ ...obs, sid: filtered[i].id });\n          }\n        }\n      }\n\n      if (allObs.length < minObs) {\n        return { consolidated: 0, reason: \"insufficient_observations\" };\n      }\n\n      const conceptGroups = new Map<string, typeof allObs>();\n      for (const obs of allObs) {\n        for (const concept of obs.concepts) {\n          const key = concept.toLowerCase();\n          if (!conceptGroups.has(key)) conceptGroups.set(key, []);\n          conceptGroups.get(key)!.push(obs);\n        }\n      }\n\n      let consolidated = 0;\n      const existingMemories = await kv.list<Memory>(KV.memories);\n      const existingTitles = new Set(\n        existingMemories.map((m) => m.title.toLowerCase()),\n      );\n\n      const MAX_LLM_CALLS = 10;\n      let llmCallCount = 0;\n\n      const sortedGroups = [...conceptGroups.entries()]\n        .filter(([, g]) => g.length >= 3)\n        .sort((a, b) => b[1].length - a[1].length);\n\n      for (const [concept, obsGroup] of sortedGroups) {\n        if (llmCallCount >= MAX_LLM_CALLS) break;\n\n        const top = obsGroup\n          .sort((a, b) => b.importance - a.importance)\n          .slice(0, 8);\n        const sessionIds = [...new Set(top.map((o) => o.sid))];\n\n        const prompt = top\n          .map(\n            (o) =>\n              `[${o.type}] ${o.title}\\n${o.narrative}\\nFiles: ${o.files.join(\", \")}\\nImportance: ${o.importance}`,\n          )\n          .join(\"\\n\\n\");\n\n        try {\n          const response = await Promise.race([\n            provider.compress(\n              CONSOLIDATION_SYSTEM,\n              `Concept: \"${concept}\"\\n\\nObservations:\\n${prompt}`,\n            ),\n            new Promise<never>((_, reject) =>\n              setTimeout(() => reject(new Error(\"compress timeout\")), 30_000),\n            ),\n          ]);\n          llmCallCount++;\n          const parsed = parseMemoryXml(response, sessionIds);\n          if (!parsed) continue;\n\n          const now = new Date().toISOString();\n          const obsIds = [...new Set(top.map((o) => o.id))];\n          const scopedProject =\n            typeof data.project === \"string\" && data.project.trim().length > 0\n              ? data.project.trim()\n              : undefined;\n\n          // A scoped consolidation run must only evolve memories that belong\n          // to the same project. Without this guard, two projects that happen\n          // to consolidate observations into an identically-titled memory would\n          // cause one project's memory to silently evolve the other's — the\n          // exact class of cross-project corruption this fix is designed to\n          // prevent. An unscoped run (no data.project, background cron path)\n          // preserves the pre-existing behavior and may evolve any memory.\n          const existingMatch = existingMemories.find(\n            (m) =>\n              m.title.toLowerCase() === parsed.title.toLowerCase() &&\n              (!scopedProject || !m.project || m.project === scopedProject),\n          );\n\n          if (existingMatch) {\n            existingMatch.isLatest = false;\n            await kv.set(KV.memories, existingMatch.id, existingMatch);\n            await recordAudit(kv, \"evolve\", \"mem::consolidate\", [existingMatch.id], {\n              action: \"mark_non_latest\",\n              concept,\n            });\n\n            const evolved: Memory = {\n              id: generateId(\"mem\"),\n              createdAt: now,\n              updatedAt: now,\n              ...parsed,\n              version: (existingMatch.version || 1) + 1,\n              parentId: existingMatch.id,\n              supersedes: [\n                existingMatch.id,\n                ...(existingMatch.supersedes || []),\n              ],\n              sourceObservationIds: obsIds,\n              isLatest: true,\n              ...(scopedProject !== undefined && { project: scopedProject }),\n            };\n            await kv.set(KV.memories, evolved.id, evolved);\n            await recordAudit(kv, \"evolve\", \"mem::consolidate\", [evolved.id], {\n              action: \"evolve_memory\",\n              oldId: existingMatch.id,\n              newId: evolved.id,\n              concept,\n            });\n            existingTitles.add(evolved.title.toLowerCase());\n            consolidated++;\n          } else {\n            const memory: Memory = {\n              id: generateId(\"mem\"),\n              createdAt: now,\n              updatedAt: now,\n              ...parsed,\n              sourceObservationIds: obsIds,\n              version: 1,\n              isLatest: true,\n              ...(scopedProject !== undefined && { project: scopedProject }),\n            };\n            await kv.set(KV.memories, memory.id, memory);\n            await recordAudit(kv, \"remember\", \"mem::consolidate\", [memory.id], {\n              action: \"create_memory\",\n              concept,\n            });\n            existingTitles.add(memory.title.toLowerCase());\n            consolidated++;\n          }\n        } catch (err) {\n          logger.warn(\"Consolidation failed for concept\", {\n            concept,\n            error: err instanceof Error ? err.message : String(err),\n          });\n        }\n      }\n\n      logger.info(\"Consolidation complete\", {\n        consolidated,\n        totalObs: allObs.length,\n      });\n      return { consolidated, totalObservations: allObs.length };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { CompressedObservation, Session } from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { logger } from \"../logger.js\";\n\ninterface Pattern {\n  type: \"co_change\" | \"error_repeat\" | \"workflow\";\n  description: string;\n  files: string[];\n  frequency: number;\n  sessions: string[];\n}\n\nexport function registerPatternsFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::patterns\", \n    async (data: { project?: string }) => {\n      const patterns: Pattern[] = [];\n\n      const sessions = await kv.list<Session>(KV.sessions);\n      const filtered = data.project\n        ? sessions.filter((s) => s.project === data.project)\n        : sessions;\n\n      const fileCoOccurrences = new Map<string, number>();\n      const fileSessionMap = new Map<string, Set<string>>();\n      const errorPatterns = new Map<\n        string,\n        { count: number; sessions: Set<string> }\n      >();\n\n      for (const session of filtered) {\n        const observations = await kv.list<CompressedObservation>(\n          KV.observations(session.id),\n        );\n        if (!observations.length) continue;\n\n        const sessionFiles = new Set<string>();\n        for (const obs of observations) {\n          if (!obs.files) continue;\n          for (const f of obs.files) {\n            sessionFiles.add(f);\n            if (!fileSessionMap.has(f)) fileSessionMap.set(f, new Set());\n            fileSessionMap.get(f)!.add(session.id);\n          }\n\n          if (obs.type === \"error\" && obs.title) {\n            const key = obs.title.toLowerCase();\n            if (!errorPatterns.has(key)) {\n              errorPatterns.set(key, { count: 0, sessions: new Set() });\n            }\n            const ep = errorPatterns.get(key)!;\n            ep.count++;\n            ep.sessions.add(session.id);\n          }\n        }\n\n        const fileList = [...sessionFiles].sort();\n        for (let i = 0; i < fileList.length; i++) {\n          for (let j = i + 1; j < fileList.length; j++) {\n            const pair = `${fileList[i]}::${fileList[j]}`;\n            fileCoOccurrences.set(pair, (fileCoOccurrences.get(pair) || 0) + 1);\n          }\n        }\n      }\n\n      for (const [pair, count] of fileCoOccurrences) {\n        if (count < 3) continue;\n        const [fileA, fileB] = pair.split(\"::\");\n        const sessionsA = fileSessionMap.get(fileA) || new Set();\n        const sessionsB = fileSessionMap.get(fileB) || new Set();\n        const commonSessions = [...sessionsA].filter((s) => sessionsB.has(s));\n\n        patterns.push({\n          type: \"co_change\",\n          description: `${fileA} and ${fileB} are frequently modified together`,\n          files: [fileA, fileB],\n          frequency: count,\n          sessions: commonSessions,\n        });\n      }\n\n      for (const [\n        errorKey,\n        { count, sessions: errorSessions },\n      ] of errorPatterns) {\n        if (count < 2) continue;\n        patterns.push({\n          type: \"error_repeat\",\n          description: `Recurring error: ${errorKey}`,\n          files: [],\n          frequency: count,\n          sessions: [...errorSessions],\n        });\n      }\n\n      patterns.sort((a, b) => b.frequency - a.frequency);\n\n      logger.info(\"Pattern detection complete\", {\n        patterns: patterns.length,\n        sessions: filtered.length,\n      });\n\n      return { patterns: patterns.slice(0, 20) };\n    },\n  );\n\n  sdk.registerFunction(\"mem::generate-rules\", \n    async (data: { project?: string }) => {\n      const result = await sdk.trigger<\n        { project?: string },\n        { patterns: Pattern[] }\n      >({ function_id: \"mem::patterns\", payload: data });\n\n      const rules: string[] = [];\n\n      for (const pattern of result.patterns) {\n        if (pattern.type === \"co_change\" && pattern.frequency >= 4) {\n          rules.push(\n            `When modifying ${pattern.files[0]}, also check ${pattern.files[1]} (co-changed ${pattern.frequency} times).`,\n          );\n        }\n        if (pattern.type === \"error_repeat\" && pattern.frequency >= 3) {\n          rules.push(\n            `Watch for: ${pattern.description} (occurred ${pattern.frequency} times across ${pattern.sessions.length} sessions).`,\n          );\n        }\n      }\n\n      logger.info(\"Rules generated\", { count: rules.length });\n      return { rules };\n    },\n  );\n}\n","import { TriggerAction, type ISdk } from \"iii-sdk\";\nimport type { Memory } from \"../types.js\";\nimport { KV, generateId, jaccardSimilarity } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { memoryToObservation } from \"../state/memory-utils.js\";\nimport { deleteAccessLog } from \"./access-tracker.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { getSearchIndex, vectorIndexAddGuarded, vectorIndexRemove, flushIndexSave } from \"./search.js\";\nimport { getAgentId } from \"../config.js\";\nimport { logger } from \"../logger.js\";\n\nexport function registerRememberFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::remember\", \n    async (data: {\n      content: string;\n      type?: string;\n      concepts?: string[];\n      files?: string[];\n      ttlDays?: number;\n      sourceObservationIds?: string[];\n      agentId?: string;\n      project?: string;\n    }) => {\n      if (\n        !data.content ||\n        typeof data.content !== \"string\" ||\n        !data.content.trim()\n      ) {\n        return { success: false, error: \"content is required\" };\n      }\n      if (data.files && !Array.isArray(data.files)) {\n        return { success: false, error: \"files must be an array\" };\n      }\n      if (data.concepts && !Array.isArray(data.concepts)) {\n        return { success: false, error: \"concepts must be an array\" };\n      }\n      if (data.sourceObservationIds && !Array.isArray(data.sourceObservationIds)) {\n        return { success: false, error: \"sourceObservationIds must be an array\" };\n      }\n      const validTypes = new Set([\n        \"pattern\",\n        \"preference\",\n        \"architecture\",\n        \"bug\",\n        \"workflow\",\n        \"fact\",\n      ]);\n      const memType = validTypes.has(data.type || \"\")\n        ? (data.type as Memory[\"type\"])\n        : \"fact\";\n\n      const now = new Date().toISOString();\n      // Normalize project early so every subsequent comparison and storage\n      // operation uses the same cleaned value. Raw data.project must not be\n      // referenced below this point.\n      const project =\n        typeof data.project === \"string\" && data.project.trim().length > 0\n          ? data.project.trim()\n          : undefined;\n\n      return withKeyedLock(\"mem:remember\", async () => {\n        const existingMemories = await kv.list<Memory>(KV.memories);\n        let supersededId: string | undefined;\n        let supersededVersion = 1;\n        let supersededMemory: Memory | undefined;\n        const lowerContent = data.content.toLowerCase();\n        for (const existing of existingMemories) {\n          if (existing.isLatest === false) continue;\n          // Never supersede a memory that belongs to a different project.\n          // Both sides must have an explicit project for the guard to engage;\n          // an unscoped memory (legacy, no project field) is treated as a\n          // wildcard so pre-existing data is not stranded.\n          if (project && existing.project && existing.project !== project) {\n            continue;\n          }\n          const similarity = jaccardSimilarity(\n            lowerContent,\n            existing.content.toLowerCase(),\n          );\n          if (similarity > 0.7) {\n            supersededId = existing.id;\n            supersededVersion = existing.version ?? 1;\n            supersededMemory = existing;\n            break;\n          }\n        }\n\n        // stamp the agent role on the memory so future recall can\n        // filter by agent. Request body wins (multi-agent runtimes\n        // explicitly tagging at write time), env AGENT_ID fallback,\n        // none → memory is unscoped (legacy behavior).\n        const callAgentId =\n          typeof data.agentId === \"string\" && data.agentId.trim().length > 0\n            ? data.agentId.trim().slice(0, 128)\n            : getAgentId();\n\n        const memory: Memory = {\n          id: generateId(\"mem\"),\n          createdAt: now,\n          updatedAt: now,\n          type: memType,\n          title: data.content.slice(0, 80),\n          content: data.content,\n          concepts: data.concepts || [],\n          files: data.files || [],\n          sessionIds: [],\n          strength: 7,\n          version: supersededId ? supersededVersion + 1 : 1,\n          parentId: supersededId,\n          supersedes: supersededId ? [supersededId] : [],\n          sourceObservationIds: (data.sourceObservationIds || []).filter(\n            (id): id is string => typeof id === \"string\" && id.length > 0,\n          ),\n          isLatest: true,\n          ...(callAgentId ? { agentId: callAgentId } : {}),\n          ...(project !== undefined && { project }),\n        };\n\n        if (data.ttlDays && typeof data.ttlDays === \"number\" && data.ttlDays > 0) {\n          memory.forgetAfter = new Date(Date.now() + data.ttlDays * 86400000).toISOString();\n        }\n\n        if (supersededMemory) {\n          supersededMemory.isLatest = false;\n          await kv.set(KV.memories, supersededMemory.id, supersededMemory);\n        }\n        await kv.set(KV.memories, memory.id, memory);\n\n        // Without this, mem::remember persists the row but the BM25\n        // index never sees it, so memory_smart_search and memory_recall\n        // return empty even seconds after save (#257). Use try/catch so\n        // an indexing failure doesn't block the save itself — the\n        // restart-time rebuild will pick the memory up either way.\n        try {\n          getSearchIndex().add(memoryToObservation(memory));\n        } catch (err) {\n          logger.warn(\"Failed to index saved memory into BM25\", {\n            memId: memory.id,\n            error: err instanceof Error ? err.message : String(err),\n          });\n        }\n        await vectorIndexAddGuarded(\n          memory.id,\n          memory.sessionIds?.[0] ?? \"memory\",\n          memory.title + \" \" + memory.content,\n          { kind: \"memory\", logId: memory.id },\n        );\n\n        if (supersededId) {\n          await sdk.trigger({\n            function_id: \"mem::cascade-update\",\n            payload: {\n              supersededMemoryId: supersededId,\n            },\n            action: TriggerAction.Void(),\n          });\n        }\n\n        logger.info(\"Memory saved\", {\n          memId: memory.id,\n          type: memory.type,\n          project: memory.project,\n        });\n        return { success: true, memory };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::forget\",\n    async (data: {\n      sessionId?: string;\n      observationIds?: string[];\n      memoryId?: string;\n    }) => {\n      let deleted = 0;\n      const deletedMemoryIds: string[] = [];\n      const deletedObservationIds: string[] = [];\n      let deletedSession = false;\n      const { decrementImageRef } = await import(\"./image-refs.js\");\n\n      if (data.memoryId) {\n        const mem = await kv.get<Memory>(KV.memories, data.memoryId);\n        await kv.delete(KV.memories, data.memoryId);\n        if (mem?.imageRef) {\n          await decrementImageRef(kv, sdk, mem.imageRef);\n        }\n        await deleteAccessLog(kv, data.memoryId);\n        getSearchIndex().remove(data.memoryId);\n        vectorIndexRemove(data.memoryId);\n        deletedMemoryIds.push(data.memoryId);\n        deleted++;\n      }\n\n      if (\n        data.sessionId &&\n        data.observationIds &&\n        data.observationIds.length > 0\n      ) {\n        for (const obsId of data.observationIds) {\n          const obs = await kv.get<{ imageData?: string; imageRef?: string }>(\n            KV.observations(data.sessionId),\n            obsId,\n          );\n          await kv.delete(KV.observations(data.sessionId), obsId);\n          if (obs?.imageData) await decrementImageRef(kv, sdk, obs.imageData);\n          if (obs?.imageRef && obs.imageRef !== obs.imageData) {\n            await decrementImageRef(kv, sdk, obs.imageRef);\n          }\n          getSearchIndex().remove(obsId);\n          vectorIndexRemove(obsId);\n          deletedObservationIds.push(obsId);\n          deleted++;\n        }\n      }\n\n      if (\n        data.sessionId &&\n        (!data.observationIds || data.observationIds.length === 0) &&\n        !data.memoryId\n      ) {\n        const observations = await kv.list<{ id: string; imageData?: string; imageRef?: string }>(\n          KV.observations(data.sessionId),\n        );\n        for (const obs of observations) {\n          await kv.delete(KV.observations(data.sessionId), obs.id);\n          if (obs.imageData) await decrementImageRef(kv, sdk, obs.imageData);\n          if (obs.imageRef && obs.imageRef !== obs.imageData) {\n            await decrementImageRef(kv, sdk, obs.imageRef);\n          }\n          getSearchIndex().remove(obs.id);\n          vectorIndexRemove(obs.id);\n          deletedObservationIds.push(obs.id);\n          deleted++;\n        }\n        await kv.delete(KV.sessions, data.sessionId);\n        await kv.delete(KV.summaries, data.sessionId);\n        deletedSession = true;\n        deleted += 2;\n      }\n\n      if (deleted > 0) {\n        await flushIndexSave();\n        await recordAudit(\n          kv,\n          \"forget\",\n          \"mem::forget\",\n          [...deletedMemoryIds, ...deletedObservationIds],\n          {\n            sessionId: data.sessionId,\n            deleted,\n            memoriesDeleted: deletedMemoryIds.length,\n            observationsDeleted: deletedObservationIds.length,\n            sessionDeleted: deletedSession,\n            reason: \"user-initiated forget\",\n          },\n        );\n      }\n\n      logger.info(\"Memory forgotten\", { deleted });\n      return { success: true, deleted };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  Session,\n  CompressedObservation,\n  RawObservation,\n  SessionSummary,\n  Memory,\n} from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { deleteAccessLog } from \"./access-tracker.js\";\nimport { logger } from \"../logger.js\";\n\ninterface EvictionConfig {\n  staleSessionDays: number;\n  lowImportanceMaxDays: number;\n  lowImportanceThreshold: number;\n  maxObservationsPerProject: number;\n}\n\nconst MS_PER_DAY = 24 * 60 * 60 * 1000;\n\nconst DEFAULTS: EvictionConfig = {\n  staleSessionDays: 30,\n  lowImportanceMaxDays: 90,\n  lowImportanceThreshold: 3,\n  maxObservationsPerProject: 10_000,\n};\n\ninterface EvictionStats {\n  staleSessions: number;\n  lowImportanceObs: number;\n  capEvictions: number;\n  expiredMemories: number;\n  nonLatestMemories: number;\n  dryRun: boolean;\n}\n\nfunction isValidRecoveryResult(result: unknown): boolean {\n  if (!result || typeof result !== \"object\") return false;\n  if (!(\"success\" in result)) return true;\n  return (result as { success?: unknown }).success !== false;\n}\n\nfunction isCompressedObservation(\n  observation: CompressedObservation | RawObservation,\n): observation is CompressedObservation {\n  return (\n    \"title\" in observation &&\n    typeof observation.title === \"string\" &&\n    observation.title.length > 0\n  );\n}\n\nasync function recoverStaleSession(\n  sdk: ISdk,\n  sessionId: string,\n): Promise<boolean> {\n  try {\n    const result = await sdk.trigger({\n      function_id: \"event::session::stopped\",\n      payload: { sessionId },\n    });\n    if (!isValidRecoveryResult(result)) {\n      logger.warn(\"Stale session recovery failed\", {\n        sessionId,\n        result,\n      });\n      return false;\n    }\n    return true;\n  } catch (err) {\n    logger.warn(\"Stale session recovery failed\", {\n      sessionId,\n      error: err instanceof Error ? err.message : String(err),\n    });\n    return false;\n  }\n}\n\nasync function runRecoveredSessionConsolidation(sdk: ISdk): Promise<void> {\n  try {\n    await sdk.trigger({\n      function_id: \"mem::consolidate-pipeline\",\n      payload: { tier: \"all\" },\n    });\n  } catch (err) {\n    logger.warn(\"Recovered session consolidation failed\", {\n      error: err instanceof Error ? err.message : String(err),\n    });\n  }\n}\n\nexport function registerEvictFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::evict\", \n    async (data: { dryRun?: boolean }): Promise<EvictionStats> => {\n      const dryRun = data?.dryRun ?? false;\n      const { decrementImageRef } = await import(\"./image-refs.js\");\n\n      const configOverride = await kv\n        .get<Partial<EvictionConfig>>(KV.config, \"eviction\")\n        .catch(() => null);\n      const cfg = { ...DEFAULTS, ...configOverride };\n\n      const now = Date.now();\n      const stats: EvictionStats = {\n        staleSessions: 0,\n        lowImportanceObs: 0,\n        capEvictions: 0,\n        expiredMemories: 0,\n        nonLatestMemories: 0,\n        dryRun,\n      };\n\n      let recoveredStaleSessions = 0;\n      const sessions = await kv.list<Session>(KV.sessions).catch(() => []);\n      const summaries = await kv\n        .list<SessionSummary>(KV.summaries)\n        .catch(() => []);\n      const summaryIds = new Set(summaries.map((s) => s.sessionId));\n\n      for (const session of sessions) {\n        if (!session.startedAt) continue;\n        const age = now - new Date(session.startedAt).getTime();\n        const staleDays = cfg.staleSessionDays * MS_PER_DAY;\n        if (age > staleDays && !summaryIds.has(session.id)) {\n          if (dryRun) {\n            stats.staleSessions++;\n          } else {\n            const observations = await kv\n              .list<CompressedObservation | RawObservation>(\n                KV.observations(session.id),\n              )\n              .catch((err) => {\n                logger.warn(\"Stale session observation scan failed\", {\n                  sessionId: session.id,\n                  error: err instanceof Error ? err.message : String(err),\n                });\n                return null;\n              });\n            if (!observations) continue;\n\n            let recovered = false;\n            const hasCompressedObservations = observations.some(\n              isCompressedObservation,\n            );\n            if (hasCompressedObservations) {\n              recovered = await recoverStaleSession(sdk, session.id);\n              if (!recovered) continue;\n              recoveredStaleSessions++;\n            } else if (observations.length > 0) {\n              logger.warn(\"Stale session has no compressed observations\", {\n                sessionId: session.id,\n              });\n              continue;\n            }\n\n            try {\n              await kv.delete(KV.sessions, session.id);\n              stats.staleSessions++;\n            } catch (err) {\n              logger.warn(\"Eviction delete failed\", {\n                resource: \"session\",\n                id: session.id,\n                error: err instanceof Error ? err.message : String(err),\n              });\n              continue;\n            }\n            await recordAudit(kv, \"delete\", \"mem::evict\", [session.id], {\n              resource: \"session\",\n              reason: recovered\n                ? \"stale_session_recovered_then_evicted\"\n                : \"stale_session_without_summary\",\n              dryRun,\n            });\n          }\n        }\n      }\n\n      if (!dryRun && recoveredStaleSessions > 0) {\n        await runRecoveredSessionConsolidation(sdk);\n      }\n\n      const projectObs = new Map<string, CompressedObservation[]>();\n      for (const session of sessions) {\n        const obs = await kv\n          .list<CompressedObservation>(KV.observations(session.id))\n          .catch(() => []);\n        const compressed = obs.filter((o) => o.title);\n\n        for (const o of compressed) {\n          if (!o.timestamp) continue;\n          const age = now - new Date(o.timestamp).getTime();\n          const maxAge = cfg.lowImportanceMaxDays * MS_PER_DAY;\n          if (\n            age > maxAge &&\n            (o.importance ?? 5) < cfg.lowImportanceThreshold\n          ) {\n            if (dryRun) {\n              stats.lowImportanceObs++;\n            } else {\n              try {\n                await kv.delete(KV.observations(session.id), o.id);\n                stats.lowImportanceObs++;\n              } catch (err) {\n                logger.warn(\"Eviction delete failed\", {\n                  resource: \"observation\",\n                  id: o.id,\n                  sessionId: session.id,\n                  error: err instanceof Error ? err.message : String(err),\n                });\n                continue;\n              }\n              if (o.imageData) await decrementImageRef(kv, sdk, o.imageData);\n              if (o.imageRef && o.imageRef !== o.imageData) await decrementImageRef(kv, sdk, o.imageRef);\n              await recordAudit(kv, \"delete\", \"mem::evict\", [o.id], {\n                resource: \"observation\",\n                reason: \"low_importance_old_observation\",\n                sessionId: session.id,\n                dryRun,\n              });\n            }\n          }\n        }\n\n        const project = session.project || \"unknown\";\n        const existing = projectObs.get(project) || [];\n        existing.push(...compressed);\n        projectObs.set(project, existing);\n      }\n\n      for (const [, obs] of projectObs) {\n        if (obs.length > cfg.maxObservationsPerProject) {\n          const sorted = obs.sort(\n            (a, b) => (a.importance ?? 5) - (b.importance ?? 5),\n          );\n          const toEvict = sorted.slice(\n            0,\n            obs.length - cfg.maxObservationsPerProject,\n          );\n          if (dryRun) {\n            stats.capEvictions += toEvict.length;\n          } else {\n            for (const o of toEvict) {\n              try {\n                await kv.delete(KV.observations(o.sessionId), o.id);\n                stats.capEvictions++;\n              } catch (err) {\n                logger.warn(\"Eviction delete failed\", {\n                  resource: \"observation\",\n                  id: o.id,\n                  sessionId: o.sessionId,\n                  error: err instanceof Error ? err.message : String(err),\n                });\n                continue;\n              }\n              if (o.imageData) await decrementImageRef(kv, sdk, o.imageData);\n              if (o.imageRef && o.imageRef !== o.imageData) await decrementImageRef(kv, sdk, o.imageRef);\n              await recordAudit(kv, \"delete\", \"mem::evict\", [o.id], {\n                resource: \"observation\",\n                reason: \"project_observation_cap\",\n                sessionId: o.sessionId,\n                dryRun,\n              });\n            }\n          }\n        }\n      }\n\n      const memories = await kv.list<Memory>(KV.memories).catch(() => []);\n      const evictedMemIds = new Set<string>();\n      for (const mem of memories) {\n        if (mem.forgetAfter) {\n          const expiry = new Date(mem.forgetAfter).getTime();\n          if (now > expiry) {\n            if (dryRun) {\n              stats.expiredMemories++;\n              evictedMemIds.add(mem.id);\n            } else {\n              try {\n                await kv.delete(KV.memories, mem.id);\n                stats.expiredMemories++;\n                evictedMemIds.add(mem.id);\n              } catch (err) {\n                logger.warn(\"Eviction delete failed\", {\n                  resource: \"memory\",\n                  id: mem.id,\n                  reason: \"expired_memory\",\n                  error: err instanceof Error ? err.message : String(err),\n                });\n                continue;\n              }\n              if (mem.imageRef) {\n                await decrementImageRef(kv, sdk, mem.imageRef);\n              }\n              await recordAudit(kv, \"delete\", \"mem::evict\", [mem.id], {\n                resource: \"memory\",\n                reason: \"expired_memory\",\n                dryRun,\n              });\n              await deleteAccessLog(kv, mem.id);\n            }\n          }\n        }\n\n        if (\n          !evictedMemIds.has(mem.id) &&\n          mem.isLatest === false &&\n          mem.createdAt\n        ) {\n          const age = now - new Date(mem.createdAt).getTime();\n          if (age > cfg.lowImportanceMaxDays * MS_PER_DAY) {\n            if (dryRun) {\n              stats.nonLatestMemories++;\n            } else {\n              try {\n                await kv.delete(KV.memories, mem.id);\n                stats.nonLatestMemories++;\n              } catch (err) {\n                logger.warn(\"Eviction delete failed\", {\n                  resource: \"memory\",\n                  id: mem.id,\n                  reason: \"old_non_latest_memory\",\n                  error: err instanceof Error ? err.message : String(err),\n                });\n                continue;\n              }\n              if (mem.imageRef) {\n                await decrementImageRef(kv, sdk, mem.imageRef);\n              }\n              await recordAudit(kv, \"delete\", \"mem::evict\", [mem.id], {\n                resource: \"memory\",\n                reason: \"old_non_latest_memory\",\n                dryRun,\n              });\n              await deleteAccessLog(kv, mem.id);\n            }\n          }\n        }\n      }\n\n      logger.info(\"Eviction complete\", { stats });\n      return stats;\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { Memory, MemoryRelation } from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { safeAudit } from \"./audit.js\";\nimport { recordAccessBatch } from \"./access-tracker.js\";\nimport { logger } from \"../logger.js\";\n\nfunction computeConfidence(\n  source: Memory,\n  target: Memory,\n  relationType: MemoryRelation[\"type\"],\n): number {\n  let score = 0.5;\n\n  const sharedSessions = source.sessionIds.filter((sid) =>\n    target.sessionIds.includes(sid),\n  );\n  score += Math.min(sharedSessions.length * 0.1, 0.3);\n\n  const now = Date.now();\n  const sourceAge = now - new Date(source.updatedAt).getTime();\n  const targetAge = now - new Date(target.updatedAt).getTime();\n  const sevenDays = 7 * 24 * 60 * 60 * 1000;\n  const ninetyDays = 90 * 24 * 60 * 60 * 1000;\n  if (sourceAge < sevenDays && targetAge < sevenDays) {\n    score += 0.1;\n  } else if (sourceAge > ninetyDays && targetAge > ninetyDays) {\n    score -= 0.1;\n  }\n\n  if (relationType === \"supersedes\") score += 0.1;\n  if (relationType === \"contradicts\") score -= 0.05;\n\n  return Math.max(0, Math.min(1, score));\n}\n\nexport function registerRelationsFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::relate\", \n    async (data: {\n      sourceId: string;\n      targetId: string;\n      type: MemoryRelation[\"type\"];\n      confidence?: number;\n    }) => {\n      const [firstId, secondId] = [data.sourceId, data.targetId].sort();\n      const lockKey =\n        firstId === secondId ? `mem:${firstId}` : `mem:${firstId}:${secondId}`;\n\n      return withKeyedLock(lockKey, async () => {\n        const source = await kv.get<Memory>(KV.memories, data.sourceId);\n        const target = await kv.get<Memory>(KV.memories, data.targetId);\n        if (!source || !target) {\n          return {\n            success: false,\n            error: \"source or target memory not found\",\n          };\n        }\n\n        const confidence =\n          data.confidence !== undefined\n            ? Math.max(0, Math.min(1, data.confidence))\n            : computeConfidence(source, target, data.type);\n\n        const relation: MemoryRelation = {\n          type: data.type,\n          sourceId: data.sourceId,\n          targetId: data.targetId,\n          createdAt: new Date().toISOString(),\n          confidence,\n        };\n\n        const relationId = generateId(\"rel\");\n        await kv.set(KV.relations, relationId, relation);\n\n        if (!source.relatedIds) source.relatedIds = [];\n        let sourceUpdated = false;\n        if (!source.relatedIds.includes(data.targetId)) {\n          source.relatedIds.push(data.targetId);\n          await kv.set(KV.memories, data.sourceId, source);\n          sourceUpdated = true;\n        }\n\n        if (!target.relatedIds) target.relatedIds = [];\n        let targetUpdated = false;\n        if (!target.relatedIds.includes(data.sourceId)) {\n          target.relatedIds.push(data.sourceId);\n          await kv.set(KV.memories, data.targetId, target);\n          targetUpdated = true;\n        }\n\n        await safeAudit(kv, \"relation_create\", \"mem::relate\", [relationId], {\n          type: data.type,\n          sourceId: data.sourceId,\n          targetId: data.targetId,\n          confidence,\n        });\n        if (sourceUpdated) {\n          await safeAudit(\n            kv,\n            \"relation_update\",\n            \"mem::relate\",\n            [data.sourceId],\n            { relationId, updatedRelatedId: data.targetId },\n          );\n        }\n        if (targetUpdated) {\n          await safeAudit(\n            kv,\n            \"relation_update\",\n            \"mem::relate\",\n            [data.targetId],\n            { relationId, updatedRelatedId: data.sourceId },\n          );\n        }\n\n        logger.info(\"Memory relation created\", {\n          relationId,\n          type: data.type,\n          source: data.sourceId,\n          target: data.targetId,\n        });\n        return { success: true, relationId, relation };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::evolve\", \n    async (data: {\n      memoryId: string;\n      newContent: string;\n      newTitle?: string;\n    }) => {\n\n      const existing = await kv.get<Memory>(KV.memories, data.memoryId);\n      if (!existing) {\n        return { success: false, error: \"memory not found\" };\n      }\n\n      const now = new Date().toISOString();\n      const evolved: Memory = {\n        ...existing,\n        id: generateId(\"mem\"),\n        createdAt: now,\n        updatedAt: now,\n        title: data.newTitle || existing.title,\n        content: data.newContent,\n        version: (existing.version || 1) + 1,\n        parentId: existing.id,\n        supersedes: [existing.id, ...(existing.supersedes || [])],\n        isLatest: true,\n      };\n\n      existing.isLatest = false;\n      await kv.set(KV.memories, existing.id, existing);\n      await safeAudit(kv, \"evolve\", \"mem::evolve\", [existing.id], {\n        operation: \"evolve\",\n        action: \"mark_non_latest\",\n        newId: evolved.id,\n      });\n\n      await kv.set(KV.memories, evolved.id, evolved);\n      await safeAudit(kv, \"evolve\", \"mem::evolve\", [evolved.id], {\n        operation: \"evolve\",\n        oldId: existing.id,\n        newId: evolved.id,\n        version: evolved.version,\n      });\n\n      const relation: MemoryRelation = {\n        type: \"supersedes\",\n        sourceId: evolved.id,\n        targetId: existing.id,\n        createdAt: now,\n        confidence: 1.0,\n      };\n      const relationId = generateId(\"rel\");\n      await kv.set(KV.relations, relationId, relation);\n      await safeAudit(kv, \"evolve\", \"mem::evolve\", [relationId], {\n        operation: \"supersedes\",\n        oldId: existing.id,\n        newId: evolved.id,\n      });\n\n      logger.info(\"Memory evolved\", {\n        oldId: existing.id,\n        newId: evolved.id,\n        version: evolved.version,\n      });\n      return { success: true, memory: evolved, previousId: existing.id };\n    },\n  );\n\n  sdk.registerFunction(\"mem::get-related\", \n    async (data: {\n      memoryId: string;\n      maxHops?: number;\n      minConfidence?: number;\n    }) => {\n      const maxHops = Math.min(data.maxHops ?? 2, 5);\n      const MAX_VISITED = 500;\n      const rawMinConf = Number(data.minConfidence);\n      const minConfidence = Number.isFinite(rawMinConf)\n        ? Math.max(0, Math.min(1, rawMinConf))\n        : 0;\n\n      const allRelations = await kv\n        .list<MemoryRelation>(KV.relations)\n        .catch(() => []);\n\n      const visited = new Set<string>();\n      const result: Array<{\n        memory: Memory;\n        hop: number;\n        confidence: number;\n      }> = [];\n      const queue: Array<{ id: string; hop: number }> = [\n        { id: data.memoryId, hop: 0 },\n      ];\n\n      while (queue.length > 0 && visited.size < MAX_VISITED) {\n        const current = queue.shift()!;\n        if (visited.has(current.id) || current.hop > maxHops) continue;\n        visited.add(current.id);\n\n        const memory = await kv.get<Memory>(KV.memories, current.id);\n        if (!memory) continue;\n\n        if (current.hop > 0) {\n          const matchingRelations = allRelations.filter(\n            (r) =>\n              (r.sourceId === current.id && visited.has(r.targetId)) ||\n              (r.targetId === current.id && visited.has(r.sourceId)),\n          );\n          const confidence =\n            matchingRelations.length > 0\n              ? Math.max(...matchingRelations.map((r) => r.confidence ?? 0.5))\n              : 0.5;\n          if (confidence >= minConfidence) {\n            result.push({ memory, hop: current.hop, confidence });\n          }\n        }\n\n        const relatedIds = memory.relatedIds || [];\n        const supersedes = memory.supersedes || [];\n        const parentId = memory.parentId ? [memory.parentId] : [];\n\n        const kvLinked = allRelations\n          .filter((r) => r.sourceId === current.id || r.targetId === current.id)\n          .map((r) => (r.sourceId === current.id ? r.targetId : r.sourceId));\n\n        const allLinks = [\n          ...new Set([...relatedIds, ...supersedes, ...parentId, ...kvLinked]),\n        ];\n\n        for (const nextId of allLinks) {\n          if (!visited.has(nextId)) {\n            queue.push({ id: nextId, hop: current.hop + 1 });\n          }\n        }\n      }\n\n      result.sort((a, b) => b.confidence - a.confidence);\n\n      void recordAccessBatch(\n        kv,\n        result.map((r) => r.memory.id),\n      );\n\n      logger.info(\"Related memories retrieved\", {\n        memoryId: data.memoryId,\n        found: result.length,\n      });\n      return { results: result };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  CompressedObservation,\n  Session,\n  TimelineEntry,\n} from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { recordAccessBatch } from \"./access-tracker.js\";\nimport { logger } from \"../logger.js\";\n\nexport function registerTimelineFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::timeline\", \n    async (data: {\n      anchor: string;\n      project?: string;\n      before?: number;\n      after?: number;\n    }) => {\n      const before = Math.max(0, Math.floor(data.before ?? 5));\n      const after = Math.max(0, Math.floor(data.after ?? 5));\n\n      if (!data.anchor || typeof data.anchor !== \"string\") {\n        return { entries: [], anchor: data.anchor, reason: \"invalid_anchor\" };\n      }\n\n      let anchorTime: number;\n      const isoPattern = /^\\d{4}-\\d{2}-\\d{2}/;\n      if (isoPattern.test(data.anchor)) {\n        anchorTime = new Date(data.anchor).getTime();\n        if (isNaN(anchorTime)) {\n          return { entries: [], anchor: data.anchor, reason: \"invalid_date\" };\n        }\n      } else {\n        const searchResults = await findByKeyword(\n          kv,\n          data.anchor,\n          data.project,\n        );\n        if (searchResults.length === 0) {\n          return { entries: [], anchor: data.anchor, reason: \"no_match\" };\n        }\n        anchorTime = new Date(searchResults[0].timestamp).getTime();\n      }\n\n      const sessions = await kv.list<Session>(KV.sessions);\n      const filtered = data.project\n        ? sessions.filter((s) => s.project === data.project)\n        : sessions;\n\n      const allObs: Array<CompressedObservation & { sid: string }> = [];\n      for (const session of filtered) {\n        const observations = await kv.list<CompressedObservation>(\n          KV.observations(session.id),\n        );\n        for (const obs of observations) {\n          if (obs.title && obs.timestamp) {\n            allObs.push({ ...obs, sid: session.id });\n          }\n        }\n      }\n\n      allObs.sort(\n        (a, b) =>\n          new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),\n      );\n\n      let anchorIdx = 0;\n      let minDist = Infinity;\n      for (let i = 0; i < allObs.length; i++) {\n        const dist = Math.abs(\n          new Date(allObs[i].timestamp).getTime() - anchorTime,\n        );\n        if (dist < minDist) {\n          minDist = dist;\n          anchorIdx = i;\n        }\n      }\n\n      const startIdx = Math.max(0, anchorIdx - before);\n      const endIdx = Math.min(allObs.length - 1, anchorIdx + after);\n      const entries: TimelineEntry[] = [];\n\n      for (let i = startIdx; i <= endIdx; i++) {\n        const obs = allObs[i];\n        const { sid, ...observation } = obs;\n        entries.push({\n          observation,\n          sessionId: sid,\n          relativePosition: i - anchorIdx,\n        });\n      }\n\n      void recordAccessBatch(\n        kv,\n        entries.map((e) => e.observation.id),\n      );\n\n      logger.info(\"Timeline retrieved\", {\n        anchor: data.anchor,\n        entries: entries.length,\n      });\n      return { entries, anchorIndex: anchorIdx - startIdx };\n    },\n  );\n}\n\nasync function findByKeyword(\n  kv: StateKV,\n  keyword: string,\n  project?: string,\n): Promise<CompressedObservation[]> {\n  const sessions = await kv.list<Session>(KV.sessions);\n  const filtered = project\n    ? sessions.filter((s) => s.project === project)\n    : sessions;\n\n  const lower = keyword.toLowerCase();\n  const matches: CompressedObservation[] = [];\n\n  for (const session of filtered) {\n    const observations = await kv.list<CompressedObservation>(\n      KV.observations(session.id),\n    );\n    for (const obs of observations) {\n      if (\n        obs.title?.toLowerCase().includes(lower) ||\n        obs.narrative?.toLowerCase().includes(lower) ||\n        obs.concepts?.some((c) => c.toLowerCase().includes(lower))\n      ) {\n        matches.push(obs);\n      }\n    }\n  }\n\n  return matches.sort(\n    (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n  );\n}\n","import { VERSION } from \"../version.js\";\n\ninterface OtelConfig {\n  serviceName: string;\n  serviceVersion: string;\n  metricsExportIntervalMs: number;\n}\n\nexport const OTEL_CONFIG: OtelConfig = {\n  serviceName: \"agentmemory\",\n  serviceVersion: VERSION,\n  metricsExportIntervalMs: 30_000,\n};\n\ninterface Counter {\n  add: (n: number) => void;\n}\ninterface Histogram {\n  record: (v: number) => void;\n}\n\ninterface Counters {\n  observationsTotal: Counter;\n  compressionSuccess: Counter;\n  compressionFailure: Counter;\n  searchTotal: Counter;\n  dedupSkipped: Counter;\n  evictionTotal: Counter;\n  circuitBreakerOpen: Counter;\n  embeddingSuccess: Counter;\n  embeddingFailure: Counter;\n  vectorSearchTotal: Counter;\n  autoForgetTotal: Counter;\n  profileGenerated: Counter;\n  claudeBridgeSync: Counter;\n  graphExtraction: Counter;\n  consolidationRun: Counter;\n  teamShare: Counter;\n  auditLog: Counter;\n  snapshotCreate: Counter;\n  governanceDelete: Counter;\n  // #771: smart-search follow-up proxy. Incremented when a session\n  // issues a second smart-search inside the configured window AND the\n  // new result set has zero overlap with the previous one (a\n  // directional signal for \"the first results didn't satisfy\"). Treat\n  // as directional, not absolute — legitimate query refinement counts\n  // here too.\n  smartSearchFollowupWithinWindow: Counter;\n  // #771: benchmark-mode counter. Incremented by the benchmark scorer\n  // when judge_correct === false AND the gold-evidence-IDs are a\n  // subset of the retrieved-context-IDs (reader missed the answer\n  // despite retrieval being correct). Never incremented by core in\n  // live use; reserved here so dashboards keep a stable name.\n  readerFailureWithEvidence: Counter;\n}\n\ninterface Histograms {\n  compressionLatency: Histogram;\n  searchLatency: Histogram;\n  contextTokens: Histogram;\n  qualityScore: Histogram;\n  embeddingLatency: Histogram;\n  vectorSearchLatency: Histogram;\n}\n\ntype Meter = {\n  createCounter: (name: string) => Counter;\n  createHistogram: (name: string) => Histogram;\n};\n\nlet counters: Counters | null = null;\nlet histograms: Histograms | null = null;\n\nconst NOOP_COUNTER: Counter = { add: () => {} };\nconst NOOP_HISTOGRAM: Histogram = { record: () => {} };\n\nconst COUNTER_NAMES: Array<[keyof Counters, string]> = [\n  [\"observationsTotal\", \"observations.total\"],\n  [\"compressionSuccess\", \"compression.success\"],\n  [\"compressionFailure\", \"compression.failure\"],\n  [\"searchTotal\", \"search.total\"],\n  [\"dedupSkipped\", \"dedup.skipped\"],\n  [\"evictionTotal\", \"eviction.total\"],\n  [\"circuitBreakerOpen\", \"circuit_breaker.open\"],\n  [\"embeddingSuccess\", \"embedding.success\"],\n  [\"embeddingFailure\", \"embedding.failure\"],\n  [\"vectorSearchTotal\", \"vector_search.total\"],\n  [\"autoForgetTotal\", \"auto_forget.total\"],\n  [\"profileGenerated\", \"profile.generated\"],\n  [\"claudeBridgeSync\", \"claude_bridge.sync\"],\n  [\"graphExtraction\", \"graph.extraction\"],\n  [\"consolidationRun\", \"consolidation.run\"],\n  [\"teamShare\", \"team.share\"],\n  [\"auditLog\", \"audit.log\"],\n  [\"snapshotCreate\", \"snapshot.create\"],\n  [\"governanceDelete\", \"governance.delete\"],\n  [\"smartSearchFollowupWithinWindow\", \"smart_search.followup_within_window_total\"],\n  [\"readerFailureWithEvidence\", \"reader_failure_with_evidence_total\"],\n];\n\nconst HISTOGRAM_NAMES: Array<[keyof Histograms, string]> = [\n  [\"compressionLatency\", \"compression.latency_ms\"],\n  [\"searchLatency\", \"search.latency_ms\"],\n  [\"contextTokens\", \"context.tokens\"],\n  [\"qualityScore\", \"quality.score\"],\n  [\"embeddingLatency\", \"embedding.latency_ms\"],\n  [\"vectorSearchLatency\", \"vector_search.latency_ms\"],\n];\n\n// Accessors so functions outside `initMetrics`'s closure can record into\n// the same counter / histogram instances after init. Before init both\n// return no-op fallbacks so call sites stay safe in tests and during\n// the boot window.\nexport function getCounters(): Counters {\n  if (counters) return counters;\n  return Object.fromEntries(\n    COUNTER_NAMES.map(([key]) => [key, NOOP_COUNTER]),\n  ) as unknown as Counters;\n}\n\nexport function getHistograms(): Histograms {\n  if (histograms) return histograms;\n  return Object.fromEntries(\n    HISTOGRAM_NAMES.map(([key]) => [key, NOOP_HISTOGRAM]),\n  ) as unknown as Histograms;\n}\n\nexport function initMetrics(getMeter?: (name: string) => Meter): {\n  counters: Counters;\n  histograms: Histograms;\n} {\n  const meter = getMeter?.(\"agentmemory\");\n\n  counters = Object.fromEntries(\n    COUNTER_NAMES.map(([key, name]) => [\n      key,\n      meter ? meter.createCounter(name) : NOOP_COUNTER,\n    ]),\n  ) as unknown as Counters;\n\n  histograms = Object.fromEntries(\n    HISTOGRAM_NAMES.map(([key, name]) => [\n      key,\n      meter ? meter.createHistogram(name) : NOOP_HISTOGRAM,\n    ]),\n  ) as unknown as Histograms;\n\n  return { counters, histograms };\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  CompactLessonResult,\n  CompactSearchResult,\n  CompressedObservation,\n  HybridSearchResult,\n  Lesson,\n} from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { recordAccessBatch } from \"./access-tracker.js\";\nimport {\n  getAgentId,\n  isAgentScopeIsolated,\n  getFollowupWindowSeconds,\n} from \"../config.js\";\nimport { logger } from \"../logger.js\";\nimport { getCounters } from \"../telemetry/setup.js\";\n\n// #771: smart-search followup-rate diagnostic. Stored per session as\n// the most recent search payload, used to detect whether the next\n// search inside the window had a disjoint result set. sessionId is\n// duplicated into the row so the hourly sweep can delete by it\n// (StateKV.list returns values only).\nexport interface RecentSearch {\n  sessionId: string;\n  query: string;\n  resultIds: string[];\n  at: number;\n}\n\n// Module-scope counter mirror so `mem::diagnostic::followup-stats` can\n// read the rate back without going through the OTEL collector. The\n// OTEL counter is still the canonical export; this is an in-process\n// convenience for `agentmemory status` + tests.\nconst followupStats = {\n  followupWithinWindow: 0,\n  agentInitiatedSearches: 0,\n};\n\n// Tracks the in-flight detection promises so tests (and shutdown\n// flushes) can wait for all queued lock bodies to drain. The Set adds\n// when a detection is queued and removes when it settles; size === 0\n// means no pending detections.\nconst pendingFollowups = new Set<Promise<void>>();\n\nexport function getFollowupStats(): {\n  followupWithinWindow: number;\n  agentInitiatedSearches: number;\n  rate: number;\n} {\n  const total = followupStats.agentInitiatedSearches;\n  return {\n    ...followupStats,\n    rate: total > 0 ? followupStats.followupWithinWindow / total : 0,\n  };\n}\n\nexport async function flushPendingFollowups(): Promise<void> {\n  // Snapshot the current pending set; new detections queued after the\n  // snapshot run in a fresh batch.\n  await Promise.all(Array.from(pendingFollowups));\n}\n\nexport function resetFollowupStatsForTests(): void {\n  followupStats.followupWithinWindow = 0;\n  followupStats.agentInitiatedSearches = 0;\n}\n\n// Compact mode trims each lesson's content for at-a-glance display. The\n// full content is fetched via memory_lesson_recall when the caller needs it.\nconst LESSON_CONTENT_PREVIEW_CHARS = 240;\n\nexport function registerSmartSearchFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  searchFn: (query: string, limit: number) => Promise<HybridSearchResult[]>,\n): void {\n  sdk.registerFunction(\"mem::smart-search\",\n    async (data: {\n      query?: string;\n      expandIds?: Array<string | { obsId: string; sessionId: string }>;\n      limit?: number;\n      project?: string;\n      includeLessons?: boolean;\n      // optional per-call agent filter for runtimes routing many\n      // roles through one server. \"*\" opts out of the env-default\n      // scope and returns hits from every agent.\n      agentId?: string;\n      // #771: session anchor for the followup-rate diagnostic. The\n      // API trigger fills this from req.body / headers; direct\n      // sdk.trigger callers can pass it explicitly.\n      sessionId?: string;\n      // #771: marks viewer-originated searches so the diagnostic\n      // ignores them — only agent-initiated re-queries should count.\n      source?: string;\n    }) => {\n\n      // Compute the agent filter once, up front. Both the expandIds\n      // branch and the hybrid-search branch consult it — otherwise\n      // expandIds becomes a cross-agent leak (#554 follow-up).\n      //\n      // #817 follow-up: fail-closed when isolated mode is on AND no\n      // agent id is resolvable from any source. Silently letting\n      // filterAgentId fall through to `undefined` would be the same\n      // cross-agent leak this filter is meant to prevent.\n      const isolated = isAgentScopeIsolated();\n      const explicitAgentId =\n        typeof data.agentId === \"string\" && data.agentId.trim().length > 0\n          ? data.agentId.trim()\n          : undefined;\n      const wildcardAgent = explicitAgentId === \"*\";\n      const envAgentId = isolated ? getAgentId() : undefined;\n      const filterAgentId = wildcardAgent\n        ? undefined\n        : explicitAgentId ?? envAgentId;\n      if (\n        isolated &&\n        !wildcardAgent &&\n        !explicitAgentId &&\n        !envAgentId\n      ) {\n        throw new Error(\n          \"mem::smart-search: AGENTMEMORY_AGENT_SCOPE=isolated is set but \" +\n            \"no agent id is available (env AGENT_ID unset and no explicit \" +\n            \"agentId in the call). Refusing to read cross-agent rows. \" +\n            'Pass agentId: \"*\" to opt in to a wildcard read.',\n        );\n      }\n\n      if (data.expandIds && data.expandIds.length > 0) {\n        const raw = data.expandIds.slice(0, 20);\n        const items = raw.map((entry) => {\n          if (typeof entry === \"string\") return { obsId: entry, sessionId: undefined as string | undefined };\n          if (entry && typeof entry === \"object\" && typeof (entry as any).obsId === \"string\") {\n            return { obsId: (entry as any).obsId, sessionId: (entry as any).sessionId as string | undefined };\n          }\n          return null;\n        }).filter((item): item is NonNullable<typeof item> => item !== null);\n\n        const expanded: Array<{\n          obsId: string;\n          sessionId: string;\n          observation: CompressedObservation;\n        }> = [];\n\n        const results = await Promise.all(\n          items.map(({ obsId, sessionId }) =>\n            findObservation(kv, obsId, sessionId).then((obs) =>\n              obs ? { obsId, sessionId: obs.sessionId, observation: obs } : null,\n            ),\n          ),\n        );\n        for (const r of results) {\n          if (r) expanded.push(r);\n        }\n\n        const scoped = filterAgentId\n          ? expanded.filter((e) => e.observation.agentId === filterAgentId)\n          : expanded;\n\n        void recordAccessBatch(\n          kv,\n          scoped.map((e) => e.observation.id),\n        );\n\n        const truncated = data.expandIds.length > raw.length;\n        logger.info(\"Smart search expanded\", {\n          requested: data.expandIds.length,\n          attempted: raw.length,\n          returned: scoped.length,\n          filteredOutOfScope: expanded.length - scoped.length,\n          truncated,\n        });\n        return { mode: \"expanded\", results: scoped, truncated };\n      }\n\n      if (!data.query || typeof data.query !== \"string\" || !data.query.trim()) {\n        return { mode: \"compact\", results: [], error: \"query is required\" };\n      }\n\n      const limit = Math.max(1, Math.min(data.limit ?? 20, 100));\n      // Lesson recall stays capped: lessons are denser than raw\n      // observations so 10 covers most recall flows.\n      const lessonLimit = Math.min(limit, 10);\n      const includeLessons = data.includeLessons !== false;\n\n      // Over-fetch when filtering. Hybrid search can't filter on\n      // agentId (BM25/vector indexes don't carry it), so we ask the\n      // searcher for more hits than we need and trim post-filter. 3×\n      // is a defensible middle ground: enough headroom for a small\n      // workload, capped at 300 so a 100-limit request never asks for\n      // thousands of hits.\n      const overFetchLimit = filterAgentId\n        ? Math.min(limit * 3, 300)\n        : limit;\n\n      const [hybridResults, lessons] = await Promise.all([\n        searchFn(data.query, overFetchLimit),\n        includeLessons\n          ? recallLessons(sdk, data.query, lessonLimit, data.project)\n          : Promise.resolve([]),\n      ]);\n\n      const filteredHybrid = filterAgentId\n        ? hybridResults\n            .filter((r) => r.observation.agentId === filterAgentId)\n            .slice(0, limit)\n        : hybridResults.slice(0, limit);\n\n      const compact: CompactSearchResult[] = filteredHybrid.map((r) => ({\n        obsId: r.observation.id,\n        sessionId: r.sessionId,\n        title: r.observation.title,\n        type: r.observation.type,\n        score: r.combinedScore,\n        timestamp: r.observation.timestamp,\n      }));\n\n      void recordAccessBatch(\n        kv,\n        compact.map((r) => r.obsId),\n      );\n\n      // #771: followup-rate diagnostic. Only fires for agent-initiated\n      // searches that carry a sessionId — viewer-originated searches\n      // (source === \"viewer\") and direct-sdk callers without a session\n      // anchor are skipped. The result-set comparison uses obsIds: a\n      // disjoint set under the window suggests the previous call's\n      // results were not used, which is our directional proxy for\n      // reader-failure-with-evidence.\n      if (\n        data.sessionId &&\n        typeof data.sessionId === \"string\" &&\n        data.source !== \"viewer\" &&\n        compact.length > 0\n      ) {\n        // Skip detection when retrieval returned nothing: an empty\n        // result set is a retrieval failure, not a reader-failure\n        // signal. Counting it as \"disjoint from prior\" would inflate\n        // the rate every time search returns no hits.\n        followupStats.agentInitiatedSearches++;\n        // Off the critical response path. The withKeyedLock(sessionId)\n        // call serializes detection per session, so two rapid\n        // back-to-back searches from the same agent still see ordered\n        // prior-row writes — the second call's lock body queues\n        // behind the first's. Other sessions run in parallel.\n        const sessionIdForFollowup = data.sessionId;\n        const queryForFollowup = data.query;\n        const compactForFollowup = compact;\n        const detection = withKeyedLock(\n          `recent-searches:${sessionIdForFollowup}`,\n          () =>\n            detectFollowup(\n              kv,\n              sessionIdForFollowup,\n              queryForFollowup,\n              compactForFollowup,\n            ),\n        )\n          .catch((err) => {\n            logger.warn(\"Smart search followup detection failed\", {\n              sessionId: sessionIdForFollowup,\n              error: err instanceof Error ? err.message : String(err),\n            });\n          })\n          .finally(() => {\n            pendingFollowups.delete(detection);\n          });\n        pendingFollowups.add(detection);\n      }\n\n      logger.info(\"Smart search compact\", {\n        query: data.query,\n        results: compact.length,\n        lessons: lessons.length,\n      });\n      const response: {\n        mode: \"compact\";\n        results: CompactSearchResult[];\n        lessons?: CompactLessonResult[];\n      } = { mode: \"compact\", results: compact };\n      if (includeLessons) response.lessons = lessons;\n      return response;\n    },\n  );\n}\n\nasync function recallLessons(\n  sdk: ISdk,\n  query: string,\n  limit: number,\n  project?: string,\n): Promise<CompactLessonResult[]> {\n  try {\n    const result = (await sdk.trigger({\n      function_id: \"mem::lesson-recall\",\n      payload: { query, limit, project },\n    })) as { success?: boolean; lessons?: Array<Lesson & { score?: number }> };\n    if (!result?.success || !Array.isArray(result.lessons)) return [];\n    return result.lessons.map((l) => ({\n      lessonId: l.id,\n      content:\n        l.content.length > LESSON_CONTENT_PREVIEW_CHARS\n          ? l.content.slice(0, LESSON_CONTENT_PREVIEW_CHARS) + \"…\"\n          : l.content,\n      confidence: l.confidence,\n      score: l.score ?? l.confidence,\n      createdAt: l.createdAt,\n      project: l.project,\n      tags: l.tags ?? [],\n    }));\n  } catch (err) {\n    logger.warn(\"Smart search: mem::lesson-recall failed; returning empty lesson list\", {\n      error: err instanceof Error ? err.message : String(err),\n    });\n    return [];\n  }\n}\n\nasync function detectFollowup(\n  kv: StateKV,\n  sessionId: string,\n  query: string,\n  compact: CompactSearchResult[],\n): Promise<void> {\n  const now = Date.now();\n  const windowMs = Math.max(1, getFollowupWindowSeconds()) * 1000;\n  const currentIds = compact.map((r) => r.obsId);\n  const current: RecentSearch = { sessionId, query, resultIds: currentIds, at: now };\n\n  const prior = await kv\n    .get<RecentSearch>(KV.recentSearches, sessionId)\n    .catch(() => null);\n\n  await kv.set(KV.recentSearches, sessionId, current);\n\n  if (!prior || typeof prior.at !== \"number\") return;\n  if (now - prior.at > windowMs) return;\n  // Same query inside the window is a retry, not a follow-up; skip so a\n  // duplicate request from a flaky client doesn't inflate the metric.\n  if (typeof prior.query === \"string\" && prior.query === query) return;\n\n  const priorIds = Array.isArray(prior.resultIds) ? prior.resultIds : [];\n  const priorSet = new Set(priorIds);\n  const hasOverlap = currentIds.some((id) => priorSet.has(id));\n  if (hasOverlap) return;\n\n  getCounters().smartSearchFollowupWithinWindow.add(1);\n  followupStats.followupWithinWindow++;\n  logger.info(\"Smart search followup detected\", {\n    sessionId,\n    windowSeconds: Math.round(windowMs / 1000),\n    priorQuery: prior.query,\n    nextQuery: query,\n    priorResultCount: priorIds.length,\n    nextResultCount: currentIds.length,\n  });\n}\n\nasync function findObservation(\n  kv: StateKV,\n  obsId: string,\n  sessionIdHint?: string,\n): Promise<CompressedObservation | null> {\n  if (sessionIdHint) {\n    const obs = await kv\n      .get<CompressedObservation>(KV.observations(sessionIdHint), obsId)\n      .catch(() => null);\n    if (obs) return obs;\n  }\n\n  const sessions = await kv.list<{ id: string }>(KV.sessions);\n  for (let i = 0; i < sessions.length; i += 5) {\n    const batch = sessions.slice(i, i + 5);\n    const results = await Promise.all(\n      batch.map((s) =>\n        kv.get<CompressedObservation>(KV.observations(s.id), obsId).catch(() => null),\n      ),\n    );\n    const found = results.find((r) => r !== null);\n    if (found) return found;\n  }\n  return null;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport { logger } from \"../logger.js\";\nimport { getFollowupStats, type RecentSearch } from \"./smart-search.js\";\nimport { getFollowupWindowSeconds } from \"../config.js\";\n\n// #771: TTL sweep for the followup-rate diagnostic scope. `recentSearches`\n// only needs the most recent entry per session, but stale rows accumulate\n// when sessions go idle. Hourly sweep deletes rows whose last update is\n// older than the retention window.\nconst RETENTION_MS = 24 * 60 * 60 * 1000;\n\nexport function registerRecentSearchesSweepFunction(\n  sdk: ISdk,\n  kv: StateKV,\n): void {\n  sdk.registerFunction(\n    \"mem::diagnostic::recent-searches-sweep\",\n    async (): Promise<{ success: true; swept: number; skipped: number }> => {\n      const cutoff = Date.now() - RETENTION_MS;\n      const rows = await kv\n        .list<Partial<RecentSearch>>(KV.recentSearches)\n        .catch(() => []);\n      let swept = 0;\n      let skipped = 0;\n      for (const row of rows) {\n        if (!row || typeof row.sessionId !== \"string\" || !row.sessionId) {\n          skipped++;\n          continue;\n        }\n        const at = typeof row.at === \"number\" ? row.at : 0;\n        if (at >= cutoff) continue;\n        try {\n          await kv.delete(KV.recentSearches, row.sessionId);\n          swept++;\n        } catch (err) {\n          logger.warn(\"recent-searches sweep delete failed\", {\n            sessionId: row.sessionId,\n            error: err instanceof Error ? err.message : String(err),\n          });\n        }\n      }\n      if (swept > 0 || skipped > 0) {\n        logger.info(\"Recent-searches sweep complete\", { swept, skipped });\n      }\n      return { success: true, swept, skipped };\n    },\n  );\n\n  // #771: read-back surface for `agentmemory status` and external\n  // dashboards that don't go through the OTEL collector.\n  sdk.registerFunction(\n    \"mem::diagnostic::followup-stats\",\n    async (): Promise<{\n      success: true;\n      windowSeconds: number;\n      agentInitiatedSearches: number;\n      followupWithinWindow: number;\n      rate: number;\n    }> => {\n      const stats = getFollowupStats();\n      return {\n        success: true,\n        windowSeconds: getFollowupWindowSeconds(),\n        agentInitiatedSearches: stats.agentInitiatedSearches,\n        followupWithinWindow: stats.followupWithinWindow,\n        rate: stats.rate,\n      };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  CompressedObservation,\n  Session,\n  ProjectProfile,\n} from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { logger } from \"../logger.js\";\n\nexport function registerProfileFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::profile\", \n    async (data: { project: string; refresh?: boolean } | undefined) => {\n      if (!data || typeof data.project !== \"string\" || !data.project.trim()) {\n        return { success: false, error: \"project is required\" };\n      }\n      const project = data.project.trim();\n\n      if (!data.refresh) {\n        const cached = await kv\n          .get<ProjectProfile>(KV.profiles, project)\n          .catch(() => null);\n        if (cached) {\n          const age = Date.now() - new Date(cached.updatedAt).getTime();\n          if (age < 3600_000) {\n            return { profile: cached, cached: true };\n          }\n        }\n      }\n\n      const sessions = await kv.list<Session>(KV.sessions);\n      const projectSessions = sessions.filter(\n        (s) => s.project === project,\n      );\n\n      if (projectSessions.length === 0) {\n        return { profile: null, reason: \"no_sessions\" };\n      }\n\n      const conceptFreq = new Map<string, number>();\n      const fileFreq = new Map<string, number>();\n      const errors: string[] = [];\n      const recentActivity: string[] = [];\n      let totalObs = 0;\n\n      const sortedSessions = projectSessions.sort(\n        (a, b) =>\n          new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime(),\n      );\n\n      const top20Sessions = sortedSessions.slice(0, 20);\n      const obsPerSession = await Promise.all(\n        top20Sessions.map((s) =>\n          kv\n            .list<CompressedObservation>(KV.observations(s.id))\n            .catch(() => [] as CompressedObservation[]),\n        ),\n      );\n\n      for (let i = 0; i < top20Sessions.length; i++) {\n        const session = top20Sessions[i];\n        const observations = obsPerSession[i];\n        totalObs += observations.length;\n\n        for (const obs of observations) {\n          for (const concept of obs.concepts || []) {\n            conceptFreq.set(concept, (conceptFreq.get(concept) || 0) + 1);\n          }\n          for (const file of obs.files || []) {\n            fileFreq.set(file, (fileFreq.get(file) || 0) + 1);\n          }\n          if (obs.type === \"error\") {\n            errors.push(obs.title);\n          }\n        }\n\n        const important = observations\n          .filter((o) => o.importance >= 7)\n          .sort((a, b) => b.importance - a.importance);\n        if (important.length > 0) {\n          recentActivity.push(\n            `[${session.startedAt.slice(0, 10)}] ${important[0].title}`,\n          );\n        }\n      }\n\n      const topConcepts = Array.from(conceptFreq.entries())\n        .sort((a, b) => b[1] - a[1])\n        .slice(0, 15)\n        .map(([concept, frequency]) => ({ concept, frequency }));\n\n      const topFiles = Array.from(fileFreq.entries())\n        .sort((a, b) => b[1] - a[1])\n        .slice(0, 15)\n        .map(([file, frequency]) => ({ file, frequency }));\n\n      const uniqueErrors = [...new Set(errors)].slice(0, 10);\n\n      const profile: ProjectProfile = {\n        project,\n        updatedAt: new Date().toISOString(),\n        topConcepts,\n        topFiles,\n        conventions: extractConventions(topConcepts, topFiles),\n        commonErrors: uniqueErrors,\n        recentActivity: recentActivity.slice(0, 10),\n        sessionCount: projectSessions.length,\n        totalObservations: totalObs,\n      };\n\n      await kv.set(KV.profiles, project, profile);\n      await recordAudit(kv, \"share\", \"mem::profile\", [project], {\n        sessionCount: projectSessions.length,\n        totalObservations: totalObs,\n      });\n\n      logger.info(\"Profile generated\", {\n        project,\n        sessions: projectSessions.length,\n        observations: totalObs,\n      });\n      return { profile, cached: false };\n    },\n  );\n}\n\nfunction extractConventions(\n  concepts: Array<{ concept: string; frequency: number }>,\n  files: Array<{ file: string; frequency: number }>,\n): string[] {\n  const conventions: string[] = [];\n\n  const tsFiles = files.filter((f) => f.file.endsWith(\".ts\")).length;\n  const jsFiles = files.filter((f) => f.file.endsWith(\".js\")).length;\n  if (tsFiles > jsFiles && tsFiles > 0) {\n    conventions.push(\"TypeScript project\");\n  }\n\n  const srcFiles = files.filter((f) => f.file.includes(\"/src/\")).length;\n  if (srcFiles > files.length * 0.5) {\n    conventions.push(\"Standard src/ directory structure\");\n  }\n\n  const testFiles = files.filter(\n    (f) => f.file.includes(\"test\") || f.file.includes(\"spec\"),\n  ).length;\n  if (testFiles > 0) {\n    conventions.push(\"Has test files\");\n  }\n\n  for (const { concept, frequency } of concepts.slice(0, 5)) {\n    if (frequency >= 3) {\n      conventions.push(`Frequently uses: ${concept}`);\n    }\n  }\n\n  return conventions;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { Memory, CompressedObservation, Session } from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { deleteAccessLog } from \"./access-tracker.js\";\nimport { getSearchIndex, vectorIndexRemove, flushIndexSave } from \"./search.js\";\nimport { logger } from \"../logger.js\";\n\nconst MS_PER_DAY = 24 * 60 * 60 * 1000;\nconst CONTRADICTION_THRESHOLD = 0.9;\n\ninterface AutoForgetResult {\n  ttlExpired: string[];\n  contradictions: Array<{\n    memoryA: string;\n    memoryB: string;\n    similarity: number;\n  }>;\n  lowValueObs: string[];\n  dryRun: boolean;\n}\n\nexport function registerAutoForgetFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::auto-forget\", \n    async (data: { dryRun?: boolean }): Promise<AutoForgetResult> => {\n      const dryRun = data?.dryRun ?? false;\n      const now = Date.now();\n      const { decrementImageRef } = await import(\"./image-refs.js\");\n\n      const result: AutoForgetResult = {\n        ttlExpired: [],\n        contradictions: [],\n        lowValueObs: [],\n        dryRun,\n      };\n\n      const memories = await kv.list<Memory>(KV.memories);\n      const deletedIds = new Set<string>();\n      for (const mem of memories) {\n        if (mem.forgetAfter) {\n          const expiry = new Date(mem.forgetAfter).getTime();\n          if (now > expiry) {\n            result.ttlExpired.push(mem.id);\n            deletedIds.add(mem.id);\n            if (!dryRun) {\n              if (mem.imageRef) {\n                await decrementImageRef(kv, sdk, mem.imageRef);\n              }\n              await kv.delete(KV.memories, mem.id);\n              await recordAudit(kv, \"delete\", \"mem::auto-forget\", [mem.id], {\n                resource: \"memory\",\n                reason: \"auto-forget TTL\",\n                timestamp: mem.forgetAfter,\n              });\n              await deleteAccessLog(kv, mem.id);\n              getSearchIndex().remove(mem.id);\n              vectorIndexRemove(mem.id);\n            }\n          }\n        }\n      }\n\n      const latestMemories = memories\n        .filter((m) => m.isLatest !== false && !deletedIds.has(m.id))\n        .sort(\n          (a, b) =>\n            new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),\n        )\n        .slice(0, 1000);\n\n      const tokenCache = new Map<string, Set<string>>();\n      for (const mem of latestMemories) {\n        tokenCache.set(\n          mem.id,\n          new Set(\n            mem.content\n              .toLowerCase()\n              .split(/\\s+/)\n              .filter((t) => t.length > 2),\n          ),\n        );\n      }\n\n      const memById = new Map(latestMemories.map((m) => [m.id, m]));\n      const conceptIndex = new Map<string, string[]>();\n      for (const mem of latestMemories) {\n        const concepts = mem.concepts || [];\n        for (const c of concepts) {\n          const key = c.toLowerCase();\n          if (!conceptIndex.has(key)) conceptIndex.set(key, []);\n          conceptIndex.get(key)!.push(mem.id);\n        }\n      }\n\n      const compared = new Set<string>();\n      for (const [, memIds] of conceptIndex) {\n        for (let i = 0; i < memIds.length; i++) {\n          for (let j = i + 1; j < memIds.length; j++) {\n            const key =\n              memIds[i] < memIds[j]\n                ? `${memIds[i]}|${memIds[j]}`\n                : `${memIds[j]}|${memIds[i]}`;\n            if (compared.has(key)) continue;\n            compared.add(key);\n\n            const setA = tokenCache.get(memIds[i])!;\n            const setB = tokenCache.get(memIds[j])!;\n            let intersection = 0;\n            if (setA.size === 0 && setB.size === 0) continue;\n            if (setA.size === 0 || setB.size === 0) continue;\n            for (const word of setA) {\n              if (setB.has(word)) intersection++;\n            }\n            const sim =\n              intersection / (setA.size + setB.size - intersection);\n\n            if (sim > CONTRADICTION_THRESHOLD) {\n              const memA = memById.get(memIds[i])!;\n              const memB = memById.get(memIds[j])!;\n              result.contradictions.push({\n                memoryA: memA.id,\n                memoryB: memB.id,\n                similarity: sim,\n              });\n\n              if (!dryRun) {\n                const older =\n                  new Date(memA.createdAt).getTime() <\n                    new Date(memB.createdAt).getTime()\n                    ? memA\n                    : memB;\n                older.isLatest = false;\n                await kv.set(KV.memories, older.id, older);\n                await recordAudit(kv, \"forget\", \"mem::auto-forget\", [older.id], {\n                  resource: \"memory\",\n                  reason: \"auto-forget contradiction\",\n                  olderId: older.id,\n                  similarity: sim,\n                });\n              }\n            }\n          }\n        }\n      }\n\n      const sessions = await kv.list<Session>(KV.sessions);\n      const obsPerSession: CompressedObservation[][] = [];\n      for (let batch = 0; batch < sessions.length; batch += 10) {\n        const chunk = sessions.slice(batch, batch + 10);\n        const results = await Promise.all(\n          chunk.map((s) =>\n            kv\n              .list<CompressedObservation>(KV.observations(s.id))\n              .catch(() => [] as CompressedObservation[]),\n          ),\n        );\n        obsPerSession.push(...results);\n      }\n      for (let i = 0; i < sessions.length; i++) {\n        for (const obs of obsPerSession[i]) {\n          if (!obs.timestamp) continue;\n          const age = now - new Date(obs.timestamp).getTime();\n          if (age > 180 * MS_PER_DAY && (obs.importance ?? 5) <= 2) {\n            result.lowValueObs.push(obs.id);\n            if (!dryRun) {\n              let deletedOk = false;\n              try {\n                await kv.delete(KV.observations(sessions[i].id), obs.id);\n                deletedOk = true;\n              } catch {\n                deletedOk = false;\n              }\n              if (deletedOk) {\n                if (obs.imageData) await decrementImageRef(kv, sdk, obs.imageData);\n                if (obs.imageRef && obs.imageRef !== obs.imageData) {\n                  await decrementImageRef(kv, sdk, obs.imageRef);\n                }\n                await recordAudit(kv, \"delete\", \"mem::auto-forget\", [obs.id], {\n                  resource: \"observation\",\n                  reason: \"auto-forget low-value observation\",\n                  sessionId: sessions[i].id,\n                  timestamp: obs.timestamp,\n                });\n                getSearchIndex().remove(obs.id);\n                vectorIndexRemove(obs.id);\n              }\n            }\n          }\n        }\n      }\n\n      if (!dryRun && (result.ttlExpired.length > 0 || result.lowValueObs.length > 0)) {\n        await flushIndexSave();\n      }\n\n      logger.info(\"Auto-forget complete\", {\n        ttlExpired: result.ttlExpired.length,\n        contradictions: result.contradictions.length,\n        lowValueObs: result.lowValueObs.length,\n        dryRun,\n      });\n      return result;\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  Session,\n  CompressedObservation,\n  Memory,\n  SessionSummary,\n  ProjectProfile,\n  ExportData,\n  GraphNode,\n  GraphEdge,\n  SemanticMemory,\n  ProceduralMemory,\n  Action,\n  ActionEdge,\n  Routine,\n  Signal,\n  Checkpoint,\n  Sentinel,\n  Sketch,\n  Crystal,\n  Facet,\n  Lesson,\n  Insight,\n  ExportPagination,\n  AccessLogExport,\n} from \"../types.js\";\nimport { normalizeAccessLog } from \"./access-tracker.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { VERSION } from \"../version.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { logger } from \"../logger.js\";\n\nexport function registerExportImportFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::export\", \n    async (data?: { maxSessions?: number; offset?: number }) => {\n      const rawMax = Number(data?.maxSessions);\n      const maxSessions = Number.isFinite(rawMax) && rawMax > 0 ? Math.min(Math.floor(rawMax), 1000) : undefined;\n      const rawOffset = Number(data?.offset);\n      const offset = Number.isFinite(rawOffset) && rawOffset >= 0 ? Math.floor(rawOffset) : 0;\n\n      const allSessions = await kv.list<Session>(KV.sessions);\n      const paginatedSessions = maxSessions !== undefined\n        ? allSessions.slice(offset, offset + maxSessions)\n        : allSessions;\n      const memories = await kv.list<Memory>(KV.memories);\n      const summaries = await kv.list<SessionSummary>(KV.summaries);\n\n      const observations: Record<string, CompressedObservation[]> = {};\n      const obsResults = await Promise.all(\n        paginatedSessions.map((session) =>\n          kv\n            .list<CompressedObservation>(KV.observations(session.id))\n            .catch(() => [] as CompressedObservation[])\n            .then((obs) => ({ sessionId: session.id, obs })),\n        ),\n      );\n      for (const { sessionId, obs } of obsResults) {\n        if (obs.length > 0) {\n          observations[sessionId] = obs;\n        }\n      }\n\n      const profiles: ProjectProfile[] = [];\n      const uniqueProjects = [...new Set(paginatedSessions.map((s) => s.project))];\n      const profileResults = await Promise.all(\n        uniqueProjects.map((project) =>\n          kv.get<ProjectProfile>(KV.profiles, project).catch(() => null),\n        ),\n      );\n      for (const profile of profileResults) {\n        if (profile) profiles.push(profile);\n      }\n\n      const [\n        graphNodes,\n        graphEdges,\n        semanticMemories,\n        proceduralMemories,\n        actions,\n        actionEdges,\n        sentinels,\n        sketches,\n        crystals,\n        facets,\n        lessons,\n        insights,\n        routines,\n        signals,\n        checkpoints,\n        accessLogs,\n      ] = await Promise.all([\n        kv.list<GraphNode>(KV.graphNodes).catch(() => []),\n        kv.list<GraphEdge>(KV.graphEdges).catch(() => []),\n        kv.list<SemanticMemory>(KV.semantic).catch(() => []),\n        kv.list<ProceduralMemory>(KV.procedural).catch(() => []),\n        kv.list<Action>(KV.actions).catch(() => []),\n        kv.list<ActionEdge>(KV.actionEdges).catch(() => []),\n        kv.list<Sentinel>(KV.sentinels).catch(() => []),\n        kv.list<Sketch>(KV.sketches).catch(() => []),\n        kv.list<Crystal>(KV.crystals).catch(() => []),\n        kv.list<Facet>(KV.facets).catch(() => []),\n        kv.list<Lesson>(KV.lessons).catch(() => []),\n        kv.list<Insight>(KV.insights).catch(() => []),\n        kv.list<Routine>(KV.routines).catch(() => []),\n        kv.list<Signal>(KV.signals).catch(() => []),\n        kv.list<Checkpoint>(KV.checkpoints).catch(() => []),\n        kv.list<AccessLogExport>(KV.accessLog).catch(() => []),\n      ]);\n\n      const exportData: ExportData = {\n        version: VERSION,\n        exportedAt: new Date().toISOString(),\n        sessions: paginatedSessions,\n        observations,\n        memories,\n        summaries,\n        profiles: profiles.length > 0 ? profiles : undefined,\n        graphNodes: graphNodes.length > 0 ? graphNodes : undefined,\n        graphEdges: graphEdges.length > 0 ? graphEdges : undefined,\n        semanticMemories:\n          semanticMemories.length > 0 ? semanticMemories : undefined,\n        proceduralMemories:\n          proceduralMemories.length > 0 ? proceduralMemories : undefined,\n        actions: actions.length > 0 ? actions : undefined,\n        actionEdges: actionEdges.length > 0 ? actionEdges : undefined,\n        sentinels: sentinels.length > 0 ? sentinels : undefined,\n        sketches: sketches.length > 0 ? sketches : undefined,\n        crystals: crystals.length > 0 ? crystals : undefined,\n        facets: facets.length > 0 ? facets : undefined,\n        lessons: lessons.length > 0 ? lessons : undefined,\n        insights: insights.length > 0 ? insights : undefined,\n        routines: routines.length > 0 ? routines : undefined,\n        signals: signals.length > 0 ? signals : undefined,\n        checkpoints: checkpoints.length > 0 ? checkpoints : undefined,\n        accessLogs: accessLogs.length > 0 ? accessLogs : undefined,\n      };\n\n      if (maxSessions !== undefined) {\n        exportData.pagination = {\n          offset,\n          limit: maxSessions,\n          total: allSessions.length,\n          hasMore: offset + maxSessions < allSessions.length,\n        };\n      }\n\n      const totalObs = Object.values(observations).reduce(\n        (sum, arr) => sum + arr.length,\n        0,\n      );\n      logger.info(\"Export complete\", {\n        sessions: paginatedSessions.length,\n        totalSessions: allSessions.length,\n        observations: totalObs,\n        memories: memories.length,\n        summaries: summaries.length,\n      });\n\n      return exportData;\n    },\n  );\n\n  sdk.registerFunction(\"mem::import\", \n    async (data: {\n      exportData: ExportData;\n      strategy?: \"merge\" | \"replace\" | \"skip\";\n    }) => {\n      if (\n        !data?.exportData ||\n        typeof data.exportData !== \"object\" ||\n        typeof (data.exportData as { version?: unknown }).version !== \"string\"\n      ) {\n        return { success: false, error: \"exportData with string version is required\" };\n      }\n      const strategy = data.strategy || \"merge\";\n      const importData = data.exportData;\n\n      const supportedVersions = new Set([\"0.3.0\", \"0.4.0\", \"0.5.0\", \"0.6.0\", \"0.6.1\", \"0.7.0\", \"0.7.2\", \"0.7.3\", \"0.7.4\", \"0.7.5\", \"0.7.6\", \"0.7.7\", \"0.7.9\", \"0.8.0\", \"0.8.1\", \"0.8.2\", \"0.8.3\", \"0.8.4\", \"0.8.5\", \"0.8.6\", \"0.8.7\", \"0.8.8\", \"0.8.9\", \"0.8.10\", \"0.8.11\", \"0.8.12\", \"0.8.13\", \"0.9.0\", \"0.9.1\", \"0.9.2\", \"0.9.3\", \"0.9.4\", \"0.9.5\", \"0.9.6\", \"0.9.7\", \"0.9.8\", \"0.9.9\", \"0.9.10\", \"0.9.11\", \"0.9.12\", \"0.9.13\", \"0.9.14\", \"0.9.15\", \"0.9.16\", \"0.9.17\", \"0.9.18\", \"0.9.19\", \"0.9.20\", \"0.9.21\", \"0.9.22\", \"0.9.23\", \"0.9.24\", \"0.9.25\", \"0.9.26\", \"0.9.27\", \"0.9.28\"]);\n      if (!supportedVersions.has(importData.version)) {\n        return {\n          success: false,\n          error: `Unsupported export version: ${importData.version}`,\n        };\n      }\n\n      const MAX_SESSIONS = 10_000;\n      const MAX_MEMORIES = 50_000;\n      const MAX_SUMMARIES = 10_000;\n      const MAX_OBS_PER_SESSION = 5_000;\n      const MAX_TOTAL_OBSERVATIONS = 500_000;\n      const MAX_ACCESS_LOGS = 50_000;\n\n      if (!Array.isArray(importData.sessions)) {\n        return { success: false, error: \"sessions must be an array\" };\n      }\n      if (!Array.isArray(importData.memories)) {\n        return { success: false, error: \"memories must be an array\" };\n      }\n      if (!Array.isArray(importData.summaries)) {\n        return { success: false, error: \"summaries must be an array\" };\n      }\n      if (\n        typeof importData.observations !== \"object\" ||\n        importData.observations === null ||\n        Array.isArray(importData.observations)\n      ) {\n        return { success: false, error: \"observations must be an object\" };\n      }\n\n      if (importData.sessions.length > MAX_SESSIONS) {\n        return {\n          success: false,\n          error: `Too many sessions (max ${MAX_SESSIONS})`,\n        };\n      }\n      if (importData.memories.length > MAX_MEMORIES) {\n        return {\n          success: false,\n          error: `Too many memories (max ${MAX_MEMORIES})`,\n        };\n      }\n      if (importData.summaries.length > MAX_SUMMARIES) {\n        return {\n          success: false,\n          error: `Too many summaries (max ${MAX_SUMMARIES})`,\n        };\n      }\n      const MAX_OBS_BUCKETS = 10_000;\n      const obsBuckets = Object.keys(importData.observations);\n      if (obsBuckets.length > MAX_OBS_BUCKETS) {\n        return {\n          success: false,\n          error: `Too many observation buckets (max ${MAX_OBS_BUCKETS})`,\n        };\n      }\n\n      let totalObservations = 0;\n      for (const [, obs] of Object.entries(importData.observations)) {\n        if (!Array.isArray(obs)) {\n          return { success: false, error: \"observation values must be arrays\" };\n        }\n        if (obs.length > MAX_OBS_PER_SESSION) {\n          return {\n            success: false,\n            error: `Too many observations per session (max ${MAX_OBS_PER_SESSION})`,\n          };\n        }\n        totalObservations += obs.length;\n      }\n      if (totalObservations > MAX_TOTAL_OBSERVATIONS) {\n        return {\n          success: false,\n          error: `Too many total observations (max ${MAX_TOTAL_OBSERVATIONS})`,\n        };\n      }\n\n      const stats = {\n        sessions: 0,\n        observations: 0,\n        memories: 0,\n        summaries: 0,\n        skipped: 0,\n      };\n\n      if (strategy === \"replace\") {\n        const existing = await kv.list<Session>(KV.sessions);\n        for (const session of existing) {\n          await kv.delete(KV.sessions, session.id);\n          const obs = await kv\n            .list<CompressedObservation>(KV.observations(session.id))\n            .catch(() => []);\n          for (const o of obs) {\n            await kv.delete(KV.observations(session.id), o.id);\n          }\n        }\n        const existingMem = await kv.list<Memory>(KV.memories);\n        for (const m of existingMem) {\n          await kv.delete(KV.memories, m.id);\n        }\n        const existingSummaries = await kv.list<SessionSummary>(KV.summaries);\n        for (const s of existingSummaries) {\n          await kv.delete(KV.summaries, s.sessionId);\n        }\n        for (const a of await kv.list<Action>(KV.actions).catch(() => [])) {\n          await kv.delete(KV.actions, a.id);\n        }\n        for (const e of await kv.list<ActionEdge>(KV.actionEdges).catch(() => [])) {\n          await kv.delete(KV.actionEdges, e.id);\n        }\n        for (const r of await kv.list<Routine>(KV.routines).catch(() => [])) {\n          await kv.delete(KV.routines, r.id);\n        }\n        for (const s of await kv.list<Signal>(KV.signals).catch(() => [])) {\n          await kv.delete(KV.signals, s.id);\n        }\n        for (const c of await kv.list<Checkpoint>(KV.checkpoints).catch(() => [])) {\n          await kv.delete(KV.checkpoints, c.id);\n        }\n        for (const s of await kv.list<Sentinel>(KV.sentinels).catch(() => [])) {\n          await kv.delete(KV.sentinels, s.id);\n        }\n        for (const s of await kv.list<Sketch>(KV.sketches).catch(() => [])) {\n          await kv.delete(KV.sketches, s.id);\n        }\n        for (const c of await kv.list<Crystal>(KV.crystals).catch(() => [])) {\n          await kv.delete(KV.crystals, c.id);\n        }\n        for (const f of await kv.list<Facet>(KV.facets).catch(() => [])) {\n          await kv.delete(KV.facets, f.id);\n        }\n        for (const l of await kv.list<Lesson>(KV.lessons).catch(() => [])) {\n          await kv.delete(KV.lessons, l.id);\n        }\n        for (const i of await kv.list<Insight>(KV.insights).catch(() => [])) {\n          await kv.delete(KV.insights, i.id);\n        }\n        for (const n of await kv.list<{ id: string }>(KV.graphNodes).catch(() => [])) {\n          await kv.delete(KV.graphNodes, n.id);\n        }\n        for (const e of await kv.list<{ id: string }>(KV.graphEdges).catch(() => [])) {\n          await kv.delete(KV.graphEdges, e.id);\n        }\n        for (const s of await kv.list<{ id: string }>(KV.semantic).catch(() => [])) {\n          await kv.delete(KV.semantic, s.id);\n        }\n        for (const p of await kv.list<{ id: string }>(KV.procedural).catch(() => [])) {\n          await kv.delete(KV.procedural, p.id);\n        }\n        for (const profile of await kv.list<ProjectProfile>(KV.profiles).catch(() => [])) {\n          await kv.delete(KV.profiles, profile.project);\n        }\n        for (const a of await kv.list<AccessLogExport>(KV.accessLog).catch(() => [])) {\n          await kv.delete(KV.accessLog, a.memoryId);\n        }\n      }\n\n      for (const session of importData.sessions) {\n        if (strategy === \"skip\") {\n          const existing = await kv\n            .get<Session>(KV.sessions, session.id)\n            .catch(() => null);\n          if (existing) {\n            stats.skipped++;\n            continue;\n          }\n        }\n        await kv.set(KV.sessions, session.id, session);\n        stats.sessions++;\n      }\n\n      for (const [sessionId, obs] of Object.entries(importData.observations)) {\n        for (const o of obs) {\n          if (strategy === \"skip\") {\n            const existing = await kv\n              .get<CompressedObservation>(KV.observations(sessionId), o.id)\n              .catch(() => null);\n            if (existing) {\n              stats.skipped++;\n              continue;\n            }\n          }\n          await kv.set(KV.observations(sessionId), o.id, o);\n          stats.observations++;\n        }\n      }\n\n      for (const memory of importData.memories) {\n        if (strategy === \"skip\") {\n          const existing = await kv\n            .get<Memory>(KV.memories, memory.id)\n            .catch(() => null);\n          if (existing) {\n            stats.skipped++;\n            continue;\n          }\n        }\n        // Older exports + hand-edited dumps can omit this field.\n        if (!Array.isArray(memory.sessionIds)) {\n          memory.sessionIds = [];\n        }\n        await kv.set(KV.memories, memory.id, memory);\n        stats.memories++;\n      }\n\n      for (const summary of importData.summaries) {\n        if (strategy === \"skip\") {\n          const existing = await kv\n            .get<SessionSummary>(KV.summaries, summary.sessionId)\n            .catch(() => null);\n          if (existing) {\n            stats.skipped++;\n            continue;\n          }\n        }\n        await kv.set(KV.summaries, summary.sessionId, summary);\n        stats.summaries++;\n      }\n\n      if (importData.graphNodes) {\n        for (const node of importData.graphNodes) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.graphNodes, node.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.graphNodes, node.id, node);\n        }\n      }\n      if (importData.graphEdges) {\n        for (const edge of importData.graphEdges) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.graphEdges, edge.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.graphEdges, edge.id, edge);\n        }\n      }\n      if (importData.semanticMemories) {\n        for (const sem of importData.semanticMemories) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.semantic, sem.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.semantic, sem.id, sem);\n        }\n      }\n      if (importData.proceduralMemories) {\n        for (const proc of importData.proceduralMemories) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.procedural, proc.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.procedural, proc.id, proc);\n        }\n      }\n      if (importData.profiles) {\n        for (const profile of importData.profiles) {\n          if (strategy === \"skip\") {\n            const existing = await kv\n              .get<ProjectProfile>(KV.profiles, profile.project)\n              .catch(() => null);\n            if (existing) {\n              stats.skipped++;\n              continue;\n            }\n          }\n          await kv.set(KV.profiles, profile.project, profile);\n        }\n      }\n\n      if (importData.actions) {\n        for (const action of importData.actions) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.actions, action.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.actions, action.id, action);\n        }\n      }\n      if (importData.actionEdges) {\n        for (const edge of importData.actionEdges) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.actionEdges, edge.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.actionEdges, edge.id, edge);\n        }\n      }\n      if (importData.routines) {\n        for (const routine of importData.routines) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.routines, routine.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.routines, routine.id, routine);\n        }\n      }\n      if (importData.signals) {\n        for (const signal of importData.signals) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.signals, signal.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.signals, signal.id, signal);\n        }\n      }\n      if (importData.checkpoints) {\n        for (const checkpoint of importData.checkpoints) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.checkpoints, checkpoint.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.checkpoints, checkpoint.id, checkpoint);\n        }\n      }\n      if (importData.sentinels) {\n        for (const sentinel of importData.sentinels) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.sentinels, sentinel.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.sentinels, sentinel.id, sentinel);\n        }\n      }\n      if (importData.sketches) {\n        for (const sketch of importData.sketches) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.sketches, sketch.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.sketches, sketch.id, sketch);\n        }\n      }\n      if (importData.crystals) {\n        for (const crystal of importData.crystals) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.crystals, crystal.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.crystals, crystal.id, crystal);\n        }\n      }\n      if (importData.facets) {\n        for (const facet of importData.facets) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.facets, facet.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.facets, facet.id, facet);\n        }\n      }\n      if (importData.lessons) {\n        for (const lesson of importData.lessons) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.lessons, lesson.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.lessons, lesson.id, lesson);\n        }\n      }\n      if (importData.insights) {\n        for (const insight of importData.insights) {\n          if (strategy === \"skip\") {\n            const existing = await kv.get(KV.insights, insight.id).catch(() => null);\n            if (existing) { stats.skipped++; continue; }\n          }\n          await kv.set(KV.insights, insight.id, insight);\n        }\n      }\n      if (importData.accessLogs) {\n        if (!Array.isArray(importData.accessLogs)) {\n          return { success: false, error: \"accessLogs must be an array\" };\n        }\n        if (importData.accessLogs.length > MAX_ACCESS_LOGS) {\n          return {\n            success: false,\n            error: `Too many access logs (max ${MAX_ACCESS_LOGS})`,\n          };\n        }\n        const memoryIds = new Set<string>(\n          importData.memories.map((m) => m.id),\n        );\n        for (const raw of importData.accessLogs) {\n          const log = normalizeAccessLog(raw);\n          if (!log.memoryId || !memoryIds.has(log.memoryId)) continue;\n          if (strategy === \"skip\") {\n            const existing = await kv\n              .get(KV.accessLog, log.memoryId)\n              .catch(() => null);\n            if (existing) {\n              stats.skipped++;\n              continue;\n            }\n          }\n          await kv.set(KV.accessLog, log.memoryId, log);\n        }\n      }\n\n      logger.info(\"Import complete\", { strategy, ...stats });\n      await recordAudit(kv, \"import\", \"mem::import\", [], {\n        strategy,\n        stats,\n      });\n      return { success: true, strategy, ...stats };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { Memory } from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { logger } from \"../logger.js\";\n\nconst MAX_CONTEXT_LENGTH = 4000;\n\nfunction escapeXml(s: string): string {\n  return s\n    .replace(/&/g, \"&amp;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\")\n    .replace(/\"/g, \"&quot;\")\n    .replace(/'/g, \"&apos;\");\n}\n\nexport function registerEnrichFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::enrich\",\n    async (data: {\n      sessionId: string;\n      files: string[];\n      terms?: string[];\n      toolName?: string;\n      project?: string;\n    }) => {\n      const project =\n        typeof data.project === \"string\" && data.project.trim().length > 0\n          ? data.project.trim()\n          : undefined;\n\n      const parts: string[] = [];\n\n      const fileContextPromise = sdk\n        .trigger<{ sessionId: string; files: string[] }, { context: string }>({\n          function_id: \"mem::file-context\",\n          payload: {\n            sessionId: data.sessionId,\n            files: data.files,\n          },\n        })\n        .catch(() => ({ context: \"\" }));\n\n      const searchQueries: string[] = [\n        ...data.files.map((f) => f.split(\"/\").pop() || f),\n        ...(data.terms || []),\n      ].filter((q) => q.length > 0);\n\n      const searchPromise =\n        searchQueries.length > 0\n          ? sdk\n              .trigger<\n                { query: string; limit: number; project?: string },\n                { results: Array<{ observation: { narrative: string } }> }\n              >({\n                function_id: \"mem::search\",\n                payload: {\n                  query: searchQueries.join(\" \"),\n                  limit: 5,\n                  ...(project !== undefined && { project }),\n                },\n              })\n              .catch(() => ({ results: [] }))\n          : Promise.resolve({ results: [] });\n\n      const bugMemoriesPromise = kv\n        .list<Memory>(KV.memories)\n        .then((memories) =>\n          memories\n            .filter(\n              (m) =>\n                m.type === \"bug\" &&\n                m.isLatest &&\n                // Guard only when both sides have an explicit project; unscoped memories pass through.\n                (!project || !m.project || m.project === project) &&\n                m.files.some((f) =>\n                  data.files.some((df) => f.includes(df) || df.includes(f)),\n                ),\n            )\n            .sort(\n              (a, b) =>\n                new Date(b.updatedAt || b.createdAt).getTime() -\n                new Date(a.updatedAt || a.createdAt).getTime(),\n            ),\n        )\n        .catch(() => []);\n\n      const [fileContext, searchResult, bugMemories] = await Promise.all([\n        fileContextPromise,\n        searchPromise,\n        bugMemoriesPromise,\n      ]);\n\n      if (fileContext.context) {\n        parts.push(fileContext.context);\n      }\n\n      if (searchResult.results.length > 0) {\n        const observations = searchResult.results\n          .map((r) => r.observation?.narrative)\n          .filter(Boolean)\n          .map((n) => escapeXml(n as string))\n          .join(\"\\n\");\n        if (observations) {\n          parts.push(\n            `<agentmemory-relevant-context>\\n${observations}\\n</agentmemory-relevant-context>`,\n          );\n        }\n      }\n\n      if (bugMemories.length > 0) {\n        const bugs = bugMemories\n          .slice(0, 3)\n          .map((m) => `- ${escapeXml(m.title)}: ${escapeXml(m.content)}`)\n          .join(\"\\n\");\n        parts.push(\n          `<agentmemory-past-errors>\\n${bugs}\\n</agentmemory-past-errors>`,\n        );\n      }\n\n      let context = parts.join(\"\\n\\n\");\n      let truncated = false;\n      if (context.length > MAX_CONTEXT_LENGTH) {\n        context = context.slice(0, MAX_CONTEXT_LENGTH);\n        truncated = true;\n      }\n\n      logger.info(\"Enrichment completed\", {\n        sessionId: data.sessionId,\n        project,\n        fileCount: data.files.length,\n        contextLength: context.length,\n        truncated,\n      });\n\n      return { context, truncated };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { Memory, ClaudeBridgeConfig } from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { logger } from \"../logger.js\";\n\nfunction parseMemoryMd(content: string): {\n  sections: Map<string, string>;\n  raw: string;\n} {\n  const sections = new Map<string, string>();\n  let currentSection = \"\";\n  let currentContent: string[] = [];\n\n  for (const line of content.split(\"\\n\")) {\n    if (line.startsWith(\"## \")) {\n      if (currentSection) {\n        sections.set(currentSection, currentContent.join(\"\\n\").trim());\n      }\n      currentSection = line.slice(3).trim();\n      currentContent = [];\n    } else {\n      currentContent.push(line);\n    }\n  }\n  if (currentSection) {\n    sections.set(currentSection, currentContent.join(\"\\n\").trim());\n  }\n\n  return { sections, raw: content };\n}\n\nfunction serializeToMemoryMd(\n  memories: Memory[],\n  projectSummary: string,\n  lineBudget: number,\n): string {\n  const lines: string[] = [];\n  lines.push(\"# Agent Memory (auto-synced by agentmemory)\");\n  lines.push(\"\");\n\n  if (projectSummary) {\n    lines.push(\"## Project Summary\");\n    lines.push(projectSummary);\n    lines.push(\"\");\n  }\n\n  lines.push(\"## Key Memories\");\n  lines.push(\"\");\n\n  const sorted = [...memories]\n    .filter((m) => m.isLatest)\n    .sort((a, b) => b.strength - a.strength);\n\n  for (const mem of sorted) {\n    if (lines.length >= lineBudget - 2) break;\n    lines.push(`### ${mem.title}`);\n    const contentLines = mem.content.split(\"\\n\");\n    for (const cl of contentLines) {\n      if (lines.length >= lineBudget - 1) break;\n      lines.push(cl);\n    }\n    lines.push(\"\");\n  }\n\n  return lines.slice(0, lineBudget).join(\"\\n\");\n}\n\nexport function registerClaudeBridgeFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  config: ClaudeBridgeConfig,\n): void {\n  sdk.registerFunction(\"mem::claude-bridge-read\", \n    async () => {\n      if (!config.enabled || !config.memoryFilePath) {\n        return { success: false, error: \"Claude bridge not configured\" };\n      }\n\n      try {\n        if (!existsSync(config.memoryFilePath)) {\n          return { success: true, content: \"\", parsed: false };\n        }\n        const content = readFileSync(config.memoryFilePath, \"utf-8\");\n        const { sections } = parseMemoryMd(content);\n\n        await kv.set(KV.claudeBridge, \"last-read\", {\n          timestamp: new Date().toISOString(),\n          sections: Object.fromEntries(sections),\n          lineCount: content.split(\"\\n\").length,\n        });\n        await recordAudit(kv, \"export\", \"mem::claude-bridge-read\", [\"last-read\"], {\n          timestamp: new Date().toISOString(),\n          sections: Object.keys(Object.fromEntries(sections)),\n          lineCount: content.split(\"\\n\").length,\n        });\n\n        logger.info(\"Claude bridge: read MEMORY.md\", {\n          path: config.memoryFilePath,\n          lines: content.split(\"\\n\").length,\n        });\n        return { success: true, content, sections: Object.fromEntries(sections) };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.error(\"Claude bridge read failed\", { error: msg });\n        return { success: false, error: msg };\n      }\n    },\n  );\n\n  sdk.registerFunction(\"mem::claude-bridge-sync\", \n    async () => {\n      if (!config.enabled || !config.memoryFilePath) {\n        return { success: false, error: \"Claude bridge not configured\" };\n      }\n\n      try {\n        const memories = await kv.list<Memory>(KV.memories);\n        const latestMemories = memories.filter((m) => m.isLatest);\n\n        let projectSummary = \"\";\n        if (config.projectPath) {\n          const profile = await kv\n            .get<{ summary?: string }>(KV.profiles, config.projectPath)\n            .catch(() => null);\n          projectSummary = profile?.summary || \"\";\n        }\n\n        const md = serializeToMemoryMd(\n          latestMemories,\n          projectSummary,\n          config.lineBudget,\n        );\n\n        const dir = dirname(config.memoryFilePath);\n        if (!existsSync(dir)) {\n          mkdirSync(dir, { recursive: true });\n        }\n        writeFileSync(config.memoryFilePath, md, \"utf-8\");\n\n        await recordAudit(kv, \"export\", \"mem::claude-bridge-sync\", [], {\n          path: config.memoryFilePath,\n          memoryCount: latestMemories.length,\n          lines: md.split(\"\\n\").length,\n        });\n\n        logger.info(\"Claude bridge: synced to MEMORY.md\", {\n          path: config.memoryFilePath,\n          memories: latestMemories.length,\n        });\n        return { success: true, path: config.memoryFilePath, lines: md.split(\"\\n\").length };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.error(\"Claude bridge sync failed\", { error: msg });\n        return { success: false, error: msg };\n      }\n    },\n  );\n}\n","export const GRAPH_EXTRACTION_SYSTEM = `You are a knowledge graph extraction engine. Given a compressed observation from a coding session, extract entities and relationships.\n\nOutput format (XML):\n<entities>\n  <entity type=\"file|function|concept|error|decision|pattern|library|person\" name=\"exact name\">\n    <property key=\"key\">value</property>\n  </entity>\n</entities>\n<relationships>\n  <relationship type=\"uses|imports|modifies|causes|fixes|depends_on|related_to\" source=\"entity name\" target=\"entity name\" weight=\"0.1-1.0\"/>\n</relationships>\n\nRules:\n- Extract concrete entities only (real file paths, function names, library names)\n- Use the most specific type available\n- Weight relationships by how strong/direct the connection is\n- If no entities found, output empty tags`;\n\nexport function buildGraphExtractionPrompt(\n  observations: Array<{\n    title: string;\n    narrative: string;\n    concepts: string[];\n    files: string[];\n    type: string;\n  }>,\n): string {\n  const items = observations\n    .map(\n      (o, i) =>\n        `[${i + 1}] Type: ${o.type}\\nTitle: ${o.title}\\nNarrative: ${o.narrative}\\nConcepts: ${(o.concepts ?? []).join(\", \")}\\nFiles: ${(o.files ?? []).join(\", \")}`,\n    )\n    .join(\"\\n\\n\");\n  return `Extract entities and relationships from these observations:\\n\\n${items}`;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  GraphNode,\n  GraphEdge,\n  GraphQueryResult,\n  GraphSnapshot,\n  CompressedObservation,\n  MemoryProvider,\n} from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport {\n  GRAPH_EXTRACTION_SYSTEM,\n  buildGraphExtractionPrompt,\n} from \"../prompts/graph-extraction.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { logger } from \"../logger.js\";\n\n// #753: keep the response payload below the iii state channel ceiling.\n// 500 nodes + their incident edges hold well under the limit on the\n// reported 11k-node / 28k-edge corpus, and 5,000 is the upper bound a\n// caller can request explicitly. Tuned conservatively because edges\n// fan out faster than nodes.\nconst DEFAULT_GRAPH_QUERY_LIMIT = 500;\nconst MAX_GRAPH_QUERY_LIMIT = 5000;\n\n// #814: the precomputed snapshot covers the top-degree subgraph used by\n// the empty-body / nodeType-only branch — the path the viewer hits on\n// tab load. Sized to match the default query limit so the snapshot can\n// service a default-cap request without falling back to live\n// enumeration. Aggregate stats (nodesByType / edgesByType) are computed\n// fresh during rebuild and stored alongside.\nconst SNAPSHOT_TOP_NODES = DEFAULT_GRAPH_QUERY_LIMIT;\nconst SNAPSHOT_KEY = \"current\";\n\n// `state::list` over a 75K-node scope can exceed the iii invocation\n// timeout. The query handler races the enumeration against this budget\n// and falls back to the snapshot (or a warning envelope) when the live\n// path is too slow. 6000ms leaves headroom under the default 8s engine\n// invocation deadline.\nconst LIVE_ENUMERATION_BUDGET_MS = 6000;\n\nfunction withTimeout<T>(p: Promise<T>, ms: number, label: string): Promise<T> {\n  return new Promise<T>((resolve, reject) => {\n    const t = setTimeout(\n      () => reject(new Error(`${label}: exceeded ${ms}ms budget`)),\n      ms,\n    );\n    p.then(\n      (v) => {\n        clearTimeout(t);\n        resolve(v);\n      },\n      (err) => {\n        clearTimeout(t);\n        reject(err);\n      },\n    );\n  });\n}\n\nfunction emptySnapshot(): GraphSnapshot {\n  return {\n    version: 1,\n    topNodes: [],\n    topEdges: [],\n    topDegrees: {},\n    stats: {\n      totalNodes: 0,\n      totalEdges: 0,\n      nodesByType: {},\n      edgesByType: {},\n    },\n    updatedAt: new Date(0).toISOString(),\n    dirty: true,\n  };\n}\n\nasync function readSnapshot(kv: StateKV): Promise<GraphSnapshot | null> {\n  try {\n    const snap = await kv.get<GraphSnapshot>(KV.graphSnapshot, SNAPSHOT_KEY);\n    if (snap && typeof snap === \"object\" && snap.version === 1) {\n      return snap;\n    }\n    return null;\n  } catch (err) {\n    logger.warn(\"Graph snapshot read failed\", {\n      error: err instanceof Error ? err.message : String(err),\n    });\n    return null;\n  }\n}\n\nfunction buildSnapshotFromArrays(\n  nodes: GraphNode[],\n  edges: GraphEdge[],\n): GraphSnapshot {\n  const liveNodes = nodes.filter((n) => !n.stale);\n  const liveEdges = edges.filter((e) => !e.stale);\n  // Build the global degree map once so we can both rank by it AND\n  // snapshot the per-top-node values into topDegrees for synchronous\n  // re-sort after incremental edge writes.\n  const degree = new Map<string, number>();\n  for (const e of liveEdges) {\n    degree.set(e.sourceNodeId, (degree.get(e.sourceNodeId) ?? 0) + 1);\n    degree.set(e.targetNodeId, (degree.get(e.targetNodeId) ?? 0) + 1);\n  }\n  const ranked = [...liveNodes]\n    .sort((a, b) => (degree.get(b.id) ?? 0) - (degree.get(a.id) ?? 0))\n    .slice(0, SNAPSHOT_TOP_NODES);\n  const rankedIds = new Set(ranked.map((n) => n.id));\n  const topEdges = liveEdges.filter(\n    (e) => rankedIds.has(e.sourceNodeId) && rankedIds.has(e.targetNodeId),\n  );\n  const topDegrees: Record<string, number> = {};\n  for (const n of ranked) {\n    topDegrees[n.id] = degree.get(n.id) ?? 0;\n  }\n  const nodesByType: Record<string, number> = {};\n  for (const n of liveNodes) {\n    nodesByType[n.type] = (nodesByType[n.type] || 0) + 1;\n  }\n  const edgesByType: Record<string, number> = {};\n  for (const e of liveEdges) {\n    edgesByType[e.type] = (edgesByType[e.type] || 0) + 1;\n  }\n  return {\n    version: 1,\n    topNodes: ranked,\n    topEdges,\n    topDegrees,\n    stats: {\n      totalNodes: liveNodes.length,\n      totalEdges: liveEdges.length,\n      nodesByType,\n      edgesByType,\n    },\n    updatedAt: new Date().toISOString(),\n    dirty: false,\n  };\n}\n\nfunction paginateFromSnapshot(\n  snap: GraphSnapshot,\n  filterType: string | undefined,\n  limit: number,\n  offset: number,\n): GraphQueryResult {\n  const filteredNodes = filterType\n    ? snap.topNodes.filter((n) => n.type === filterType)\n    : snap.topNodes;\n  const total = filterType\n    ? snap.stats.nodesByType[filterType] ?? 0\n    : snap.stats.totalNodes;\n  const pageNodes = filteredNodes.slice(offset, offset + limit);\n  const pageIds = new Set(pageNodes.map((n) => n.id));\n  const pageEdges = snap.topEdges.filter(\n    (e) => pageIds.has(e.sourceNodeId) && pageIds.has(e.targetNodeId),\n  );\n  return {\n    nodes: pageNodes,\n    edges: pageEdges,\n    depth: 0,\n    totalNodes: total,\n    totalEdges: snap.stats.totalEdges,\n    truncated: total > pageNodes.length,\n    limit,\n    offset,\n    fromSnapshot: true,\n  };\n}\n\n// #814 v2: the rebuild path won't terminate on corpora large enough\n// that kv.list returns a payload too big to JSON.parse without\n// starving the iii heartbeat. We don't actually know the corpus size\n// without enumerating, but we can refuse to start a rebuild if the\n// snapshot's recorded `totalNodes` already exceeds this threshold —\n// the rebuild path is unreliable above it, and an incremental\n// extract-driven snapshot is the right approach for those corpora.\n// Operators above the threshold should use mem::graph-reset and let\n// future extracts rebuild incrementally.\nconst REBUILD_SAFE_NODE_CEILING = 25000;\n\nfunction nameIndexKey(type: string, name: string): string {\n  return `${type}|${name}`;\n}\n\nfunction edgeIndexKey(\n  sourceNodeId: string,\n  targetNodeId: string,\n  type: string,\n): string {\n  return `${sourceNodeId}|${targetNodeId}|${type}`;\n}\n\n// Mutates `snap` to apply a +1 (or -1) degree delta for nodeId,\n// maintaining the top-N ranking. Returns the new degree. Reads /\n// writes the per-node degree counter via targeted kv.get/set so we\n// never enumerate. Top-N membership flips when:\n//   - node's new degree > current min in topNodes AND it's not in\n//     topNodes (promote, evict tail if topNodes is full)\n//   - node IS in topNodes and its position needs resorting (re-sort\n//     topNodes in place)\nasync function applyDegreeDelta(\n  kv: StateKV,\n  snap: GraphSnapshot,\n  nodeId: string,\n  delta: number,\n): Promise<number> {\n  const prev = (await kv.get<number>(KV.graphNodeDegree, nodeId)) ?? 0;\n  const next = Math.max(0, prev + delta);\n  await kv.set(KV.graphNodeDegree, nodeId, next);\n\n  const inTop = snap.topNodes.findIndex((n) => n.id === nodeId);\n  if (inTop !== -1) {\n    // Cache the new degree in topDegrees so the comparator runs\n    // synchronously over numbers, not async kv.get calls. Re-sort\n    // descending by degree.\n    snap.topDegrees[nodeId] = next;\n    snap.topNodes.sort(\n      (a, b) =>\n        (snap.topDegrees[b.id] ?? 0) - (snap.topDegrees[a.id] ?? 0),\n    );\n    return next;\n  }\n\n  if (snap.topNodes.length < SNAPSHOT_TOP_NODES) {\n    // Capacity available — fetch + promote.\n    const node = await kv.get<GraphNode>(KV.graphNodes, nodeId);\n    if (node && !node.stale) {\n      snap.topNodes.push(node);\n      snap.topDegrees[node.id] = next;\n      snap.topNodes.sort(\n        (a, b) =>\n          (snap.topDegrees[b.id] ?? 0) - (snap.topDegrees[a.id] ?? 0),\n      );\n    }\n    return next;\n  }\n\n  // topNodes is full; the cutoff is the tail's cached degree.\n  const tailEntry = snap.topNodes[snap.topNodes.length - 1];\n  if (!tailEntry) return next;\n  const tailDegree = snap.topDegrees[tailEntry.id] ?? 0;\n  if (next > tailDegree) {\n    const node = await kv.get<GraphNode>(KV.graphNodes, nodeId);\n    if (node && !node.stale) {\n      const evicted = snap.topNodes.pop();\n      if (evicted) delete snap.topDegrees[evicted.id];\n      snap.topNodes.push(node);\n      snap.topDegrees[node.id] = next;\n      snap.topNodes.sort(\n        (a, b) =>\n          (snap.topDegrees[b.id] ?? 0) - (snap.topDegrees[a.id] ?? 0),\n      );\n    }\n  }\n  return next;\n}\n\nfunction snapshotPushEdgeIfBothInTop(\n  snap: GraphSnapshot,\n  edge: GraphEdge,\n): void {\n  const topIds = new Set(snap.topNodes.map((n) => n.id));\n  if (topIds.has(edge.sourceNodeId) && topIds.has(edge.targetNodeId)) {\n    // Dedupe in case the same edge gets pushed twice.\n    if (!snap.topEdges.find((e) => e.id === edge.id)) {\n      snap.topEdges.push(edge);\n    }\n  }\n}\n\nfunction mergeNode(\n  existing: GraphNode,\n  incoming: GraphNode,\n  obsIds: string[],\n  capturedAt: string,\n): GraphNode {\n  return {\n    ...existing,\n    sourceObservationIds: [\n      ...new Set([\n        ...existing.sourceObservationIds,\n        ...incoming.sourceObservationIds,\n        ...obsIds,\n      ]),\n    ],\n    properties: { ...existing.properties, ...incoming.properties },\n    updatedAt: capturedAt,\n  };\n}\n\nfunction mergeEdge(\n  existing: GraphEdge,\n  obsIds: string[],\n): GraphEdge {\n  return {\n    ...existing,\n    sourceObservationIds: [\n      ...new Set([...existing.sourceObservationIds, ...obsIds]),\n    ],\n  };\n}\n\nfunction resolvePagination(\n  rawLimit: number | undefined,\n  rawOffset: number | undefined,\n): { limit: number; offset: number } {\n  const requested = typeof rawLimit === \"number\" && Number.isFinite(rawLimit)\n    ? Math.floor(rawLimit)\n    : DEFAULT_GRAPH_QUERY_LIMIT;\n  const limit = Math.max(1, Math.min(requested, MAX_GRAPH_QUERY_LIMIT));\n  const offset = Math.max(\n    0,\n    typeof rawOffset === \"number\" && Number.isFinite(rawOffset)\n      ? Math.floor(rawOffset)\n      : 0,\n  );\n  return { limit, offset };\n}\n\nfunction paginate(\n  nodes: GraphNode[],\n  allEdges: GraphEdge[],\n  depth: number,\n  limit: number,\n  offset: number,\n): GraphQueryResult {\n  const totalNodes = nodes.length;\n  const pageNodes = nodes.slice(offset, offset + limit);\n  const pageNodeIds = new Set(pageNodes.map((n) => n.id));\n  // Edges restricted to the page so the response payload scales with\n  // `limit`, not with the global edge count. An edge is included only\n  // when BOTH endpoints land in the page — half-edges to nodes outside\n  // the page would render as dangling links in the viewer.\n  const pageEdges = allEdges.filter(\n    (e) => pageNodeIds.has(e.sourceNodeId) && pageNodeIds.has(e.targetNodeId),\n  );\n  // Total edges (for the same node universe). Counted unbounded so the\n  // viewer can show \"showing X of Y\" without re-querying.\n  const universeIds = new Set(nodes.map((n) => n.id));\n  const totalEdges = allEdges.reduce(\n    (count, e) =>\n      universeIds.has(e.sourceNodeId) && universeIds.has(e.targetNodeId)\n        ? count + 1\n        : count,\n    0,\n  );\n  return {\n    nodes: pageNodes,\n    edges: pageEdges,\n    depth,\n    totalNodes,\n    totalEdges,\n    truncated: totalNodes > pageNodes.length,\n    limit,\n    offset,\n  };\n}\n\n// Parse all key=\"value\" pairs from a tag's attribute string, in any\n// order. The previous parser hard-coded attribute order\n// (type before name on <entity>, type/source/target/weight on\n// <relationship>) and silently dropped nodes/edges when the upstream\n// LLM emitted attributes in a different order — Codex in particular\n// likes to lead with `name=` (#635).\nfunction parseAttrs(raw: string): Record<string, string> {\n  const attrs: Record<string, string> = {};\n  const attrRegex = /([A-Za-z_][\\w:-]*)=\"([^\"]*)\"/g;\n  let m;\n  while ((m = attrRegex.exec(raw)) !== null) {\n    attrs[m[1]] = m[2];\n  }\n  return attrs;\n}\n\nfunction parseGraphXml(\n  xml: string,\n  observationIds: string[],\n): {\n  nodes: GraphNode[];\n  edges: GraphEdge[];\n} {\n  const nodes: GraphNode[] = [];\n  const edges: GraphEdge[] = [];\n  const now = new Date().toISOString();\n\n  // Two passes because <entity> can be self-closing or have a body\n  // (<property> children). The self-closing form needs `[^>]*[^/]` on\n  // the attr group so the trailing `/` isn't swallowed into the match\n  // (root cause of #494). The explicit-close form picks up the\n  // property block.\n  const entitySelfClose = /<entity\\b([^>]*?)\\/>/g;\n  const entityWithBody = /<entity\\b([^>]*[^/])>([\\s\\S]*?)<\\/entity>/g;\n\n  const addEntity = (rawAttrs: string, propsBlock = \"\"): void => {\n    const attrs = parseAttrs(rawAttrs);\n    const type = attrs[\"type\"] as GraphNode[\"type\"] | undefined;\n    const name = attrs[\"name\"];\n    if (!type || !name) return;\n    const properties: Record<string, string> = {};\n    const propRegex = /<property\\s+key=\"([^\"]+)\">([^<]*)<\\/property>/g;\n    let propMatch;\n    while ((propMatch = propRegex.exec(propsBlock)) !== null) {\n      properties[propMatch[1]] = propMatch[2];\n    }\n    nodes.push({\n      id: generateId(\"gn\"),\n      type,\n      name,\n      properties,\n      sourceObservationIds: observationIds,\n      createdAt: now,\n    });\n  };\n\n  let match;\n  while ((match = entitySelfClose.exec(xml)) !== null) {\n    addEntity(match[1]);\n  }\n  while ((match = entityWithBody.exec(xml)) !== null) {\n    addEntity(match[1], match[2]);\n  }\n\n  const relRegex = /<relationship\\b([^>]*?)\\/>/g;\n  while ((match = relRegex.exec(xml)) !== null) {\n    const attrs = parseAttrs(match[1]);\n    const type = attrs[\"type\"] as GraphEdge[\"type\"] | undefined;\n    const sourceName = attrs[\"source\"];\n    const targetName = attrs[\"target\"];\n    if (!type || !sourceName || !targetName) continue;\n    const parsedWeight = parseFloat(attrs[\"weight\"] ?? \"\");\n    const weight = Number.isFinite(parsedWeight) ? parsedWeight : 0.5;\n\n    const sourceNode = nodes.find((n) => n.name === sourceName);\n    const targetNode = nodes.find((n) => n.name === targetName);\n    if (!sourceNode || !targetNode) continue;\n    edges.push({\n      id: generateId(\"ge\"),\n      type,\n      sourceNodeId: sourceNode.id,\n      targetNodeId: targetNode.id,\n      weight: Math.max(0, Math.min(1, weight)),\n      sourceObservationIds: observationIds,\n      createdAt: now,\n    });\n  }\n\n  return { nodes, edges };\n}\n\nexport function registerGraphFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\"mem::graph-extract\", \n    async (data: { observations: CompressedObservation[] }) => {\n      if (!data.observations || data.observations.length === 0) {\n        return { success: false, error: \"No observations provided\" };\n      }\n\n      const prompt = buildGraphExtractionPrompt(\n        data.observations.map((o) => ({\n          title: o.title,\n          narrative: o.narrative,\n          concepts: o.concepts,\n          files: o.files,\n          type: o.type,\n        })),\n      );\n\n      try {\n        const response = await provider.compress(\n          GRAPH_EXTRACTION_SYSTEM,\n          prompt,\n        );\n\n        const obsIds = data.observations.map((o) => o.id);\n        const { nodes, edges } = parseGraphXml(response, obsIds);\n\n        // #814 v2: targeted name-index lookups replace the O(n) scan\n        // over `kv.list<GraphNode>(KV.graphNodes)`. At 75K nodes the\n        // list payload exceeds the iii heartbeat budget and the worker\n        // dies before merge can complete. Each name-index entry is a\n        // single small kv.get/set pair.\n        const snap = (await readSnapshot(kv)) ?? emptySnapshot();\n        const capturedAt = new Date().toISOString();\n        let newNodeCount = 0;\n        let newEdgeCount = 0;\n        const newEdgesForTopCheck: GraphEdge[] = [];\n\n        for (const node of nodes) {\n          const indexKey = nameIndexKey(node.type, node.name);\n          const existingId = await kv.get<string>(\n            KV.graphNameIndex,\n            indexKey,\n          );\n\n          let existing: GraphNode | null = null;\n          if (existingId) {\n            existing = await kv.get<GraphNode>(KV.graphNodes, existingId);\n            // #825 follow-up: name-index lookups can resolve into\n            // pre-reset rows. Drop them so extract writes a fresh\n            // node + index entry instead of silently reconnecting\n            // to a legacy orphan (which would keep the snapshot at\n            // 0 forever after a reset).\n            if (\n              existing &&\n              snap.resetAt &&\n              typeof existing.createdAt === \"string\" &&\n              existing.createdAt < snap.resetAt\n            ) {\n              existing = null;\n            }\n          }\n\n          if (existing) {\n            const merged = mergeNode(existing, node, obsIds, capturedAt);\n            await kv.set(KV.graphNodes, existing.id, merged);\n            // Update topNodes entry if present so a stale clone isn't\n            // returned from the snapshot fast path.\n            const topIdx = snap.topNodes.findIndex(\n              (n) => n.id === existing!.id,\n            );\n            if (topIdx !== -1) snap.topNodes[topIdx] = merged;\n          } else {\n            await kv.set(KV.graphNodes, node.id, node);\n            await kv.set(KV.graphNameIndex, indexKey, node.id);\n            await kv.set(KV.graphNodeDegree, node.id, 0);\n            snap.stats.totalNodes += 1;\n            snap.stats.nodesByType[node.type] =\n              (snap.stats.nodesByType[node.type] ?? 0) + 1;\n            newNodeCount += 1;\n            if (snap.topNodes.length < SNAPSHOT_TOP_NODES) {\n              // Degree 0 still beats an empty slot — sit at the tail\n              // until edges arrive and promote.\n              snap.topNodes.push(node);\n              snap.topDegrees[node.id] = 0;\n            }\n          }\n        }\n\n        for (const edge of edges) {\n          const eKey = edgeIndexKey(\n            edge.sourceNodeId,\n            edge.targetNodeId,\n            edge.type,\n          );\n          const existingId = await kv.get<string>(KV.graphEdgeKey, eKey);\n\n          let existing: GraphEdge | null = null;\n          if (existingId) {\n            existing = await kv.get<GraphEdge>(KV.graphEdges, existingId);\n            // Same #825 orphan check as the node path above.\n            if (\n              existing &&\n              snap.resetAt &&\n              typeof existing.createdAt === \"string\" &&\n              existing.createdAt < snap.resetAt\n            ) {\n              existing = null;\n            }\n          }\n\n          if (existing) {\n            const merged = mergeEdge(existing, obsIds);\n            await kv.set(KV.graphEdges, existing.id, merged);\n            // Replace cached topEdges entry too if present.\n            const topIdx = snap.topEdges.findIndex(\n              (e) => e.id === existing!.id,\n            );\n            if (topIdx !== -1) snap.topEdges[topIdx] = merged;\n          } else {\n            await kv.set(KV.graphEdges, edge.id, edge);\n            await kv.set(KV.graphEdgeKey, eKey, edge.id);\n            snap.stats.totalEdges += 1;\n            snap.stats.edgesByType[edge.type] =\n              (snap.stats.edgesByType[edge.type] ?? 0) + 1;\n            newEdgeCount += 1;\n            await applyDegreeDelta(kv, snap, edge.sourceNodeId, +1);\n            await applyDegreeDelta(kv, snap, edge.targetNodeId, +1);\n            newEdgesForTopCheck.push(edge);\n          }\n        }\n\n        // Push newly-added edges into snapshot.topEdges if both\n        // endpoints are in the top-N (post-degree-delta). Done after\n        // all degree updates so the topIds set is stable.\n        for (const edge of newEdgesForTopCheck) {\n          snapshotPushEdgeIfBothInTop(snap, edge);\n        }\n\n        if (newNodeCount > 0 || newEdgeCount > 0) {\n          snap.updatedAt = capturedAt;\n          snap.dirty = false;\n          await kv.set(KV.graphSnapshot, SNAPSHOT_KEY, snap);\n        }\n\n        await recordAudit(kv, \"observe\", \"mem::graph-extract\", obsIds, {\n          nodesExtracted: nodes.length,\n          edgesExtracted: edges.length,\n        });\n\n        logger.info(\"Graph extraction complete\", {\n          nodes: nodes.length,\n          edges: edges.length,\n          newNodes: newNodeCount,\n          newEdges: newEdgeCount,\n        });\n        return {\n          success: true,\n          nodesAdded: nodes.length,\n          edgesAdded: edges.length,\n        };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.error(\"Graph extraction failed\", { error: msg });\n        return { success: false, error: msg };\n      }\n    },\n  );\n\n  // #753: every branch now applies a default cap and reports the\n  // unbounded `total*` counts. Before this change, an unfiltered POST\n  // /graph/query body (`{}`) on a corpus with ~10k+ nodes serialized\n  // to a payload large enough that the iii state response channel\n  // rejected it with HTTP 500 \"Invocation stopped\", leaving the viewer\n  // graph tab silently blank.\n  sdk.registerFunction(\"mem::graph-query\",\n    async (data: {\n      startNodeId?: string;\n      nodeType?: string;\n      maxDepth?: number;\n      query?: string;\n      limit?: number;\n      offset?: number;\n    }): Promise<GraphQueryResult> => {\n      const maxDepth = Math.min(data.maxDepth || 3, 5);\n      const { limit, offset } = resolvePagination(data.limit, data.offset);\n\n      // #814 v2: the empty-body / nodeType-only path NEVER enumerates.\n      // It reads the snapshot exclusively. The snapshot is updated\n      // inline by graph-extract, so for newly-built corpora it's\n      // always current. For legacy corpora missing a snapshot the\n      // operator must run mem::graph-snapshot-rebuild (safe under\n      // REBUILD_SAFE_NODE_CEILING) or mem::graph-reset to wipe and\n      // rebuild incrementally from new observations.\n      const noWalk = !data.query && !data.startNodeId;\n      if (noWalk) {\n        const snap = await readSnapshot(kv);\n        if (snap && snap.stats.totalNodes > 0) {\n          return paginateFromSnapshot(snap, data.nodeType, limit, offset);\n        }\n        return {\n          nodes: [],\n          edges: [],\n          depth: 0,\n          totalNodes: 0,\n          totalEdges: 0,\n          truncated: false,\n          limit,\n          offset,\n          warning:\n            \"No graph snapshot available. Either no graph has been \" +\n            \"extracted yet, or you are on a legacy corpus from a pre-#814 \" +\n            \"agentmemory build. Run POST /agentmemory/graph/snapshot-rebuild \" +\n            \"(safe up to ~25K nodes) or POST /agentmemory/graph/reset to \" +\n            \"wipe and let future extracts repopulate.\",\n        };\n      }\n\n      // Query / startNodeId paths still need broader access. Race the\n      // live enumeration against a wall-clock budget so a long\n      // kv.list doesn't block the worker indefinitely. On timeout the\n      // caller gets a snapshot-backed approximation instead of a 500.\n      let allNodes: GraphNode[];\n      let allEdges: GraphEdge[];\n      try {\n        const [rawNodes, rawEdges] = await withTimeout(\n          Promise.all([\n            kv.list<GraphNode>(KV.graphNodes),\n            kv.list<GraphEdge>(KV.graphEdges),\n          ]),\n          LIVE_ENUMERATION_BUDGET_MS,\n          \"graph-query enumeration\",\n        );\n        allNodes = rawNodes.filter((n) => !n.stale);\n        allEdges = rawEdges.filter((e) => !e.stale);\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.warn(\"Graph query enumeration timed out, using snapshot\", {\n          error: msg,\n        });\n        const snap = await readSnapshot(kv);\n        if (snap) {\n          return {\n            ...paginateFromSnapshot(snap, data.nodeType, limit, offset),\n            warning:\n              \"Live graph enumeration exceeded budget. Query / \" +\n              \"startNodeId paths degrade on >25K-node corpora until a \" +\n              \"per-node edge index lands. Result reflects top-degree \" +\n              \"snapshot, not the requested walk.\",\n          };\n        }\n        return {\n          nodes: [],\n          edges: [],\n          depth: 0,\n          totalNodes: 0,\n          totalEdges: 0,\n          truncated: false,\n          limit,\n          offset,\n          warning:\n            \"Graph enumeration exceeded budget and no snapshot is available.\",\n        };\n      }\n\n      if (data.query) {\n        const lower = data.query.toLowerCase();\n        const matchingNodes = allNodes.filter(\n          (n) =>\n            n.name.toLowerCase().includes(lower) ||\n            Object.values(n.properties).some(\n              (v) => typeof v === \"string\" && v.toLowerCase().includes(lower),\n            ),\n        );\n        return paginate(matchingNodes, allEdges, 0, limit, offset);\n      }\n\n      if (data.startNodeId) {\n        const visited = new Set<string>();\n        const visitedEdges = new Set<string>();\n        const resultNodes: GraphNode[] = [];\n        const resultEdges: GraphEdge[] = [];\n        const queue: Array<{ nodeId: string; depth: number }> = [\n          { nodeId: data.startNodeId, depth: 0 },\n        ];\n\n        while (queue.length > 0) {\n          const { nodeId, depth } = queue.shift()!;\n          if (visited.has(nodeId) || depth > maxDepth) continue;\n          visited.add(nodeId);\n\n          const node = allNodes.find((n) => n.id === nodeId);\n          if (node) {\n            if (!data.nodeType || node.type === data.nodeType) {\n              resultNodes.push(node);\n            }\n          }\n\n          const neighborEdges = allEdges.filter(\n            (e) => e.sourceNodeId === nodeId || e.targetNodeId === nodeId,\n          );\n          for (const edge of neighborEdges) {\n            if (!visitedEdges.has(edge.id)) {\n              visitedEdges.add(edge.id);\n              resultEdges.push(edge);\n            }\n            const nextId =\n              edge.sourceNodeId === nodeId\n                ? edge.targetNodeId\n                : edge.sourceNodeId;\n            if (!visited.has(nextId)) {\n              queue.push({ nodeId: nextId, depth: depth + 1 });\n            }\n          }\n        }\n\n        return paginate(resultNodes, resultEdges, maxDepth, limit, offset);\n      }\n\n      // Unreachable — noWalk branch handles the rest.\n      return paginate([], [], 0, limit, offset);\n    },\n  );\n\n  // #814 v2: graph-stats reads the snapshot exclusively. The snapshot\n  // is maintained inline by mem::graph-extract, so for any corpus built\n  // on a post-#814 agentmemory the stats are always current without an\n  // enumeration. Legacy corpora without a snapshot get an empty\n  // envelope + a warning pointing at the snapshot-rebuild or graph-reset\n  // endpoints — never a 500.\n  sdk.registerFunction(\"mem::graph-stats\", async () => {\n    const snap = await readSnapshot(kv);\n    if (snap) {\n      return {\n        ...snap.stats,\n        fromSnapshot: true,\n        updatedAt: snap.updatedAt,\n        ...(snap.dirty\n          ? {\n              warning:\n                \"Snapshot is marked dirty (write was in-flight when read). \" +\n                \"Counts are eventually consistent.\",\n            }\n          : {}),\n      };\n    }\n    return {\n      totalNodes: 0,\n      totalEdges: 0,\n      nodesByType: {},\n      edgesByType: {},\n      fromSnapshot: false,\n      warning:\n        \"No graph snapshot available. Run POST /agentmemory/graph/snapshot-rebuild \" +\n        \"(safe up to ~25K nodes) or POST /agentmemory/graph/reset to wipe \" +\n        \"and let future extracts repopulate.\",\n    };\n  });\n\n  // #814 v2: explicit rebuild backfills the snapshot AND the name /\n  // edge-key / degree indexes from existing graphNodes/graphEdges\n  // scopes. This is the path operators run once after upgrading to a\n  // post-#814 build to bring legacy corpora online. It enumerates via\n  // kv.list — the same pair that breaks at 75K+ — so we refuse to\n  // run on corpora large enough that the response payload would\n  // block the worker heartbeat. Above the ceiling the only safe path\n  // is mem::graph-reset followed by incremental re-extraction.\n  sdk.registerFunction(\n    \"mem::graph-snapshot-rebuild\",\n    async (data?: { force?: boolean }) => {\n      const started = Date.now();\n      // #825: pre-flight refusal for legacy corpora. The old guard\n      // checked node count AFTER kv.list, but the heartbeat dies at\n      // ~0.35s on a 75K-node response — long before the wall-clock\n      // budget can fire. We can't safely enumerate to discover size.\n      //\n      // Heuristic: if no snapshot exists, the corpus is either empty\n      // or legacy. The empty case has nothing to rebuild; the legacy\n      // case will crash. Refuse both unless `force: true` is passed\n      // (operator opt-in to attempt rebuild on a corpus they know is\n      // small enough — typically under 10K nodes on the default iii\n      // state adapter).\n      // Strict boolean check on force — accept only literal `true`,\n      // never truthy strings/numbers, so a hand-crafted JSON payload\n      // can't accidentally bypass the legacy-corpus safeguard.\n      const forceRebuild = data?.force === true;\n      try {\n        const existing = await readSnapshot(kv);\n        if (!existing && !forceRebuild) {\n          logger.warn(\"Graph snapshot rebuild refused: no prior snapshot\", {\n            hint: \"legacy corpus or empty store\",\n          });\n          return {\n            success: false,\n            legacyCorpus: true,\n            error:\n              \"No prior snapshot found. Rebuild would call kv.list on \" +\n              \"KV.graphNodes/Edges, which heartbeat-crashes the worker \" +\n              \"on corpora past the iii state response budget (~25K nodes). \" +\n              \"Either (a) call POST /agentmemory/graph/reset to drop into \" +\n              \"incremental-only mode and rebuild from new extracts, or \" +\n              \"(b) re-send with `force: true` if you're certain the \" +\n              \"corpus is small.\",\n          };\n        }\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.warn(\"Graph snapshot pre-flight read failed\", { error: msg });\n        // Fall through; the user passed force=true or the snapshot\n        // read itself failed (separate problem).\n      }\n\n      try {\n        const [nodes, edges] = await withTimeout(\n          Promise.all([\n            kv.list<GraphNode>(KV.graphNodes),\n            kv.list<GraphEdge>(KV.graphEdges),\n          ]),\n          LIVE_ENUMERATION_BUDGET_MS,\n          \"graph-snapshot-rebuild enumeration\",\n        );\n\n      if (nodes.length > REBUILD_SAFE_NODE_CEILING) {\n        logger.warn(\"Graph snapshot rebuild aborted: corpus too large\", {\n          totalNodes: nodes.length,\n          ceiling: REBUILD_SAFE_NODE_CEILING,\n        });\n        return {\n          success: false,\n          tooLarge: true,\n          totalNodes: nodes.length,\n          ceiling: REBUILD_SAFE_NODE_CEILING,\n          error:\n            `Corpus has ${nodes.length} graph nodes; safe-rebuild ceiling ` +\n            `is ${REBUILD_SAFE_NODE_CEILING}. Run POST /agentmemory/graph/reset ` +\n            `to wipe and let future extracts rebuild incrementally.`,\n        };\n      }\n\n      // Backfill the targeted-lookup indexes so post-rebuild\n      // graph-extract calls hit the O(1) path instead of falling\n      // through to the (already-removed) full-scope scan. Batch\n      // writes via Promise.all to avoid N sequential round-trips —\n      // BATCH_SIZE bounds in-flight writes so we don't open thousands\n      // of concurrent state channels on huge corpora.\n      const liveNodes = nodes.filter((n) => !n.stale);\n      const liveEdges = edges.filter((e) => !e.stale);\n      const degree = new Map<string, number>();\n      for (const e of liveEdges) {\n        degree.set(e.sourceNodeId, (degree.get(e.sourceNodeId) ?? 0) + 1);\n        degree.set(e.targetNodeId, (degree.get(e.targetNodeId) ?? 0) + 1);\n      }\n      const BATCH_SIZE = 100;\n      for (let i = 0; i < liveNodes.length; i += BATCH_SIZE) {\n        const batch = liveNodes.slice(i, i + BATCH_SIZE);\n        await Promise.all(\n          batch.flatMap((n) => [\n            kv.set(KV.graphNameIndex, nameIndexKey(n.type, n.name), n.id),\n            kv.set(KV.graphNodeDegree, n.id, degree.get(n.id) ?? 0),\n          ]),\n        );\n      }\n      for (let i = 0; i < liveEdges.length; i += BATCH_SIZE) {\n        const batch = liveEdges.slice(i, i + BATCH_SIZE);\n        await Promise.all(\n          batch.map((e) =>\n            kv.set(\n              KV.graphEdgeKey,\n              edgeIndexKey(e.sourceNodeId, e.targetNodeId, e.type),\n              e.id,\n            ),\n          ),\n        );\n      }\n\n      const snap = buildSnapshotFromArrays(nodes, edges);\n      await kv.set(KV.graphSnapshot, SNAPSHOT_KEY, snap);\n      const tookMs = Date.now() - started;\n      logger.info(\"Graph snapshot rebuilt\", {\n        totalNodes: snap.stats.totalNodes,\n        totalEdges: snap.stats.totalEdges,\n        topNodes: snap.topNodes.length,\n        topEdges: snap.topEdges.length,\n        tookMs,\n      });\n      return {\n        success: true,\n        ...snap.stats,\n        topNodes: snap.topNodes.length,\n        topEdges: snap.topEdges.length,\n        updatedAt: snap.updatedAt,\n        tookMs,\n      };\n    } catch (err) {\n      const msg = err instanceof Error ? err.message : String(err);\n      logger.error(\"Graph snapshot rebuild failed\", { error: msg });\n      return { success: false, error: msg };\n    }\n  });\n\n  // #814 v2 + #825: clean-restart escape hatch for corpora of any\n  // size, including the legacy 75K+ case that crashes kv.list.\n  //\n  // Previous reset walked kv.list<GraphNode/Edge>(...) which is the\n  // exact primitive that heartbeat-crashes the worker on the corpus\n  // this reset was meant to recover (Allan's repro, 0.35s death).\n  //\n  // The new design is enumeration-free: write an empty snapshot and\n  // return. The hot path (mem::graph-query empty-body, mem::graph-stats)\n  // reads ONLY the snapshot post-#816, so a fresh empty snapshot\n  // makes the graph behave as if it were empty for every read.\n  //\n  // Future extracts repopulate the snapshot + side-indexes\n  // incrementally (graph-extract is O(1) per node post-#816 — it does\n  // not consult the legacy rows).\n  //\n  // Trade-off: legacy rows in KV.graphNodes / KV.graphEdges remain on\n  // disk as unreferenced orphans. They consume disk but are never\n  // read by any post-#816 code path. Cleanup is deferred to a future\n  // chunked-vacuum job; #816's broken vacuum-via-list strategy is\n  // what we are leaving behind here.\n  sdk.registerFunction(\"mem::graph-reset\", async () => {\n    const started = Date.now();\n    // Stamp resetAt=now on the empty snapshot. Future\n    // mem::graph-extract calls compare each name-index lookup's\n    // existing node `createdAt` against this timestamp; anything\n    // older counts as an orphan and is dropped from the merge path,\n    // forcing extract to write a fresh row instead of reconnecting\n    // to a pre-reset entry.\n    const resetSnapshot: GraphSnapshot = {\n      ...emptySnapshot(),\n      resetAt: new Date().toISOString(),\n    };\n    await kv.set(KV.graphSnapshot, SNAPSHOT_KEY, resetSnapshot);\n    const counts: Record<string, number> = {\n      [KV.graphSnapshot]: 1,\n    };\n    const tookMs = Date.now() - started;\n    logger.info(\"Graph state reset\", { counts, tookMs });\n    return { success: true, cleared: counts, tookMs };\n  });\n}\n","export const SEMANTIC_MERGE_SYSTEM = `You are a memory consolidation engine. Given overlapping episodic memories (session summaries), extract stable factual knowledge.\n\nOutput format (XML):\n<facts>\n  <fact confidence=\"0.0-1.0\">Concise factual statement</fact>\n</facts>\n\nRules:\n- Extract only facts that appear in 2+ episodes or are highly confident\n- Confidence reflects how well-supported the fact is across episodes\n- Combine overlapping information into single concise facts\n- Skip ephemeral details (specific error messages, temporary states)`;\n\nexport function buildSemanticMergePrompt(\n  episodes: Array<{ title: string; narrative: string; concepts: string[] }>,\n): string {\n  const items = episodes\n    .map(\n      (e, i) =>\n        `[Episode ${i + 1}]\\nTitle: ${e.title}\\nNarrative: ${e.narrative}\\nConcepts: ${e.concepts.join(\", \")}`,\n    )\n    .join(\"\\n\\n\");\n  return `Consolidate these episodic memories into stable facts:\\n\\n${items}`;\n}\n\nexport const PROCEDURAL_EXTRACTION_SYSTEM = `You are a procedural memory extractor. Given repeated patterns and workflows observed across sessions, extract reusable procedures.\n\nOutput format (XML):\n<procedures>\n  <procedure name=\"short descriptive name\" trigger=\"when to use this procedure\">\n    <step>Step 1 description</step>\n    <step>Step 2 description</step>\n  </procedure>\n</procedures>\n\nRules:\n- Only extract procedures observed 2+ times\n- Steps should be concrete and actionable\n- Trigger condition should be specific enough to match automatically`;\n\nexport function buildProceduralExtractionPrompt(\n  patterns: Array<{ content: string; frequency: number }>,\n): string {\n  const items = patterns\n    .map((p, i) => `[Pattern ${i + 1}] (seen ${p.frequency}x)\\n${p.content}`)\n    .join(\"\\n\\n\");\n  return `Extract reusable procedures from these recurring patterns:\\n\\n${items}`;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  SemanticMemory,\n  ProceduralMemory,\n  SessionSummary,\n  Memory,\n  MemoryProvider,\n} from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport {\n  SEMANTIC_MERGE_SYSTEM,\n  buildSemanticMergePrompt,\n  PROCEDURAL_EXTRACTION_SYSTEM,\n  buildProceduralExtractionPrompt,\n} from \"../prompts/consolidation.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { getConsolidationDecayDays, isConsolidationEnabled } from \"../config.js\";\nimport { logger } from \"../logger.js\";\n\nfunction applyDecay(\n  items: Array<{\n    strength: number;\n    lastAccessedAt?: string;\n    updatedAt: string;\n  }>,\n  decayDays: number,\n): void {\n  if (decayDays <= 0 || !Number.isFinite(decayDays)) return;\n  const now = Date.now();\n  for (const item of items) {\n    const lastAccess = item.lastAccessedAt || item.updatedAt;\n    const daysSince =\n      (now - new Date(lastAccess).getTime()) / (1000 * 60 * 60 * 24);\n    if (daysSince > decayDays) {\n      const decayPeriods = Math.floor(daysSince / decayDays);\n      item.strength = Math.max(\n        0.1,\n        item.strength * Math.pow(0.9, decayPeriods),\n      );\n    }\n  }\n}\n\nexport function registerConsolidationPipelineFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\"mem::consolidate-pipeline\", \n    async (data?: { tier?: string; force?: boolean; project?: string }) => {\n      if (!data?.force && !isConsolidationEnabled()) {\n        return { success: false, skipped: true, reason: \"Consolidation disabled: set CONSOLIDATION_ENABLED=true or configure an LLM provider (ANTHROPIC_API_KEY / OPENAI_API_KEY / OPENROUTER_API_KEY / GEMINI_API_KEY / GOOGLE_API_KEY / MINIMAX_API_KEY / OPENAI_BASE_URL / AGENTMEMORY_PROVIDER=agent-sdk)\" };\n      }\n      const tier = data?.tier || \"all\";\n      const decayDays = getConsolidationDecayDays();\n      const results: Record<string, unknown> = {};\n\n      if (tier === \"all\" || tier === \"semantic\") {\n        const summaries = await kv.list<SessionSummary>(KV.summaries);\n        const existingSemantic = await kv.list<SemanticMemory>(KV.semantic);\n\n        if (summaries.length >= 5) {\n          const recentSummaries = summaries\n            .sort(\n              (a, b) =>\n                new Date(b.createdAt).getTime() -\n                new Date(a.createdAt).getTime(),\n            )\n            .slice(0, 20);\n\n          const prompt = buildSemanticMergePrompt(\n            recentSummaries.map((s) => ({\n              title: s.title,\n              narrative: s.narrative,\n              concepts: s.concepts,\n            })),\n          );\n\n          try {\n            const response = await provider.summarize(\n              SEMANTIC_MERGE_SYSTEM,\n              prompt,\n            );\n\n            const factRegex = /<fact\\s+confidence=\"([^\"]+)\">([^<]+)<\\/fact>/g;\n            let match;\n            let newFacts = 0;\n            const now = new Date().toISOString();\n\n            while ((match = factRegex.exec(response)) !== null) {\n              const parsedConf = parseFloat(match[1]);\n              const confidence = Number.isNaN(parsedConf) ? 0.5 : parsedConf;\n              const fact = match[2].trim();\n\n              const existing = existingSemantic.find(\n                (s) => s.fact.toLowerCase() === fact.toLowerCase(),\n              );\n              if (existing) {\n                existing.accessCount++;\n                existing.lastAccessedAt = now;\n                existing.updatedAt = now;\n                existing.confidence = Math.max(existing.confidence, confidence);\n                await kv.set(KV.semantic, existing.id, existing);\n              } else {\n                const sem: SemanticMemory = {\n                  id: generateId(\"sem\"),\n                  fact,\n                  confidence,\n                  sourceSessionIds: recentSummaries.map((s) => s.sessionId),\n                  sourceMemoryIds: [],\n                  accessCount: 1,\n                  lastAccessedAt: now,\n                  strength: confidence,\n                  createdAt: now,\n                  updatedAt: now,\n                };\n                await kv.set(KV.semantic, sem.id, sem);\n                newFacts++;\n              }\n            }\n            results.semantic = { newFacts, totalSummaries: summaries.length };\n          } catch (err) {\n            const msg = err instanceof Error ? err.message : String(err);\n            logger.error(\"Semantic consolidation failed\", { error: msg });\n            results.semantic = { error: msg };\n          }\n        } else {\n          results.semantic = {\n            skipped: true,\n            reason: \"fewer than 5 summaries\",\n          };\n        }\n      }\n\n      if (tier === \"all\" || tier === \"reflect\") {\n        try {\n          const reflectResult = await sdk.trigger({ function_id: \"mem::reflect\", payload: {\n            maxClusters: 10,\n            project: data?.project,\n          } });\n          results.reflect = reflectResult;\n        } catch (err) {\n          const msg = err instanceof Error ? err.message : String(err);\n          logger.warn(\"Reflect tier failed\", { error: msg });\n          results.reflect = { error: msg };\n        }\n      }\n\n      if (tier === \"all\" || tier === \"procedural\") {\n        const memories = await kv.list<Memory>(KV.memories);\n        const patterns = memories\n          .filter((m) => m.isLatest && m.type === \"pattern\")\n          .map((m) => ({\n            content: m.content,\n            frequency: m.sessionIds.length || 1,\n          }))\n          .filter((p) => p.frequency >= 2);\n\n        if (patterns.length >= 2) {\n          const prompt = buildProceduralExtractionPrompt(patterns);\n\n          try {\n            const response = await provider.summarize(\n              PROCEDURAL_EXTRACTION_SYSTEM,\n              prompt,\n            );\n\n            const procRegex =\n              /<procedure\\s+name=\"([^\"]+)\"\\s+trigger=\"([^\"]+)\">([\\s\\S]*?)<\\/procedure>/g;\n            let match;\n            let newProcs = 0;\n            const now = new Date().toISOString();\n            const existingProcs = await kv.list<ProceduralMemory>(\n              KV.procedural,\n            );\n\n            while ((match = procRegex.exec(response)) !== null) {\n              const name = match[1];\n              const trigger = match[2];\n              const stepsBlock = match[3];\n              const steps: string[] = [];\n\n              const stepRegex = /<step>([^<]+)<\\/step>/g;\n              let stepMatch;\n              while ((stepMatch = stepRegex.exec(stepsBlock)) !== null) {\n                steps.push(stepMatch[1].trim());\n              }\n\n              const existing = existingProcs.find(\n                (p) => p.name.toLowerCase() === name.toLowerCase(),\n              );\n              if (existing) {\n                existing.frequency++;\n                existing.updatedAt = now;\n                existing.strength = Math.min(1, existing.strength + 0.1);\n                await kv.set(KV.procedural, existing.id, existing);\n              } else {\n                const proc: ProceduralMemory = {\n                  id: generateId(\"proc\"),\n                  name,\n                  steps,\n                  triggerCondition: trigger,\n                  frequency: 1,\n                  sourceSessionIds: [],\n                  strength: 0.5,\n                  createdAt: now,\n                  updatedAt: now,\n                };\n                await kv.set(KV.procedural, proc.id, proc);\n                newProcs++;\n              }\n            }\n            results.procedural = {\n              newProcedures: newProcs,\n              patternsAnalyzed: patterns.length,\n            };\n          } catch (err) {\n            const msg = err instanceof Error ? err.message : String(err);\n            logger.error(\"Procedural extraction failed\", { error: msg });\n            results.procedural = { error: msg };\n          }\n        } else {\n          results.procedural = {\n            skipped: true,\n            reason: \"fewer than 2 recurring patterns\",\n          };\n        }\n      }\n\n      if (tier === \"all\" || tier === \"decay\") {\n        const semantic = await kv.list<SemanticMemory>(KV.semantic);\n        applyDecay(semantic, decayDays);\n        for (const s of semantic) {\n          await kv.set(KV.semantic, s.id, s);\n        }\n\n        const procedural = await kv.list<ProceduralMemory>(KV.procedural);\n        applyDecay(procedural, decayDays);\n        for (const p of procedural) {\n          await kv.set(KV.procedural, p.id, p);\n        }\n\n        results.decay = {\n          semantic: semantic.length,\n          procedural: procedural.length,\n        };\n      }\n\n      if (process.env[\"OBSIDIAN_AUTO_EXPORT\"] === \"true\") {\n        try {\n          await sdk.trigger({ function_id: \"mem::obsidian-export\", payload: {} });\n          results.obsidianExport = { success: true };\n        } catch (err) {\n          const msg = err instanceof Error ? err.message : String(err);\n          logger.warn(\"Obsidian auto-export failed\", { error: msg });\n          results.obsidianExport = { success: false, error: msg };\n        }\n      }\n\n      await recordAudit(kv, \"consolidate\", \"mem::consolidate-pipeline\", [], {\n        tier,\n        results,\n      });\n\n      logger.info(\"Consolidation pipeline complete\", { tier, results });\n      return { success: true, results };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  TeamConfig,\n  TeamSharedItem,\n  TeamProfile,\n  Memory,\n} from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { logger } from \"../logger.js\";\n\nconst VALID_ITEM_TYPES = new Set([\"memory\", \"pattern\", \"observation\"]);\n\nexport function registerTeamFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  config: TeamConfig,\n): void {\n  sdk.registerFunction(\"mem::team-share\", \n    async (data: {\n      itemId: string;\n      itemType: \"memory\" | \"pattern\" | \"observation\";\n      sessionId?: string;\n      project?: string;\n    }) => {\n      if (!data) {\n        return { success: false, error: \"payload required\" };\n      }\n      if (!data.itemId || !data.itemType) {\n        return { success: false, error: \"itemId and itemType are required\" };\n      }\n      if (!VALID_ITEM_TYPES.has(data.itemType)) {\n        return { success: false, error: `Invalid itemType: ${data.itemType}` };\n      }\n\n      let content: unknown;\n      if (data.itemType === \"observation\") {\n        if (!data.sessionId) {\n          return {\n            success: false,\n            error: \"sessionId is required for observations\",\n          };\n        }\n        content = await kv.get(KV.observations(data.sessionId), data.itemId);\n      } else {\n        content = await kv.get<Memory>(KV.memories, data.itemId);\n      }\n      if (!content) {\n        return { success: false, error: \"Item not found\" };\n      }\n\n      const shared: TeamSharedItem = {\n        id: generateId(\"ts\"),\n        sharedBy: config.userId,\n        sharedAt: new Date().toISOString(),\n        type: data.itemType,\n        content,\n        project: data.project || \"\",\n        visibility: \"shared\",\n      };\n\n      await kv.set(KV.teamShared(config.teamId), shared.id, shared);\n\n      await recordAudit(kv, \"share\", \"mem::team-share\", [data.itemId], {\n        teamId: config.teamId,\n        userId: config.userId,\n        itemType: data.itemType,\n      });\n\n      logger.info(\"Team share\", {\n        teamId: config.teamId,\n        itemId: data.itemId,\n      });\n      return { success: true, sharedItem: shared };\n    },\n  );\n\n  sdk.registerFunction(\"mem::team-feed\", \n    async (data?: { limit?: number }) => {\n      const limit = data?.limit ?? 20;\n      const items = await kv.list<TeamSharedItem>(KV.teamShared(config.teamId));\n\n      const filtered = items.filter((i) => i.visibility === \"shared\");\n      const sorted = filtered\n        .sort(\n          (a, b) =>\n            new Date(b.sharedAt).getTime() - new Date(a.sharedAt).getTime(),\n        )\n        .slice(0, limit);\n\n      return { items: sorted, total: filtered.length };\n    },\n  );\n\n  sdk.registerFunction(\"mem::team-profile\",  async () => {\n    const items = await kv.list<TeamSharedItem>(KV.teamShared(config.teamId));\n\n    const members = [...new Set(items.map((i) => i.sharedBy))];\n\n    const conceptCounts = new Map<string, number>();\n    const fileCounts = new Map<string, number>();\n    const patterns: string[] = [];\n\n    for (const item of items) {\n      if (item.type === \"memory\" || item.type === \"pattern\") {\n        const mem = item.content as Memory;\n        if (mem?.concepts) {\n          for (const c of mem.concepts) {\n            conceptCounts.set(c, (conceptCounts.get(c) || 0) + 1);\n          }\n        }\n        if (mem?.files) {\n          for (const f of mem.files) {\n            fileCounts.set(f, (fileCounts.get(f) || 0) + 1);\n          }\n        }\n        if (item.type === \"pattern\" && mem?.content) {\n          patterns.push(mem.content.slice(0, 100));\n        }\n      }\n    }\n\n    const topConcepts = [...conceptCounts.entries()]\n      .sort((a, b) => b[1] - a[1])\n      .slice(0, 10)\n      .map(([concept, frequency]) => ({ concept, frequency }));\n\n    const topFiles = [...fileCounts.entries()]\n      .sort((a, b) => b[1] - a[1])\n      .slice(0, 10)\n      .map(([file, frequency]) => ({ file, frequency }));\n\n    const profile: TeamProfile = {\n      teamId: config.teamId,\n      members,\n      topConcepts,\n      topFiles,\n      sharedPatterns: patterns.slice(0, 10),\n      totalSharedItems: items.length,\n      updatedAt: new Date().toISOString(),\n    };\n\n    await kv.set(KV.teamProfile(config.teamId), \"profile\", profile);\n    await recordAudit(\n      kv,\n      \"share\",\n      \"mem::team-profile\",\n      [\"profile\"],\n      {\n        teamId: config.teamId,\n        members: members.length,\n        totalSharedItems: items.length,\n      },\n      undefined,\n      config.userId,\n    );\n    return profile;\n  });\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { Memory, GovernanceFilter, AuditEntry } from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { recordAudit, safeAudit, queryAudit } from \"./audit.js\";\nimport { deleteAccessLog } from \"./access-tracker.js\";\nimport { getSearchIndex, vectorIndexRemove, flushIndexSave } from \"./search.js\";\nimport { logger } from \"../logger.js\";\n\nexport function registerGovernanceFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::governance-delete\", \n    async (data: { memoryIds: string[]; reason?: string }) => {\n      if (\n        !data.memoryIds ||\n        !Array.isArray(data.memoryIds) ||\n        data.memoryIds.length === 0\n      ) {\n        return { success: false, error: \"memoryIds array is required\" };\n      }\n\n      let deleted = 0;\n      for (const id of data.memoryIds) {\n        const mem = await kv.get<Memory>(KV.memories, id);\n        if (mem) {\n          await kv.delete(KV.memories, id);\n          await deleteAccessLog(kv, id);\n          getSearchIndex().remove(id);\n          vectorIndexRemove(id);\n          deleted++;\n        }\n      }\n\n      if (deleted > 0) await flushIndexSave();\n\n      await recordAudit(\n        kv,\n        \"delete\",\n        \"mem::governance-delete\",\n        data.memoryIds,\n        {\n          reason: data.reason || \"manual deletion\",\n          deleted,\n        },\n      );\n\n      logger.info(\"Governance delete\", {\n        requested: data.memoryIds.length,\n        deleted,\n      });\n      return { success: true, deleted, total: data.memoryIds.length };\n    },\n  );\n\n  sdk.registerFunction(\"mem::governance-bulk\", \n    async (data: GovernanceFilter & { dryRun?: boolean }) => {\n\n      const hasFilter =\n        (data.type && data.type.length > 0) ||\n        data.dateFrom ||\n        data.dateTo ||\n        data.qualityBelow !== undefined;\n      if (!hasFilter && !data.dryRun) {\n        return {\n          success: false,\n          error: \"At least one filter is required for non-dryRun bulk delete\",\n        };\n      }\n\n      const memories = await kv.list<Memory>(KV.memories);\n      let candidates = memories;\n\n      if (data.type && data.type.length > 0) {\n        candidates = candidates.filter((m) => data.type!.includes(m.type));\n      }\n      if (data.dateFrom) {\n        const from = new Date(data.dateFrom).getTime();\n        if (Number.isNaN(from)) {\n          return { success: false, error: \"Invalid dateFrom format\" };\n        }\n        candidates = candidates.filter(\n          (m) => new Date(m.createdAt).getTime() >= from,\n        );\n      }\n      if (data.dateTo) {\n        const to = new Date(data.dateTo).getTime();\n        if (Number.isNaN(to)) {\n          return { success: false, error: \"Invalid dateTo format\" };\n        }\n        candidates = candidates.filter(\n          (m) => new Date(m.createdAt).getTime() <= to,\n        );\n      }\n      if (data.qualityBelow !== undefined) {\n        candidates = candidates.filter((m) => m.strength < data.qualityBelow!);\n      }\n\n      if (data.dryRun) {\n        return {\n          success: true,\n          dryRun: true,\n          wouldDelete: candidates.length,\n          ids: candidates.map((m) => m.id),\n        };\n      }\n\n      const BATCH_SIZE = 50;\n      const successfulIds: string[] = [];\n      const failures: Array<{ id: string; error: string }> = [];\n      for (let i = 0; i < candidates.length; i += BATCH_SIZE) {\n        const batch = candidates.slice(i, i + BATCH_SIZE);\n        const results = await Promise.allSettled(\n          batch.map(async (mem) => {\n            await kv.delete(KV.memories, mem.id);\n            await deleteAccessLog(kv, mem.id);\n            getSearchIndex().remove(mem.id);\n            vectorIndexRemove(mem.id);\n          }),\n        );\n        results.forEach((result, j) => {\n          const mem = batch[j];\n          if (result.status === \"fulfilled\") {\n            successfulIds.push(mem.id);\n          } else {\n            logger.warn(\"Governance bulk delete failed\", {\n              memoryId: mem.id,\n              error:\n                result.reason instanceof Error\n                  ? result.reason.message\n                  : String(result.reason),\n            });\n            failures.push({\n              id: mem.id,\n              error: \"delete_failed\",\n            });\n          }\n        });\n      }\n\n      if (successfulIds.length > 0) await flushIndexSave();\n\n      await safeAudit(\n        kv,\n        \"delete\",\n        \"mem::governance-bulk\",\n        successfulIds,\n        {\n          filter: data,\n          deleted: successfulIds.length,\n          failed: failures.length,\n          failures: failures.length > 0 ? failures : undefined,\n        },\n      );\n\n      logger.info(\"Governance bulk delete\", {\n        deleted: successfulIds.length,\n        failed: failures.length,\n      });\n      return {\n        success: failures.length === 0,\n        deleted: successfulIds.length,\n        failed: failures.length,\n        failures: failures.length > 0 ? failures : undefined,\n      };\n    },\n  );\n\n  sdk.registerFunction(\"mem::audit-query\", \n    async (data?: {\n      operation?: AuditEntry[\"operation\"];\n      dateFrom?: string;\n      dateTo?: string;\n      limit?: number;\n    }) => {\n      return queryAudit(kv, data);\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { existsSync, mkdirSync, writeFileSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type {\n  SnapshotMeta,\n  Session,\n  Memory,\n  GraphNode,\n  AccessLogExport,\n} from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { VERSION } from \"../version.js\";\nimport { logger } from \"../logger.js\";\n\nconst COMMIT_HASH_RE = /^[0-9a-f]{7,40}$/i;\n\nconst execFileAsync = promisify(execFile);\n\nasync function gitExec(dir: string, args: string[]): Promise<string> {\n  const { stdout } = await execFileAsync(\"git\", args, { cwd: dir });\n  return stdout.trim();\n}\n\nasync function ensureGitRepo(dir: string): Promise<void> {\n  if (!existsSync(dir)) {\n    mkdirSync(dir, { recursive: true });\n  }\n  if (!existsSync(join(dir, \".git\"))) {\n    await gitExec(dir, [\"init\"]);\n    await gitExec(dir, [\"config\", \"user.email\", \"agentmemory@local\"]);\n    await gitExec(dir, [\"config\", \"user.name\", \"agentmemory\"]);\n  }\n}\n\nexport function registerSnapshotFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  snapshotDir: string,\n): void {\n  sdk.registerFunction(\"mem::snapshot-create\", \n    async (data?: { message?: string }) => {\n\n      try {\n        await ensureGitRepo(snapshotDir);\n        const ts = new Date().toISOString();\n\n        const sessions = await kv.list<Session>(KV.sessions);\n        const memories = await kv.list<Memory>(KV.memories);\n        const graphNodes = await kv.list<GraphNode>(KV.graphNodes);\n        const accessLogs = await kv\n          .list<AccessLogExport>(KV.accessLog)\n          .catch(() => [] as AccessLogExport[]);\n\n        const observations: Record<string, unknown[]> = {};\n        for (const session of sessions) {\n          const obs = await kv\n            .list(KV.observations(session.id))\n            .catch(() => []);\n          if (obs.length > 0) {\n            observations[session.id] = obs;\n          }\n        }\n\n        const state = {\n          version: VERSION,\n          timestamp: ts,\n          sessions,\n          memories,\n          graphNodes,\n          observations,\n          accessLogs,\n        };\n\n        writeFileSync(\n          join(snapshotDir, \"state.json\"),\n          JSON.stringify(state, null, 2),\n          \"utf-8\",\n        );\n\n        await gitExec(snapshotDir, [\"add\", \".\"]);\n\n        const message = data?.message || `Snapshot ${ts}`;\n        try {\n          await gitExec(snapshotDir, [\"commit\", \"-m\", message]);\n        } catch (commitErr) {\n          const errMsg =\n            commitErr instanceof Error ? commitErr.message : String(commitErr);\n          if (errMsg.includes(\"nothing to commit\")) {\n            return { success: true, message: \"No changes to snapshot\" };\n          }\n          throw commitErr;\n        }\n\n        const commitHash = await gitExec(snapshotDir, [\"rev-parse\", \"HEAD\"]);\n\n        const meta: SnapshotMeta = {\n          id: generateId(\"snap\"),\n          commitHash,\n          createdAt: ts,\n          message,\n          stats: {\n            sessions: sessions.length,\n            observations: Object.values(observations).reduce(\n              (sum, arr) => sum + arr.length,\n              0,\n            ),\n            memories: memories.length,\n            graphNodes: graphNodes.length,\n          },\n        };\n\n        await recordAudit(kv, \"export\", \"mem::snapshot-create\", [meta.id], {\n          commitHash,\n          stats: meta.stats,\n        });\n\n        logger.info(\"Snapshot created\", { commitHash });\n        return { success: true, snapshot: meta };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.error(\"Snapshot failed\", { error: msg });\n        return { success: false, error: msg };\n      }\n    },\n  );\n\n  sdk.registerFunction(\"mem::snapshot-list\",  async () => {\n    try {\n      if (!existsSync(join(snapshotDir, \".git\"))) {\n        return { snapshots: [] };\n      }\n      const log = await gitExec(snapshotDir, [\n        \"log\",\n        \"--format=%H|%aI|%s\",\n        \"-20\",\n      ]);\n      const snapshots = log\n        .split(\"\\n\")\n        .filter(Boolean)\n        .map((line) => {\n          const parts = line.split(\"|\");\n          const [hash, date] = parts;\n          const msg = parts.slice(2).join(\"|\");\n          return { commitHash: hash, createdAt: date, message: msg };\n        });\n      return { snapshots };\n    } catch {\n      return { snapshots: [] };\n    }\n  });\n\n  sdk.registerFunction(\"mem::snapshot-restore\", \n    async (data: { commitHash: string } | undefined) => {\n      if (!data || typeof data.commitHash !== \"string\" || !data.commitHash.trim()) {\n        return { success: false, error: \"commitHash is required\" };\n      }\n      if (!COMMIT_HASH_RE.test(data.commitHash)) {\n        return { success: false, error: \"Invalid commitHash format\" };\n      }\n\n      try {\n        await gitExec(snapshotDir, [\n          \"checkout\",\n          data.commitHash,\n          \"--\",\n          \"state.json\",\n        ]);\n        const content = readFileSync(join(snapshotDir, \"state.json\"), \"utf-8\");\n        const state = JSON.parse(content) as {\n          sessions?: Array<{ id: string } & Record<string, unknown>>;\n          memories?: Array<{ id: string } & Record<string, unknown>>;\n          graphNodes?: Array<{ id: string } & Record<string, unknown>>;\n          observations?: Record<\n            string,\n            Array<{ id: string } & Record<string, unknown>>\n          >;\n          accessLogs?: AccessLogExport[];\n        };\n\n        if (state.sessions) {\n          for (const session of state.sessions) {\n            await kv.set(KV.sessions, session.id, session);\n          }\n        }\n        if (state.memories) {\n          for (const memory of state.memories) {\n            await kv.set(KV.memories, memory.id, memory);\n          }\n        }\n        if (state.graphNodes) {\n          for (const node of state.graphNodes) {\n            await kv.set(KV.graphNodes, node.id, node);\n          }\n        }\n        if (state.observations) {\n          for (const [sessionId, obs] of Object.entries(state.observations)) {\n            for (const o of obs) {\n              await kv.set(KV.observations(sessionId), o.id, o);\n            }\n          }\n        }\n        if (state.accessLogs) {\n          for (const log of state.accessLogs) {\n            await kv.set(KV.accessLog, log.memoryId, log);\n          }\n        }\n\n        await gitExec(snapshotDir, [\"checkout\", \"HEAD\", \"--\", \"state.json\"]);\n\n        await recordAudit(kv, \"import\", \"mem::snapshot-restore\", [], {\n          commitHash: data.commitHash,\n          sessions: state.sessions?.length || 0,\n          memories: state.memories?.length || 0,\n          graphNodes: state.graphNodes?.length || 0,\n        });\n\n        logger.info(\"Snapshot restored\", {\n          commitHash: data.commitHash,\n        });\n        return { success: true, commitHash: data.commitHash };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.error(\"Snapshot restore failed\", { error: msg });\n        return { success: false, error: msg };\n      }\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport type { Action, ActionEdge } from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\n\nexport function registerActionsFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::action-create\", \n    async (data: {\n      title: string;\n      description?: string;\n      priority?: number;\n      createdBy?: string;\n      project?: string;\n      tags?: string[];\n      parentId?: string;\n      sourceObservationIds?: string[];\n      sourceMemoryIds?: string[];\n      edges?: Array<{ type: string; targetActionId: string }>;\n    }) => {\n      if (!data.title || typeof data.title !== \"string\") {\n        return { success: false, error: \"title is required\" };\n      }\n\n      return withKeyedLock(\"mem:actions\", async () => {\n        const now = new Date().toISOString();\n        const action: Action = {\n          id: generateId(\"act\"),\n          title: data.title.trim(),\n          description: (data.description || \"\").trim(),\n          status: \"pending\",\n          priority: Math.max(1, Math.min(10, data.priority || 5)),\n          createdAt: now,\n          updatedAt: now,\n          createdBy: data.createdBy || \"unknown\",\n          project: data.project,\n          tags: data.tags || [],\n          sourceObservationIds: data.sourceObservationIds || [],\n          sourceMemoryIds: data.sourceMemoryIds || [],\n          parentId: data.parentId,\n        };\n\n        if (data.parentId) {\n          const parent = await kv.get<Action>(KV.actions, data.parentId);\n          if (!parent) {\n            return { success: false, error: \"parent action not found\" };\n          }\n        }\n\n        const validEdgeTypes = [\n          \"requires\",\n          \"unlocks\",\n          \"spawned_by\",\n          \"gated_by\",\n          \"conflicts_with\",\n        ];\n        const pendingEdges: ActionEdge[] = [];\n        let hasRequires = false;\n        if (data.edges && Array.isArray(data.edges)) {\n          for (const e of data.edges) {\n            if (!validEdgeTypes.includes(e.type)) {\n              return { success: false, error: `invalid edge type: ${e.type}` };\n            }\n            const targetAction = await kv.get<Action>(KV.actions, e.targetActionId);\n            if (!targetAction) {\n              return { success: false, error: `target action not found: ${e.targetActionId}` };\n            }\n            if (e.type === \"requires\") hasRequires = true;\n            pendingEdges.push({\n              id: generateId(\"ae\"),\n              type: e.type as ActionEdge[\"type\"],\n              sourceActionId: action.id,\n              targetActionId: e.targetActionId,\n              createdAt: now,\n            });\n          }\n        }\n\n        if (hasRequires) {\n          action.status = \"blocked\";\n        }\n\n        await kv.set(KV.actions, action.id, action);\n        await recordAudit(kv, \"action_create\", \"mem::action-create\", [action.id], {\n          actor: data.createdBy || \"unknown\",\n          action,\n          edges: pendingEdges,\n        });\n\n        for (const edge of pendingEdges) {\n          await kv.set(KV.actionEdges, edge.id, edge);\n        }\n\n        return { success: true, action, edges: pendingEdges };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::action-update\", \n    async (data: {\n      actionId: string;\n      status?: Action[\"status\"];\n      title?: string;\n      description?: string;\n      priority?: number;\n      assignedTo?: string;\n      result?: string;\n      tags?: string[];\n    }) => {\n      if (!data.actionId) {\n        return { success: false, error: \"actionId is required\" };\n      }\n\n      return withKeyedLock(`mem:action:${data.actionId}`, async () => {\n        const action = await kv.get<Action>(KV.actions, data.actionId);\n        if (!action) {\n          return { success: false, error: \"action not found\" };\n        }\n        const before = { ...action };\n\n        if (data.status !== undefined) action.status = data.status;\n        if (data.title !== undefined) action.title = data.title.trim();\n        if (data.description !== undefined)\n          action.description = data.description.trim();\n        if (data.priority !== undefined)\n          action.priority = Math.max(1, Math.min(10, data.priority));\n        if (data.assignedTo !== undefined) action.assignedTo = data.assignedTo;\n        if (data.result !== undefined) action.result = data.result;\n        if (data.tags !== undefined) action.tags = data.tags;\n        action.updatedAt = new Date().toISOString();\n\n        await kv.set(KV.actions, action.id, action);\n        await recordAudit(kv, \"action_update\", \"mem::action-update\", [action.id], {\n          actor: data.assignedTo || \"unknown\",\n          before,\n          after: action,\n        });\n\n        if (data.status === \"done\") {\n          await propagateCompletion(kv, action.id);\n        }\n\n        return { success: true, action };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::action-edge-create\", \n    async (data: {\n      sourceActionId: string;\n      targetActionId: string;\n      type: string;\n      metadata?: Record<string, unknown>;\n    }) => {\n      if (!data.sourceActionId || !data.targetActionId || !data.type) {\n        return {\n          success: false,\n          error: \"sourceActionId, targetActionId, and type are required\",\n        };\n      }\n\n      const validTypes = [\n        \"requires\",\n        \"unlocks\",\n        \"spawned_by\",\n        \"gated_by\",\n        \"conflicts_with\",\n      ];\n      if (!validTypes.includes(data.type)) {\n        return {\n          success: false,\n          error: `type must be one of: ${validTypes.join(\", \")}`,\n        };\n      }\n\n      const sourceAction = await kv.get<Action>(KV.actions, data.sourceActionId);\n      if (!sourceAction) {\n        return { success: false, error: \"source action not found\" };\n      }\n      const targetAction = await kv.get<Action>(KV.actions, data.targetActionId);\n      if (!targetAction) {\n        return { success: false, error: \"target action not found\" };\n      }\n\n      const edge: ActionEdge = {\n        id: generateId(\"ae\"),\n        type: data.type as ActionEdge[\"type\"],\n        sourceActionId: data.sourceActionId,\n        targetActionId: data.targetActionId,\n        createdAt: new Date().toISOString(),\n        metadata: data.metadata,\n      };\n\n      await kv.set(KV.actionEdges, edge.id, edge);\n      await recordAudit(kv, \"action_create\", \"mem::action-edge-create\", [edge.id], {\n        actor: \"unknown\",\n        edge,\n      });\n      return { success: true, edge };\n    },\n  );\n\n  sdk.registerFunction(\"mem::action-list\", \n    async (data: {\n      status?: string;\n      project?: string;\n      parentId?: string;\n      tags?: string[];\n      limit?: number;\n    }) => {\n      let actions = await kv.list<Action>(KV.actions);\n\n      if (data.status) {\n        actions = actions.filter((a) => a.status === data.status);\n      }\n      if (data.project) {\n        actions = actions.filter((a) => a.project === data.project);\n      }\n      if (data.parentId) {\n        actions = actions.filter((a) => a.parentId === data.parentId);\n      }\n      if (data.tags && data.tags.length > 0) {\n        actions = actions.filter((a) =>\n          data.tags!.some((t) => a.tags.includes(t)),\n        );\n      }\n\n      actions.sort(\n        (a, b) =>\n          new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n      );\n\n      const limit = data.limit || 50;\n      return { success: true, actions: actions.slice(0, limit) };\n    },\n  );\n\n  sdk.registerFunction(\"mem::action-get\", \n    async (data: { actionId: string }) => {\n      if (!data.actionId) {\n        return { success: false, error: \"actionId is required\" };\n      }\n      const action = await kv.get<Action>(KV.actions, data.actionId);\n      if (!action) {\n        return { success: false, error: \"action not found\" };\n      }\n\n      const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n      const edges = allEdges.filter(\n        (e) =>\n          e.sourceActionId === data.actionId ||\n          e.targetActionId === data.actionId,\n      );\n\n      const children = (await kv.list<Action>(KV.actions)).filter(\n        (a) => a.parentId === data.actionId,\n      );\n\n      return { success: true, action, edges, children };\n    },\n  );\n}\n\nasync function propagateCompletion(\n  kv: StateKV,\n  completedActionId: string,\n): Promise<void> {\n  const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n  const unlockEdges = allEdges.filter(\n    (e) =>\n      e.targetActionId === completedActionId &&\n      (e.type === \"requires\" || e.type === \"unlocks\"),\n  );\n\n  const allActions = await kv.list<Action>(KV.actions);\n  const actionMap = new Map(allActions.map((a) => [a.id, a]));\n\n  for (const edge of unlockEdges) {\n    const candidateId = edge.sourceActionId;\n    await withKeyedLock(`mem:action:${candidateId}`, async () => {\n      const action = await kv.get<Action>(KV.actions, candidateId);\n      if (action && action.status === \"blocked\") {\n        const deps = allEdges.filter(\n          (e) => e.sourceActionId === action.id && e.type === \"requires\",\n        );\n        const allDone = deps.every((d) => {\n          const target = actionMap.get(d.targetActionId);\n          return target && target.status === \"done\";\n        });\n        if (allDone) {\n          action.status = \"pending\";\n          action.updatedAt = new Date().toISOString();\n          await kv.set(KV.actions, action.id, action);\n        }\n      }\n    });\n  }\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport type { Action, ActionEdge, Checkpoint, Lease } from \"../types.js\";\n\nexport interface FrontierItem {\n  action: Action;\n  score: number;\n  blockers: string[];\n  leased: boolean;\n}\n\nexport function registerFrontierFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::frontier\", \n    async (data: {\n      project?: string;\n      agentId?: string;\n      limit?: number;\n      includeLeasedByOthers?: boolean;\n    }) => {\n      const actions = await kv.list<Action>(KV.actions);\n      const edges = await kv.list<ActionEdge>(KV.actionEdges);\n      const leases = await kv.list<Lease>(KV.leases);\n      const checkpoints = await kv.list<Checkpoint>(KV.checkpoints);\n      const now = Date.now();\n\n      const activeLeaseMap = new Map<string, Lease>();\n      for (const lease of leases) {\n        if (\n          lease.status === \"active\" &&\n          new Date(lease.expiresAt).getTime() > now\n        ) {\n          activeLeaseMap.set(lease.actionId, lease);\n        }\n      }\n\n      const checkpointMap = new Map<string, Checkpoint>();\n      for (const cp of checkpoints) {\n        checkpointMap.set(cp.id, cp);\n      }\n\n      const actionMap = new Map<string, Action>();\n      for (const a of actions) actionMap.set(a.id, a);\n\n      const frontier: FrontierItem[] = [];\n\n      for (const action of actions) {\n        if (action.status === \"done\" || action.status === \"cancelled\") continue;\n        if (data.project && action.project !== data.project) continue;\n\n        const blockers: string[] = [];\n        const inEdges = edges.filter(\n          (e) => e.sourceActionId === action.id && e.type === \"requires\",\n        );\n\n        for (const edge of inEdges) {\n          const dep = actionMap.get(edge.targetActionId);\n          if (dep && dep.status !== \"done\") {\n            blockers.push(`requires:${dep.id}:${dep.title}`);\n          }\n        }\n\n        const gateEdges = edges.filter(\n          (e) => e.sourceActionId === action.id && e.type === \"gated_by\",\n        );\n        for (const edge of gateEdges) {\n          const cp = checkpointMap.get(edge.targetActionId);\n          if (cp && cp.status !== \"passed\") {\n            blockers.push(`checkpoint:${cp.id}:${cp.name}`);\n          }\n        }\n\n        const conflictEdges = edges.filter(\n          (e) =>\n            (e.sourceActionId === action.id ||\n              e.targetActionId === action.id) &&\n            e.type === \"conflicts_with\",\n        );\n        for (const edge of conflictEdges) {\n          const otherId =\n            edge.sourceActionId === action.id\n              ? edge.targetActionId\n              : edge.sourceActionId;\n          const other = actionMap.get(otherId);\n          if (other && other.status === \"active\") {\n            blockers.push(`conflict:${other.id}:${other.title}`);\n          }\n        }\n\n        if (blockers.length > 0) continue;\n\n        const lease = activeLeaseMap.get(action.id);\n        const leasedByOther =\n          lease && data.agentId && lease.agentId !== data.agentId;\n        if (leasedByOther && !data.includeLeasedByOthers) continue;\n\n        const score = computeScore(action, edges, now);\n\n        frontier.push({\n          action,\n          score,\n          blockers: [],\n          leased: !!lease,\n        });\n      }\n\n      frontier.sort((a, b) => b.score - a.score);\n      const limit = data.limit || 20;\n\n      return {\n        success: true,\n        frontier: frontier.slice(0, limit),\n        totalActions: actions.length,\n        totalUnblocked: frontier.length,\n      };\n    },\n  );\n\n  sdk.registerFunction(\"mem::next\", \n    async (data: { project?: string; agentId?: string }) => {\n      const result = await sdk.trigger<\n        { project?: string; agentId?: string; limit?: number },\n        {\n          success: boolean;\n          frontier: FrontierItem[];\n          totalActions: number;\n          totalUnblocked: number;\n        }\n      >({ function_id: \"mem::frontier\", payload: {\n        project: data.project,\n        agentId: data.agentId,\n        limit: 1,\n      } });\n\n      if (!result.success) {\n        return {\n          success: false,\n          suggestion: null,\n          message: \"Failed to compute frontier\",\n          totalActions: 0,\n        };\n      }\n      if (result.frontier.length === 0) {\n        return {\n          success: true,\n          suggestion: null,\n          message: \"No actionable work found\",\n          totalActions: result.totalActions || 0,\n        };\n      }\n\n      const top = result.frontier[0];\n      return {\n        success: true,\n        suggestion: {\n          actionId: top.action.id,\n          title: top.action.title,\n          description: top.action.description,\n          priority: top.action.priority,\n          score: top.score,\n          tags: top.action.tags,\n        },\n        message: `Suggested: ${top.action.title} (priority ${top.action.priority}, score ${top.score.toFixed(2)})`,\n        totalActions: result.totalActions,\n        totalUnblocked: result.totalUnblocked,\n      };\n    },\n  );\n}\n\nfunction computeScore(\n  action: Action,\n  edges: ActionEdge[],\n  now: number,\n): number {\n  let score = action.priority * 10;\n\n  const ageHours =\n    (now - new Date(action.createdAt).getTime()) / (1000 * 60 * 60);\n  score += Math.min(ageHours * 0.5, 20);\n\n  const unlockCount = edges.filter(\n    (e) => e.sourceActionId === action.id && e.type === \"unlocks\",\n  ).length;\n  score += unlockCount * 5;\n\n  if (edges.some((e) => e.sourceActionId === action.id && e.type === \"spawned_by\")) {\n    score += 3;\n  }\n\n  if (action.status === \"active\") score += 15;\n\n  return Math.round(score * 100) / 100;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport type { Action, Lease } from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\n\nconst DEFAULT_LEASE_TTL_MS = 10 * 60 * 1000;\nconst MAX_LEASE_TTL_MS = 60 * 60 * 1000;\n\nexport function registerLeasesFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::lease-acquire\", \n    async (data: { actionId: string; agentId: string; ttlMs?: number }) => {\n      if (!data.actionId || !data.agentId) {\n        return { success: false, error: \"actionId and agentId are required\" };\n      }\n\n      const rawTtl = typeof data.ttlMs === \"number\" && Number.isFinite(data.ttlMs) && data.ttlMs > 0\n        ? data.ttlMs\n        : DEFAULT_LEASE_TTL_MS;\n      const ttl = Math.min(rawTtl, MAX_LEASE_TTL_MS);\n\n      return withKeyedLock(`mem:action:${data.actionId}`, async () => {\n        const action = await kv.get<Action>(KV.actions, data.actionId);\n        if (!action) {\n          return { success: false, error: \"action not found\" };\n        }\n        if (action.status === \"done\" || action.status === \"cancelled\") {\n          return { success: false, error: \"action already completed\" };\n        }\n        if (action.status === \"blocked\") {\n          return { success: false, error: \"action is blocked\" };\n        }\n\n        const existingLeases = await kv.list<Lease>(KV.leases);\n        const activeLease = existingLeases.find(\n          (l) =>\n            l.actionId === data.actionId &&\n            l.status === \"active\" &&\n            new Date(l.expiresAt).getTime() > Date.now(),\n        );\n\n        if (activeLease) {\n          if (activeLease.agentId === data.agentId) {\n            return {\n              success: true,\n              lease: activeLease,\n              renewed: false,\n              message: \"Already holding this lease\",\n            };\n          }\n          return {\n            success: false,\n            error: \"action already leased\",\n            heldBy: activeLease.agentId,\n            expiresAt: activeLease.expiresAt,\n          };\n        }\n\n        const now = new Date();\n        const lease: Lease = {\n          id: generateId(\"lse\"),\n          actionId: data.actionId,\n          agentId: data.agentId,\n          acquiredAt: now.toISOString(),\n          expiresAt: new Date(now.getTime() + ttl).toISOString(),\n          status: \"active\",\n        };\n\n        await kv.set(KV.leases, lease.id, lease);\n        await recordAudit(kv, \"lease_acquire\", \"mem::lease-acquire\", [lease.id], {\n          actionId: data.actionId,\n          agentId: data.agentId,\n          expiresAt: lease.expiresAt,\n        });\n\n        const before = { ...action };\n        action.status = \"active\";\n        action.assignedTo = data.agentId;\n        action.updatedAt = now.toISOString();\n        await kv.set(KV.actions, action.id, action);\n        await recordAudit(kv, \"action_update\", \"mem::lease-acquire\", [action.id], {\n          before,\n          after: action,\n        });\n\n        return { success: true, lease, renewed: false };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::lease-release\", \n    async (data: { actionId: string; agentId: string; result?: string }) => {\n      if (!data.actionId || !data.agentId) {\n        return { success: false, error: \"actionId and agentId are required\" };\n      }\n\n      return withKeyedLock(`mem:action:${data.actionId}`, async () => {\n        const leases = await kv.list<Lease>(KV.leases);\n        const activeLease = leases.find(\n          (l) =>\n            l.actionId === data.actionId &&\n            l.agentId === data.agentId &&\n            l.status === \"active\" &&\n            new Date(l.expiresAt).getTime() > Date.now(),\n        );\n\n        if (!activeLease) {\n          return { success: false, error: \"no active lease found for this agent\" };\n        }\n\n        activeLease.status = \"released\";\n        await kv.set(KV.leases, activeLease.id, activeLease);\n        await recordAudit(kv, \"lease_release\", \"mem::lease-release\", [activeLease.id], {\n          actionId: data.actionId,\n          agentId: data.agentId,\n          status: \"released\",\n        });\n\n        const action = await kv.get<Action>(KV.actions, data.actionId);\n        if (action && action.status === \"active\" && action.assignedTo === data.agentId) {\n          const before = { ...action };\n          if (data.result) {\n            action.status = \"done\";\n            action.result = data.result;\n          } else {\n            action.status = \"pending\";\n          }\n          action.assignedTo = undefined;\n          action.updatedAt = new Date().toISOString();\n          await kv.set(KV.actions, action.id, action);\n          await recordAudit(kv, \"action_update\", \"mem::lease-release\", [action.id], {\n            before,\n            after: action,\n            agentId: data.agentId,\n          });\n        }\n\n        return { success: true, released: true };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::lease-renew\", \n    async (data: { actionId: string; agentId: string; ttlMs?: number }) => {\n      if (!data.actionId || !data.agentId) {\n        return { success: false, error: \"actionId and agentId are required\" };\n      }\n\n      const rawTtl = typeof data.ttlMs === \"number\" && Number.isFinite(data.ttlMs) && data.ttlMs > 0\n        ? data.ttlMs\n        : DEFAULT_LEASE_TTL_MS;\n      const ttl = Math.min(rawTtl, MAX_LEASE_TTL_MS);\n\n      return withKeyedLock(`mem:action:${data.actionId}`, async () => {\n        const leases = await kv.list<Lease>(KV.leases);\n        const activeLease = leases.find(\n          (l) =>\n            l.actionId === data.actionId &&\n            l.agentId === data.agentId &&\n            l.status === \"active\" &&\n            new Date(l.expiresAt).getTime() > Date.now(),\n        );\n\n        if (!activeLease) {\n          return { success: false, error: \"no active (non-expired) lease to renew\" };\n        }\n\n        const now = new Date();\n        const base = Math.max(now.getTime(), new Date(activeLease.expiresAt).getTime());\n        const beforeLease = { ...activeLease };\n        activeLease.expiresAt = new Date(base + ttl).toISOString();\n        activeLease.renewedAt = now.toISOString();\n        await kv.set(KV.leases, activeLease.id, activeLease);\n        await recordAudit(kv, \"lease_renew\", \"mem::lease-renew\", [activeLease.id], {\n          actionId: data.actionId,\n          agentId: data.agentId,\n          before: beforeLease,\n          after: activeLease,\n        });\n\n        return { success: true, lease: activeLease };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::lease-cleanup\", \n    async () => {\n      const leases = await kv.list<Lease>(KV.leases);\n      const now = Date.now();\n      let expired = 0;\n\n      for (const lease of leases) {\n        if (\n          lease.status === \"active\" &&\n          new Date(lease.expiresAt).getTime() <= now\n        ) {\n          const didExpire = await withKeyedLock(\n            `mem:action:${lease.actionId}`,\n            async () => {\n              const currentLease = await kv.get<Lease>(KV.leases, lease.id);\n              if (\n                !currentLease ||\n                currentLease.status !== \"active\" ||\n                new Date(currentLease.expiresAt).getTime() > Date.now()\n              ) {\n                return false;\n              }\n              currentLease.status = \"expired\";\n              await kv.set(KV.leases, currentLease.id, currentLease);\n              await recordAudit(kv, \"lease_release\", \"mem::lease-cleanup\", [currentLease.id], {\n                action: \"expire\",\n                actionId: currentLease.actionId,\n                agentId: currentLease.agentId,\n              });\n\n              const action = await kv.get<Action>(KV.actions, currentLease.actionId);\n              const otherActiveLease = (await kv.list<Lease>(KV.leases)).some(\n                (l) =>\n                  l.id !== currentLease.id &&\n                  l.actionId === currentLease.actionId &&\n                  l.status === \"active\" &&\n                  new Date(l.expiresAt).getTime() > Date.now(),\n              );\n              if (\n                action &&\n                !otherActiveLease &&\n                action.status === \"active\" &&\n                action.assignedTo === currentLease.agentId\n              ) {\n                action.status = \"pending\";\n                action.assignedTo = undefined;\n                action.updatedAt = new Date().toISOString();\n                await kv.set(KV.actions, action.id, action);\n                await recordAudit(kv, \"action_update\", \"mem::lease-cleanup\", [action.id], {\n                  action: \"status-change\",\n                  newStatus: action.status,\n                  actionId: action.id,\n                });\n              }\n              return true;\n            },\n          );\n          if (didExpire) expired++;\n        }\n      }\n\n      return { success: true, expired };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport type { Action, Routine, RoutineStep, RoutineRun } from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\n\nexport function registerRoutinesFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::routine-create\", \n    async (data: {\n      name: string;\n      description?: string;\n      steps: RoutineStep[];\n      tags?: string[];\n      frozen?: boolean;\n      sourceProceduralIds?: string[];\n    }) => {\n      if (!data.name || !Array.isArray(data.steps) || data.steps.length === 0) {\n        return { success: false, error: \"name and steps are required\" };\n      }\n\n      for (let i = 0; i < data.steps.length; i++) {\n        if (!data.steps[i].title?.trim()) {\n          return { success: false, error: `step ${i} must have a title` };\n        }\n      }\n\n      const orders = data.steps.map((s, i) => s.order ?? i);\n      const uniqueOrders = new Set(orders);\n      if (uniqueOrders.size !== orders.length) {\n        return { success: false, error: \"duplicate step orders\" };\n      }\n      for (const step of data.steps) {\n        if (step.dependsOn) {\n          for (const dep of step.dependsOn) {\n            if (!uniqueOrders.has(dep)) {\n              return { success: false, error: `step ${step.order ?? data.steps.indexOf(step)} depends on unknown order ${dep}` };\n            }\n          }\n        }\n      }\n\n      const now = new Date().toISOString();\n      const routine: Routine = {\n        id: generateId(\"rtn\"),\n        name: data.name.trim(),\n        description: (data.description || \"\").trim(),\n        steps: data.steps.map((s, i) => ({\n          order: s.order ?? i,\n          title: s.title,\n          description: s.description || \"\",\n          actionTemplate: s.actionTemplate || {},\n          dependsOn: s.dependsOn || [],\n        })),\n        createdAt: now,\n        updatedAt: now,\n        frozen: data.frozen ?? true,\n        tags: data.tags || [],\n        sourceProceduralIds: data.sourceProceduralIds || [],\n      };\n\n      await kv.set(KV.routines, routine.id, routine);\n      await recordAudit(kv, \"routine_run\", \"mem::routine-create\", [routine.id], {\n        action: \"routine.create\",\n        stepCount: routine.steps.length,\n      });\n      return { success: true, routine };\n    },\n  );\n\n  sdk.registerFunction(\"mem::routine-list\", \n    async (data: { frozen?: boolean; tags?: string[] }) => {\n      let routines = await kv.list<Routine>(KV.routines);\n      if (data.frozen !== undefined) {\n        routines = routines.filter((r) => r.frozen === data.frozen);\n      }\n      if (data.tags && data.tags.length > 0) {\n        routines = routines.filter((r) =>\n          data.tags!.some((t) => r.tags.includes(t)),\n        );\n      }\n      routines.sort(\n        (a, b) =>\n          new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n      );\n      return { success: true, routines };\n    },\n  );\n\n  sdk.registerFunction(\"mem::routine-run\", \n    async (data: {\n      routineId: string;\n      initiatedBy?: string;\n      project?: string;\n      overrides?: Record<number, Partial<Action>>;\n    }) => {\n      if (!data.routineId) {\n        return { success: false, error: \"routineId is required\" };\n      }\n\n      return withKeyedLock(`mem:routine:${data.routineId}`, async () => {\n        const routine = await kv.get<Routine>(KV.routines, data.routineId);\n        if (!routine) {\n          return { success: false, error: \"routine not found\" };\n        }\n\n        const now = new Date().toISOString();\n        const stepOrderToActionId = new Map<number, string>();\n        const actionIds: string[] = [];\n        const stepStatus: Record<number, \"pending\" | \"active\" | \"done\" | \"failed\"> = {};\n\n        for (const step of routine.steps) {\n          const template = step.actionTemplate || {};\n          const override = data.overrides?.[step.order] || {};\n\n          const hasDeps = (step.dependsOn || []).length > 0;\n          const action: Action = {\n            id: generateId(\"act\"),\n            title: override.title || template.title || step.title,\n            description:\n              override.description ||\n              template.description ||\n              step.description,\n            status: hasDeps ? \"blocked\" : \"pending\",\n            priority:\n              override.priority ?? template.priority ?? 5,\n            createdAt: now,\n            updatedAt: now,\n            createdBy: data.initiatedBy || \"routine\",\n            project: data.project || template.project,\n            tags: [\n              ...(template.tags || []),\n              ...(override.tags || []),\n              `routine:${routine.id}`,\n            ],\n            sourceObservationIds: [],\n            sourceMemoryIds: [],\n            metadata: { routineId: routine.id, stepOrder: step.order },\n          };\n\n          await kv.set(KV.actions, action.id, action);\n          stepOrderToActionId.set(step.order, action.id);\n          actionIds.push(action.id);\n          stepStatus[step.order] = \"pending\";\n        }\n\n        for (const step of routine.steps) {\n          const actionId = stepOrderToActionId.get(step.order);\n          if (!actionId) continue;\n\n          for (const depOrder of step.dependsOn) {\n            const depActionId = stepOrderToActionId.get(depOrder);\n            if (!depActionId) continue;\n            const edge = {\n              id: generateId(\"ae\"),\n              type: \"requires\" as const,\n              sourceActionId: actionId,\n              targetActionId: depActionId,\n              createdAt: now,\n            };\n            await kv.set(KV.actionEdges, edge.id, edge);\n          }\n        }\n\n        const run: RoutineRun = {\n          id: generateId(\"run\"),\n          routineId: routine.id,\n          status: \"running\",\n          startedAt: now,\n          actionIds,\n          stepStatus,\n          initiatedBy: data.initiatedBy || \"unknown\",\n        };\n\n        await kv.set(KV.routineRuns, run.id, run);\n        await recordAudit(kv, \"routine_run\", \"mem::routine-run\", [run.id], {\n          action: \"routine.run\",\n          routineId: routine.id,\n          actionIds,\n          initiatedBy: data.initiatedBy || \"unknown\",\n        });\n\n        return {\n          success: true,\n          run,\n          actionsCreated: actionIds.length,\n        };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::routine-status\", \n    async (data: { runId: string }) => {\n      if (!data.runId) {\n        return { success: false, error: \"runId is required\" };\n      }\n\n      const run = await kv.get<RoutineRun>(KV.routineRuns, data.runId);\n      if (!run) {\n        return { success: false, error: \"run not found\" };\n      }\n\n      const actionStates: Array<{\n        actionId: string;\n        status: string;\n        title: string;\n      }> = [];\n      let allDone = true;\n      let anyFailed = false;\n\n      let statusChanged = false;\n      for (const actionId of run.actionIds) {\n        const action = await kv.get<Action>(KV.actions, actionId);\n        if (action) {\n          actionStates.push({\n            actionId: action.id,\n            status: action.status,\n            title: action.title,\n          });\n          if (action.status !== \"done\") allDone = false;\n          if (action.status === \"cancelled\") anyFailed = true;\n\n          const stepOrder = (action.metadata as { stepOrder?: number })?.stepOrder;\n          if (stepOrder !== undefined && stepOrder in run.stepStatus) {\n            let mapped: \"pending\" | \"active\" | \"done\" | \"failed\";\n            if (action.status === \"cancelled\") {\n              mapped = \"failed\";\n            } else if (action.status === \"blocked\") {\n              mapped = \"pending\";\n            } else {\n              mapped = action.status as \"pending\" | \"active\" | \"done\";\n            }\n            if (run.stepStatus[stepOrder] !== mapped) {\n              run.stepStatus[stepOrder] = mapped;\n              statusChanged = true;\n            }\n          }\n        } else {\n          actionStates.push({\n            actionId,\n            status: \"cancelled\",\n            title: \"(missing)\",\n          });\n          allDone = false;\n          anyFailed = true;\n        }\n      }\n\n      if (allDone && run.status === \"running\") {\n        run.status = \"completed\";\n        run.completedAt = new Date().toISOString();\n        statusChanged = true;\n      } else if (anyFailed && run.status === \"running\") {\n        run.status = \"failed\";\n        statusChanged = true;\n      }\n\n      if (statusChanged) {\n        await kv.set(KV.routineRuns, run.id, run);\n        await recordAudit(kv, \"routine_run\", \"mem::routine-status\", [run.id], {\n          action: \"routine.status\",\n          status: run.status,\n        });\n      }\n\n      return {\n        success: true,\n        run,\n        actions: actionStates,\n        progress: {\n          total: run.actionIds.length,\n          done: actionStates.filter((a) => a.status === \"done\").length,\n          active: actionStates.filter((a) => a.status === \"active\").length,\n          pending: actionStates.filter((a) => a.status === \"pending\").length,\n          blocked: actionStates.filter((a) => a.status === \"blocked\").length,\n          cancelled: actionStates.filter((a) => a.status === \"cancelled\").length,\n        },\n      };\n    },\n  );\n\n  sdk.registerFunction(\"mem::routine-freeze\", \n    async (data: { routineId: string }) => {\n      if (!data.routineId) {\n        return { success: false, error: \"routineId is required\" };\n      }\n      return withKeyedLock(`mem:routine:${data.routineId}`, async () => {\n        const routine = await kv.get<Routine>(KV.routines, data.routineId);\n        if (!routine) {\n          return { success: false, error: \"routine not found\" };\n        }\n        routine.frozen = true;\n        routine.updatedAt = new Date().toISOString();\n        await kv.set(KV.routines, routine.id, routine);\n        await recordAudit(kv, \"routine_run\", \"mem::routine-freeze\", [routine.id], {\n          action: \"routine.freeze\",\n          frozen: true,\n        });\n        return { success: true, routine };\n      });\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { Signal } from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\n\nexport function registerSignalsFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::signal-send\", \n    async (data: {\n      from: string;\n      to?: string;\n      content: string;\n      type?: Signal[\"type\"];\n      threadId?: string;\n      replyTo?: string;\n      metadata?: Record<string, unknown>;\n      expiresInMs?: number;\n    }) => {\n      if (!data.from?.trim() || !data.content?.trim()) {\n        return { success: false, error: \"from and non-empty content are required\" };\n      }\n\n      const now = new Date();\n      let threadId = data.threadId;\n\n      if (data.replyTo && !threadId) {\n        const parent = await kv.get<Signal>(KV.signals, data.replyTo);\n        if (parent) {\n          threadId = parent.threadId || parent.id;\n        }\n      }\n\n      const signal: Signal = {\n        id: generateId(\"sig\"),\n        from: data.from,\n        to: data.to,\n        content: data.content.trim(),\n        type: data.type || \"info\",\n        threadId: threadId || generateId(\"thr\"),\n        replyTo: data.replyTo,\n        metadata: data.metadata,\n        createdAt: now.toISOString(),\n        expiresAt: data.expiresInMs\n          ? new Date(now.getTime() + data.expiresInMs).toISOString()\n          : undefined,\n      };\n\n      await kv.set(KV.signals, signal.id, signal);\n      await recordAudit(kv, \"signal_send\", \"mem::signal-send\", [signal.id], {\n        action: \"create\",\n        from: data.from,\n        to: data.to,\n        type: signal.type,\n      });\n\n      return { success: true, signal };\n    },\n  );\n\n  sdk.registerFunction(\"mem::signal-read\", \n    async (data: {\n      agentId: string;\n      unreadOnly?: boolean;\n      threadId?: string;\n      type?: string;\n      limit?: number;\n    }) => {\n      if (!data.agentId) {\n        return { success: false, error: \"agentId is required\" };\n      }\n\n      let signals = await kv.list<Signal>(KV.signals);\n      const now = Date.now();\n\n      signals = signals.filter((s) => {\n        if (s.expiresAt && new Date(s.expiresAt).getTime() <= now) return false;\n        if (s.to && s.to !== data.agentId && s.from !== data.agentId)\n          return false;\n        if (!s.to && s.from !== data.agentId) return true;\n        return true;\n      });\n\n      if (data.unreadOnly) {\n        signals = signals.filter((s) => !s.readAt && s.to === data.agentId);\n      }\n      if (data.threadId) {\n        signals = signals.filter((s) => s.threadId === data.threadId);\n      }\n      if (data.type) {\n        signals = signals.filter((s) => s.type === data.type);\n      }\n\n      signals.sort(\n        (a, b) =>\n          new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),\n      );\n\n      const limit = data.limit || 50;\n      const results = signals.slice(0, limit);\n\n      for (const sig of results) {\n        if (!sig.readAt && sig.to === data.agentId) {\n          const beforeReadAt = sig.readAt;\n          sig.readAt = new Date().toISOString();\n          await recordAudit(kv, \"signal_send\", \"mem::signal-read\", [sig.id], {\n            action: \"signal.mark_read\",\n            actor: data.agentId,\n            beforeReadAt,\n            afterReadAt: sig.readAt,\n          });\n          await kv.set(KV.signals, sig.id, sig);\n        }\n      }\n\n      return { success: true, signals: results };\n    },\n  );\n\n  sdk.registerFunction(\"mem::signal-threads\", \n    async (data: { agentId: string; limit?: number }) => {\n      if (!data.agentId) {\n        return { success: false, error: \"agentId is required\" };\n      }\n\n      const signals = await kv.list<Signal>(KV.signals);\n      const now = Date.now();\n\n      const relevant = signals.filter((s) => {\n        if (s.expiresAt && new Date(s.expiresAt).getTime() <= now) return false;\n        return (\n          s.from === data.agentId ||\n          s.to === data.agentId ||\n          !s.to\n        );\n      });\n\n      const threadMap = new Map<\n        string,\n        { threadId: string; messages: number; lastMessage: string; participants: Set<string> }\n      >();\n\n      for (const sig of relevant) {\n        const tid = sig.threadId || sig.id;\n        const existing = threadMap.get(tid);\n        if (existing) {\n          existing.messages++;\n          existing.participants.add(sig.from);\n          if (sig.to) existing.participants.add(sig.to);\n          if (new Date(sig.createdAt) > new Date(existing.lastMessage)) {\n            existing.lastMessage = sig.createdAt;\n          }\n        } else {\n          const participants = new Set<string>([sig.from]);\n          if (sig.to) participants.add(sig.to);\n          threadMap.set(tid, {\n            threadId: tid,\n            messages: 1,\n            lastMessage: sig.createdAt,\n            participants,\n          });\n        }\n      }\n\n      const threads = Array.from(threadMap.values())\n        .map((t) => ({\n          ...t,\n          participants: Array.from(t.participants),\n        }))\n        .sort(\n          (a, b) =>\n            new Date(b.lastMessage).getTime() -\n            new Date(a.lastMessage).getTime(),\n        )\n        .slice(0, data.limit || 20);\n\n      return { success: true, threads };\n    },\n  );\n\n  sdk.registerFunction(\"mem::signal-cleanup\", \n    async () => {\n      const signals = await kv.list<Signal>(KV.signals);\n      const now = Date.now();\n      let removed = 0;\n\n      for (const sig of signals) {\n        if (sig.expiresAt && new Date(sig.expiresAt).getTime() <= now) {\n          await recordAudit(kv, \"delete\", \"mem::signal-cleanup\", [sig.id], {\n            action: \"delete\",\n            resource: \"Signal\",\n            before: sig,\n          });\n          await kv.delete(KV.signals, sig.id);\n          removed++;\n        }\n      }\n\n      return { success: true, removed };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport type { Action, ActionEdge, Checkpoint } from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\n\nexport function registerCheckpointsFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::checkpoint-create\", \n    async (data: {\n      name: string;\n      description?: string;\n      type?: Checkpoint[\"type\"];\n      linkedActionIds?: string[];\n      expiresInMs?: number;\n    }) => {\n      if (!data.name) {\n        return { success: false, error: \"name is required\" };\n      }\n\n      const validTypes: Checkpoint[\"type\"][] = [\"ci\", \"approval\", \"deploy\", \"external\", \"timer\"];\n      if (data.type && !validTypes.includes(data.type)) {\n        return { success: false, error: `invalid checkpoint type: ${data.type}. Must be one of: ${validTypes.join(\", \")}` };\n      }\n\n      const now = new Date();\n      const checkpoint: Checkpoint = {\n        id: generateId(\"ckpt\"),\n        name: data.name.trim(),\n        description: (data.description || \"\").trim(),\n        status: \"pending\",\n        type: data.type || \"external\",\n        createdAt: now.toISOString(),\n        linkedActionIds: data.linkedActionIds || [],\n        expiresAt: data.expiresInMs\n          ? new Date(now.getTime() + data.expiresInMs).toISOString()\n          : undefined,\n      };\n\n      if (data.linkedActionIds && data.linkedActionIds.length > 0) {\n        for (const actionId of data.linkedActionIds) {\n          const action = await kv.get<Action>(KV.actions, actionId);\n          if (!action) {\n            return { success: false, error: `linked action not found: ${actionId}` };\n          }\n        }\n      }\n\n      await kv.set(KV.checkpoints, checkpoint.id, checkpoint);\n      await recordAudit(kv, \"checkpoint_resolve\", \"mem::checkpoint-create\", [checkpoint.id], {\n        action: \"create\",\n        type: checkpoint.type,\n        name: checkpoint.name,\n      });\n\n      if (data.linkedActionIds && data.linkedActionIds.length > 0) {\n        for (const actionId of data.linkedActionIds) {\n          const edge: ActionEdge = {\n            id: generateId(\"ae\"),\n            type: \"gated_by\",\n            sourceActionId: actionId,\n            targetActionId: checkpoint.id,\n            createdAt: now.toISOString(),\n          };\n          await kv.set(KV.actionEdges, edge.id, edge);\n\n          const action = await kv.get<Action>(KV.actions, actionId);\n          if (action && action.status === \"pending\") {\n            const previousStatus = action.status;\n            action.status = \"blocked\";\n            action.updatedAt = now.toISOString();\n            await kv.set(KV.actions, action.id, action);\n            await recordAudit(kv, \"action_update\", \"mem::checkpoint-create\", [action.id], {\n              action: \"status-change\",\n              previousStatus,\n              newStatus: action.status,\n              checkpointId: checkpoint.id,\n            });\n          }\n        }\n      }\n\n      return { success: true, checkpoint };\n    },\n  );\n\n  sdk.registerFunction(\"mem::checkpoint-resolve\", \n    async (data: {\n      checkpointId: string;\n      status: \"passed\" | \"failed\";\n      resolvedBy?: string;\n      result?: unknown;\n    }) => {\n      if (!data.checkpointId || !data.status) {\n        return {\n          success: false,\n          error: \"checkpointId and status are required\",\n        };\n      }\n\n      return withKeyedLock(\n        `mem:checkpoint:${data.checkpointId}`,\n        async () => {\n          const checkpoint = await kv.get<Checkpoint>(\n            KV.checkpoints,\n            data.checkpointId,\n          );\n          if (!checkpoint) {\n            return { success: false, error: \"checkpoint not found\" };\n          }\n          if (checkpoint.status !== \"pending\") {\n            return {\n              success: false,\n              error: `checkpoint already ${checkpoint.status}`,\n            };\n          }\n\n          checkpoint.status = data.status;\n          checkpoint.resolvedAt = new Date().toISOString();\n          checkpoint.resolvedBy = data.resolvedBy;\n          checkpoint.result = data.result;\n\n          await kv.set(KV.checkpoints, checkpoint.id, checkpoint);\n          await recordAudit(kv, \"checkpoint_resolve\", \"mem::checkpoint-resolve\", [checkpoint.id], {\n            action: \"resolve\",\n            resolvedBy: data.resolvedBy,\n            result: data.result,\n            newStatus: checkpoint.status,\n          });\n\n          let unblockedCount = 0;\n          if (data.status === \"passed\" && checkpoint.linkedActionIds.length > 0) {\n            const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n            const allCheckpoints = await kv.list<Checkpoint>(KV.checkpoints);\n            const allActions = await kv.list<Action>(KV.actions);\n            const cpMap = new Map(allCheckpoints.map((c) => [c.id, c]));\n            const actionMap = new Map(allActions.map((a) => [a.id, a]));\n\n            for (const actionId of checkpoint.linkedActionIds) {\n              await withKeyedLock(`mem:action:${actionId}`, async () => {\n                const action = await kv.get<Action>(KV.actions, actionId);\n                if (action && action.status === \"blocked\") {\n                  const gates = allEdges.filter(\n                    (e) => e.sourceActionId === actionId && e.type === \"gated_by\",\n                  );\n                  const allGatesPassed = gates.every((g) => {\n                    const cp = cpMap.get(g.targetActionId);\n                    return cp && cp.status === \"passed\";\n                  });\n                  const requires = allEdges.filter(\n                    (e) => e.sourceActionId === actionId && e.type === \"requires\",\n                  );\n                  const allRequiresMet = requires.every((r) => {\n                    const dep = actionMap.get(r.targetActionId);\n                    return dep && dep.status === \"done\";\n                  });\n                  if (allGatesPassed && allRequiresMet) {\n                    const previousStatus = action.status;\n                    action.status = \"pending\";\n                    action.updatedAt = new Date().toISOString();\n                    await kv.set(KV.actions, action.id, action);\n                    await recordAudit(kv, \"action_update\", \"mem::checkpoint-resolve\", [action.id], {\n                      action: \"unblock\",\n                      checkpointId: checkpoint.id,\n                      previousStatus,\n                      newStatus: action.status,\n                    });\n                    unblockedCount++;\n                  }\n                }\n              });\n            }\n          }\n\n          return { success: true, checkpoint, unblockedCount };\n        },\n      );\n    },\n  );\n\n  sdk.registerFunction(\"mem::checkpoint-list\", \n    async (data: { status?: string; type?: string }) => {\n      let checkpoints = await kv.list<Checkpoint>(KV.checkpoints);\n\n      if (data.status) {\n        checkpoints = checkpoints.filter((c) => c.status === data.status);\n      }\n      if (data.type) {\n        checkpoints = checkpoints.filter((c) => c.type === data.type);\n      }\n\n      checkpoints.sort(\n        (a, b) =>\n          new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),\n      );\n\n      return { success: true, checkpoints };\n    },\n  );\n\n  sdk.registerFunction(\"mem::checkpoint-expire\", \n    async () => {\n      const checkpoints = await kv.list<Checkpoint>(KV.checkpoints);\n      const now = Date.now();\n      let expired = 0;\n\n      for (const cp of checkpoints) {\n        if (\n          cp.status === \"pending\" &&\n          cp.expiresAt &&\n          new Date(cp.expiresAt).getTime() <= now\n        ) {\n          const didExpire = await withKeyedLock(\n            `mem:checkpoint:${cp.id}`,\n            async () => {\n              const fresh = await kv.get<Checkpoint>(KV.checkpoints, cp.id);\n              if (!fresh || fresh.status !== \"pending\") return false;\n              fresh.status = \"expired\";\n              fresh.resolvedAt = new Date().toISOString();\n              await kv.set(KV.checkpoints, fresh.id, fresh);\n              await recordAudit(kv, \"checkpoint_resolve\", \"mem::checkpoint-expire\", [fresh.id], {\n                action: \"expire\",\n                previousStatus: \"pending\",\n                newStatus: \"expired\",\n              });\n              return true;\n            },\n          );\n          if (didExpire) expired++;\n        }\n      }\n\n      return { success: true, expired };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { Action, ActionEdge, RoutineRun, MemoryProvider } from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\n\nconst FLOW_COMPRESS_SYSTEM = `You are a workflow summarizer. Given a completed action chain, produce a concise summary capturing:\n1. The overall goal and outcome\n2. Key steps taken and their results\n3. Any notable decisions or discoveries\n4. Lessons learned\n\nOutput as XML:\n<summary>\n<goal>What was the workflow trying to achieve</goal>\n<outcome>What happened</outcome>\n<steps>Numbered list of key steps</steps>\n<discoveries>Any new insights or discoveries</discoveries>\n<lesson>What to remember for next time</lesson>\n</summary>`;\n\nexport function registerFlowCompressFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\"mem::flow-compress\", \n    async (data: { runId?: string; actionIds?: string[]; project?: string }) => {\n      let actionsToCompress: Action[] = [];\n\n      if (data.runId) {\n        const run = await kv.get<RoutineRun>(KV.routineRuns, data.runId);\n        if (!run) {\n          return { success: false, error: \"run not found\" };\n        }\n        for (const id of run.actionIds) {\n          const action = await kv.get<Action>(KV.actions, id);\n          if (action) actionsToCompress.push(action);\n        }\n      } else if (data.actionIds && data.actionIds.length > 0) {\n        for (const id of data.actionIds) {\n          const action = await kv.get<Action>(KV.actions, id);\n          if (action) actionsToCompress.push(action);\n        }\n      } else if (data.project) {\n        const allActions = await kv.list<Action>(KV.actions);\n        actionsToCompress = allActions.filter(\n          (a) => a.project === data.project && a.status === \"done\",\n        );\n      } else {\n        return {\n          success: false,\n          error: \"runId, actionIds, or project is required\",\n        };\n      }\n\n      const doneActions = actionsToCompress.filter(\n        (a) => a.status === \"done\",\n      );\n      if (doneActions.length === 0) {\n        return {\n          success: true,\n          message: \"No completed actions to compress\",\n          compressed: 0,\n        };\n      }\n\n      const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n      const relevantIds = new Set(doneActions.map((a) => a.id));\n      const relevantEdges = allEdges.filter(\n        (e) =>\n          relevantIds.has(e.sourceActionId) ||\n          relevantIds.has(e.targetActionId),\n      );\n\n      const prompt = buildFlowPrompt(doneActions, relevantEdges);\n\n      try {\n        const response = await provider.summarize(\n          FLOW_COMPRESS_SYSTEM,\n          prompt,\n        );\n        const summary = parseFlowSummary(response);\n        const ts = new Date().toISOString();\n\n        const memory = {\n          id: generateId(\"mem\"),\n          createdAt: ts,\n          updatedAt: ts,\n          type: \"workflow\" as const,\n          title: summary.goal || `Workflow: ${doneActions.length} actions`,\n          content: formatSummary(summary),\n          concepts: extractConcepts(doneActions),\n          files: extractFiles(doneActions),\n          sessionIds: [],\n          strength: 1.0,\n          version: 1,\n          isLatest: true,\n          metadata: {\n            flowCompressed: true,\n            actionCount: doneActions.length,\n            actionIds: doneActions.map((a) => a.id),\n          },\n        };\n\n        await kv.set(KV.memories, memory.id, memory);\n        await recordAudit(kv, \"compress\", \"mem::flow-compress\", [memory.id], {\n          action: \"compress_flow\",\n          flowCompressed: true,\n          actionCount: doneActions.length,\n          project: data.project,\n        });\n\n        return {\n          success: true,\n          compressed: doneActions.length,\n          memoryId: memory.id,\n          summary,\n        };\n      } catch (err) {\n        return {\n          success: false,\n          error: `compression failed: ${String(err)}`,\n          compressed: 0,\n        };\n      }\n    },\n  );\n}\n\nfunction buildFlowPrompt(\n  actions: Action[],\n  edges: ActionEdge[],\n): string {\n  const lines: string[] = [\"## Completed Action Chain\\n\"];\n\n  const sorted = [...actions].sort(\n    (a, b) =>\n      new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(),\n  );\n\n  for (const action of sorted) {\n    lines.push(`### ${action.title}`);\n    if (action.description) lines.push(action.description);\n    if (action.result) lines.push(`Result: ${action.result}`);\n    lines.push(`Priority: ${action.priority}, Tags: ${(action.tags ?? []).join(\", \")}`);\n    lines.push(\"\");\n  }\n\n  if (edges.length > 0) {\n    lines.push(\"## Dependencies\");\n    for (const edge of edges) {\n      lines.push(`- ${edge.sourceActionId} --${edge.type}--> ${edge.targetActionId}`);\n    }\n  }\n\n  return lines.join(\"\\n\");\n}\n\nfunction parseFlowSummary(response: string): {\n  goal: string;\n  outcome: string;\n  steps: string;\n  discoveries: string;\n  lesson: string;\n} {\n  const extract = (tag: string): string => {\n    const match = response.match(\n      new RegExp(`<${tag}>([\\\\s\\\\S]*?)</${tag}>`),\n    );\n    return match ? match[1].trim() : \"\";\n  };\n  return {\n    goal: extract(\"goal\"),\n    outcome: extract(\"outcome\"),\n    steps: extract(\"steps\"),\n    discoveries: extract(\"discoveries\"),\n    lesson: extract(\"lesson\"),\n  };\n}\n\nfunction formatSummary(s: {\n  goal: string;\n  outcome: string;\n  steps: string;\n  discoveries: string;\n  lesson: string;\n}): string {\n  const parts: string[] = [];\n  if (s.goal) parts.push(`Goal: ${s.goal}`);\n  if (s.outcome) parts.push(`Outcome: ${s.outcome}`);\n  if (s.steps) parts.push(`Steps: ${s.steps}`);\n  if (s.discoveries) parts.push(`Discoveries: ${s.discoveries}`);\n  if (s.lesson) parts.push(`Lesson: ${s.lesson}`);\n  return parts.join(\"\\n\\n\");\n}\n\nfunction extractConcepts(actions: Action[]): string[] {\n  const concepts = new Set<string>();\n  for (const a of actions) {\n    for (const tag of a.tags ?? []) {\n      if (!tag.startsWith(\"routine:\")) concepts.add(tag);\n    }\n  }\n  return Array.from(concepts);\n}\n\nfunction extractFiles(actions: Action[]): string[] {\n  const files = new Set<string>();\n  for (const a of actions) {\n    if (a.metadata && typeof a.metadata === \"object\") {\n      const meta = a.metadata as Record<string, unknown>;\n      if (Array.isArray(meta.files)) {\n        for (const f of meta.files) {\n          if (typeof f === \"string\") files.add(f);\n        }\n      }\n    }\n  }\n  return Array.from(files);\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { recordAudit } from \"./audit.js\";\nimport type {\n  MeshPeer,\n  Memory,\n  Action,\n  SemanticMemory,\n  ProceduralMemory,\n  MemoryRelation,\n  GraphNode,\n  GraphEdge,\n} from \"../types.js\";\nimport { lookup } from \"node:dns/promises\";\nimport { isIP } from \"node:net\";\n\nfunction isPrivateIP(ip: string): boolean {\n  if (ip === \"127.0.0.1\" || ip === \"::1\" || ip === \"0.0.0.0\") return true;\n  if (ip.startsWith(\"10.\") || ip.startsWith(\"192.168.\")) return true;\n  if (/^172\\.(1[6-9]|2\\d|3[01])\\./.test(ip)) return true;\n  if (ip === \"169.254.169.254\") return true;\n  if (ip.startsWith(\"fe80:\") || ip.startsWith(\"fc00:\") || ip.startsWith(\"fd\")) return true;\n  if (ip.startsWith(\"::ffff:\")) {\n    const v4 = ip.slice(7);\n    return isPrivateIP(v4);\n  }\n  return false;\n}\n\nasync function isAllowedUrl(urlStr: string): Promise<boolean> {\n  try {\n    const parsed = new URL(urlStr);\n    if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") return false;\n    if (parsed.username || parsed.password) return false;\n    const host = parsed.hostname.toLowerCase();\n\n    if (host === \"localhost\") return false;\n    if (isIP(host) && isPrivateIP(host)) return false;\n\n    if (!isIP(host)) {\n      try {\n        const resolved = await lookup(host, { all: true });\n        if (resolved.some((r) => isPrivateIP(r.address))) return false;\n      } catch {\n        // DNS resolution failed — allow the URL (the actual fetch will fail if unreachable)\n      }\n    }\n\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nconst DEFAULT_SHARED_SCOPES = [\n  \"memories\",\n  \"actions\",\n  \"semantic\",\n  \"procedural\",\n  \"relations\",\n  \"graph:nodes\",\n  \"graph:edges\",\n];\n\ninterface MeshSyncPayload {\n  memories?: Memory[];\n  actions?: Action[];\n  semantic?: SemanticMemory[];\n  procedural?: ProceduralMemory[];\n  relations?: MemoryRelation[];\n  graphNodes?: GraphNode[];\n  graphEdges?: GraphEdge[];\n}\n\nasync function lwwMergeList<T extends { id: string }>(\n  kv: StateKV,\n  scope: string,\n  items: T[] | undefined,\n  lockPrefix: string,\n  tsField: \"updatedAt\" | \"createdAt\",\n): Promise<number> {\n  if (!items || !Array.isArray(items)) return 0;\n  let count = 0;\n  for (const item of items) {\n    if (!item.id || typeof item.id !== \"string\") continue;\n    const ts = (item as Record<string, unknown>)[tsField];\n    if (typeof ts !== \"string\" || Number.isNaN(new Date(ts).getTime())) continue;\n    const wrote = await withKeyedLock(`${lockPrefix}:${item.id}`, async () => {\n      const existing = await kv.get<T>(scope, item.id);\n      if (!existing) {\n        await kv.set(scope, item.id, item);\n        return true;\n      }\n      const existingTs = (existing as Record<string, unknown>)[tsField] as string;\n      if (new Date(ts) > new Date(existingTs)) {\n        await kv.set(scope, item.id, item);\n        return true;\n      }\n      return false;\n    });\n    if (wrote) count++;\n  }\n  return count;\n}\n\nfunction graphNodeTs(node: GraphNode): string {\n  return node.updatedAt || node.createdAt;\n}\n\nasync function lwwMergeGraphNodes(\n  kv: StateKV,\n  items: GraphNode[] | undefined,\n): Promise<number> {\n  if (!items || !Array.isArray(items)) return 0;\n  let count = 0;\n  for (const item of items) {\n    if (!item.id || typeof item.id !== \"string\") continue;\n    const ts = graphNodeTs(item);\n    if (!ts || Number.isNaN(new Date(ts).getTime())) continue;\n    const wrote = await withKeyedLock(`mem:gnode:${item.id}`, async () => {\n      const existing = await kv.get<GraphNode>(KV.graphNodes, item.id);\n      if (!existing) {\n        await kv.set(KV.graphNodes, item.id, item);\n        return true;\n      }\n      if (new Date(ts) > new Date(graphNodeTs(existing))) {\n        await kv.set(KV.graphNodes, item.id, item);\n        return true;\n      }\n      return false;\n    });\n    if (wrote) count++;\n  }\n  return count;\n}\n\nexport function registerMeshFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  meshAuthToken?: string,\n): void {\n  sdk.registerFunction(\"mem::mesh-register\",\n    async (data: {\n      url: string;\n      name: string;\n      sharedScopes?: string[];\n      syncFilter?: { project?: string };\n    }) => {\n      if (!data || typeof data !== \"object\") {\n        return { success: false, error: \"payload required\" };\n      }\n      if (!data.url || !data.name) {\n        return { success: false, error: \"url and name are required\" };\n      }\n\n      if (!(await isAllowedUrl(data.url))) {\n        return { success: false, error: \"URL blocked: private/local address not allowed\" };\n      }\n\n      const existing = await kv.list<MeshPeer>(KV.mesh);\n      const duplicate = existing.find((p) => p.url === data.url);\n      if (duplicate) {\n        return { success: false, error: \"peer already registered\", peerId: duplicate.id };\n      }\n\n      const peer: MeshPeer = {\n        id: generateId(\"peer\"),\n        url: data.url,\n        name: data.name,\n        status: \"disconnected\",\n        sharedScopes: data.sharedScopes || DEFAULT_SHARED_SCOPES,\n        syncFilter: data.syncFilter,\n      };\n\n      await kv.set(KV.mesh, peer.id, peer);\n      await recordAudit(kv, \"mesh_sync\", \"mem::mesh-register\", [peer.id], {\n        action: \"mesh.register\",\n        peerId: peer.id,\n        name: peer.name,\n        url: peer.url,\n        sharedScopes: peer.sharedScopes,\n      });\n      return { success: true, peer };\n    },\n  );\n\n  sdk.registerFunction(\"mem::mesh-list\", \n    async () => {\n      const peers = await kv.list<MeshPeer>(KV.mesh);\n      return { success: true, peers };\n    },\n  );\n\n  sdk.registerFunction(\"mem::mesh-sync\",\n    async (data: { peerId?: string; scopes?: string[]; direction?: \"push\" | \"pull\" | \"both\" }) => {\n      if (!meshAuthToken) {\n        return {\n          success: false,\n          error: \"mesh sync requires AGENTMEMORY_SECRET\",\n        };\n      }\n      if (!data || typeof data !== \"object\") {\n        data = {};\n      }\n\n      const direction = data.direction || \"both\";\n      let peers: MeshPeer[];\n\n      if (data.peerId) {\n        const peer = await kv.get<MeshPeer>(KV.mesh, data.peerId);\n        if (!peer) return { success: false, error: \"peer not found\" };\n        peers = [peer];\n      } else {\n        peers = await kv.list<MeshPeer>(KV.mesh);\n      }\n\n      const results: Array<{\n        peerId: string;\n        peerName: string;\n        pushed: number;\n        pulled: number;\n        errors: string[];\n      }> = [];\n\n      for (const peer of peers) {\n        const result = {\n          peerId: peer.id,\n          peerName: peer.name,\n          pushed: 0,\n          pulled: 0,\n          errors: [] as string[],\n        };\n\n        peer.status = \"syncing\";\n        await kv.set(KV.mesh, peer.id, peer);\n        await recordAudit(kv, \"mesh_sync\", \"mem::mesh-sync\", [peer.id], {\n          action: \"mesh.sync.start\",\n          direction,\n          scopes: data.scopes || peer.sharedScopes,\n        });\n\n        const scopes = data.scopes || peer.sharedScopes;\n\n        try {\n          if (!(await isAllowedUrl(peer.url))) {\n            result.errors.push(\"peer URL blocked: private/local address not allowed\");\n            peer.status = \"error\";\n            await kv.set(KV.mesh, peer.id, peer);\n            await recordAudit(kv, \"mesh_sync\", \"mem::mesh-sync\", [peer.id], {\n              action: \"mesh.sync.error\",\n              error: \"peer URL blocked: private/local address not allowed\",\n            });\n            results.push(result);\n            continue;\n          }\n\n          if (direction === \"push\" || direction === \"both\") {\n            const pushData = await collectSyncData(kv, scopes, peer.lastSyncAt, peer.syncFilter);\n            try {\n              const response = await fetch(`${peer.url}/agentmemory/mesh/receive`, {\n                method: \"POST\",\n                headers: {\n                  \"Content-Type\": \"application/json\",\n                  Authorization: `Bearer ${meshAuthToken}`,\n                },\n                body: JSON.stringify(pushData),\n                signal: AbortSignal.timeout(30000),\n                redirect: \"error\",\n              });\n              if (response.ok) {\n                const body = (await response.json()) as { accepted: number };\n                result.pushed = body.accepted || 0;\n              } else {\n                result.errors.push(`push failed: HTTP ${response.status}`);\n              }\n            } catch (err) {\n              result.errors.push(`push failed: ${String(err)}`);\n            }\n          }\n\n          if (direction === \"pull\" || direction === \"both\") {\n            try {\n              const response = await fetch(\n                `${peer.url}/agentmemory/mesh/export?since=${peer.lastSyncAt || \"\"}`,\n                {\n                  headers: {\n                    Authorization: `Bearer ${meshAuthToken}`,\n                  },\n                  signal: AbortSignal.timeout(30000),\n                  redirect: \"error\",\n                },\n              );\n              if (response.ok) {\n                const pullData = (await response.json()) as {\n                  memories?: Memory[];\n                  actions?: Action[];\n                };\n                result.pulled = await applySyncData(kv, pullData, scopes);\n              } else {\n                result.errors.push(`pull failed: HTTP ${response.status}`);\n              }\n            } catch (err) {\n              result.errors.push(`pull failed: ${String(err)}`);\n            }\n          }\n\n          peer.status = result.errors.length > 0 ? \"error\" : \"connected\";\n          if (result.errors.length === 0) {\n            peer.lastSyncAt = new Date().toISOString();\n          }\n        } catch (err) {\n          peer.status = \"disconnected\";\n          result.errors.push(String(err));\n        }\n\n        await kv.set(KV.mesh, peer.id, peer);\n        await recordAudit(kv, \"mesh_sync\", \"mem::mesh-sync\", [peer.id], {\n          action: result.errors.length > 0 ? \"mesh.sync.error\" : \"mesh.sync.complete\",\n          direction,\n          scopes,\n          pushed: result.pushed,\n          pulled: result.pulled,\n          errors: result.errors,\n          lastSyncAt: peer.lastSyncAt,\n        });\n        results.push(result);\n      }\n\n      return { success: true, results };\n    },\n  );\n\n  sdk.registerFunction(\"mem::mesh-receive\",\n    async (data: MeshSyncPayload) => {\n      if (!data || typeof data !== \"object\") {\n        return { success: false, error: \"payload required\" };\n      }\n      let accepted = 0;\n\n      accepted += await lwwMergeList(kv, KV.memories, data.memories, \"mem:memory\", \"updatedAt\");\n      accepted += await lwwMergeList(kv, KV.actions, data.actions, \"mem:action\", \"updatedAt\");\n      accepted += await lwwMergeList(kv, KV.semantic, data.semantic, \"mem:semantic\", \"updatedAt\");\n      accepted += await lwwMergeList(kv, KV.procedural, data.procedural, \"mem:procedural\", \"updatedAt\");\n      if (data.relations && Array.isArray(data.relations)) {\n        for (const rel of data.relations) {\n          if (!rel.sourceId || !rel.targetId || !rel.type) continue;\n          const relKey = `${rel.sourceId}:${rel.targetId}:${rel.type}`;\n          await withKeyedLock(`mem:relation:${relKey}`, async () => {\n            const existing = await kv.get<MemoryRelation>(KV.relations, relKey);\n            if (!existing) {\n              await kv.set(KV.relations, relKey, rel);\n              await recordAudit(kv, \"mesh_sync\", \"mem::mesh-receive\", [relKey], {\n                action: \"mesh.receive.relation\",\n                accepted: true,\n              });\n              accepted++;\n            }\n          });\n        }\n      }\n      accepted += await lwwMergeGraphNodes(kv, data.graphNodes);\n      accepted += await lwwMergeList(kv, KV.graphEdges, data.graphEdges, \"mem:gedge\", \"createdAt\");\n      await recordAudit(kv, \"mesh_sync\", \"mem::mesh-receive\", [], {\n        action: \"mesh.receive\",\n        accepted,\n      });\n\n      return { success: true, accepted };\n    },\n  );\n\n  sdk.registerFunction(\"mem::mesh-remove\",\n    async (data: { peerId: string }) => {\n      if (!data || typeof data !== \"object\" || !data.peerId) {\n        return { success: false, error: \"peerId is required\" };\n      }\n      await kv.delete(KV.mesh, data.peerId);\n      await recordAudit(kv, \"mesh_sync\", \"mem::mesh-remove\", [data.peerId], {\n        action: \"mesh.remove\",\n      });\n      return { success: true };\n    },\n  );\n}\n\nfunction deltaFilter<T>(\n  items: T[],\n  sinceTime: number,\n  tsField: \"updatedAt\" | \"createdAt\",\n): T[] {\n  return items.filter(\n    (item) => new Date((item as Record<string, unknown>)[tsField] as string).getTime() > sinceTime,\n  );\n}\n\nasync function collectSyncData(\n  kv: StateKV,\n  scopes: string[],\n  since?: string,\n  syncFilter?: { project?: string },\n): Promise<MeshSyncPayload> {\n  const result: MeshSyncPayload = {};\n  const parsed = since ? new Date(since).getTime() : 0;\n  const sinceTime = Number.isNaN(parsed) ? 0 : parsed;\n\n  if (scopes.includes(\"memories\")) {\n    const all = await kv.list<Memory>(KV.memories);\n    result.memories = deltaFilter(all, sinceTime, \"updatedAt\");\n  }\n\n  if (scopes.includes(\"actions\")) {\n    let all = await kv.list<Action>(KV.actions);\n    if (syncFilter?.project) {\n      all = all.filter((a) => a.project === syncFilter.project);\n    }\n    result.actions = deltaFilter(all, sinceTime, \"updatedAt\");\n  }\n\n  const projectScoped = !!syncFilter?.project;\n\n  if (scopes.includes(\"semantic\") && !projectScoped) {\n    const all = await kv.list<SemanticMemory>(KV.semantic);\n    result.semantic = deltaFilter(all, sinceTime, \"updatedAt\");\n  }\n\n  if (scopes.includes(\"procedural\") && !projectScoped) {\n    const all = await kv.list<ProceduralMemory>(KV.procedural);\n    result.procedural = deltaFilter(all, sinceTime, \"updatedAt\");\n  }\n\n  if (scopes.includes(\"relations\") && !projectScoped) {\n    const all = await kv.list<MemoryRelation>(KV.relations);\n    result.relations = deltaFilter(all, sinceTime, \"createdAt\");\n  }\n\n  if (scopes.includes(\"graph:nodes\") && !projectScoped) {\n    const all = await kv.list<GraphNode>(KV.graphNodes);\n    result.graphNodes = all.filter(\n      (n) => new Date(graphNodeTs(n)).getTime() > sinceTime,\n    );\n  }\n\n  if (scopes.includes(\"graph:edges\") && !projectScoped) {\n    const all = await kv.list<GraphEdge>(KV.graphEdges);\n    result.graphEdges = deltaFilter(all, sinceTime, \"createdAt\");\n  }\n\n  return result;\n}\n\nasync function applySyncData(\n  kv: StateKV,\n  data: MeshSyncPayload,\n  scopes: string[],\n): Promise<number> {\n  let applied = 0;\n\n  if (scopes.includes(\"memories\")) {\n    applied += await lwwMergeList(kv, KV.memories, data.memories, \"mem:memory\", \"updatedAt\");\n  }\n  if (scopes.includes(\"actions\")) {\n    applied += await lwwMergeList(kv, KV.actions, data.actions, \"mem:action\", \"updatedAt\");\n  }\n  if (scopes.includes(\"semantic\")) {\n    applied += await lwwMergeList(kv, KV.semantic, data.semantic, \"mem:semantic\", \"updatedAt\");\n  }\n  if (scopes.includes(\"procedural\")) {\n    applied += await lwwMergeList(kv, KV.procedural, data.procedural, \"mem:procedural\", \"updatedAt\");\n  }\n  if (scopes.includes(\"relations\") && data.relations) {\n    for (const rel of data.relations) {\n      if (!rel.sourceId || !rel.targetId || !rel.type) continue;\n      const relKey = `${rel.sourceId}:${rel.targetId}:${rel.type}`;\n      const wrote = await withKeyedLock(`mem:relation:${relKey}`, async () => {\n        const existing = await kv.get<MemoryRelation>(KV.relations, relKey);\n        if (!existing) {\n          await kv.set(KV.relations, relKey, rel);\n          return true;\n        }\n        return false;\n      });\n      if (wrote) applied++;\n    }\n  }\n  if (scopes.includes(\"graph:nodes\")) {\n    applied += await lwwMergeGraphNodes(kv, data.graphNodes);\n  }\n  if (scopes.includes(\"graph:edges\")) {\n    applied += await lwwMergeList(kv, KV.graphEdges, data.graphEdges, \"mem:gedge\", \"createdAt\");\n  }\n\n  return applied;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport type { Session } from \"../types.js\";\nimport { execFile } from \"node:child_process\";\nimport { resolve } from \"node:path\";\n\nfunction execAsync(\n  cmd: string,\n  args: string[],\n  cwd: string,\n): Promise<string> {\n  return new Promise((resolve, reject) => {\n    execFile(cmd, args, { cwd, timeout: 5000 }, (err, stdout) => {\n      if (err) reject(err);\n      else resolve(stdout.trim());\n    });\n  });\n}\n\nexport function registerBranchAwareFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::detect-worktree\", \n    async (data: { cwd: string }) => {\n      if (!data.cwd) {\n        return { success: false, error: \"cwd is required\" };\n      }\n\n      try {\n        const gitDir = await execAsync(\n          \"git\",\n          [\"rev-parse\", \"--git-dir\"],\n          data.cwd,\n        );\n        const commonDir = await execAsync(\n          \"git\",\n          [\"rev-parse\", \"--git-common-dir\"],\n          data.cwd,\n        );\n        const branch = await execAsync(\n          \"git\",\n          [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"],\n          data.cwd,\n        ).catch(() => \"detached\");\n\n        const topLevel = await execAsync(\n          \"git\",\n          [\"rev-parse\", \"--show-toplevel\"],\n          data.cwd,\n        );\n\n        const isWorktree = resolve(data.cwd, gitDir) !== resolve(data.cwd, commonDir);\n        const mainRepoRoot = isWorktree\n          ? resolve(data.cwd, commonDir, \"..\")\n          : topLevel;\n\n        return {\n          success: true,\n          isWorktree,\n          branch,\n          topLevel,\n          mainRepoRoot,\n          gitDir: resolve(data.cwd, gitDir),\n          commonDir: resolve(data.cwd, commonDir),\n        };\n      } catch {\n        return {\n          success: true,\n          isWorktree: false,\n          branch: null,\n          topLevel: data.cwd,\n          mainRepoRoot: data.cwd,\n          gitDir: null,\n          commonDir: null,\n        };\n      }\n    },\n  );\n\n  sdk.registerFunction(\"mem::list-worktrees\", \n    async (data: { cwd: string }) => {\n      if (!data.cwd) {\n        return { success: false, error: \"cwd is required\" };\n      }\n\n      try {\n        const output = await execAsync(\n          \"git\",\n          [\"worktree\", \"list\", \"--porcelain\"],\n          data.cwd,\n        );\n\n        const worktrees: Array<{\n          path: string;\n          head: string;\n          branch: string;\n          bare: boolean;\n        }> = [];\n\n        const blocks = output.split(\"\\n\\n\").filter(Boolean);\n        for (const block of blocks) {\n          const lines = block.split(\"\\n\");\n          const wt: { path: string; head: string; branch: string; bare: boolean } = {\n            path: \"\",\n            head: \"\",\n            branch: \"\",\n            bare: false,\n          };\n          for (const line of lines) {\n            if (line.startsWith(\"worktree \")) wt.path = line.slice(9);\n            else if (line.startsWith(\"HEAD \")) wt.head = line.slice(5);\n            else if (line.startsWith(\"branch \"))\n              wt.branch = line.slice(7).replace(\"refs/heads/\", \"\");\n            else if (line === \"bare\") wt.bare = true;\n          }\n          if (wt.path) worktrees.push(wt);\n        }\n\n        return { success: true, worktrees };\n      } catch {\n        return { success: true, worktrees: [] };\n      }\n    },\n  );\n\n  sdk.registerFunction(\"mem::branch-sessions\", \n    async (data: { cwd: string; branch?: string }) => {\n      if (!data.cwd) {\n        return { success: false, error: \"cwd is required\" };\n      }\n\n      const worktreeInfo = await sdk.trigger<\n        { cwd: string },\n        {\n          success: boolean;\n          isWorktree: boolean;\n          mainRepoRoot: string;\n          branch: string | null;\n        }\n      >({ function_id: \"mem::detect-worktree\", payload: { cwd: data.cwd } });\n\n      const projectRoot = worktreeInfo.mainRepoRoot || data.cwd;\n      const branch = data.branch || worktreeInfo.branch;\n\n      const sessions = await kv.list<Session>(KV.sessions);\n\n      const matching = sessions.filter((s) => {\n        if (s.project === projectRoot || s.cwd === projectRoot) return true;\n        if (s.cwd.startsWith(projectRoot + \"/\")) return true;\n        return false;\n      });\n\n      matching.sort(\n        (a, b) =>\n          new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime(),\n      );\n\n      return {\n        success: true,\n        sessions: matching,\n        projectRoot,\n        branch,\n        isWorktree: worktreeInfo.isWorktree,\n      };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport type { Action, ActionEdge, Checkpoint, CompressedObservation, FunctionMetrics, Sentinel, Session } from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\n\nconst VALID_TYPES: Sentinel[\"type\"][] = [\n  \"webhook\",\n  \"timer\",\n  \"threshold\",\n  \"pattern\",\n  \"approval\",\n  \"custom\",\n];\n\nexport function registerSentinelsFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::sentinel-create\", \n    async (data: {\n      name: string;\n      type: Sentinel[\"type\"];\n      config?: Record<string, unknown>;\n      linkedActionIds?: string[];\n      expiresInMs?: number;\n    }) => {\n      if (!data.name || typeof data.name !== \"string\") {\n        return { success: false, error: \"name is required\" };\n      }\n      if (!data.type || !VALID_TYPES.includes(data.type)) {\n        return {\n          success: false,\n          error: `type must be one of: ${VALID_TYPES.join(\", \")}`,\n        };\n      }\n\n      if (data.type === \"threshold\") {\n        const cfg = data.config as\n          | { metric?: string; operator?: string; value?: number }\n          | undefined;\n        if (\n          !cfg ||\n          !cfg.metric ||\n          ![\"gt\", \"lt\", \"eq\"].includes(cfg.operator || \"\") ||\n          typeof cfg.value !== \"number\"\n        ) {\n          return {\n            success: false,\n            error:\n              \"threshold config requires metric, operator (gt|lt|eq), and numeric value\",\n          };\n        }\n      }\n\n      if (data.type === \"pattern\") {\n        const cfg = data.config as { pattern?: string } | undefined;\n        if (!cfg || !cfg.pattern || typeof cfg.pattern !== \"string\") {\n          return {\n            success: false,\n            error: \"pattern config requires a pattern string\",\n          };\n        }\n      }\n\n      if (data.type === \"webhook\") {\n        const cfg = data.config as { path?: string } | undefined;\n        if (!cfg || !cfg.path || typeof cfg.path !== \"string\") {\n          return {\n            success: false,\n            error: \"webhook config requires a path string\",\n          };\n        }\n      }\n\n      if (data.type === \"timer\") {\n        const cfg = data.config as { durationMs?: number } | undefined;\n        if (!cfg || typeof cfg.durationMs !== \"number\" || cfg.durationMs <= 0) {\n          return {\n            success: false,\n            error: \"timer config requires a positive durationMs\",\n          };\n        }\n      }\n\n      if (data.linkedActionIds && data.linkedActionIds.length > 0) {\n        for (const actionId of data.linkedActionIds) {\n          const action = await kv.get<Action>(KV.actions, actionId);\n          if (!action) {\n            return {\n              success: false,\n              error: `linked action not found: ${actionId}`,\n            };\n          }\n        }\n      }\n\n      const now = new Date();\n      const sentinel: Sentinel = {\n        id: generateId(\"snl\"),\n        name: data.name.trim(),\n        type: data.type,\n        status: \"watching\",\n        config: data.config || {},\n        createdAt: now.toISOString(),\n        linkedActionIds: data.linkedActionIds || [],\n        expiresAt: data.expiresInMs\n          ? new Date(now.getTime() + data.expiresInMs).toISOString()\n          : undefined,\n      };\n\n      await kv.set(KV.sentinels, sentinel.id, sentinel);\n      await recordAudit(kv, \"sentinel_create\", \"mem::sentinel-create\", [sentinel.id], {\n        action: \"sentinel.create\",\n        type: sentinel.type,\n        linkedActionIds: sentinel.linkedActionIds,\n      });\n\n      if (data.linkedActionIds && data.linkedActionIds.length > 0) {\n        for (const actionId of data.linkedActionIds) {\n          const edge: ActionEdge = {\n            id: generateId(\"ae\"),\n            type: \"gated_by\",\n            sourceActionId: actionId,\n            targetActionId: sentinel.id,\n            createdAt: now.toISOString(),\n          };\n          await kv.set(KV.actionEdges, edge.id, edge);\n          await recordAudit(kv, \"sentinel_create\", \"mem::sentinel-create\", [edge.id], {\n            action: \"sentinel.create.edge\",\n            sentinelId: sentinel.id,\n            sourceActionId: actionId,\n          });\n        }\n      }\n\n      if (data.type === \"timer\") {\n        const durationMs = (data.config as { durationMs: number }).durationMs;\n        setTimeout(async () => {\n          try {\n            await withKeyedLock(`mem:sentinel:${sentinel.id}`, async () => {\n              const fresh = await kv.get<Sentinel>(KV.sentinels, sentinel.id);\n              if (!fresh || fresh.status !== \"watching\") return;\n              fresh.status = \"triggered\";\n              fresh.triggeredAt = new Date().toISOString();\n              fresh.result = { reason: \"timer_elapsed\", durationMs };\n              await kv.set(KV.sentinels, fresh.id, fresh);\n              await recordAudit(kv, \"sentinel_trigger\", \"mem::sentinel-create\", [fresh.id], {\n                action: \"sentinel.timer_trigger\",\n                reason: \"timer_elapsed\",\n                durationMs,\n              });\n              await unblockLinkedActions(kv, fresh);\n            });\n          } catch (err) {\n            console.error(\"sentinel timer callback failed\", sentinel.id, err);\n          }\n        }, durationMs);\n      }\n\n      return { success: true, sentinel };\n    },\n  );\n\n  sdk.registerFunction(\"mem::sentinel-trigger\", \n    async (data: { sentinelId: string; result?: unknown }) => {\n      if (!data.sentinelId) {\n        return { success: false, error: \"sentinelId is required\" };\n      }\n\n      return withKeyedLock(\n        `mem:sentinel:${data.sentinelId}`,\n        async () => {\n          const sentinel = await kv.get<Sentinel>(\n            KV.sentinels,\n            data.sentinelId,\n          );\n          if (!sentinel) {\n            return { success: false, error: \"sentinel not found\" };\n          }\n          if (sentinel.status !== \"watching\") {\n            return {\n              success: false,\n              error: `sentinel already ${sentinel.status}`,\n            };\n          }\n\n          sentinel.status = \"triggered\";\n          sentinel.triggeredAt = new Date().toISOString();\n          sentinel.result = data.result;\n\n          await kv.set(KV.sentinels, sentinel.id, sentinel);\n          await recordAudit(kv, \"sentinel_trigger\", \"mem::sentinel-trigger\", [sentinel.id], {\n            action: \"sentinel.trigger\",\n            result: data.result,\n          });\n\n          let unblockedCount = 0;\n          if (sentinel.linkedActionIds.length > 0) {\n            unblockedCount = await unblockLinkedActions(kv, sentinel);\n          }\n\n          return { success: true, sentinel, unblockedCount };\n        },\n      );\n    },\n  );\n\n  sdk.registerFunction(\"mem::sentinel-check\", \n    async () => {\n      const sentinels = await kv.list<Sentinel>(KV.sentinels);\n      const active = sentinels.filter((s) => s.status === \"watching\");\n      const triggered: string[] = [];\n\n      for (const sentinel of active) {\n        if (sentinel.type === \"threshold\") {\n          const cfg = sentinel.config as {\n            metric: string;\n            operator: \"gt\" | \"lt\" | \"eq\";\n            value: number;\n          };\n          const metrics = await kv.get<FunctionMetrics>(\n            KV.metrics,\n            cfg.metric,\n          );\n          if (!metrics) continue;\n\n          const current = metrics.totalCalls;\n          let matched = false;\n          if (cfg.operator === \"gt\") matched = current > cfg.value;\n          else if (cfg.operator === \"lt\") matched = current < cfg.value;\n          else if (cfg.operator === \"eq\") matched = current === cfg.value;\n\n          if (matched) {\n            await withKeyedLock(\n              `mem:sentinel:${sentinel.id}`,\n              async () => {\n                const fresh = await kv.get<Sentinel>(\n                  KV.sentinels,\n                  sentinel.id,\n                );\n                if (!fresh || fresh.status !== \"watching\") return;\n                fresh.status = \"triggered\";\n                fresh.triggeredAt = new Date().toISOString();\n                fresh.result = {\n                  reason: \"threshold_crossed\",\n                  metric: cfg.metric,\n                  currentValue: current,\n                  threshold: cfg.value,\n                  operator: cfg.operator,\n                };\n                await kv.set(KV.sentinels, fresh.id, fresh);\n                await recordAudit(kv, \"sentinel_trigger\", \"mem::sentinel-check\", [fresh.id], {\n                  action: \"sentinel.threshold_trigger\",\n                  result: fresh.result,\n                });\n                await unblockLinkedActions(kv, fresh);\n              },\n            );\n            triggered.push(sentinel.id);\n          }\n        }\n\n        if (sentinel.type === \"pattern\") {\n          const cfg = sentinel.config as { pattern: string };\n          const regex = new RegExp(cfg.pattern, \"i\");\n          const sessions = await kv.list<Session>(KV.sessions);\n          let matchedObs: CompressedObservation | null = null;\n\n          for (const session of sessions) {\n            const observations = await kv.list<CompressedObservation>(\n              KV.observations(session.id),\n            );\n            const recent = observations\n              .filter(\n                (o) =>\n                  new Date(o.timestamp).getTime() >=\n                  new Date(sentinel.createdAt).getTime(),\n              )\n              .find((o) => regex.test(o.title));\n            if (recent) {\n              matchedObs = recent;\n              break;\n            }\n          }\n\n          if (matchedObs) {\n            await withKeyedLock(\n              `mem:sentinel:${sentinel.id}`,\n              async () => {\n                const fresh = await kv.get<Sentinel>(\n                  KV.sentinels,\n                  sentinel.id,\n                );\n                if (!fresh || fresh.status !== \"watching\") return;\n                fresh.status = \"triggered\";\n                fresh.triggeredAt = new Date().toISOString();\n                fresh.result = {\n                  reason: \"pattern_matched\",\n                  pattern: cfg.pattern,\n                  matchedObservationId: matchedObs!.id,\n                  matchedTitle: matchedObs!.title,\n                };\n                await kv.set(KV.sentinels, fresh.id, fresh);\n                await recordAudit(kv, \"sentinel_trigger\", \"mem::sentinel-check\", [fresh.id], {\n                  action: \"sentinel.pattern_trigger\",\n                  result: fresh.result,\n                });\n                await unblockLinkedActions(kv, fresh);\n              },\n            );\n            triggered.push(sentinel.id);\n          }\n        }\n      }\n\n      return { success: true, triggered, checkedCount: active.length };\n    },\n  );\n\n  sdk.registerFunction(\"mem::sentinel-cancel\", \n    async (data: { sentinelId: string }) => {\n      if (!data.sentinelId) {\n        return { success: false, error: \"sentinelId is required\" };\n      }\n\n      return withKeyedLock(\n        `mem:sentinel:${data.sentinelId}`,\n        async () => {\n          const sentinel = await kv.get<Sentinel>(\n            KV.sentinels,\n            data.sentinelId,\n          );\n          if (!sentinel) {\n            return { success: false, error: \"sentinel not found\" };\n          }\n          if (sentinel.status !== \"watching\") {\n            return {\n              success: false,\n              error: `cannot cancel sentinel with status ${sentinel.status}`,\n            };\n          }\n\n          sentinel.status = \"cancelled\";\n          await kv.set(KV.sentinels, sentinel.id, sentinel);\n          await recordAudit(kv, \"sentinel_trigger\", \"mem::sentinel-cancel\", [sentinel.id], {\n            action: \"sentinel.cancel\",\n            status: \"cancelled\",\n          });\n\n          return { success: true, sentinel };\n        },\n      );\n    },\n  );\n\n  sdk.registerFunction(\"mem::sentinel-list\", \n    async (data: { status?: string; type?: string }) => {\n      let sentinels = await kv.list<Sentinel>(KV.sentinels);\n\n      if (data.status) {\n        sentinels = sentinels.filter((s) => s.status === data.status);\n      }\n      if (data.type) {\n        sentinels = sentinels.filter((s) => s.type === data.type);\n      }\n\n      sentinels.sort(\n        (a, b) =>\n          new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),\n      );\n\n      return { success: true, sentinels };\n    },\n  );\n\n  sdk.registerFunction(\"mem::sentinel-expire\", \n    async () => {\n      const sentinels = await kv.list<Sentinel>(KV.sentinels);\n      const now = Date.now();\n      let expired = 0;\n\n      for (const sentinel of sentinels) {\n        if (\n          sentinel.status === \"watching\" &&\n          sentinel.expiresAt &&\n          new Date(sentinel.expiresAt).getTime() <= now\n        ) {\n          const didExpire = await withKeyedLock(\n            `mem:sentinel:${sentinel.id}`,\n            async () => {\n              const fresh = await kv.get<Sentinel>(\n                KV.sentinels,\n                sentinel.id,\n              );\n              if (!fresh || fresh.status !== \"watching\") return false;\n              fresh.status = \"expired\";\n              fresh.triggeredAt = new Date().toISOString();\n              await kv.set(KV.sentinels, fresh.id, fresh);\n              await recordAudit(kv, \"sentinel_trigger\", \"mem::sentinel-expire\", [fresh.id], {\n                action: \"sentinel.expire\",\n                status: \"expired\",\n              });\n              return true;\n            },\n          );\n          if (didExpire) expired++;\n        }\n      }\n\n      return { success: true, expired };\n    },\n  );\n}\n\nasync function unblockLinkedActions(\n  kv: StateKV,\n  sentinel: Sentinel,\n): Promise<number> {\n  if (sentinel.linkedActionIds.length === 0) return 0;\n\n  const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n  const allSentinels = await kv.list<Sentinel>(KV.sentinels);\n  const allCheckpoints = await kv.list<Checkpoint>(KV.checkpoints);\n  const gateMap = new Map<string, { status: string }>();\n  for (const s of allSentinels) gateMap.set(s.id, { status: s.status === \"triggered\" ? \"passed\" : s.status });\n  for (const c of allCheckpoints) gateMap.set(c.id, { status: c.status });\n\n  let unblockedCount = 0;\n\n  for (const actionId of sentinel.linkedActionIds) {\n    await withKeyedLock(`mem:action:${actionId}`, async () => {\n      const action = await kv.get<Action>(KV.actions, actionId);\n      if (action && action.status === \"blocked\") {\n        const gates = allEdges.filter(\n          (e) => e.sourceActionId === actionId && e.type === \"gated_by\",\n        );\n        const allPassed = gates.every((g) => {\n          const gate = gateMap.get(g.targetActionId);\n          return gate && gate.status === \"passed\";\n        });\n        if (allPassed) {\n          action.status = \"pending\";\n          action.updatedAt = new Date().toISOString();\n          await kv.set(KV.actions, action.id, action);\n          await recordAudit(kv, \"action_update\", \"mem::sentinel-unblock\", [action.id], {\n            action: \"action.unblocked\",\n            sentinelId: sentinel.id,\n          });\n          unblockedCount++;\n        }\n      }\n    });\n  }\n\n  return unblockedCount;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport type { Action, ActionEdge, Sketch } from \"../types.js\";\nimport { safeAudit } from \"./audit.js\";\n\nexport function registerSketchesFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::sketch-create\", \n    async (data: {\n      title: string;\n      description?: string;\n      expiresInMs?: number;\n      project?: string;\n    }) => {\n      if (!data.title || typeof data.title !== \"string\") {\n        return { success: false, error: \"title is required\" };\n      }\n\n      const now = new Date();\n      const expiresInMs = data.expiresInMs || 3600000;\n      const sketch: Sketch = {\n        id: generateId(\"sk\"),\n        title: data.title.trim(),\n        description: (data.description || \"\").trim(),\n        status: \"active\",\n        actionIds: [],\n        project: data.project,\n        createdAt: now.toISOString(),\n        expiresAt: new Date(now.getTime() + expiresInMs).toISOString(),\n      };\n\n      await kv.set(KV.sketches, sketch.id, sketch);\n      await safeAudit(kv, \"sketch_create\", \"mem::sketch-create\", [sketch.id], {\n        action: \"create\",\n        title: sketch.title,\n      });\n      return { success: true, sketch };\n    },\n  );\n\n  sdk.registerFunction(\"mem::sketch-add\", \n    async (data: {\n      sketchId: string;\n      title: string;\n      description?: string;\n      priority?: number;\n      dependsOn?: string[];\n    }) => {\n      if (!data.sketchId) {\n        return { success: false, error: \"sketchId is required\" };\n      }\n      if (!data.title || typeof data.title !== \"string\") {\n        return { success: false, error: \"title is required\" };\n      }\n\n      return withKeyedLock(`mem:sketch:${data.sketchId}`, async () => {\n        const sketch = await kv.get<Sketch>(KV.sketches, data.sketchId);\n        if (!sketch) {\n          return { success: false, error: \"sketch not found\" };\n        }\n        if (sketch.status !== \"active\") {\n          return { success: false, error: \"sketch is not active\" };\n        }\n\n        const now = new Date().toISOString();\n        const action: Action = {\n          id: generateId(\"act\"),\n          title: data.title.trim(),\n          description: (data.description || \"\").trim(),\n          status: \"pending\",\n          priority: Math.max(1, Math.min(10, data.priority || 5)),\n          createdAt: now,\n          updatedAt: now,\n          createdBy: \"sketch\",\n          project: sketch.project,\n          tags: [],\n          sourceObservationIds: [],\n          sourceMemoryIds: [],\n          sketchId: data.sketchId,\n        };\n\n        if (data.dependsOn && data.dependsOn.length > 0) {\n          const sketchActionSet = new Set(sketch.actionIds);\n          for (const depId of data.dependsOn) {\n            if (!sketchActionSet.has(depId)) {\n              return {\n                success: false,\n                error: `dependency ${depId} not found in this sketch`,\n              };\n            }\n          }\n        }\n\n        await kv.set(KV.actions, action.id, action);\n        await safeAudit(kv, \"sketch_create\", \"mem::sketch-add\", [action.id], {\n          action: \"add.action\",\n          sketchId: sketch.id,\n        });\n\n        const createdEdges: ActionEdge[] = [];\n        if (data.dependsOn && data.dependsOn.length > 0) {\n          for (const depId of data.dependsOn) {\n            const edge: ActionEdge = {\n              id: generateId(\"ae\"),\n              type: \"requires\",\n              sourceActionId: action.id,\n              targetActionId: depId,\n              createdAt: now,\n            };\n            await kv.set(KV.actionEdges, edge.id, edge);\n            await safeAudit(kv, \"sketch_create\", \"mem::sketch-add\", [edge.id], {\n              action: \"add.edge\",\n              sketchId: sketch.id,\n            });\n            createdEdges.push(edge);\n          }\n        }\n\n        sketch.actionIds.push(action.id);\n        await kv.set(KV.sketches, sketch.id, sketch);\n        await safeAudit(kv, \"sketch_create\", \"mem::sketch-add\", [sketch.id], {\n          action: \"add.sketch-update\",\n          addedActionId: action.id,\n        });\n\n        return { success: true, action, edges: createdEdges };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::sketch-promote\", \n    async (data: { sketchId: string; project?: string }) => {\n      if (!data.sketchId) {\n        return { success: false, error: \"sketchId is required\" };\n      }\n\n      return withKeyedLock(`mem:sketch:${data.sketchId}`, async () => {\n        const sketch = await kv.get<Sketch>(KV.sketches, data.sketchId);\n        if (!sketch) {\n          return { success: false, error: \"sketch not found\" };\n        }\n        if (sketch.status !== \"active\") {\n          return { success: false, error: \"sketch is not active\" };\n        }\n\n        const promotedIds: string[] = [];\n        for (const actionId of sketch.actionIds) {\n          const action = await kv.get<Action>(KV.actions, actionId);\n          if (action) {\n            delete action.sketchId;\n            if (data.project) {\n              action.project = data.project;\n            }\n            action.updatedAt = new Date().toISOString();\n            await kv.set(KV.actions, action.id, action);\n            await safeAudit(kv, \"sketch_promote\", \"mem::sketch-promote\", [action.id], {\n              action: \"promote.action\",\n              sketchId: sketch.id,\n            });\n            promotedIds.push(action.id);\n          }\n        }\n\n        sketch.status = \"promoted\";\n        sketch.promotedAt = new Date().toISOString();\n        await kv.set(KV.sketches, sketch.id, sketch);\n        await safeAudit(kv, \"sketch_promote\", \"mem::sketch-promote\", [sketch.id], {\n          action: \"promote.sketch\",\n          promotedIds,\n        });\n\n        return { success: true, promotedIds };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::sketch-discard\", \n    async (data: { sketchId: string }) => {\n      if (!data.sketchId) {\n        return { success: false, error: \"sketchId is required\" };\n      }\n\n      return withKeyedLock(`mem:sketch:${data.sketchId}`, async () => {\n        const sketch = await kv.get<Sketch>(KV.sketches, data.sketchId);\n        if (!sketch) {\n          return { success: false, error: \"sketch not found\" };\n        }\n        if (sketch.status !== \"active\") {\n          return { success: false, error: \"sketch is not active\" };\n        }\n\n        const actionIdSet = new Set(sketch.actionIds);\n\n        const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n        for (const edge of allEdges) {\n          if (\n            actionIdSet.has(edge.sourceActionId) ||\n            actionIdSet.has(edge.targetActionId)\n          ) {\n            await kv.delete(KV.actionEdges, edge.id);\n            await safeAudit(kv, \"sketch_discard\", \"mem::sketch-discard\", [edge.id], {\n              action: \"discard.edge\",\n              sketchId: sketch.id,\n            });\n          }\n        }\n\n        for (const actionId of sketch.actionIds) {\n          await kv.delete(KV.actions, actionId);\n          await safeAudit(kv, \"sketch_discard\", \"mem::sketch-discard\", [actionId], {\n            action: \"discard.action\",\n            sketchId: sketch.id,\n          });\n        }\n\n        sketch.status = \"discarded\";\n        sketch.discardedAt = new Date().toISOString();\n        await kv.set(KV.sketches, sketch.id, sketch);\n        await safeAudit(kv, \"sketch_discard\", \"mem::sketch-discard\", [sketch.id], {\n          action: \"discard.sketch\",\n        });\n\n        return { success: true, discardedCount: sketch.actionIds.length };\n      });\n    },\n  );\n\n  sdk.registerFunction(\"mem::sketch-list\", \n    async (data: { status?: string; project?: string }) => {\n      let sketches = await kv.list<Sketch>(KV.sketches);\n\n      if (data.status) {\n        sketches = sketches.filter((s) => s.status === data.status);\n      }\n      if (data.project) {\n        sketches = sketches.filter((s) => s.project === data.project);\n      }\n\n      sketches.sort(\n        (a, b) =>\n          new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),\n      );\n\n      const results = sketches.map((s) => ({\n        ...s,\n        actionCount: s.actionIds.length,\n      }));\n\n      return { success: true, sketches: results };\n    },\n  );\n\n  sdk.registerFunction(\"mem::sketch-gc\", \n    async () => {\n      const sketches = await kv.list<Sketch>(KV.sketches);\n      const now = Date.now();\n      let collected = 0;\n\n      for (const sketch of sketches) {\n        if (\n          sketch.status !== \"active\" ||\n          new Date(sketch.expiresAt).getTime() > now\n        ) {\n          continue;\n        }\n\n        await withKeyedLock(`mem:sketch:${sketch.id}`, async () => {\n          const current = await kv.get<Sketch>(KV.sketches, sketch.id);\n          if (\n            !current ||\n            current.status !== \"active\" ||\n            new Date(current.expiresAt).getTime() > now\n          ) {\n            return;\n          }\n\n          const actionIdSet = new Set(current.actionIds);\n\n          const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n          for (const edge of allEdges) {\n            if (\n              actionIdSet.has(edge.sourceActionId) ||\n              actionIdSet.has(edge.targetActionId)\n            ) {\n              await kv.delete(KV.actionEdges, edge.id);\n              await safeAudit(kv, \"sketch_discard\", \"mem::sketch-gc\", [edge.id], {\n                action: \"gc.edge\",\n                sketchId: current.id,\n              });\n            }\n          }\n\n          for (const actionId of current.actionIds) {\n            await kv.delete(KV.actions, actionId);\n            await safeAudit(kv, \"sketch_discard\", \"mem::sketch-gc\", [actionId], {\n              action: \"gc.action\",\n              sketchId: current.id,\n            });\n          }\n\n          current.status = \"discarded\";\n          current.discardedAt = new Date().toISOString();\n          await kv.set(KV.sketches, current.id, current);\n          await safeAudit(kv, \"sketch_discard\", \"mem::sketch-gc\", [current.id], {\n            action: \"gc.sketch\",\n          });\n          collected++;\n        });\n      }\n\n      return { success: true, collected };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { Action, ActionEdge, Crystal, MemoryProvider } from \"../types.js\";\n\ninterface CrystalDigest {\n  narrative: string;\n  keyOutcomes: string[];\n  filesAffected: string[];\n  lessons: string[];\n}\n\nconst CRYSTALLIZE_SYSTEM = `You are summarizing a completed chain of agent actions into a compact digest.\nExtract: (1) what was accomplished in 1-2 sentences, (2) key decisions as bullet points,\n(3) files affected, (4) any lessons or patterns worth remembering.\nReturn as JSON: { \"narrative\": \"...\", \"keyOutcomes\": [\"...\"], \"filesAffected\": [\"...\"], \"lessons\": [\"...\"] }`;\n\nexport function registerCrystallizeFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\"mem::crystallize\", \n    async (data: {\n      actionIds: string[];\n      sessionId?: string;\n      project?: string;\n    }) => {\n      if (!data.actionIds || data.actionIds.length === 0) {\n        return { success: false, error: \"actionIds is required\" };\n      }\n\n      const actions: Action[] = [];\n      for (const id of data.actionIds) {\n        const action = await kv.get<Action>(KV.actions, id);\n        if (!action) {\n          return { success: false, error: `action not found: ${id}` };\n        }\n        if (action.status !== \"done\" && action.status !== \"cancelled\") {\n          return {\n            success: false,\n            error: `action ${id} has status \"${action.status}\", expected \"done\" or \"cancelled\"`,\n          };\n        }\n        actions.push(action);\n      }\n\n      const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n      const idSet = new Set(data.actionIds);\n      const relevantEdges = allEdges.filter(\n        (e) => idSet.has(e.sourceActionId) || idSet.has(e.targetActionId),\n      );\n\n      const prompt = buildChainText(actions, relevantEdges);\n\n      try {\n        const response = await provider.summarize(CRYSTALLIZE_SYSTEM, prompt);\n        const digest = parseDigest(response);\n\n        const crystal: Crystal = {\n          id: generateId(\"crys\"),\n          narrative: digest.narrative,\n          keyOutcomes: digest.keyOutcomes,\n          filesAffected: digest.filesAffected,\n          lessons: digest.lessons,\n          sourceActionIds: data.actionIds,\n          sessionId: data.sessionId,\n          project: data.project,\n          createdAt: new Date().toISOString(),\n        };\n\n        await kv.set(KV.crystals, crystal.id, crystal);\n\n        await Promise.all(\n          digest.lessons.map((lesson) =>\n            sdk\n              .trigger({\n                function_id: \"mem::lesson-save\",\n                payload: {\n                  content: lesson,\n                  context: crystal.narrative,\n                  confidence: 0.6,\n                  project: data.project,\n                  tags: [],\n                  source: \"crystal\",\n                  sourceIds: [crystal.id],\n                },\n              })\n              .catch(() => {}),\n          ),\n        );\n\n        for (const action of actions) {\n          const updated = { ...action, crystallizedInto: crystal.id };\n          await kv.set(KV.actions, action.id, updated);\n        }\n\n        return { success: true, crystal };\n      } catch (err) {\n        return {\n          success: false,\n          error: `crystallization failed: ${String(err)}`,\n        };\n      }\n    },\n  );\n\n  sdk.registerFunction(\"mem::crystal-list\", \n    async (data: {\n      project?: string;\n      sessionId?: string;\n      limit?: number;\n    }) => {\n      const limit = data.limit ?? 20;\n      let crystals = await kv.list<Crystal>(KV.crystals);\n\n      if (data.project) {\n        crystals = crystals.filter((c) => c.project === data.project);\n      }\n      if (data.sessionId) {\n        crystals = crystals.filter((c) => c.sessionId === data.sessionId);\n      }\n\n      crystals.sort(\n        (a, b) =>\n          new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),\n      );\n\n      return { success: true, crystals: crystals.slice(0, limit) };\n    },\n  );\n\n  sdk.registerFunction(\"mem::crystal-get\", \n    async (data: { crystalId: string }) => {\n      if (!data.crystalId) {\n        return { success: false, error: \"crystalId is required\" };\n      }\n\n      const crystal = await kv.get<Crystal>(KV.crystals, data.crystalId);\n      if (!crystal) {\n        return { success: false, error: \"crystal not found\" };\n      }\n\n      return { success: true, crystal };\n    },\n  );\n\n  sdk.registerFunction(\"mem::auto-crystallize\", \n    async (data: {\n      olderThanDays?: number;\n      project?: string;\n      dryRun?: boolean;\n    }) => {\n      const olderThanDays = data.olderThanDays ?? 7;\n      const dryRun = data.dryRun ?? false;\n      const cutoff = Date.now() - olderThanDays * 24 * 60 * 60 * 1000;\n\n      let allActions = await kv.list<Action>(KV.actions);\n\n      allActions = allActions.filter(\n        (a) =>\n          a.status === \"done\" &&\n          !a.crystallizedInto &&\n          new Date(a.createdAt).getTime() < cutoff,\n      );\n\n      if (data.project) {\n        allActions = allActions.filter((a) => a.project === data.project);\n      }\n\n      if (allActions.length === 0) {\n        return { success: true, groupCount: 0, crystalIds: [] };\n      }\n\n      const groups = new Map<string, Action[]>();\n      for (const action of allActions) {\n        const key = action.parentId ?? action.project ?? \"_ungrouped\";\n        const group = groups.get(key);\n        if (group) {\n          group.push(action);\n        } else {\n          groups.set(key, [action]);\n        }\n      }\n\n      if (dryRun) {\n        const groupSummaries = Array.from(groups.entries()).map(\n          ([key, actions]) => ({\n            groupKey: key,\n            actionCount: actions.length,\n            actionIds: actions.map((a) => a.id),\n          }),\n        );\n        return {\n          success: true,\n          dryRun: true,\n          groupCount: groups.size,\n          groups: groupSummaries,\n          crystalIds: [],\n        };\n      }\n\n      const crystalIds: string[] = [];\n      for (const [, groupActions] of groups) {\n        const actionIds = groupActions.map((a) => a.id);\n        const project = groupActions[0].project;\n\n        try {\n          const result = (await sdk.trigger({ function_id: \"mem::crystallize\", payload: {\n            actionIds,\n            project,\n          } })) as { success: boolean; crystal?: Crystal };\n\n          if (result.success && result.crystal) {\n            crystalIds.push(result.crystal.id);\n          }\n        } catch {\n          continue;\n        }\n      }\n\n      return {\n        success: true,\n        groupCount: groups.size,\n        crystalIds,\n      };\n    },\n  );\n}\n\nfunction buildChainText(actions: Action[], edges: ActionEdge[]): string {\n  const lines: string[] = [\"## Completed Action Chain\\n\"];\n\n  const sorted = [...actions].sort(\n    (a, b) =>\n      new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(),\n  );\n\n  for (const action of sorted) {\n    lines.push(`### ${action.title}`);\n    if (action.description) lines.push(action.description);\n    if (action.result) lines.push(`Result: ${action.result}`);\n    lines.push(\n      `Tags: ${(action.tags ?? []).join(\", \")}`,\n    );\n    lines.push(\"\");\n  }\n\n  if (edges.length > 0) {\n    lines.push(\"## Dependencies\");\n    for (const edge of edges) {\n      lines.push(\n        `- ${edge.sourceActionId} --${edge.type}--> ${edge.targetActionId}`,\n      );\n    }\n  }\n\n  return lines.join(\"\\n\");\n}\n\nfunction parseDigest(response: string): CrystalDigest {\n  try {\n    const jsonMatch = response.match(/\\{[\\s\\S]*\\}/);\n    if (!jsonMatch) {\n      return {\n        narrative: response,\n        keyOutcomes: [],\n        filesAffected: [],\n        lessons: [],\n      };\n    }\n    const parsed = JSON.parse(jsonMatch[0]) as Record<string, unknown>;\n    return {\n      narrative:\n        typeof parsed.narrative === \"string\" ? parsed.narrative : response,\n      keyOutcomes: Array.isArray(parsed.keyOutcomes)\n        ? (parsed.keyOutcomes as string[])\n        : [],\n      filesAffected: Array.isArray(parsed.filesAffected)\n        ? (parsed.filesAffected as string[])\n        : [],\n      lessons: Array.isArray(parsed.lessons)\n        ? (parsed.lessons as string[])\n        : [],\n    };\n  } catch {\n    return {\n      narrative: response,\n      keyOutcomes: [],\n      filesAffected: [],\n      lessons: [],\n    };\n  }\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { recordAudit } from \"./audit.js\";\nimport type {\n  Action,\n  ActionEdge,\n  DiagnosticCheck,\n  Insight,\n  Lease,\n  Lesson,\n  Checkpoint,\n  Crystal,\n  ProceduralMemory,\n  SemanticMemory,\n  SessionSummary,\n  Signal,\n  Sentinel,\n  Sketch,\n  MeshPeer,\n  Session,\n  Memory,\n} from \"../types.js\";\n\nconst ALL_CATEGORIES = [\n  \"actions\",\n  \"leases\",\n  \"sentinels\",\n  \"sketches\",\n  \"signals\",\n  \"sessions\",\n  \"memories\",\n  \"lessons\",\n  \"summaries\",\n  \"semantic\",\n  \"procedural\",\n  \"crystals\",\n  \"insights\",\n  \"mesh\",\n];\n\nconst TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1000;\nconst ONE_HOUR_MS = 60 * 60 * 1000;\n\nexport function registerDiagnosticsFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::diagnose\", \n    async (data: { categories?: string[] }) => {\n      const categories = data.categories && data.categories.length > 0\n        ? data.categories.filter((c) => ALL_CATEGORIES.includes(c))\n        : ALL_CATEGORIES;\n\n      const checks: DiagnosticCheck[] = [];\n      const now = Date.now();\n\n      if (categories.includes(\"actions\")) {\n        const actions = await kv.list<Action>(KV.actions);\n        const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n        const leases = await kv.list<Lease>(KV.leases);\n        const actionMap = new Map(actions.map((a) => [a.id, a]));\n\n        for (const action of actions) {\n          if (action.status === \"active\") {\n            const hasActiveLease = leases.some(\n              (l) =>\n                l.actionId === action.id &&\n                l.status === \"active\" &&\n                new Date(l.expiresAt).getTime() > now,\n            );\n            if (!hasActiveLease) {\n              checks.push({\n                name: `active-no-lease:${action.id}`,\n                category: \"actions\",\n                status: \"warn\",\n                message: `Action \"${action.title}\" is active but has no active lease`,\n                fixable: false,\n              });\n            }\n          }\n\n          if (action.status === \"blocked\") {\n            const deps = allEdges.filter(\n              (e) => e.sourceActionId === action.id && e.type === \"requires\",\n            );\n            if (deps.length > 0) {\n              const allDone = deps.every((d) => {\n                const target = actionMap.get(d.targetActionId);\n                return target && target.status === \"done\";\n              });\n              if (allDone) {\n                checks.push({\n                  name: `blocked-deps-done:${action.id}`,\n                  category: \"actions\",\n                  status: \"fail\",\n                  message: `Action \"${action.title}\" is blocked but all dependencies are done`,\n                  fixable: true,\n                });\n              }\n            }\n          }\n\n          if (action.status === \"pending\") {\n            const deps = allEdges.filter(\n              (e) => e.sourceActionId === action.id && e.type === \"requires\",\n            );\n            if (deps.length > 0) {\n              const hasUnsatisfied = deps.some((d) => {\n                const target = actionMap.get(d.targetActionId);\n                return !target || target.status !== \"done\";\n              });\n              if (hasUnsatisfied) {\n                checks.push({\n                  name: `pending-unsatisfied-deps:${action.id}`,\n                  category: \"actions\",\n                  status: \"fail\",\n                  message: `Action \"${action.title}\" is pending but has unsatisfied dependencies`,\n                  fixable: true,\n                });\n              }\n            }\n          }\n        }\n\n        if (\n          !checks.some((c) => c.category === \"actions\" && c.status !== \"pass\")\n        ) {\n          checks.push({\n            name: \"actions-ok\",\n            category: \"actions\",\n            status: \"pass\",\n            message: `All ${actions.length} actions are consistent`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"leases\")) {\n        const leases = await kv.list<Lease>(KV.leases);\n        const actions = await kv.list<Action>(KV.actions);\n        const actionIds = new Set(actions.map((a) => a.id));\n        let leaseIssues = 0;\n\n        for (const lease of leases) {\n          if (\n            lease.status === \"active\" &&\n            new Date(lease.expiresAt).getTime() <= now\n          ) {\n            checks.push({\n              name: `expired-lease:${lease.id}`,\n              category: \"leases\",\n              status: \"fail\",\n              message: `Lease ${lease.id} for action ${lease.actionId} expired at ${lease.expiresAt}`,\n              fixable: true,\n            });\n            leaseIssues++;\n          }\n\n          if (!actionIds.has(lease.actionId)) {\n            checks.push({\n              name: `orphaned-lease:${lease.id}`,\n              category: \"leases\",\n              status: \"fail\",\n              message: `Lease ${lease.id} references non-existent action ${lease.actionId}`,\n              fixable: true,\n            });\n            leaseIssues++;\n          }\n        }\n\n        if (leaseIssues === 0) {\n          checks.push({\n            name: \"leases-ok\",\n            category: \"leases\",\n            status: \"pass\",\n            message: `All ${leases.length} leases are healthy`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"sentinels\")) {\n        const sentinels = await kv.list<Sentinel>(KV.sentinels);\n        const actions = await kv.list<Action>(KV.actions);\n        const actionIds = new Set(actions.map((a) => a.id));\n        let sentinelIssues = 0;\n\n        for (const sentinel of sentinels) {\n          if (\n            sentinel.status === \"watching\" &&\n            sentinel.expiresAt &&\n            new Date(sentinel.expiresAt).getTime() <= now\n          ) {\n            checks.push({\n              name: `expired-sentinel:${sentinel.id}`,\n              category: \"sentinels\",\n              status: \"fail\",\n              message: `Sentinel \"${sentinel.name}\" expired at ${sentinel.expiresAt}`,\n              fixable: true,\n            });\n            sentinelIssues++;\n          }\n\n          for (const actionId of sentinel.linkedActionIds) {\n            if (!actionIds.has(actionId)) {\n              checks.push({\n                name: `sentinel-missing-action:${sentinel.id}:${actionId}`,\n                category: \"sentinels\",\n                status: \"warn\",\n                message: `Sentinel \"${sentinel.name}\" references non-existent action ${actionId}`,\n                fixable: false,\n              });\n              sentinelIssues++;\n            }\n          }\n        }\n\n        if (sentinelIssues === 0) {\n          checks.push({\n            name: \"sentinels-ok\",\n            category: \"sentinels\",\n            status: \"pass\",\n            message: `All ${sentinels.length} sentinels are healthy`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"sketches\")) {\n        const sketches = await kv.list<Sketch>(KV.sketches);\n        let sketchIssues = 0;\n\n        for (const sketch of sketches) {\n          if (\n            sketch.status === \"active\" &&\n            new Date(sketch.expiresAt).getTime() <= now\n          ) {\n            checks.push({\n              name: `expired-sketch:${sketch.id}`,\n              category: \"sketches\",\n              status: \"fail\",\n              message: `Sketch \"${sketch.title}\" expired at ${sketch.expiresAt}`,\n              fixable: true,\n            });\n            sketchIssues++;\n          }\n        }\n\n        if (sketchIssues === 0) {\n          checks.push({\n            name: \"sketches-ok\",\n            category: \"sketches\",\n            status: \"pass\",\n            message: `All ${sketches.length} sketches are healthy`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"signals\")) {\n        const signals = await kv.list<Signal>(KV.signals);\n        let signalIssues = 0;\n\n        for (const signal of signals) {\n          if (\n            signal.expiresAt &&\n            new Date(signal.expiresAt).getTime() <= now\n          ) {\n            checks.push({\n              name: `expired-signal:${signal.id}`,\n              category: \"signals\",\n              status: \"fail\",\n              message: `Signal from \"${signal.from}\" expired at ${signal.expiresAt}`,\n              fixable: true,\n            });\n            signalIssues++;\n          }\n        }\n\n        if (signalIssues === 0) {\n          checks.push({\n            name: \"signals-ok\",\n            category: \"signals\",\n            status: \"pass\",\n            message: `All ${signals.length} signals are healthy`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"sessions\")) {\n        const sessions = await kv.list<Session>(KV.sessions);\n        let sessionIssues = 0;\n\n        for (const session of sessions) {\n          if (\n            session.status === \"active\" &&\n            now - new Date(session.startedAt).getTime() > TWENTY_FOUR_HOURS_MS\n          ) {\n            checks.push({\n              name: `abandoned-session:${session.id}`,\n              category: \"sessions\",\n              status: \"warn\",\n              message: `Session ${session.id} has been active for over 24 hours`,\n              fixable: false,\n            });\n            sessionIssues++;\n          }\n        }\n\n        if (sessionIssues === 0) {\n          checks.push({\n            name: \"sessions-ok\",\n            category: \"sessions\",\n            status: \"pass\",\n            message: `All ${sessions.length} sessions are healthy`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"memories\")) {\n        const memories = await kv.list<Memory>(KV.memories);\n        const memoryIds = new Set(memories.map((m) => m.id));\n        const supersededBy = new Map<string, string>();\n        let memoryIssues = 0;\n\n        for (const memory of memories) {\n          if (memory.supersedes && memory.supersedes.length > 0) {\n            for (const sid of memory.supersedes) {\n              if (!memoryIds.has(sid)) {\n                checks.push({\n                  name: `memory-missing-supersedes:${memory.id}:${sid}`,\n                  category: \"memories\",\n                  status: \"warn\",\n                  message: `Memory \"${memory.title}\" supersedes non-existent memory ${sid}`,\n                  fixable: false,\n                });\n                memoryIssues++;\n              }\n              supersededBy.set(sid, memory.id);\n            }\n          }\n        }\n\n        for (const memory of memories) {\n          if (memory.isLatest && supersededBy.has(memory.id)) {\n            checks.push({\n              name: `memory-stale-latest:${memory.id}`,\n              category: \"memories\",\n              status: \"fail\",\n              message: `Memory \"${memory.title}\" has isLatest=true but is superseded by ${supersededBy.get(memory.id)}`,\n              fixable: true,\n            });\n            memoryIssues++;\n          }\n        }\n\n        // Project-coverage check: unscoped memories (no project field) will\n        // appear in every project's context and search results until the\n        // infer-memory-projects migration runs. Surface a count so operators\n        // know the backfill is still pending and can trigger it explicitly.\n        const latestMemories = memories.filter((m) => m.isLatest);\n        const unscopedCount = latestMemories.filter((m) => !m.project).length;\n        if (unscopedCount === 0) {\n          checks.push({\n            name: \"memory-project-coverage\",\n            category: \"memories\",\n            status: \"pass\",\n            message: `All ${latestMemories.length} latest memories have a project scope`,\n            fixable: false,\n          });\n        } else if (unscopedCount <= 10) {\n          checks.push({\n            name: \"memory-project-coverage\",\n            category: \"memories\",\n            status: \"warn\",\n            message: `${unscopedCount} of ${latestMemories.length} latest memories have no project scope — run POST /agentmemory/migrate {\"step\":\"infer-memory-projects\"} to backfill`,\n            fixable: true,\n          });\n        } else {\n          checks.push({\n            name: \"memory-project-coverage\",\n            category: \"memories\",\n            status: \"fail\",\n            message: `${unscopedCount} of ${latestMemories.length} latest memories have no project scope — run POST /agentmemory/migrate {\"step\":\"infer-memory-projects\"} to backfill`,\n            fixable: true,\n          });\n        }\n\n        if (memoryIssues === 0) {\n          checks.push({\n            name: \"memories-ok\",\n            category: \"memories\",\n            status: \"pass\",\n            message: `All ${memories.length} memories are structurally consistent`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"lessons\")) {\n        // Counts only live lessons (deleted=true rows are tombstoned).\n        // Catches bad confidence values that would silently break recall\n        // scoring (memory_lesson_recall multiplies by confidence).\n        const lessons = await kv.list<Lesson>(KV.lessons);\n        const live = lessons.filter((l) => !l.deleted);\n        let lessonIssues = 0;\n        for (const l of live) {\n          // Number.isFinite rejects NaN / Infinity / non-numbers; a\n          // corrupted row passing those would silently survive the < / >\n          // range check (e.g. NaN < 0 is false, NaN > 1 is false, so the\n          // bad row would be \"healthy\") and skew memory_lesson_recall's\n          // scoring downstream. Surface as warning.\n          if (\n            !Number.isFinite(l.confidence) ||\n            l.confidence < 0 ||\n            l.confidence > 1\n          ) {\n            checks.push({\n              name: `lesson-bad-confidence:${l.id}`,\n              category: \"lessons\",\n              status: \"warn\",\n              message: `Lesson ${l.id} has confidence ${l.confidence} (expected finite number in 0..1)`,\n              fixable: false,\n            });\n            lessonIssues++;\n          }\n        }\n        if (lessonIssues === 0) {\n          checks.push({\n            name: \"lessons-ok\",\n            category: \"lessons\",\n            status: \"pass\",\n            message: `All ${live.length} lessons are healthy (${lessons.length - live.length} tombstoned)`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"summaries\")) {\n        const summaries = await kv.list<SessionSummary>(KV.summaries);\n        let summaryIssues = 0;\n        for (const s of summaries) {\n          // typeof guard before .trim() — a corrupted row with title=null\n          // or title=42 would otherwise throw and abort the whole diagnose\n          // run before later categories get checked.\n          if (typeof s.title !== \"string\" || s.title.trim().length === 0) {\n            checks.push({\n              name: `summary-missing-title:${s.sessionId}`,\n              category: \"summaries\",\n              status: \"warn\",\n              message: `Summary for session ${s.sessionId} has no title`,\n              fixable: false,\n            });\n            summaryIssues++;\n          }\n        }\n        if (summaryIssues === 0) {\n          checks.push({\n            name: \"summaries-ok\",\n            category: \"summaries\",\n            status: \"pass\",\n            message: `All ${summaries.length} session summaries are consistent`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"semantic\")) {\n        const semantic = await kv.list<SemanticMemory>(KV.semantic);\n        let semanticIssues = 0;\n        for (const s of semantic) {\n          if (\n            !Number.isFinite(s.confidence) ||\n            s.confidence < 0 ||\n            s.confidence > 1\n          ) {\n            checks.push({\n              name: `semantic-bad-confidence:${s.id}`,\n              category: \"semantic\",\n              status: \"warn\",\n              message: `Semantic fact ${s.id} has confidence ${s.confidence} (expected finite number in 0..1)`,\n              fixable: false,\n            });\n            semanticIssues++;\n          }\n        }\n        if (semanticIssues === 0) {\n          checks.push({\n            name: \"semantic-ok\",\n            category: \"semantic\",\n            status: \"pass\",\n            message: `All ${semantic.length} semantic memories are consistent`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"procedural\")) {\n        const procedural = await kv.list<ProceduralMemory>(KV.procedural);\n        let proceduralIssues = 0;\n        for (const p of procedural) {\n          if (!Array.isArray(p.steps) || p.steps.length === 0) {\n            checks.push({\n              name: `procedural-empty-steps:${p.id}`,\n              category: \"procedural\",\n              status: \"warn\",\n              message: `Procedural memory \"${p.name}\" (${p.id}) has no steps`,\n              fixable: false,\n            });\n            proceduralIssues++;\n          }\n        }\n        if (proceduralIssues === 0) {\n          checks.push({\n            name: \"procedural-ok\",\n            category: \"procedural\",\n            status: \"pass\",\n            message: `All ${procedural.length} procedural memories are consistent`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"crystals\")) {\n        const crystals = await kv.list<Crystal>(KV.crystals);\n        let crystalIssues = 0;\n        for (const c of crystals) {\n          if (typeof c.narrative !== \"string\" || c.narrative.trim().length === 0) {\n            checks.push({\n              name: `crystal-empty-narrative:${c.id}`,\n              category: \"crystals\",\n              status: \"warn\",\n              message: `Crystal ${c.id} has empty narrative`,\n              fixable: false,\n            });\n            crystalIssues++;\n          }\n        }\n        if (crystalIssues === 0) {\n          checks.push({\n            name: \"crystals-ok\",\n            category: \"crystals\",\n            status: \"pass\",\n            message: `All ${crystals.length} crystals are consistent`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"insights\")) {\n        const insights = await kv.list<Insight>(KV.insights);\n        let insightIssues = 0;\n        for (const i of insights) {\n          if (\n            !Number.isFinite(i.confidence) ||\n            i.confidence < 0 ||\n            i.confidence > 1\n          ) {\n            checks.push({\n              name: `insight-bad-confidence:${i.id}`,\n              category: \"insights\",\n              status: \"warn\",\n              message: `Insight ${i.id} has confidence ${i.confidence} (expected finite number in 0..1)`,\n              fixable: false,\n            });\n            insightIssues++;\n          }\n        }\n        if (insightIssues === 0) {\n          checks.push({\n            name: \"insights-ok\",\n            category: \"insights\",\n            status: \"pass\",\n            message: `All ${insights.length} insights are consistent`,\n            fixable: false,\n          });\n        }\n      }\n\n      if (categories.includes(\"mesh\")) {\n        const peers = await kv.list<MeshPeer>(KV.mesh);\n        let meshIssues = 0;\n\n        for (const peer of peers) {\n          if (\n            peer.lastSyncAt &&\n            now - new Date(peer.lastSyncAt).getTime() > ONE_HOUR_MS\n          ) {\n            checks.push({\n              name: `stale-peer:${peer.id}`,\n              category: \"mesh\",\n              status: \"warn\",\n              message: `Peer \"${peer.name}\" last synced over 1 hour ago`,\n              fixable: false,\n            });\n            meshIssues++;\n          }\n\n          if (peer.status === \"error\") {\n            checks.push({\n              name: `error-peer:${peer.id}`,\n              category: \"mesh\",\n              status: \"warn\",\n              message: `Peer \"${peer.name}\" is in error state`,\n              fixable: false,\n            });\n            meshIssues++;\n          }\n        }\n\n        if (meshIssues === 0) {\n          checks.push({\n            name: \"mesh-ok\",\n            category: \"mesh\",\n            status: \"pass\",\n            message: `All ${peers.length} mesh peers are healthy`,\n            fixable: false,\n          });\n        }\n      }\n\n      const summary = {\n        pass: checks.filter((c) => c.status === \"pass\").length,\n        warn: checks.filter((c) => c.status === \"warn\").length,\n        fail: checks.filter((c) => c.status === \"fail\").length,\n        fixable: checks.filter((c) => c.fixable).length,\n      };\n\n      return { success: true, checks, summary };\n    },\n  );\n\n  sdk.registerFunction(\"mem::heal\", \n    async (data: { categories?: string[]; dryRun?: boolean }) => {\n      const dryRun = data.dryRun ?? false;\n      const categories = data.categories && data.categories.length > 0\n        ? data.categories.filter((c) => ALL_CATEGORIES.includes(c))\n        : ALL_CATEGORIES;\n\n      let fixed = 0;\n      let skipped = 0;\n      const details: string[] = [];\n      const now = Date.now();\n\n      if (categories.includes(\"actions\")) {\n        const actions = await kv.list<Action>(KV.actions);\n        const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n        const actionMap = new Map(actions.map((a) => [a.id, a]));\n\n        for (const action of actions) {\n          if (action.status === \"blocked\") {\n            const deps = allEdges.filter(\n              (e) => e.sourceActionId === action.id && e.type === \"requires\",\n            );\n            if (deps.length > 0) {\n              const allDone = deps.every((d) => {\n                const target = actionMap.get(d.targetActionId);\n                return target && target.status === \"done\";\n              });\n              if (allDone) {\n                if (dryRun) {\n                  details.push(\n                    `[dry-run] Would unblock action \"${action.title}\" (${action.id})`,\n                  );\n                  fixed++;\n                  continue;\n                }\n                const didFix = await withKeyedLock(\n                  `mem:action:${action.id}`,\n                  async () => {\n                    const fresh = await kv.get<Action>(KV.actions, action.id);\n                    if (!fresh || fresh.status !== \"blocked\") return false;\n                    const freshEdges = await kv.list<ActionEdge>(KV.actionEdges);\n                    const freshDeps = freshEdges.filter(\n                      (e) =>\n                        e.sourceActionId === fresh.id && e.type === \"requires\",\n                    );\n                    const freshActions = await kv.list<Action>(KV.actions);\n                    const freshMap = new Map(\n                      freshActions.map((a) => [a.id, a]),\n                    );\n                    const stillAllDone = freshDeps.every((d) => {\n                      const target = freshMap.get(d.targetActionId);\n                      return target && target.status === \"done\";\n                    });\n                    if (!stillAllDone) return false;\n                    fresh.status = \"pending\";\n                    fresh.updatedAt = new Date().toISOString();\n                    await kv.set(KV.actions, fresh.id, fresh);\n                    await recordAudit(kv, \"heal\", \"mem::heal\", [fresh.id], {\n                      reason: \"blocked-deps-done\",\n                      previousStatus: \"blocked\",\n                      newStatus: \"pending\",\n                    });\n                    return true;\n                  },\n                );\n                if (didFix) {\n                  details.push(\n                    `Unblocked action \"${action.title}\" (${action.id})`,\n                  );\n                  fixed++;\n                } else {\n                  skipped++;\n                }\n              }\n            }\n          }\n\n          if (action.status === \"pending\") {\n            const deps = allEdges.filter(\n              (e) => e.sourceActionId === action.id && e.type === \"requires\",\n            );\n            if (deps.length > 0) {\n              const hasUnsatisfied = deps.some((d) => {\n                const target = actionMap.get(d.targetActionId);\n                return !target || target.status !== \"done\";\n              });\n              if (hasUnsatisfied) {\n                if (dryRun) {\n                  details.push(\n                    `[dry-run] Would block action \"${action.title}\" (${action.id})`,\n                  );\n                  fixed++;\n                  continue;\n                }\n                const didFix = await withKeyedLock(\n                  `mem:action:${action.id}`,\n                  async () => {\n                    const fresh = await kv.get<Action>(KV.actions, action.id);\n                    if (!fresh || fresh.status !== \"pending\") return false;\n                    const freshEdges = await kv.list<ActionEdge>(KV.actionEdges);\n                    const freshDeps = freshEdges.filter(\n                      (e) =>\n                        e.sourceActionId === fresh.id && e.type === \"requires\",\n                    );\n                    const freshActions = await kv.list<Action>(KV.actions);\n                    const freshMap = new Map(\n                      freshActions.map((a) => [a.id, a]),\n                    );\n                    const stillUnsatisfied = freshDeps.some((d) => {\n                      const target = freshMap.get(d.targetActionId);\n                      return !target || target.status !== \"done\";\n                    });\n                    if (!stillUnsatisfied) return false;\n                    fresh.status = \"blocked\";\n                    fresh.updatedAt = new Date().toISOString();\n                    await kv.set(KV.actions, fresh.id, fresh);\n                    await recordAudit(kv, \"heal\", \"mem::heal\", [fresh.id], {\n                      reason: \"pending-unsatisfied-deps\",\n                      previousStatus: \"pending\",\n                      newStatus: \"blocked\",\n                    });\n                    return true;\n                  },\n                );\n                if (didFix) {\n                  details.push(\n                    `Blocked action \"${action.title}\" (${action.id})`,\n                  );\n                  fixed++;\n                } else {\n                  skipped++;\n                }\n              }\n            }\n          }\n        }\n      }\n\n      if (categories.includes(\"leases\")) {\n        const leases = await kv.list<Lease>(KV.leases);\n        const actions = await kv.list<Action>(KV.actions);\n        const actionIds = new Set(actions.map((a) => a.id));\n\n        for (const lease of leases) {\n          if (\n            lease.status === \"active\" &&\n            new Date(lease.expiresAt).getTime() <= now\n          ) {\n            if (dryRun) {\n              details.push(\n                `[dry-run] Would expire lease ${lease.id} for action ${lease.actionId}`,\n              );\n              fixed++;\n              continue;\n            }\n            const didFix = await withKeyedLock(\n              `mem:action:${lease.actionId}`,\n              async () => {\n                const fresh = await kv.get<Lease>(KV.leases, lease.id);\n                if (\n                  !fresh ||\n                  fresh.status !== \"active\" ||\n                  new Date(fresh.expiresAt).getTime() > Date.now()\n                ) {\n                  return false;\n                }\n                fresh.status = \"expired\";\n                await kv.set(KV.leases, fresh.id, fresh);\n                await recordAudit(kv, \"heal\", \"mem::heal\", [fresh.id], {\n                  entityType: \"lease\",\n                  reason: \"expired-lease\",\n                  newStatus: \"expired\",\n                });\n\n                const action = await kv.get<Action>(KV.actions, fresh.actionId);\n                if (\n                  action &&\n                  action.status === \"active\" &&\n                  action.assignedTo === fresh.agentId\n                ) {\n                  action.status = \"pending\";\n                  action.assignedTo = undefined;\n                  action.updatedAt = new Date().toISOString();\n                  await kv.set(KV.actions, action.id, action);\n                  await recordAudit(kv, \"heal\", \"mem::heal\", [action.id], {\n                    entityType: \"action\",\n                    reason: \"release-expired-lease\",\n                    newStatus: \"pending\",\n                  });\n                }\n                return true;\n              },\n            );\n            if (didFix) {\n              details.push(\n                `Expired lease ${lease.id} for action ${lease.actionId}`,\n              );\n              fixed++;\n            } else {\n              skipped++;\n            }\n            continue;\n          }\n\n          if (!actionIds.has(lease.actionId)) {\n            if (dryRun) {\n              details.push(\n                `[dry-run] Would delete orphaned lease ${lease.id}`,\n              );\n              fixed++;\n              continue;\n            }\n            await kv.delete(KV.leases, lease.id);\n            await recordAudit(kv, \"heal\", \"mem::heal\", [lease.id], {\n              entityType: \"lease\",\n              reason: \"orphaned-lease\",\n              action: \"delete\",\n            });\n            details.push(`Deleted orphaned lease ${lease.id}`);\n            fixed++;\n          }\n        }\n      }\n\n      if (categories.includes(\"sentinels\")) {\n        const sentinels = await kv.list<Sentinel>(KV.sentinels);\n\n        for (const sentinel of sentinels) {\n          if (\n            sentinel.status === \"watching\" &&\n            sentinel.expiresAt &&\n            new Date(sentinel.expiresAt).getTime() <= now\n          ) {\n            if (dryRun) {\n              details.push(\n                `[dry-run] Would expire sentinel \"${sentinel.name}\" (${sentinel.id})`,\n              );\n              fixed++;\n              continue;\n            }\n            const didFix = await withKeyedLock(\n              `mem:sentinel:${sentinel.id}`,\n              async () => {\n                const fresh = await kv.get<Sentinel>(\n                  KV.sentinels,\n                  sentinel.id,\n                );\n                if (!fresh || fresh.status !== \"watching\") return false;\n                if (\n                  !fresh.expiresAt ||\n                  new Date(fresh.expiresAt).getTime() > Date.now()\n                ) {\n                  return false;\n                }\n                fresh.status = \"expired\";\n                await kv.set(KV.sentinels, fresh.id, fresh);\n                await recordAudit(kv, \"heal\", \"mem::heal\", [fresh.id], {\n                  entityType: \"sentinel\",\n                  reason: \"expired-sentinel\",\n                  newStatus: \"expired\",\n                });\n                return true;\n              },\n            );\n            if (didFix) {\n              details.push(\n                `Expired sentinel \"${sentinel.name}\" (${sentinel.id})`,\n              );\n              fixed++;\n            } else {\n              skipped++;\n            }\n          }\n        }\n      }\n\n      if (categories.includes(\"sketches\")) {\n        const sketches = await kv.list<Sketch>(KV.sketches);\n\n        for (const sketch of sketches) {\n          if (\n            sketch.status === \"active\" &&\n            new Date(sketch.expiresAt).getTime() <= now\n          ) {\n            if (dryRun) {\n              details.push(\n                `[dry-run] Would discard expired sketch \"${sketch.title}\" (${sketch.id})`,\n              );\n              fixed++;\n              continue;\n            }\n            const didFix = await withKeyedLock(\n              `mem:sketch:${sketch.id}`,\n              async () => {\n                const fresh = await kv.get<Sketch>(KV.sketches, sketch.id);\n                if (\n                  !fresh ||\n                  fresh.status !== \"active\" ||\n                  new Date(fresh.expiresAt).getTime() > Date.now()\n                ) {\n                  return false;\n                }\n\n                const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n                const actionIdSet = new Set(fresh.actionIds);\n                for (const edge of allEdges) {\n                  if (\n                    actionIdSet.has(edge.sourceActionId) ||\n                    actionIdSet.has(edge.targetActionId)\n                  ) {\n                    await kv.delete(KV.actionEdges, edge.id);\n                    await recordAudit(kv, \"heal\", \"mem::heal\", [edge.id], {\n                      entityType: \"actionEdge\",\n                      reason: \"sketch-gc-discard\",\n                      action: \"delete\",\n                    });\n                  }\n                }\n                for (const actionId of fresh.actionIds) {\n                  await kv.delete(KV.actions, actionId);\n                  await recordAudit(kv, \"heal\", \"mem::heal\", [actionId], {\n                    entityType: \"action\",\n                    reason: \"sketch-gc-discard\",\n                    action: \"delete\",\n                  });\n                }\n\n                fresh.status = \"discarded\";\n                fresh.discardedAt = new Date().toISOString();\n                await kv.set(KV.sketches, fresh.id, fresh);\n                await recordAudit(kv, \"heal\", \"mem::heal\", [fresh.id], {\n                  entityType: \"sketch\",\n                  reason: \"expired-sketch\",\n                  newStatus: \"discarded\",\n                });\n                return true;\n              },\n            );\n            if (didFix) {\n              details.push(\n                `Discarded expired sketch \"${sketch.title}\" (${sketch.id})`,\n              );\n              fixed++;\n            } else {\n              skipped++;\n            }\n          }\n        }\n      }\n\n      if (categories.includes(\"signals\")) {\n        const signals = await kv.list<Signal>(KV.signals);\n\n        for (const signal of signals) {\n          if (\n            signal.expiresAt &&\n            new Date(signal.expiresAt).getTime() <= now\n          ) {\n            if (dryRun) {\n              details.push(\n                `[dry-run] Would delete expired signal ${signal.id}`,\n              );\n              fixed++;\n              continue;\n            }\n            await kv.delete(KV.signals, signal.id);\n            await recordAudit(kv, \"heal\", \"mem::heal\", [signal.id], {\n              entityType: \"signal\",\n              reason: \"expired-signal\",\n              action: \"delete\",\n            });\n            details.push(`Deleted expired signal ${signal.id}`);\n            fixed++;\n          }\n        }\n      }\n\n      if (categories.includes(\"memories\")) {\n        const memories = await kv.list<Memory>(KV.memories);\n        const supersededBy = new Map<string, string>();\n\n        for (const memory of memories) {\n          if (memory.supersedes && memory.supersedes.length > 0) {\n            for (const sid of memory.supersedes) {\n              supersededBy.set(sid, memory.id);\n            }\n          }\n        }\n\n        for (const memory of memories) {\n          if (memory.isLatest && supersededBy.has(memory.id)) {\n            if (dryRun) {\n              details.push(\n                `[dry-run] Would set isLatest=false on memory \"${memory.title}\" (${memory.id})`,\n              );\n              fixed++;\n              continue;\n            }\n            const didFix = await withKeyedLock(\n              `mem:memory:${memory.id}`,\n              async () => {\n                const fresh = await kv.get<Memory>(KV.memories, memory.id);\n                if (!fresh || !fresh.isLatest) return false;\n                fresh.isLatest = false;\n                fresh.updatedAt = new Date().toISOString();\n                await kv.set(KV.memories, fresh.id, fresh);\n                await recordAudit(kv, \"heal\", \"mem::heal\", [fresh.id], {\n                  entityType: \"memory\",\n                  reason: \"superseded-memory-mark-non-latest\",\n                  action: \"update\",\n                });\n                return true;\n              },\n            );\n            if (didFix) {\n              details.push(\n                `Set isLatest=false on memory \"${memory.title}\" (${memory.id})`,\n              );\n              fixed++;\n            } else {\n              skipped++;\n            }\n          }\n        }\n      }\n\n      return { success: true, fixed, skipped, details };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { Facet } from \"../types.js\";\n\nexport function registerFacetsFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::facet-tag\", \n    async (data: {\n      targetId: string;\n      targetType: string;\n      dimension: string;\n      value: string;\n    }) => {\n      if (!data.targetId || typeof data.targetId !== \"string\") {\n        return { success: false, error: \"targetId is required\" };\n      }\n\n      const validTypes = [\"action\", \"memory\", \"observation\"];\n      if (!validTypes.includes(data.targetType)) {\n        return {\n          success: false,\n          error: `targetType must be one of: ${validTypes.join(\", \")}`,\n        };\n      }\n\n      if (\n        !data.dimension ||\n        typeof data.dimension !== \"string\" ||\n        data.dimension.trim() === \"\"\n      ) {\n        return { success: false, error: \"dimension is required\" };\n      }\n\n      if (\n        !data.value ||\n        typeof data.value !== \"string\" ||\n        data.value.trim() === \"\"\n      ) {\n        return { success: false, error: \"value is required\" };\n      }\n\n      const dimension = data.dimension.trim();\n      const value = data.value.trim();\n\n      const existing = await kv.list<Facet>(KV.facets);\n      const duplicate = existing.find(\n        (f) =>\n          f.targetId === data.targetId &&\n          f.dimension === dimension &&\n          f.value === value,\n      );\n      if (duplicate) {\n        return { success: true, facet: duplicate, skipped: true };\n      }\n\n      const facet: Facet = {\n        id: generateId(\"fct\"),\n        targetId: data.targetId,\n        targetType: data.targetType as Facet[\"targetType\"],\n        dimension,\n        value,\n        createdAt: new Date().toISOString(),\n      };\n\n      await kv.set(KV.facets, facet.id, facet);\n      return { success: true, facet };\n    },\n  );\n\n  sdk.registerFunction(\"mem::facet-untag\", \n    async (data: {\n      targetId: string;\n      dimension: string;\n      value?: string;\n    }) => {\n      if (!data.targetId) {\n        return { success: false, error: \"targetId is required\" };\n      }\n      if (!data.dimension) {\n        return { success: false, error: \"dimension is required\" };\n      }\n\n      const all = await kv.list<Facet>(KV.facets);\n      const matches = all.filter((f) => {\n        if (f.targetId !== data.targetId || f.dimension !== data.dimension) {\n          return false;\n        }\n        if (data.value !== undefined) {\n          return f.value === data.value;\n        }\n        return true;\n      });\n\n      for (const f of matches) {\n        await kv.delete(KV.facets, f.id);\n      }\n\n      return { success: true, removed: matches.length };\n    },\n  );\n\n  sdk.registerFunction(\"mem::facet-query\", \n    async (data: {\n      matchAll?: string[];\n      matchAny?: string[];\n      targetType?: string;\n      limit?: number;\n    }) => {\n      if (\n        (!data.matchAll || data.matchAll.length === 0) &&\n        (!data.matchAny || data.matchAny.length === 0)\n      ) {\n        return {\n          success: false,\n          error: \"at least one of matchAll or matchAny is required\",\n        };\n      }\n\n      const all = await kv.list<Facet>(KV.facets);\n      const filtered = data.targetType\n        ? all.filter((f) => f.targetType === data.targetType)\n        : all;\n\n      const targetFacetMap = new Map<string, { targetType: string; facetKeys: Set<string> }>();\n      for (const f of filtered) {\n        const key = `${f.dimension}:${f.value}`;\n        let entry = targetFacetMap.get(f.targetId);\n        if (!entry) {\n          entry = { targetType: f.targetType, facetKeys: new Set() };\n          targetFacetMap.set(f.targetId, entry);\n        }\n        entry.facetKeys.add(key);\n      }\n\n      const results: Array<{ targetId: string; targetType: string; matchedFacets: string[] }> = [];\n\n      for (const [targetId, entry] of targetFacetMap) {\n        const matched: string[] = [];\n\n        if (data.matchAll && data.matchAll.length > 0) {\n          const allPresent = data.matchAll.every((k) => entry.facetKeys.has(k));\n          if (!allPresent) continue;\n          for (const k of data.matchAll) {\n            if (!matched.includes(k)) matched.push(k);\n          }\n        }\n\n        if (data.matchAny && data.matchAny.length > 0) {\n          const anyPresent = data.matchAny.filter((k) => entry.facetKeys.has(k));\n          if (anyPresent.length === 0) continue;\n          for (const k of anyPresent) {\n            if (!matched.includes(k)) matched.push(k);\n          }\n        }\n\n        results.push({\n          targetId,\n          targetType: entry.targetType,\n          matchedFacets: matched,\n        });\n      }\n\n      const limit = data.limit || 50;\n      return { success: true, results: results.slice(0, limit) };\n    },\n  );\n\n  sdk.registerFunction(\"mem::facet-get\", \n    async (data: { targetId: string }) => {\n      if (!data.targetId) {\n        return { success: false, error: \"targetId is required\" };\n      }\n\n      const all = await kv.list<Facet>(KV.facets);\n      const targetFacets = all.filter((f) => f.targetId === data.targetId);\n\n      const dimMap = new Map<string, string[]>();\n      for (const f of targetFacets) {\n        let values = dimMap.get(f.dimension);\n        if (!values) {\n          values = [];\n          dimMap.set(f.dimension, values);\n        }\n        values.push(f.value);\n      }\n\n      const dimensions = Array.from(dimMap.entries()).map(([dimension, values]) => ({\n        dimension,\n        values,\n      }));\n\n      return { success: true, dimensions };\n    },\n  );\n\n  sdk.registerFunction(\"mem::facet-stats\", \n    async (data: { targetType?: string }) => {\n      const all = await kv.list<Facet>(KV.facets);\n      const filtered = data.targetType\n        ? all.filter((f) => f.targetType === data.targetType)\n        : all;\n\n      const dimMap = new Map<string, Map<string, number>>();\n      for (const f of filtered) {\n        let valueMap = dimMap.get(f.dimension);\n        if (!valueMap) {\n          valueMap = new Map();\n          dimMap.set(f.dimension, valueMap);\n        }\n        valueMap.set(f.value, (valueMap.get(f.value) || 0) + 1);\n      }\n\n      const dimensions = Array.from(dimMap.entries()).map(([dimension, valueMap]) => ({\n        dimension,\n        values: Array.from(valueMap.entries()).map(([value, count]) => ({\n          value,\n          count,\n        })),\n      }));\n\n      return { success: true, dimensions, totalFacets: filtered.length };\n    },\n  );\n\n  sdk.registerFunction(\"mem::facet-dimensions\", \n    async () => {\n      const all = await kv.list<Facet>(KV.facets);\n\n      const counts = new Map<string, number>();\n      for (const f of all) {\n        counts.set(f.dimension, (counts.get(f.dimension) || 0) + 1);\n      }\n\n      const dimensions = Array.from(counts.entries()).map(([dimension, count]) => ({\n        dimension,\n        count,\n      }));\n\n      return { success: true, dimensions };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport type {\n  Memory,\n  CompressedObservation,\n  Session,\n} from \"../types.js\";\n\nexport function registerVerifyFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::verify\", \n    async (data: { id: string }) => {\n      if (!data.id || typeof data.id !== \"string\") {\n        return { success: false, error: \"id is required\" };\n      }\n\n      const memory = await kv.get<Memory>(KV.memories, data.id);\n      if (memory) {\n        const observationIds = memory.sourceObservationIds || [];\n        const observations: Array<{\n          observation: CompressedObservation;\n          session?: Session;\n        }> = [];\n\n        for (const obsId of observationIds) {\n          const obs = await findObservation(kv, obsId, memory.sessionIds);\n          if (obs) {\n            const session = await kv.get<Session>(KV.sessions, obs.sessionId);\n            observations.push({ observation: obs, session: session || undefined });\n          }\n        }\n\n        return {\n          success: true,\n          type: \"memory\",\n          memory: {\n            id: memory.id,\n            title: memory.title,\n            type: memory.type,\n            version: memory.version,\n            strength: memory.strength,\n            isLatest: memory.isLatest,\n            createdAt: memory.createdAt,\n            updatedAt: memory.updatedAt,\n            supersedes: memory.supersedes,\n            parentId: memory.parentId,\n          },\n          citations: observations.map((o) => ({\n            observationId: o.observation.id,\n            title: o.observation.title,\n            type: o.observation.type,\n            confidence: o.observation.confidence,\n            timestamp: o.observation.timestamp,\n            sessionId: o.observation.sessionId,\n            sessionProject: o.session?.project,\n            sessionStatus: o.session?.status,\n          })),\n          citationCount: observations.length,\n        };\n      }\n\n      const obs = await findObservation(kv, data.id);\n      if (obs) {\n        const session = await kv.get<Session>(KV.sessions, obs.sessionId);\n        return {\n          success: true,\n          type: \"observation\",\n          observation: {\n            id: obs.id,\n            title: obs.title,\n            type: obs.type,\n            confidence: obs.confidence,\n            importance: obs.importance,\n            timestamp: obs.timestamp,\n            sessionId: obs.sessionId,\n          },\n          session: session\n            ? {\n                id: session.id,\n                project: session.project,\n                status: session.status,\n                startedAt: session.startedAt,\n              }\n            : null,\n          citationCount: 0,\n          citations: [],\n        };\n      }\n\n      return { success: false, error: \"not found\" };\n    },\n  );\n}\n\nasync function findObservation(\n  kv: StateKV,\n  obsId: string,\n  hintSessionIds?: string[],\n): Promise<CompressedObservation | null> {\n  if (hintSessionIds) {\n    for (const sid of hintSessionIds) {\n      const obs = await kv.get<CompressedObservation>(KV.observations(sid), obsId);\n      if (obs) return obs;\n    }\n  }\n  const sessions = await kv.list<Session>(KV.sessions);\n  for (const session of sessions) {\n    if (hintSessionIds?.includes(session.id)) continue;\n    const obs = await kv.get<CompressedObservation>(\n      KV.observations(session.id),\n      obsId,\n    );\n    if (obs) return obs;\n  }\n  return null;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport type { Memory, GraphNode, GraphEdge } from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\n\nexport function registerCascadeFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::cascade-update\", \n    async (data: { supersededMemoryId: string }) => {\n      if (!data.supersededMemoryId || typeof data.supersededMemoryId !== \"string\") {\n        return { success: false, error: \"supersededMemoryId is required\" };\n      }\n\n      const superseded = await kv.get<Memory>(KV.memories, data.supersededMemoryId);\n      if (!superseded) {\n        return { success: false, error: \"superseded memory not found\" };\n      }\n\n      let flaggedNodes = 0;\n      let flaggedEdges = 0;\n      let flaggedMemories = 0;\n\n      const obsIds = new Set(superseded.sourceObservationIds || []);\n\n      if (obsIds.size > 0) {\n        const now = new Date().toISOString();\n        const nodes = await kv.list<GraphNode>(KV.graphNodes);\n        for (const node of nodes) {\n          if (node.stale) continue;\n          const overlap = (node.sourceObservationIds ?? []).some((id) => obsIds.has(id));\n          if (overlap) {\n            node.stale = true;\n            node.updatedAt = now;\n            await kv.set(KV.graphNodes, node.id, node);\n            await recordAudit(kv, \"consolidate\", \"mem::cascade-update\", [node.id], {\n              resourceType: \"GraphNode\",\n              change: \"marked stale from superseded memory\",\n              supersededMemoryId: data.supersededMemoryId,\n            });\n            flaggedNodes++;\n          }\n        }\n\n        const edges = await kv.list<GraphEdge>(KV.graphEdges);\n        for (const edge of edges) {\n          if (edge.stale) continue;\n          const overlap = (edge.sourceObservationIds ?? []).some((id) => obsIds.has(id));\n          if (overlap) {\n            edge.stale = true;\n            await kv.set(KV.graphEdges, edge.id, edge);\n            await recordAudit(kv, \"consolidate\", \"mem::cascade-update\", [edge.id], {\n              resourceType: \"GraphEdge\",\n              change: \"marked stale from superseded memory\",\n              supersededMemoryId: data.supersededMemoryId,\n            });\n            flaggedEdges++;\n          }\n        }\n      }\n\n      const supersededConcepts = new Set(\n        (superseded.concepts ?? []).map((c) => c.toLowerCase()),\n      );\n      if (supersededConcepts.size >= 2) {\n        const allMemories = await kv.list<Memory>(KV.memories);\n        for (const mem of allMemories) {\n          if (mem.id === data.supersededMemoryId) continue;\n          if (!mem.isLatest) continue;\n\n          const sharedCount = (mem.concepts ?? []).filter((c) =>\n            supersededConcepts.has(c.toLowerCase()),\n          ).length;\n          if (sharedCount >= 2) {\n            flaggedMemories++;\n          }\n        }\n      }\n\n      return {\n        success: true,\n        flagged: {\n          nodes: flaggedNodes,\n          edges: flaggedEdges,\n          siblingMemories: flaggedMemories,\n        },\n        total: flaggedNodes + flaggedEdges + flaggedMemories,\n      };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, fingerprintId } from \"../state/schema.js\";\nimport type { Lesson } from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\n\nfunction reinforceLesson(lesson: Lesson): void {\n  const now = new Date().toISOString();\n  lesson.reinforcements++;\n  lesson.confidence = Math.min(\n    1.0,\n    lesson.confidence + 0.1 * (1 - lesson.confidence),\n  );\n  lesson.lastReinforcedAt = now;\n  lesson.updatedAt = now;\n}\n\nexport function registerLessonsFunctions(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\"mem::lesson-save\", \n    async (data: {\n      content: string;\n      context?: string;\n      confidence?: number;\n      project?: string;\n      tags?: string[];\n      source?: \"crystal\" | \"manual\" | \"consolidation\";\n      sourceIds?: string[];\n    }) => {\n      if (!data.content?.trim()) {\n        return { success: false, error: \"content is required\" };\n      }\n\n      const fp = fingerprintId(\"lsn\", data.content.trim().toLowerCase());\n      const existing = await kv.get<Lesson>(KV.lessons, fp);\n\n      if (existing && !existing.deleted) {\n        reinforceLesson(existing);\n        if (data.context && !existing.context) {\n          existing.context = data.context;\n        }\n        await kv.set(KV.lessons, existing.id, existing);\n\n        try {\n          await recordAudit(kv, \"lesson_strengthen\", \"mem::lesson-save\", [\n            existing.id,\n          ]);\n        } catch {}\n\n        return {\n          success: true,\n          action: \"strengthened\",\n          lesson: existing,\n        };\n      }\n\n      const confidence =\n        typeof data.confidence === \"number\" &&\n        data.confidence >= 0 &&\n        data.confidence <= 1\n          ? data.confidence\n          : 0.5;\n\n      const now = new Date().toISOString();\n      const lesson: Lesson = {\n        id: fp,\n        content: data.content.trim(),\n        context: data.context?.trim() || \"\",\n        confidence,\n        reinforcements: 0,\n        source: data.source || \"manual\",\n        sourceIds: data.sourceIds || [],\n        project: data.project,\n        tags: data.tags || [],\n        createdAt: now,\n        updatedAt: now,\n        decayRate: 0.05,\n      };\n\n      await kv.set(KV.lessons, lesson.id, lesson);\n\n      try {\n        await recordAudit(kv, \"lesson_save\", \"mem::lesson-save\", [lesson.id]);\n      } catch {}\n\n      return { success: true, action: \"created\", lesson };\n    },\n  );\n\n  sdk.registerFunction(\"mem::lesson-recall\", \n    async (data: {\n      query: string;\n      project?: string;\n      minConfidence?: number;\n      limit?: number;\n    }) => {\n      if (!data.query?.trim()) {\n        return { success: false, error: \"query is required\" };\n      }\n\n      const query = data.query.toLowerCase();\n      const minConfidence = data.minConfidence ?? 0.1;\n      const limit = data.limit ?? 10;\n\n      let lessons = await kv.list<Lesson>(KV.lessons);\n\n      lessons = lessons.filter(\n        (l) => !l.deleted && l.confidence >= minConfidence,\n      );\n\n      if (data.project) {\n        lessons = lessons.filter((l) => l.project === data.project);\n      }\n\n      const scored = lessons\n        .map((l) => {\n          const text = `${l.content} ${l.context} ${l.tags.join(\" \")}`.toLowerCase();\n          const terms = query.split(/\\s+/).filter((t) => t.length > 1);\n          const matchCount = terms.filter((t) => text.includes(t)).length;\n          if (matchCount === 0) return null;\n\n          const relevance = matchCount / terms.length;\n          const daysSinceReinforced = l.lastReinforcedAt\n            ? (Date.now() - new Date(l.lastReinforcedAt).getTime()) /\n              (1000 * 60 * 60 * 24)\n            : (Date.now() - new Date(l.createdAt).getTime()) /\n              (1000 * 60 * 60 * 24);\n          const recencyBoost = 1 / (1 + daysSinceReinforced * 0.01);\n          const score = l.confidence * relevance * recencyBoost;\n\n          return { lesson: l, score };\n        })\n        .filter(Boolean) as Array<{ lesson: Lesson; score: number }>;\n\n      scored.sort((a, b) => b.score - a.score);\n\n      try {\n        await recordAudit(kv, \"lesson_recall\", \"mem::lesson-recall\", [], {\n          query: data.query,\n          resultCount: scored.length,\n        });\n      } catch {}\n\n      return {\n        success: true,\n        lessons: scored.slice(0, limit).map((s) => ({\n          ...s.lesson,\n          score: Math.round(s.score * 1000) / 1000,\n        })),\n      };\n    },\n  );\n\n  sdk.registerFunction(\"mem::lesson-list\", \n    async (data: {\n      project?: string;\n      source?: string;\n      minConfidence?: number;\n      limit?: number;\n    }) => {\n      const limit = data.limit ?? 50;\n      const minConfidence = data.minConfidence ?? 0;\n      let lessons = await kv.list<Lesson>(KV.lessons);\n\n      lessons = lessons.filter(\n        (l) => !l.deleted && l.confidence >= minConfidence,\n      );\n\n      if (data.project) {\n        lessons = lessons.filter((l) => l.project === data.project);\n      }\n      if (data.source) {\n        lessons = lessons.filter((l) => l.source === data.source);\n      }\n\n      lessons.sort((a, b) => b.confidence - a.confidence);\n\n      return { success: true, lessons: lessons.slice(0, limit) };\n    },\n  );\n\n  sdk.registerFunction(\"mem::lesson-strengthen\", \n    async (data: { lessonId: string }) => {\n      if (!data.lessonId) {\n        return { success: false, error: \"lessonId is required\" };\n      }\n\n      const lesson = await kv.get<Lesson>(KV.lessons, data.lessonId);\n      if (!lesson || lesson.deleted) {\n        return { success: false, error: \"lesson not found\" };\n      }\n\n      reinforceLesson(lesson);\n\n      await kv.set(KV.lessons, lesson.id, lesson);\n\n      try {\n        await recordAudit(kv, \"lesson_strengthen\", \"mem::lesson-strengthen\", [\n          lesson.id,\n        ]);\n      } catch {}\n\n      return { success: true, lesson };\n    },\n  );\n\n  sdk.registerFunction(\"mem::lesson-decay-sweep\", \n    async () => {\n      const lessons = await kv.list<Lesson>(KV.lessons);\n      let decayed = 0;\n      let softDeleted = 0;\n      const now = Date.now();\n      const timestamp = new Date().toISOString();\n      const dirty: Lesson[] = [];\n      const auditEvents: Array<{\n        id: string;\n        action: \"decay\" | \"soft-delete\";\n        beforeConfidence: number;\n        afterConfidence: number;\n        beforeDeleted: boolean;\n        afterDeleted: boolean;\n      }> = [];\n\n      for (const lesson of lessons) {\n        if (lesson.deleted) continue;\n\n        const baseline = lesson.lastDecayedAt || lesson.lastReinforcedAt || lesson.createdAt;\n        const weeksSinceBaseline =\n          (now - new Date(baseline).getTime()) / (1000 * 60 * 60 * 24 * 7);\n\n        if (weeksSinceBaseline < 1) continue;\n\n        const decay = lesson.decayRate * weeksSinceBaseline;\n        const newConfidence = Math.max(0.05, lesson.confidence - decay);\n\n        if (newConfidence !== lesson.confidence) {\n          const beforeConfidence = lesson.confidence;\n          const beforeDeleted = !!lesson.deleted;\n          lesson.confidence = Math.round(newConfidence * 1000) / 1000;\n          lesson.lastDecayedAt = timestamp;\n          lesson.updatedAt = timestamp;\n\n          if (lesson.confidence <= 0.1 && lesson.reinforcements === 0) {\n            lesson.deleted = true;\n            softDeleted++;\n          } else {\n            decayed++;\n          }\n\n          dirty.push(lesson);\n          auditEvents.push({\n            id: lesson.id,\n            action: lesson.deleted ? \"soft-delete\" : \"decay\",\n            beforeConfidence,\n            afterConfidence: lesson.confidence,\n            beforeDeleted,\n            afterDeleted: !!lesson.deleted,\n          });\n        }\n      }\n\n      await Promise.all(dirty.map((l) => kv.set(KV.lessons, l.id, l)));\n      await Promise.all(\n        auditEvents.map((event) =>\n          recordAudit(kv, \"lesson_strengthen\", \"mem::lesson-decay-sweep\", [event.id], {\n            action: event.action,\n            actor: \"system\",\n            reason: \"decay-sweep\",\n            before: {\n              confidence: event.beforeConfidence,\n              deleted: event.beforeDeleted,\n            },\n            after: {\n              confidence: event.afterConfidence,\n              deleted: event.afterDeleted,\n            },\n          }),\n        ),\n      );\n\n      return { success: true, decayed, softDeleted, total: lessons.length };\n    },\n  );\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join, resolve, sep } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport type {\n  Memory,\n  Lesson,\n  Crystal,\n  Session,\n} from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\nconst DEFAULT_EXPORT_ROOT = join(homedir(), \".agentmemory\");\n\nfunction getExportRoot(): string {\n  return resolve(process.env[\"AGENTMEMORY_EXPORT_ROOT\"] || DEFAULT_EXPORT_ROOT);\n}\n\nfunction resolveVaultDir(vaultDir?: string): string | null {\n  const root = getExportRoot();\n  const resolved = resolve(vaultDir || join(root, \"vault\"));\n  if (resolved === root || resolved.startsWith(root + sep)) {\n    return resolved;\n  }\n  return null;\n}\n\nfunction sanitize(name: string): string {\n  return name.replace(/[<>:\"/\\\\|?*\\x00-\\x1f]/g, \"_\").slice(0, 100);\n}\n\n// #729: every record helper used to crash on null/undefined fields,\n// poisoning the whole export. These helpers stay strict about types but\n// return sensible fallbacks instead of throwing.\nfunction hasExportId<T extends { id?: unknown }>(\n  item: T | null | undefined,\n): item is T & { id: string } {\n  return !!item && typeof (item as { id?: unknown }).id === \"string\" && (item as { id: string }).id.length > 0;\n}\n\nfunction safeArray<T>(value: unknown): T[] {\n  return Array.isArray(value) ? (value as T[]) : [];\n}\n\nfunction safeString(value: unknown, fallback = \"\"): string {\n  return typeof value === \"string\" ? value : fallback;\n}\n\nfunction safeTimestamp(value: unknown): number {\n  if (typeof value !== \"string\") return 0;\n  const time = new Date(value).getTime();\n  return Number.isFinite(time) ? time : 0;\n}\n\nfunction toFrontmatter(obj: Record<string, unknown>): string {\n  const lines = [\"---\"];\n  for (const [key, value] of Object.entries(obj)) {\n    if (value === undefined || value === null) continue;\n    if (Array.isArray(value)) {\n      lines.push(`${key}: [${value.map((v) => JSON.stringify(String(v))).join(\", \")}]`);\n    } else {\n      lines.push(`${key}: ${JSON.stringify(value)}`);\n    }\n  }\n  lines.push(\"---\");\n  return lines.join(\"\\n\");\n}\n\nfunction memoryToMd(m: Memory): string {\n  const concepts = safeArray<string>(m.concepts);\n  const files = safeArray<string>(m.files);\n  const relatedIds = safeArray<string>(m.relatedIds);\n  const supersedes = safeArray<string>(m.supersedes);\n  const title = safeString(m.title, m.id);\n\n  const fm = toFrontmatter({\n    id: m.id,\n    type: m.type,\n    created: m.createdAt,\n    updated: m.updatedAt,\n    strength: m.strength,\n    version: m.version,\n    concepts,\n    files,\n  });\n\n  const relatedLines = relatedIds.map((id) => `- [[${id}]]`).join(\"\\n\");\n  const supersedesLines = supersedes\n    .map((id) => `- [[${id}]] (superseded)`)\n    .join(\"\\n\");\n\n  const sections = [\n    fm,\n    \"\",\n    `# ${title}`,\n    \"\",\n    safeString(m.content),\n  ];\n\n  if (concepts.length > 0) {\n    sections.push(\n      \"\",\n      \"## Concepts\",\n      concepts.map((c) => `#${c.replace(/\\s+/g, \"-\")}`).join(\" \"),\n    );\n  }\n  if (relatedLines) {\n    sections.push(\"\", \"## Related\", relatedLines);\n  }\n  if (supersedesLines) {\n    sections.push(\"\", \"## Supersedes\", supersedesLines);\n  }\n\n  return sections.join(\"\\n\");\n}\n\nfunction lessonToMd(l: Lesson): string {\n  const tags = safeArray<string>(l.tags);\n  const sourceIds = safeArray<string>(l.sourceIds);\n  const content = safeString(l.content);\n  const headline = content ? content.slice(0, 80) : l.id;\n\n  const fm = toFrontmatter({\n    id: l.id,\n    type: \"lesson\",\n    source: l.source,\n    confidence: l.confidence,\n    reinforcements: l.reinforcements,\n    created: l.createdAt,\n    updated: l.updatedAt,\n    project: l.project,\n    tags,\n    decayRate: l.decayRate,\n  });\n\n  const sourceLinks = sourceIds.map((id) => `- [[${id}]]`).join(\"\\n\");\n\n  const sections = [\n    fm,\n    \"\",\n    `# Lesson: ${headline}`,\n    \"\",\n    content,\n  ];\n\n  if (l.context) {\n    sections.push(\"\", \"## Context\", l.context);\n  }\n  if (tags.length > 0) {\n    sections.push(\n      \"\",\n      \"## Tags\",\n      tags.map((t) => `#${t.replace(/\\s+/g, \"-\")}`).join(\" \"),\n    );\n  }\n  if (sourceLinks) {\n    sections.push(\"\", \"## Sources\", sourceLinks);\n  }\n\n  return sections.join(\"\\n\");\n}\n\nfunction crystalToMd(c: Crystal): string {\n  const keyOutcomes = safeArray<string>(c.keyOutcomes);\n  const lessons = safeArray<string>(c.lessons);\n  const filesAffected = safeArray<string>(c.filesAffected);\n  const sourceActionIds = safeArray<string>(c.sourceActionIds);\n  const narrative = safeString(c.narrative);\n  const headline = narrative ? narrative.slice(0, 80) : c.id;\n\n  const fm = toFrontmatter({\n    id: c.id,\n    type: \"crystal\",\n    created: c.createdAt,\n    project: c.project,\n    sessionId: c.sessionId,\n    filesAffected,\n  });\n\n  const actionLinks = sourceActionIds.map((id) => `- [[${id}]]`).join(\"\\n\");\n\n  const sections = [\n    fm,\n    \"\",\n    `# Crystal: ${headline}`,\n    \"\",\n    narrative,\n    \"\",\n    \"## Key Outcomes\",\n    ...keyOutcomes.map((o) => `- ${o}`),\n  ];\n\n  if (lessons.length > 0) {\n    sections.push(\"\", \"## Lessons\", ...lessons.map((l) => `- ${l}`));\n  }\n  if (filesAffected.length > 0) {\n    sections.push(\"\", \"## Files\", ...filesAffected.map((f) => `- \\`${f}\\``));\n  }\n  if (actionLinks) {\n    sections.push(\"\", \"## Source Actions\", actionLinks);\n  }\n\n  return sections.join(\"\\n\");\n}\n\nfunction sessionToMd(s: Session): string {\n  const project = safeString(s.project, \"unknown\");\n  const status = safeString(s.status, \"unknown\");\n  const startedAt = safeString(s.startedAt, \"\");\n  const cwd = safeString(s.cwd, \"\");\n\n  const fm = toFrontmatter({\n    id: s.id,\n    type: \"session\",\n    project,\n    status,\n    started: startedAt || undefined,\n    ended: s.endedAt,\n    observations: s.observationCount,\n  });\n\n  return [\n    fm,\n    \"\",\n    `# Session: ${project}`,\n    \"\",\n    `**Status:** ${status}`,\n    startedAt ? `**Started:** ${startedAt}` : \"\",\n    s.endedAt ? `**Ended:** ${s.endedAt}` : \"\",\n    `**Observations:** ${s.observationCount ?? 0}`,\n    cwd ? `**CWD:** \\`${cwd}\\`` : \"\",\n  ]\n    .filter(Boolean)\n    .join(\"\\n\");\n}\n\ninterface ExportError {\n  id: string;\n  path: string;\n  error: string;\n}\n\nexport function registerObsidianExportFunction(\n  sdk: ISdk,\n  kv: StateKV,\n): void {\n  sdk.registerFunction(\"mem::obsidian-export\",\n    async (data: { vaultDir?: string; types?: string[] } | undefined) => {\n      if (!data || typeof data !== \"object\") {\n        return { success: false, error: \"payload is required\" };\n      }\n      if (data.vaultDir !== undefined && typeof data.vaultDir !== \"string\") {\n        return { success: false, error: \"vaultDir must be a string\" };\n      }\n      if (data.types !== undefined) {\n        if (\n          !Array.isArray(data.types) ||\n          !data.types.every((t): t is string => typeof t === \"string\")\n        ) {\n          return { success: false, error: \"types must be an array of strings\" };\n        }\n      }\n\n      const vaultDir = resolveVaultDir(data.vaultDir);\n      if (!vaultDir) {\n        return {\n          success: false,\n          error: `vaultDir must be inside ${getExportRoot()}`,\n        };\n      }\n      const exportTypes = new Set(\n        data.types ?? [\"memories\", \"lessons\", \"crystals\", \"sessions\"],\n      );\n\n      const dirs = {\n        memories: join(vaultDir, \"memories\"),\n        lessons: join(vaultDir, \"lessons\"),\n        crystals: join(vaultDir, \"crystals\"),\n        sessions: join(vaultDir, \"sessions\"),\n      };\n\n      // Outer try/catch keeps the function from ever throwing out to the\n      // iii engine's HTTP serializer; #729 surfaced an unhandled\n      // TypeError as `{\"error\":\"[object Object]\"}`. With this guard the\n      // worst case is `{success: false, error: <string>}`.\n      try {\n        await Promise.all(\n          Object.values(dirs).map((dir) => mkdir(dir, { recursive: true })),\n        );\n\n        const stats = { memories: 0, lessons: 0, crystals: 0, sessions: 0 };\n        const errors: ExportError[] = [];\n        const memoryMoc: string[] = [];\n        const lessonMoc: string[] = [];\n        const crystalMoc: string[] = [];\n        const sessionMoc: string[] = [];\n\n        const [memories, lessons, crystals, sessions] = await Promise.all([\n          exportTypes.has(\"memories\") ? kv.list<Memory>(KV.memories) : Promise.resolve([] as Memory[]),\n          exportTypes.has(\"lessons\") ? kv.list<Lesson>(KV.lessons) : Promise.resolve([] as Lesson[]),\n          exportTypes.has(\"crystals\") ? kv.list<Crystal>(KV.crystals) : Promise.resolve([] as Crystal[]),\n          exportTypes.has(\"sessions\") ? kv.list<Session>(KV.sessions) : Promise.resolve([] as Session[]),\n        ]);\n\n        for (const m of memories.filter(\n          (m): m is Memory & { id: string } => hasExportId(m) && m.isLatest === true,\n        )) {\n          const filename = `${sanitize(m.id)}.md`;\n          const filepath = join(dirs.memories, filename);\n          try {\n            await writeFile(filepath, memoryToMd(m));\n            stats.memories++;\n            memoryMoc.push(\n              `- [[memories/${sanitize(m.id)}|${safeString(m.title, m.id)}]] (${m.type}, strength: ${m.strength ?? 0})`,\n            );\n          } catch (err) {\n            errors.push({\n              id: m.id,\n              path: filepath,\n              error: err instanceof Error ? err.message : String(err),\n            });\n          }\n        }\n\n        for (const l of lessons.filter(\n          (l): l is Lesson & { id: string } => hasExportId(l) && !l.deleted,\n        )) {\n          const filename = `${sanitize(l.id)}.md`;\n          const filepath = join(dirs.lessons, filename);\n          try {\n            await writeFile(filepath, lessonToMd(l));\n            stats.lessons++;\n            const headline = safeString(l.content).slice(0, 60) || l.id;\n            lessonMoc.push(\n              `- [[lessons/${sanitize(l.id)}|${headline}]] (confidence: ${l.confidence ?? 0})`,\n            );\n          } catch (err) {\n            errors.push({\n              id: l.id,\n              path: filepath,\n              error: err instanceof Error ? err.message : String(err),\n            });\n          }\n        }\n\n        for (const c of crystals.filter(hasExportId)) {\n          const filename = `${sanitize(c.id)}.md`;\n          const filepath = join(dirs.crystals, filename);\n          try {\n            await writeFile(filepath, crystalToMd(c));\n            stats.crystals++;\n            const headline = safeString(c.narrative).slice(0, 60) || c.id;\n            crystalMoc.push(`- [[crystals/${sanitize(c.id)}|${headline}]]`);\n          } catch (err) {\n            errors.push({\n              id: c.id,\n              path: filepath,\n              error: err instanceof Error ? err.message : String(err),\n            });\n          }\n        }\n\n        const recent = sessions\n          .filter(hasExportId)\n          .sort((a, b) => safeTimestamp(b.startedAt) - safeTimestamp(a.startedAt))\n          .slice(0, 50);\n        for (const s of recent) {\n          const filename = `${sanitize(s.id)}.md`;\n          const filepath = join(dirs.sessions, filename);\n          try {\n            await writeFile(filepath, sessionToMd(s));\n            stats.sessions++;\n            sessionMoc.push(\n              `- [[sessions/${sanitize(s.id)}|${safeString(s.project, \"unknown\")} (${safeString(s.status, \"unknown\")})]]`,\n            );\n          } catch (err) {\n            errors.push({\n              id: s.id,\n              path: filepath,\n              error: err instanceof Error ? err.message : String(err),\n            });\n          }\n        }\n\n        const exportedAt = new Date().toISOString();\n        const moc = [\n          \"---\",\n          \"type: moc\",\n          `exported: ${exportedAt}`,\n          \"---\",\n          \"\",\n          \"# agentmemory vault\",\n          \"\",\n          `Exported: ${exportedAt}`,\n          \"\",\n          `## Memories (${stats.memories})`,\n          ...memoryMoc,\n          \"\",\n          `## Lessons (${stats.lessons})`,\n          ...lessonMoc,\n          \"\",\n          `## Crystals (${stats.crystals})`,\n          ...crystalMoc,\n          \"\",\n          `## Sessions (${stats.sessions})`,\n          ...sessionMoc,\n        ].join(\"\\n\");\n\n        await writeFile(join(vaultDir, \"MOC.md\"), moc);\n\n        await recordAudit(kv, \"obsidian_export\", \"mem::obsidian-export\", [], {\n          vaultDir,\n          stats,\n        });\n\n        return {\n          success: true,\n          exported: stats,\n          errors: errors.length > 0 ? errors : undefined,\n          vaultDir,\n        };\n      } catch (err) {\n        return {\n          success: false,\n          error: err instanceof Error ? err.message : String(err),\n          vaultDir,\n        };\n      }\n    },\n  );\n}\n","export const REFLECT_SYSTEM = `You are a higher-order reasoning engine. Given a cluster of related concepts, facts, lessons, and action outcomes, synthesize cross-cutting insights that span multiple individual memories.\n\nOutput format (XML):\n<insights>\n  <insight confidence=\"0.0-1.0\" title=\"Short descriptive title\">\n    The higher-order observation or principle. Should be actionable and non-obvious — something that only becomes visible when viewing multiple memories together.\n  </insight>\n</insights>\n\nRules:\n- Identify patterns, principles, or strategies that span 2+ source items\n- Confidence reflects how well-supported the insight is across sources\n- Title should be a concise label (under 60 chars)\n- Content should be the actual observation (1-3 sentences)\n- Prefer actionable insights over abstract summaries\n- Skip insights that merely restate a single source item\n- Always emit confidence attribute before title attribute`;\n\nexport function buildReflectPrompt(cluster: {\n  concepts: string[];\n  facts: Array<{ fact: string; confidence: number }>;\n  lessons: Array<{ content: string; confidence: number }>;\n  crystalNarratives: string[];\n}): string {\n  const sections: string[] = [];\n\n  sections.push(`## Concept Cluster: ${cluster.concepts.join(\", \")}`);\n\n  if (cluster.facts.length > 0) {\n    sections.push(\n      \"\\n## Known Facts\",\n      ...cluster.facts.map(\n        (f) => `- [confidence=${f.confidence}] ${f.fact}`,\n      ),\n    );\n  }\n\n  if (cluster.lessons.length > 0) {\n    sections.push(\n      \"\\n## Lessons Learned\",\n      ...cluster.lessons.map(\n        (l) => `- [confidence=${l.confidence}] ${l.content}`,\n      ),\n    );\n  }\n\n  if (cluster.crystalNarratives.length > 0) {\n    sections.push(\n      \"\\n## Completed Work Summaries\",\n      ...cluster.crystalNarratives.map((n) => `- ${n}`),\n    );\n  }\n\n  return `Synthesize higher-order insights from this cluster of related memories:\\n\\n${sections.join(\"\\n\")}`;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, fingerprintId } from \"../state/schema.js\";\nimport type {\n  Insight,\n  GraphNode,\n  GraphEdge,\n  SemanticMemory,\n  Lesson,\n  Crystal,\n  MemoryProvider,\n} from \"../types.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { REFLECT_SYSTEM, buildReflectPrompt } from \"../prompts/reflect.js\";\n\ninterface ConceptCluster {\n  concepts: string[];\n  facts: Array<{ fact: string; confidence: number }>;\n  lessons: Array<{ content: string; confidence: number }>;\n  crystalNarratives: string[];\n  factIds: string[];\n  lessonIds: string[];\n  crystalIds: string[];\n}\n\nfunction reinforceInsight(insight: Insight): void {\n  const now = new Date().toISOString();\n  insight.reinforcements++;\n  insight.confidence = Math.min(\n    1.0,\n    insight.confidence + 0.1 * (1 - insight.confidence),\n  );\n  insight.lastReinforcedAt = now;\n  insight.updatedAt = now;\n}\n\nfunction buildGraphClusters(\n  nodes: GraphNode[],\n  edges: GraphEdge[],\n  maxClusters: number,\n): string[][] {\n  const conceptNodes = nodes.filter(\n    (n) => n.type === \"concept\" && !n.stale,\n  );\n  if (conceptNodes.length === 0) return [];\n\n  const edgeMap = new Map<string, Set<string>>();\n  for (const edge of edges) {\n    if (edge.stale) continue;\n    if (!edgeMap.has(edge.sourceNodeId))\n      edgeMap.set(edge.sourceNodeId, new Set());\n    if (!edgeMap.has(edge.targetNodeId))\n      edgeMap.set(edge.targetNodeId, new Set());\n    edgeMap.get(edge.sourceNodeId)!.add(edge.targetNodeId);\n    edgeMap.get(edge.targetNodeId)!.add(edge.sourceNodeId);\n  }\n\n  const degree = new Map<string, number>();\n  for (const node of conceptNodes) {\n    degree.set(node.id, edgeMap.get(node.id)?.size || 0);\n  }\n\n  const sorted = [...conceptNodes].sort(\n    (a, b) => (degree.get(b.id) || 0) - (degree.get(a.id) || 0),\n  );\n\n  const visited = new Set<string>();\n  const clusters: string[][] = [];\n  const conceptNodeIds = new Set(conceptNodes.map((n) => n.id));\n\n  for (const seed of sorted) {\n    if (visited.has(seed.id) || clusters.length >= maxClusters) break;\n\n    const cluster: string[] = [];\n    const queue = [seed.id];\n    const seen = new Set<string>();\n    let depth = 0;\n\n    while (queue.length > 0 && depth <= 2) {\n      const levelCount = queue.length;\n      for (let i = 0; i < levelCount; i++) {\n        const current = queue.shift()!;\n        if (seen.has(current)) continue;\n        seen.add(current);\n\n        if (conceptNodeIds.has(current)) {\n          const node = conceptNodes.find((n) => n.id === current);\n          if (node) cluster.push(node.name);\n          visited.add(current);\n        }\n\n        const neighbors = edgeMap.get(current) || new Set();\n        for (const neighbor of neighbors) {\n          if (!seen.has(neighbor)) queue.push(neighbor);\n        }\n      }\n      depth++;\n    }\n\n    if (cluster.length >= 2) clusters.push(cluster);\n  }\n\n  return clusters;\n}\n\nfunction buildJaccardClusters(\n  semanticMemories: SemanticMemory[],\n  lessons: Lesson[],\n  maxClusters: number,\n): string[][] {\n  const allConcepts = new Map<string, Set<string>>();\n\n  for (const sem of semanticMemories) {\n    const terms = sem.fact.toLowerCase().split(/\\s+/).filter((t) => t.length > 3);\n    for (const term of terms) {\n      if (!allConcepts.has(term)) allConcepts.set(term, new Set());\n      allConcepts.get(term)!.add(sem.id);\n    }\n  }\n  for (const lesson of lessons) {\n    for (const tag of lesson.tags) {\n      const key = tag.toLowerCase();\n      if (!allConcepts.has(key)) allConcepts.set(key, new Set());\n      allConcepts.get(key)!.add(lesson.id);\n    }\n  }\n\n  const conceptList = [...allConcepts.keys()].filter(\n    (k) => (allConcepts.get(k)?.size || 0) >= 2,\n  );\n\n  const visited = new Set<string>();\n  const clusters: string[][] = [];\n\n  for (const concept of conceptList) {\n    if (visited.has(concept) || clusters.length >= maxClusters) break;\n\n    const cluster = [concept];\n    visited.add(concept);\n\n    const docsA = allConcepts.get(concept) || new Set();\n    for (const other of conceptList) {\n      if (visited.has(other)) continue;\n      const docsB = allConcepts.get(other) || new Set();\n      let intersection = 0;\n      for (const d of docsA) {\n        if (docsB.has(d)) intersection++;\n      }\n      const union = docsA.size + docsB.size - intersection;\n      const similarity = union > 0 ? intersection / union : 0;\n      if (similarity > 0.3) {\n        cluster.push(other);\n        visited.add(other);\n      }\n    }\n\n    if (cluster.length >= 2) clusters.push(cluster);\n  }\n\n  return clusters;\n}\n\nexport function registerReflectFunctions(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\"mem::reflect\", \n    async (data: { maxClusters?: number; project?: string }) => {\n      const maxClusters = Math.min(data?.maxClusters ?? 10, 20);\n      const maxInsightsPerCluster = 5;\n      const maxTotal = 50;\n\n      const [graphNodes, graphEdges, semanticMemories, lessons, crystals] =\n        await Promise.all([\n          kv.list<GraphNode>(KV.graphNodes).catch(() => []),\n          kv.list<GraphEdge>(KV.graphEdges).catch(() => []),\n          kv.list<SemanticMemory>(KV.semantic).catch(() => []),\n          kv.list<Lesson>(KV.lessons).catch(() => []),\n          kv.list<Crystal>(KV.crystals).catch(() => []),\n        ]);\n\n      let activeLessons = lessons.filter((l) => !l.deleted);\n      if (data?.project) {\n        activeLessons = activeLessons.filter((l) => l.project === data.project);\n      }\n\n      let conceptClusters = buildGraphClusters(\n        graphNodes,\n        graphEdges,\n        maxClusters,\n      );\n\n      const usedFallback = conceptClusters.length === 0;\n      if (usedFallback) {\n        conceptClusters = buildJaccardClusters(\n          semanticMemories,\n          activeLessons,\n          maxClusters,\n        );\n      }\n\n      let newInsights = 0;\n      let reinforced = 0;\n      let clustersSkipped = 0;\n      let totalInsights = 0;\n\n      for (const conceptNames of conceptClusters) {\n        if (totalInsights >= maxTotal) break;\n\n        const conceptSet = new Set(conceptNames.map((c) => c.toLowerCase()));\n\n        const clusterFacts = semanticMemories.filter((s) => {\n          const factTerms = s.fact.toLowerCase().split(/\\s+/);\n          return factTerms.some((t) => conceptSet.has(t));\n        });\n\n        const clusterLessons = activeLessons.filter((l) =>\n          l.tags.some((t) => conceptSet.has(t.toLowerCase())) ||\n          conceptNames.some((c) =>\n            l.content.toLowerCase().includes(c.toLowerCase()),\n          ),\n        );\n\n        const clusterCrystals = crystals.filter((c) =>\n          (c.lessons || []).some((l) =>\n            conceptNames.some((cn) =>\n              l.toLowerCase().includes(cn.toLowerCase()),\n            ),\n          ),\n        );\n\n        const totalItems =\n          clusterFacts.length + clusterLessons.length + clusterCrystals.length;\n        if (totalItems < 3) {\n          clustersSkipped++;\n          continue;\n        }\n\n        const cluster: ConceptCluster = {\n          concepts: conceptNames,\n          facts: clusterFacts.map((f) => ({\n            fact: f.fact,\n            confidence: f.confidence,\n          })),\n          lessons: clusterLessons.map((l) => ({\n            content: l.content,\n            confidence: l.confidence,\n          })),\n          crystalNarratives: clusterCrystals.map((c) => c.narrative),\n          factIds: clusterFacts.map((f) => f.id),\n          lessonIds: clusterLessons.map((l) => l.id),\n          crystalIds: clusterCrystals.map((c) => c.id),\n        };\n\n        try {\n          const prompt = buildReflectPrompt(cluster);\n          const response = await provider.summarize(REFLECT_SYSTEM, prompt);\n\n          const insightRegex =\n            /<insight\\s+confidence=\"([^\"]+)\"\\s+title=\"([^\"]+)\">([\\s\\S]*?)<\\/insight>/g;\n          let match;\n          let clusterCount = 0;\n\n          while (\n            (match = insightRegex.exec(response)) !== null &&\n            clusterCount < maxInsightsPerCluster &&\n            totalInsights < maxTotal\n          ) {\n            const parsedConf = parseFloat(match[1]);\n            const confidence = Number.isNaN(parsedConf)\n              ? 0.5\n              : Math.max(0, Math.min(1, parsedConf));\n            const title = match[2].trim();\n            const content = match[3].trim();\n\n            if (!content) continue;\n\n            const fp = fingerprintId(\"ins\", content.trim().toLowerCase());\n            const existing = await kv.get<Insight>(KV.insights, fp);\n\n            if (existing && !existing.deleted) {\n              reinforceInsight(existing);\n              await kv.set(KV.insights, existing.id, existing);\n              reinforced++;\n            } else {\n              const now = new Date().toISOString();\n              const insight: Insight = {\n                id: fp,\n                title,\n                content,\n                confidence,\n                reinforcements: 0,\n                sourceConceptCluster: conceptNames,\n                sourceMemoryIds: cluster.factIds,\n                sourceLessonIds: cluster.lessonIds,\n                sourceCrystalIds: cluster.crystalIds,\n                project: data?.project,\n                tags: conceptNames,\n                createdAt: now,\n                updatedAt: now,\n                decayRate: 0.05,\n              };\n              await kv.set(KV.insights, insight.id, insight);\n              newInsights++;\n            }\n\n            clusterCount++;\n            totalInsights++;\n          }\n        } catch {\n          continue;\n        }\n      }\n\n      try {\n        await recordAudit(kv, \"reflect\", \"mem::reflect\", [], {\n          newInsights,\n          reinforced,\n          clustersProcessed: conceptClusters.length - clustersSkipped,\n          clustersSkipped,\n          usedFallback,\n        });\n      } catch {}\n\n      return {\n        success: true,\n        newInsights,\n        reinforced,\n        clustersProcessed: conceptClusters.length - clustersSkipped,\n        clustersSkipped,\n        usedFallback,\n      };\n    },\n  );\n\n  sdk.registerFunction(\"mem::insight-list\", \n    async (data: {\n      project?: string;\n      minConfidence?: number;\n      limit?: number;\n    }) => {\n      const limit = data?.limit ?? 50;\n      const minConfidence = data?.minConfidence ?? 0;\n      let items = await kv.list<Insight>(KV.insights);\n\n      items = items.filter(\n        (i) => !i.deleted && i.confidence >= minConfidence,\n      );\n\n      if (data?.project) {\n        items = items.filter((i) => i.project === data.project);\n      }\n\n      items.sort((a, b) => b.confidence - a.confidence);\n\n      return { success: true, insights: items.slice(0, limit) };\n    },\n  );\n\n  sdk.registerFunction(\"mem::insight-search\", \n    async (data: {\n      query: string;\n      project?: string;\n      minConfidence?: number;\n      limit?: number;\n    }) => {\n      if (!data?.query?.trim()) {\n        return { success: false, error: \"query is required\" };\n      }\n\n      const query = data.query.toLowerCase();\n      const minConfidence = data.minConfidence ?? 0.1;\n      const limit = data.limit ?? 10;\n\n      let items = await kv.list<Insight>(KV.insights);\n      items = items.filter(\n        (i) => !i.deleted && i.confidence >= minConfidence,\n      );\n\n      if (data.project) {\n        items = items.filter((i) => i.project === data.project);\n      }\n\n      const terms = query.split(/\\s+/).filter((t) => t.length > 1);\n      const scored = items\n        .map((i) => {\n          const text =\n            `${i.title} ${i.content} ${i.tags.join(\" \")}`.toLowerCase();\n          const matchCount = terms.filter((t) => text.includes(t)).length;\n          if (matchCount === 0) return null;\n\n          const relevance = matchCount / terms.length;\n          const daysSince = i.lastReinforcedAt\n            ? (Date.now() - new Date(i.lastReinforcedAt).getTime()) /\n              (1000 * 60 * 60 * 24)\n            : (Date.now() - new Date(i.createdAt).getTime()) /\n              (1000 * 60 * 60 * 24);\n          const recencyBoost = 1 / (1 + daysSince * 0.01);\n          const score = i.confidence * relevance * recencyBoost;\n\n          return { insight: i, score };\n        })\n        .filter(Boolean) as Array<{ insight: Insight; score: number }>;\n\n      scored.sort((a, b) => b.score - a.score);\n\n      try {\n        await recordAudit(kv, \"insight_search\", \"mem::insight-search\", [], {\n          query: data.query,\n          resultCount: scored.length,\n        });\n      } catch {}\n\n      return {\n        success: true,\n        insights: scored.slice(0, limit).map((s) => ({\n          ...s.insight,\n          score: Math.round(s.score * 1000) / 1000,\n        })),\n      };\n    },\n  );\n\n  sdk.registerFunction(\"mem::insight-decay-sweep\", \n    async () => {\n      const items = await kv.list<Insight>(KV.insights);\n      let decayed = 0;\n      let softDeleted = 0;\n      const now = Date.now();\n      const timestamp = new Date().toISOString();\n      const dirty: Insight[] = [];\n\n      for (const insight of items) {\n        if (insight.deleted) continue;\n\n        const baseline =\n          insight.lastDecayedAt ||\n          insight.lastReinforcedAt ||\n          insight.createdAt;\n        const weeksSince =\n          (now - new Date(baseline).getTime()) / (1000 * 60 * 60 * 24 * 7);\n\n        if (weeksSince < 1) continue;\n\n        const decay = insight.decayRate * weeksSince;\n        const newConfidence = Math.max(0.05, insight.confidence - decay);\n\n        if (newConfidence !== insight.confidence) {\n          insight.confidence = Math.round(newConfidence * 1000) / 1000;\n          insight.lastDecayedAt = timestamp;\n          insight.updatedAt = timestamp;\n\n          if (insight.confidence <= 0.1 && insight.reinforcements === 0) {\n            insight.deleted = true;\n            softDeleted++;\n          } else {\n            decayed++;\n          }\n\n          dirty.push(insight);\n        }\n      }\n\n      await Promise.all(dirty.map((i) => kv.set(KV.insights, i.id, i)));\n      await recordAudit(kv, \"reflect\", \"mem::insight-decay-sweep\", dirty.map((i) => i.id), {\n        event: \"insight.decay\",\n        decayed,\n        softDeleted,\n        total: items.length,\n        timestamp,\n      });\n\n      return { success: true, decayed, softDeleted, total: items.length };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { Memory, CompressedObservation, ContextBlock } from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { recordAccessBatch } from \"./access-tracker.js\";\nimport { logger } from \"../logger.js\";\n\nconst CORE_SCOPE = \"mem:core-memory\";\n\ninterface CoreMemoryEntry {\n  id: string;\n  content: string;\n  importance: number;\n  pinned: boolean;\n  accessCount: number;\n  lastAccessedAt: string;\n  createdAt: string;\n}\n\nfunction estimateTokens(text: string): number {\n  return Math.ceil(text.length / 3);\n}\n\nfunction scoreEntry(entry: CoreMemoryEntry, now: number): number {\n  const recencyMs = now - new Date(entry.lastAccessedAt).getTime();\n  const recencyDays = recencyMs / (1000 * 60 * 60 * 24);\n  const recencyScore = 1 / (1 + recencyDays * 0.1);\n  const accessScore = Math.log2(entry.accessCount + 1) / 10;\n  const importanceScore = entry.importance / 10;\n  return importanceScore * 0.5 + recencyScore * 0.3 + accessScore * 0.2;\n}\n\nexport function registerWorkingMemoryFunctions(\n  sdk: ISdk,\n  kv: StateKV,\n  tokenBudget: number,\n): void {\n  sdk.registerFunction(\"mem::core-add\", \n    async (data: {\n      content: string;\n      importance?: number;\n      pinned?: boolean;\n    }) => {\n      if (!data?.content?.trim()) {\n        return { success: false, error: \"content is required\" };\n      }\n      const now = new Date().toISOString();\n      const entry: CoreMemoryEntry = {\n        id: generateId(\"core\"),\n        content: data.content.trim(),\n        importance: Math.min(10, Math.max(1, data.importance ?? 7)),\n        pinned: data.pinned ?? false,\n        accessCount: 0,\n        lastAccessedAt: now,\n        createdAt: now,\n      };\n      await kv.set(CORE_SCOPE, entry.id, entry);\n\n      try {\n        await recordAudit(kv, \"core_add\", \"mem::core-add\", [entry.id], {\n          content: entry.content.slice(0, 100),\n          importance: entry.importance,\n          pinned: entry.pinned,\n        });\n      } catch {}\n\n      return { success: true, id: entry.id };\n    },\n  );\n\n  sdk.registerFunction(\"mem::core-remove\", \n    async (data: { id: string }) => {\n      if (!data?.id) return { success: false, error: \"id is required\" };\n      await kv.delete(CORE_SCOPE, data.id);\n\n      try {\n        await recordAudit(kv, \"core_remove\", \"mem::core-remove\", [data.id], {});\n      } catch {}\n\n      return { success: true };\n    },\n  );\n\n  sdk.registerFunction(\"mem::core-list\", \n    async () => {\n      const entries = await kv.list<CoreMemoryEntry>(CORE_SCOPE);\n      entries.sort((a, b) => b.importance - a.importance);\n      return {\n        success: true,\n        entries,\n        totalTokens: entries.reduce(\n          (sum, e) => sum + estimateTokens(e.content),\n          0,\n        ),\n      };\n    },\n  );\n\n  sdk.registerFunction(\"mem::working-context\", \n    async (data: { budget?: number }) => {\n      const budget = data.budget || tokenBudget;\n      const now = Date.now();\n      let usedTokens = 0;\n\n      const coreEntries = await kv.list<CoreMemoryEntry>(CORE_SCOPE);\n\n      const pinned = coreEntries.filter((e) => e.pinned);\n      const unpinned = coreEntries\n        .filter((e) => !e.pinned)\n        .sort((a, b) => scoreEntry(b, now) - scoreEntry(a, now));\n\n      const coreLines: string[] = [];\n      const coreBudget = Math.floor(budget * 0.3);\n      const accessUpdates: Array<{ id: string; entry: CoreMemoryEntry }> = [];\n      const accessTimestamp = new Date().toISOString();\n\n      for (const entry of [...pinned, ...unpinned]) {\n        const tokens = estimateTokens(entry.content);\n        if (usedTokens + tokens > coreBudget && !entry.pinned) continue;\n        coreLines.push(`- ${entry.content}`);\n        usedTokens += tokens;\n\n        entry.accessCount++;\n        entry.lastAccessedAt = accessTimestamp;\n        accessUpdates.push({ id: entry.id, entry });\n      }\n\n      Promise.allSettled(\n        accessUpdates.map(({ id, entry }) => kv.set(CORE_SCOPE, id, entry)),\n      ).catch(() => {});\n\n      const archivalLines: string[] = [];\n\n      const memories = await kv.list<Memory>(KV.memories);\n      const active = memories\n        .filter((m) => m.isLatest !== false)\n        .sort((a, b) => {\n          const strengthDiff = b.strength - a.strength;\n          if (Math.abs(strengthDiff) > 0.2) return strengthDiff;\n          return (\n            new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()\n          );\n        });\n\n      const archivalIds: string[] = [];\n      for (const mem of active) {\n        const tokens = estimateTokens(mem.content);\n        if (usedTokens + tokens > budget) continue;\n        archivalLines.push(`- [${mem.type}] ${mem.title}: ${mem.content}`);\n        archivalIds.push(mem.id);\n        usedTokens += tokens;\n      }\n\n      void recordAccessBatch(kv, archivalIds);\n\n      const pagedOut = active.length - archivalLines.length;\n\n      const sections: string[] = [];\n      if (coreLines.length > 0) {\n        sections.push(`## Core Memory\\n${coreLines.join(\"\\n\")}`);\n      }\n      if (archivalLines.length > 0) {\n        sections.push(`## Archival Memory\\n${archivalLines.join(\"\\n\")}`);\n      }\n      if (pagedOut > 0) {\n        sections.push(\n          `_${pagedOut} memories paged to archival (use mem::search to retrieve)_`,\n        );\n      }\n\n      const context = sections.join(\"\\n\\n\");\n\n      logger.info(\"Working context built\", {\n        coreEntries: coreLines.length,\n        archivalEntries: archivalLines.length,\n        pagedOut,\n        tokens: usedTokens,\n        budget,\n      });\n\n      return {\n        success: true,\n        context,\n        coreEntries: coreLines.length,\n        archivalEntries: archivalLines.length,\n        pagedOut,\n        tokens: usedTokens,\n        budget,\n      };\n    },\n  );\n\n  sdk.registerFunction(\"mem::auto-page\", \n    async (data: { budget?: number }) => {\n      const budget = data?.budget || tokenBudget;\n      const coreBudget = Math.floor(budget * 0.3);\n\n      const entries = await kv.list<CoreMemoryEntry>(CORE_SCOPE);\n      let totalTokens = entries.reduce(\n        (sum, e) => sum + estimateTokens(e.content),\n        0,\n      );\n\n      if (totalTokens <= coreBudget) {\n        return { success: true, paged: 0, totalTokens, budget: coreBudget };\n      }\n\n      const now = Date.now();\n      const unpinned = entries\n        .filter((e) => !e.pinned)\n        .sort((a, b) => scoreEntry(a, now) - scoreEntry(b, now));\n\n      let paged = 0;\n      const pagedIds: string[] = [];\n      for (const entry of unpinned) {\n        if (totalTokens <= coreBudget) break;\n        const tokens = estimateTokens(entry.content);\n\n        const archivalMemory: Memory = {\n          id: generateId(\"mem\"),\n          createdAt: entry.createdAt,\n          updatedAt: new Date().toISOString(),\n          type: \"fact\",\n          title: entry.content.slice(0, 80),\n          content: entry.content,\n          concepts: [],\n          files: [],\n          sessionIds: [],\n          strength: entry.importance / 10,\n          version: 1,\n          isLatest: true,\n        };\n        await kv.set(KV.memories, archivalMemory.id, archivalMemory);\n        await kv.delete(CORE_SCOPE, entry.id);\n\n        totalTokens -= tokens;\n        paged++;\n        pagedIds.push(entry.id);\n      }\n\n      if (paged > 0) {\n        try {\n          await recordAudit(kv, \"auto_page\", \"mem::auto-page\", pagedIds, {\n            paged,\n            budget: coreBudget,\n          });\n        } catch {}\n      }\n\n      return { success: true, paged, totalTokens, budget: coreBudget };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  CompressedObservation,\n  SessionSummary,\n  ProceduralMemory,\n  Session,\n  MemoryProvider,\n} from \"../types.js\";\nimport { KV, generateId, fingerprintId } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { logger } from \"../logger.js\";\n\nconst SKILL_EXTRACT_SYSTEM = `You are a skill extraction engine. Given a completed multi-step task session, extract a reusable procedural skill document.\n\nOutput format:\n<skill>\n<trigger>When the agent encounters [specific situation/pattern]</trigger>\n<title>Short skill title</title>\n<steps>\n<step>First concrete action</step>\n<step>Second concrete action</step>\n</steps>\n<expected_outcome>What success looks like</expected_outcome>\n<tags>comma,separated,tags</tags>\n</skill>\n\nRules:\n- Extract ONLY if the session shows a clear multi-step procedure that succeeded\n- Steps must be concrete and actionable, not vague\n- The trigger should describe WHEN to apply this skill\n- If the session is exploratory with no clear procedure, output <no-skill/>\n- Maximum 10 steps per skill`;\n\nfunction buildSkillPrompt(\n  summary: SessionSummary,\n  observations: CompressedObservation[],\n): string {\n  const obsText = observations\n    .filter((o) => o.importance >= 4)\n    .sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime())\n    .slice(0, 30)\n    .map(\n      (o) =>\n        `[${o.type}] ${o.title}${o.narrative ? \": \" + o.narrative : \"\"}`,\n    )\n    .join(\"\\n\");\n\n  return `## Session Summary\nTitle: ${summary.title}\nNarrative: ${summary.narrative}\nKey Decisions: ${summary.keyDecisions.join(\"; \")}\nFiles Modified: ${summary.filesModified.join(\", \")}\nConcepts: ${summary.concepts.join(\", \")}\n\n## Observations (${observations.length} total, showing top by importance)\n${obsText}`;\n}\n\nfunction parseSkillXml(\n  xml: string,\n): {\n  trigger: string;\n  title: string;\n  steps: string[];\n  expectedOutcome: string;\n  tags: string[];\n} | null {\n  if (xml.includes(\"<no-skill/>\")) return null;\n\n  const triggerMatch = xml.match(/<trigger>([\\s\\S]*?)<\\/trigger>/);\n  const titleMatch = xml.match(/<title>([\\s\\S]*?)<\\/title>/);\n  const stepsMatch = xml.match(/<steps>([\\s\\S]*?)<\\/steps>/);\n  const outcomeMatch = xml.match(\n    /<expected_outcome>([\\s\\S]*?)<\\/expected_outcome>/,\n  );\n  const tagsMatch = xml.match(/<tags>([\\s\\S]*?)<\\/tags>/);\n\n  if (!triggerMatch || !titleMatch || !stepsMatch) return null;\n\n  const stepRegex = /<step>([\\s\\S]*?)<\\/step>/g;\n  const steps: string[] = [];\n  let match;\n  while ((match = stepRegex.exec(stepsMatch[1])) !== null) {\n    const step = match[1].trim();\n    if (step) steps.push(step);\n  }\n\n  if (steps.length < 2) return null;\n\n  return {\n    trigger: triggerMatch[1].trim(),\n    title: titleMatch[1].trim(),\n    steps,\n    expectedOutcome: outcomeMatch?.[1]?.trim() || \"\",\n    tags: tagsMatch?.[1]\n      ?.split(\",\")\n      .map((t) => t.trim())\n      .filter(Boolean) || [],\n  };\n}\n\nexport function registerSkillExtractFunctions(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\"mem::skill-extract\", \n    async (data: { sessionId: string }) => {\n      if (!data?.sessionId) {\n        return { success: false, error: \"sessionId is required\" };\n      }\n\n      const session = await kv\n        .get<Session>(KV.sessions, data.sessionId)\n        .catch(() => null);\n      if (!session) {\n        return { success: false, error: \"session not found\" };\n      }\n      if (session.status !== \"completed\") {\n        return {\n          success: false,\n          error: \"session must be completed before skill extraction\",\n        };\n      }\n\n      const [summary, observations] = await Promise.all([\n        kv.get<SessionSummary>(KV.summaries, data.sessionId).catch(() => null),\n        kv.list<CompressedObservation>(KV.observations(data.sessionId)).catch(() => []),\n      ]);\n      if (!summary) {\n        return {\n          success: false,\n          error: \"no summary — run mem::summarize first\",\n        };\n      }\n      if (observations.length < 3) {\n        return { success: false, error: \"too few observations for skill extraction\" };\n      }\n\n      try {\n        const prompt = buildSkillPrompt(summary, observations);\n        const response = await provider.summarize(\n          SKILL_EXTRACT_SYSTEM,\n          prompt,\n        );\n        const parsed = parseSkillXml(response);\n\n        if (!parsed) {\n          logger.info(\"No skill extracted — session was exploratory\", {\n            sessionId: data.sessionId,\n          });\n          return { success: true, extracted: false, reason: \"no clear procedure found\" };\n        }\n\n        const fp = fingerprintId(\n          \"skill\",\n          JSON.stringify({\n            title: parsed.title.toLowerCase(),\n            trigger: parsed.trigger.toLowerCase(),\n            steps: parsed.steps.map((s) => s.toLowerCase().trim()),\n          }),\n        );\n        const existing = await kv\n          .get<ProceduralMemory>(KV.procedural, fp)\n          .catch(() => null);\n\n        if (existing) {\n          const alreadyReinforced = existing.sourceSessionIds.includes(data.sessionId);\n          if (!alreadyReinforced) {\n            existing.strength = Math.min(1.0, existing.strength + 0.15);\n            existing.frequency++;\n            existing.sourceSessionIds = [...existing.sourceSessionIds, data.sessionId];\n          }\n          existing.updatedAt = new Date().toISOString();\n          await kv.set(KV.procedural, existing.id, existing);\n\n          try {\n            await recordAudit(kv, \"skill_extract\", \"mem::skill-extract\", [], {\n              skillId: existing.id,\n              reinforced: true,\n              sessionId: data.sessionId,\n            });\n          } catch {}\n\n          logger.info(\"Skill reinforced\", {\n            id: existing.id,\n            name: parsed.title,\n          });\n          return {\n            success: true,\n            extracted: true,\n            reinforced: true,\n            skill: existing,\n          };\n        }\n\n        const now = new Date().toISOString();\n        const skill: ProceduralMemory = {\n          id: fp,\n          name: parsed.title,\n          triggerCondition: parsed.trigger,\n          steps: parsed.steps,\n          expectedOutcome: parsed.expectedOutcome,\n          strength: 0.6,\n          frequency: 1,\n          tags: parsed.tags,\n          concepts: summary.concepts,\n          sourceSessionIds: [data.sessionId],\n          sourceObservationIds: observations\n            .slice(0, 10)\n            .map((o) => o.id),\n          createdAt: now,\n          updatedAt: now,\n        };\n\n        await kv.set(KV.procedural, skill.id, skill);\n\n        try {\n          await recordAudit(kv, \"skill_extract\", \"mem::skill-extract\", [], {\n            skillId: skill.id,\n            title: parsed.title,\n            steps: parsed.steps.length,\n            sessionId: data.sessionId,\n          });\n        } catch {}\n\n        logger.info(\"Skill extracted\", {\n          id: skill.id,\n          title: parsed.title,\n          steps: parsed.steps.length,\n        });\n\n        return { success: true, extracted: true, reinforced: false, skill };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.error(\"Skill extraction failed\", { error: msg });\n        return { success: false, error: msg };\n      }\n    },\n  );\n\n  sdk.registerFunction(\"mem::skill-list\", \n    async (data: { limit?: number }) => {\n      const limit = data?.limit ?? 50;\n      const skills = await kv.list<ProceduralMemory>(KV.procedural);\n      const sorted = skills.sort((a, b) => b.strength - a.strength);\n      return {\n        success: true,\n        skills: sorted.slice(0, limit),\n        total: sorted.length,\n      };\n    },\n  );\n\n  sdk.registerFunction(\"mem::skill-match\", \n    async (data: { query: string; limit?: number }) => {\n      if (!data?.query?.trim()) {\n        return { success: false, error: \"query is required\" };\n      }\n\n      const limit = data.limit ?? 5;\n      const query = data.query.toLowerCase();\n      const terms = query.split(/\\s+/).filter((t) => t.length > 2);\n\n      const skills = await kv.list<ProceduralMemory>(KV.procedural);\n\n      const scored = skills\n        .map((skill) => {\n          const text =\n            `${skill.name} ${skill.triggerCondition} ${(skill.tags || []).join(\" \")} ${skill.steps.join(\" \")}`.toLowerCase();\n          const matchCount = terms.filter((t) => text.includes(t)).length;\n          if (matchCount === 0) return null;\n          const relevance = matchCount / terms.length;\n          return { skill, score: relevance * skill.strength };\n        })\n        .filter(Boolean) as Array<{\n        skill: ProceduralMemory;\n        score: number;\n      }>;\n\n      scored.sort((a, b) => b.score - a.score);\n\n      return {\n        success: true,\n        matches: scored.slice(0, limit),\n      };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  CompressedObservation,\n  EnrichedChunk,\n  MemoryProvider,\n} from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { logger } from \"../logger.js\";\n\nconst SLIDING_WINDOW_SYSTEM = `You are a contextual enrichment engine. Given a primary observation and its surrounding context window (previous and next observations from the same session), produce an enriched version.\n\nYour tasks:\n1. ENTITY RESOLUTION: Replace all pronouns, implicit references (\"that framework\", \"the file\", \"it\", \"he/she\") with the explicit entity names found in the context window.\n2. PREFERENCE MAPPING: Extract any user preferences, constraints, or opinions expressed directly or indirectly.\n3. CONTEXT BRIDGES: Add brief contextual links that make this chunk self-contained without reading adjacent chunks.\n\nOutput EXACTLY this XML:\n<enriched>\n  <content>The fully enriched, self-contained text with all references resolved</content>\n  <resolved_entities>\n    <entity original=\"pronoun or reference\" resolved=\"explicit entity name\"/>\n  </resolved_entities>\n  <preferences>\n    <preference>extracted user preference or constraint</preference>\n  </preferences>\n  <context_bridges>\n    <bridge>contextual link to adjacent information</bridge>\n  </context_bridges>\n</enriched>\n\nRules:\n- The enriched content MUST be understandable in complete isolation\n- Resolve ALL ambiguous references using the context window\n- Do not hallucinate entities not present in the window\n- Preserve factual accuracy while adding clarity`;\n\nfunction buildWindowPrompt(\n  primary: CompressedObservation,\n  before: CompressedObservation[],\n  after: CompressedObservation[],\n): string {\n  const parts: string[] = [];\n\n  if (before.length > 0) {\n    parts.push(\"=== PRECEDING CONTEXT ===\");\n    for (const obs of before) {\n      parts.push(`[${obs.type}] ${obs.title}: ${obs.narrative}`);\n      if (obs.facts.length > 0) parts.push(`Facts: ${obs.facts.join(\"; \")}`);\n      if (obs.concepts.length > 0)\n        parts.push(`Concepts: ${obs.concepts.join(\", \")}`);\n    }\n  }\n\n  parts.push(\"\\n=== PRIMARY OBSERVATION (enrich this) ===\");\n  parts.push(`Type: ${primary.type}`);\n  parts.push(`Title: ${primary.title}`);\n  if (primary.subtitle) parts.push(`Subtitle: ${primary.subtitle}`);\n  parts.push(`Narrative: ${primary.narrative}`);\n  if (primary.facts.length > 0)\n    parts.push(`Facts: ${primary.facts.join(\"; \")}`);\n  if (primary.concepts.length > 0)\n    parts.push(`Concepts: ${primary.concepts.join(\", \")}`);\n  if (primary.files.length > 0)\n    parts.push(`Files: ${primary.files.join(\", \")}`);\n\n  if (after.length > 0) {\n    parts.push(\"\\n=== FOLLOWING CONTEXT ===\");\n    for (const obs of after) {\n      parts.push(`[${obs.type}] ${obs.title}: ${obs.narrative}`);\n      if (obs.facts.length > 0) parts.push(`Facts: ${obs.facts.join(\"; \")}`);\n    }\n  }\n\n  return parts.join(\"\\n\");\n}\n\nfunction parseEnrichedXml(xml: string): {\n  content: string;\n  resolvedEntities: Record<string, string>;\n  preferences: string[];\n  contextBridges: string[];\n} | null {\n  const contentMatch = xml.match(/<content>([\\s\\S]*?)<\\/content>/);\n  if (!contentMatch) return null;\n\n  const resolvedEntities: Record<string, string> = {};\n  const entityRegex =\n    /<entity\\s+original=\"([^\"]+)\"\\s+resolved=\"([^\"]+)\"\\s*\\/>/g;\n  let match;\n  while ((match = entityRegex.exec(xml)) !== null) {\n    resolvedEntities[match[1]] = match[2];\n  }\n\n  const preferences: string[] = [];\n  const prefRegex = /<preference>([^<]+)<\\/preference>/g;\n  while ((match = prefRegex.exec(xml)) !== null) {\n    preferences.push(match[1]);\n  }\n\n  const contextBridges: string[] = [];\n  const bridgeRegex = /<bridge>([^<]+)<\\/bridge>/g;\n  while ((match = bridgeRegex.exec(xml)) !== null) {\n    contextBridges.push(match[1]);\n  }\n\n  return {\n    content: contentMatch[1].trim(),\n    resolvedEntities,\n    preferences,\n    contextBridges,\n  };\n}\n\nexport function registerSlidingWindowFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\"mem::enrich-window\", \n    async (data: {\n      observationId: string;\n      sessionId: string;\n      lookback?: number;\n      lookahead?: number;\n    }) => {\n      if (\n        !data ||\n        typeof data.sessionId !== \"string\" ||\n        !data.sessionId.trim() ||\n        typeof data.observationId !== \"string\" ||\n        !data.observationId.trim()\n      ) {\n        return { success: false, error: \"sessionId and observationId are required\" };\n      }\n      const sessionId = data.sessionId.trim();\n      const observationId = data.observationId.trim();\n      const hprev = data.lookback ?? 3;\n      const hnext = data.lookahead ?? 2;\n\n      const allObs = await kv.list<CompressedObservation>(\n        KV.observations(sessionId),\n      );\n      allObs.sort(\n        (a, b) =>\n          new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),\n      );\n\n      const primaryIdx = allObs.findIndex((o) => o.id === observationId);\n      if (primaryIdx === -1) {\n        return { success: false, error: \"Observation not found\" };\n      }\n\n      const primary = allObs[primaryIdx];\n      const before = allObs.slice(Math.max(0, primaryIdx - hprev), primaryIdx);\n      const after = allObs.slice(primaryIdx + 1, primaryIdx + 1 + hnext);\n\n      if (before.length === 0 && after.length === 0) {\n        return {\n          success: true,\n          enriched: null,\n          reason: \"No adjacent context available\",\n        };\n      }\n\n      try {\n        const prompt = buildWindowPrompt(primary, before, after);\n        const response = await provider.compress(\n          SLIDING_WINDOW_SYSTEM,\n          prompt,\n        );\n        const parsed = parseEnrichedXml(response);\n\n        if (!parsed) {\n          logger.warn(\"Failed to parse enrichment XML\", {\n            obsId: data.observationId,\n          });\n          return { success: false, error: \"parse_failed\" };\n        }\n\n        const enriched: EnrichedChunk = {\n          id: generateId(\"ec\"),\n          originalObsId: observationId,\n          sessionId,\n          content: parsed.content,\n          resolvedEntities: parsed.resolvedEntities,\n          preferences: parsed.preferences,\n          contextBridges: parsed.contextBridges,\n          windowStart: Math.max(0, primaryIdx - hprev),\n          windowEnd: Math.min(allObs.length - 1, primaryIdx + hnext),\n          createdAt: new Date().toISOString(),\n        };\n\n        await kv.set(\n          KV.enrichedChunks(sessionId),\n          observationId,\n          enriched,\n        );\n        await recordAudit(kv, \"observe\", \"mem::enrich-window\", [enriched.id], {\n          action: \"persist_enriched_chunk\",\n          sessionId,\n          observationId,\n        });\n\n        logger.info(\"Observation enriched via sliding window\", {\n          obsId: observationId,\n          entitiesResolved: Object.keys(parsed.resolvedEntities).length,\n          preferencesFound: parsed.preferences.length,\n          bridges: parsed.contextBridges.length,\n        });\n\n        return { success: true, enriched };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.error(\"Sliding window enrichment failed\", { error: msg });\n        return { success: false, error: msg };\n      }\n    },\n  );\n\n  sdk.registerFunction(\"mem::enrich-session\", \n    async (data: {\n      sessionId: string;\n      lookback?: number;\n      lookahead?: number;\n      minImportance?: number;\n    }) => {\n      if (!data || typeof data.sessionId !== \"string\" || !data.sessionId.trim()) {\n        return { success: false, error: \"sessionId is required\" };\n      }\n      const sessionId = data.sessionId.trim();\n      const allObs = await kv.list<CompressedObservation>(\n        KV.observations(sessionId),\n      );\n      const minImp = data.minImportance ?? 4;\n      const toEnrich = allObs.filter((o) => o.importance >= minImp);\n\n      let enriched = 0;\n      let failed = 0;\n\n      for (const obs of toEnrich) {\n        try {\n          const result = (await sdk.trigger({ function_id: \"mem::enrich-window\", payload: {\n            observationId: obs.id,\n            sessionId,\n            lookback: data.lookback ?? 3,\n            lookahead: data.lookahead ?? 2,\n          } })) as { success?: boolean } | undefined;\n          if (result?.success) enriched++;\n          else failed++;\n        } catch {\n          failed++;\n        }\n      }\n\n      logger.info(\"Session enrichment complete\", {\n        sessionId,\n        total: toEnrich.length,\n        enriched,\n        failed,\n      });\n\n      return { success: true, total: toEnrich.length, enriched, failed };\n    },\n  );\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  GraphNode,\n  GraphEdge,\n  GraphEdgeType,\n  EdgeContext,\n  TemporalState,\n  MemoryProvider,\n} from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { logger } from \"../logger.js\";\n\nconst TEMPORAL_EXTRACTION_SYSTEM = `You are a temporal knowledge extraction engine. Given observations, extract entities AND their temporal relationships with full context metadata.\n\nFor each relationship, you MUST provide:\n1. Semantic relation type\n2. Temporal validity (when this fact became true in the real world)\n3. Context metadata: WHY this relationship exists, what reasoning led to it, what alternatives were considered\n\nOutput EXACTLY this XML:\n<temporal_graph>\n  <entities>\n    <entity type=\"file|function|concept|error|decision|pattern|library|person|project|preference|location|organization|event\" name=\"exact name\">\n      <property key=\"key\">value</property>\n      <alias>alternate name</alias>\n    </entity>\n  </entities>\n  <relationships>\n    <relationship type=\"uses|imports|modifies|causes|fixes|depends_on|related_to|works_at|prefers|blocked_by|caused_by|optimizes_for|rejected|avoids|located_in|succeeded_by\"\n      source=\"entity name\" target=\"entity name\" weight=\"0.1-1.0\"\n      valid_from=\"ISO date or 'unknown'\" valid_to=\"ISO date or 'current'\">\n      <reasoning>WHY this relationship exists</reasoning>\n      <sentiment>positive|negative|neutral</sentiment>\n      <alternatives>\n        <alt>alternative that was considered</alt>\n      </alternatives>\n    </relationship>\n  </relationships>\n</temporal_graph>\n\nRules:\n- NEVER overwrite existing relationships — always create new versioned edges\n- Extract temporal validity from context clues (\"since last month\", \"in 2024\", \"currently\")\n- Capture reasoning/motivation behind each relationship\n- Weight relationships by directness: 1.0 = explicit statement, 0.5 = inferred, 0.1 = speculative`;\n\nfunction parseTemporalGraphXml(\n  xml: string,\n  observationIds: string[],\n): { nodes: GraphNode[]; edges: GraphEdge[] } {\n  const nodes: GraphNode[] = [];\n  const edges: GraphEdge[] = [];\n  const now = new Date().toISOString();\n\n  const entityRegex =\n    /<entity\\s+type=\"([^\"]+)\"\\s+name=\"([^\"]+)\"[^>]*>([\\s\\S]*?)<\\/entity>/g;\n  let match;\n  while ((match = entityRegex.exec(xml)) !== null) {\n    const type = match[1] as GraphNode[\"type\"];\n    const name = match[2];\n    const propsBlock = match[3];\n    const properties: Record<string, string> = {};\n    const aliases: string[] = [];\n\n    const propRegex = /<property\\s+key=\"([^\"]+)\">([^<]*)<\\/property>/g;\n    let propMatch;\n    while ((propMatch = propRegex.exec(propsBlock)) !== null) {\n      properties[propMatch[1]] = propMatch[2];\n    }\n\n    const aliasRegex = /<alias>([^<]+)<\\/alias>/g;\n    while ((propMatch = aliasRegex.exec(propsBlock)) !== null) {\n      aliases.push(propMatch[1]);\n    }\n\n    nodes.push({\n      id: generateId(\"gn\"),\n      type,\n      name,\n      properties,\n      sourceObservationIds: observationIds,\n      createdAt: now,\n      aliases: aliases.length > 0 ? aliases : undefined,\n    });\n  }\n\n  const relRegex =\n    /<relationship\\s+type=\"([^\"]+)\"\\s+source=\"([^\"]+)\"\\s+target=\"([^\"]+)\"\\s+weight=\"([^\"]+)\"(?:\\s+valid_from=\"([^\"]*)\")?(?:\\s+valid_to=\"([^\"]*)\")?[^>]*>([\\s\\S]*?)<\\/relationship>/g;\n  while ((match = relRegex.exec(xml)) !== null) {\n    const type = match[1] as GraphEdgeType;\n    const sourceName = match[2];\n    const targetName = match[3];\n    const parsedWeight = parseFloat(match[4]);\n    const weight = Number.isNaN(parsedWeight) ? 0.5 : parsedWeight;\n    const validFrom = match[5] || undefined;\n    const validTo = match[6] || undefined;\n    const metaBlock = match[7] || \"\";\n\n    const sourceNode = nodes.find(\n      (n) =>\n        n.name === sourceName ||\n        (n.aliases && n.aliases.includes(sourceName)),\n    );\n    const targetNode = nodes.find(\n      (n) =>\n        n.name === targetName ||\n        (n.aliases && n.aliases.includes(targetName)),\n    );\n\n    if (sourceNode && targetNode) {\n      const reasoning =\n        metaBlock.match(/<reasoning>([^<]*)<\\/reasoning>/)?.[1] || undefined;\n      const sentiment =\n        metaBlock.match(/<sentiment>([^<]*)<\\/sentiment>/)?.[1] || undefined;\n      const alternatives: string[] = [];\n      const altRegex = /<alt>([^<]+)<\\/alt>/g;\n      let altMatch;\n      while ((altMatch = altRegex.exec(metaBlock)) !== null) {\n        alternatives.push(altMatch[1]);\n      }\n\n      const context: EdgeContext = {};\n      if (reasoning) context.reasoning = reasoning;\n      if (sentiment) context.sentiment = sentiment;\n      if (alternatives.length > 0) context.alternatives = alternatives;\n      context.confidence = Math.max(0, Math.min(1, weight));\n\n      edges.push({\n        id: generateId(\"ge\"),\n        type,\n        sourceNodeId: sourceNode.id,\n        targetNodeId: targetNode.id,\n        weight: Math.max(0, Math.min(1, weight)),\n        sourceObservationIds: observationIds,\n        createdAt: now,\n        tcommit: now,\n        tvalid:\n          validFrom && validFrom !== \"unknown\" ? validFrom : undefined,\n        tvalidEnd:\n          validTo && validTo !== \"current\" ? validTo : undefined,\n        context: Object.keys(context).length > 0 ? context : undefined,\n        version: 1,\n        isLatest: true,\n      });\n    }\n  }\n\n  return { nodes, edges };\n}\n\nexport function registerTemporalGraphFunctions(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\"mem::temporal-graph-extract\", \n    async (data: {\n      observations: Array<{\n        id: string;\n        title: string;\n        narrative: string;\n        concepts: string[];\n        files: string[];\n        type: string;\n        timestamp: string;\n      }>;\n    }) => {\n      if (!data.observations || data.observations.length === 0) {\n        return { success: false, error: \"No observations provided\" };\n      }\n\n      const items = data.observations\n        .map(\n          (o, i) =>\n            `[${i + 1}] Type: ${o.type}\\nTimestamp: ${o.timestamp}\\nTitle: ${o.title}\\nNarrative: ${o.narrative}\\nConcepts: ${(o.concepts ?? []).join(\", \")}\\nFiles: ${(o.files ?? []).join(\", \")}`,\n        )\n        .join(\"\\n\\n\");\n\n      try {\n        const response = await provider.compress(\n          TEMPORAL_EXTRACTION_SYSTEM,\n          `Extract temporal knowledge graph from:\\n\\n${items}`,\n        );\n\n        const obsIds = data.observations.map((o) => o.id);\n        const { nodes, edges } = parseTemporalGraphXml(response, obsIds);\n\n        const existingNodes = await kv.list<GraphNode>(KV.graphNodes);\n        const existingEdges = await kv.list<GraphEdge>(KV.graphEdges);\n\n        const idRemap = new Map<string, string>();\n        for (const node of nodes) {\n          const existing = existingNodes.find(\n            (n) =>\n              n.name === node.name && n.type === node.type,\n          );\n          if (existing) {\n            const oldId = node.id;\n            const merged = {\n              ...existing,\n              sourceObservationIds: [\n                ...new Set([\n                  ...existing.sourceObservationIds,\n                  ...obsIds,\n                ]),\n              ],\n              properties: { ...existing.properties, ...node.properties },\n              updatedAt: new Date().toISOString(),\n              aliases: [\n                ...new Set([\n                  ...(existing.aliases || []),\n                  ...(node.aliases || []),\n                ]),\n              ],\n            };\n            if (merged.aliases.length === 0) delete (merged as any).aliases;\n            await kv.set(KV.graphNodes, existing.id, merged);\n            node.id = existing.id;\n            idRemap.set(oldId, existing.id);\n          } else {\n            await kv.set(KV.graphNodes, node.id, node);\n            existingNodes.push(node);\n          }\n        }\n\n        for (const edge of edges) {\n          if (idRemap.has(edge.sourceNodeId)) {\n            edge.sourceNodeId = idRemap.get(edge.sourceNodeId)!;\n          }\n          if (idRemap.has(edge.targetNodeId)) {\n            edge.targetNodeId = idRemap.get(edge.targetNodeId)!;\n          }\n          const existingKey = `${edge.sourceNodeId}|${edge.targetNodeId}|${edge.type}`;\n          const existingEdge = existingEdges.find(\n            (e) =>\n              `${e.sourceNodeId}|${e.targetNodeId}|${e.type}` ===\n              existingKey,\n          );\n\n          if (existingEdge) {\n            const updatedOld = {\n              ...existingEdge,\n              isLatest: false,\n              tvalidEnd:\n                existingEdge.tvalidEnd || new Date().toISOString(),\n              supersededBy: edge.id,\n            };\n            await kv.set(KV.graphEdges, existingEdge.id, updatedOld);\n\n            await kv.set(KV.graphEdgeHistory, existingEdge.id, updatedOld);\n\n            edge.version = (existingEdge.version || 1) + 1;\n          }\n\n          await kv.set(KV.graphEdges, edge.id, edge);\n          existingEdges.push(edge);\n        }\n\n        logger.info(\"Temporal graph extraction complete\", {\n          nodes: nodes.length,\n          edges: edges.length,\n        });\n        return {\n          success: true,\n          nodesAdded: nodes.length,\n          edgesAdded: edges.length,\n        };\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err);\n        logger.error(\"Temporal graph extraction failed\", { error: msg });\n        return { success: false, error: msg };\n      }\n    },\n  );\n\n  sdk.registerFunction(\"mem::temporal-query\", \n    async (data: {\n      entityName: string;\n      asOf?: string;\n      includeHistory?: boolean;\n    }): Promise<TemporalState | { error: string }> => {\n      const allNodes = await kv.list<GraphNode>(KV.graphNodes);\n      const allEdges = await kv.list<GraphEdge>(KV.graphEdges);\n\n      const entity = allNodes.find(\n        (n) =>\n          n.name.toLowerCase() === data.entityName.toLowerCase() ||\n          (n.aliases &&\n            n.aliases.some(\n              (a) =>\n                a.toLowerCase() === data.entityName.toLowerCase(),\n            )),\n      );\n\n      if (!entity) {\n        return { error: `Entity \"${data.entityName}\" not found` } as any;\n      }\n\n      const relatedEdges = allEdges.filter(\n        (e) => e.sourceNodeId === entity.id || e.targetNodeId === entity.id,\n      );\n\n      const historicalEdges = await kv\n        .list<GraphEdge>(KV.graphEdgeHistory)\n        .catch(() => [] as GraphEdge[]);\n      const entityHistory = historicalEdges.filter(\n        (e) => e.sourceNodeId === entity.id || e.targetNodeId === entity.id,\n      );\n\n      const allEntityEdges = [...relatedEdges, ...entityHistory];\n\n      if (data.asOf) {\n        const asOfTime = new Date(data.asOf).getTime();\n        const validEdges = allEntityEdges.filter((e) => {\n          const commitTime = new Date(\n            e.tcommit || e.createdAt,\n          ).getTime();\n          if (commitTime > asOfTime) return false;\n          if (e.tvalid) {\n            const validTime = new Date(e.tvalid).getTime();\n            if (validTime > asOfTime) return false;\n          }\n          if (e.tvalidEnd) {\n            const endTime = new Date(e.tvalidEnd).getTime();\n            if (endTime < asOfTime) return false;\n          }\n          return true;\n        });\n\n        const currentEdges = getLatestByKey(validEdges);\n        const historical = data.includeHistory ? validEdges : [];\n\n        return {\n          entity,\n          currentEdges,\n          historicalEdges: historical,\n          timeline: buildTimeline(allEntityEdges),\n        };\n      }\n\n      const currentEdges = relatedEdges.filter(\n        (e) => e.isLatest !== false,\n      );\n\n      return {\n        entity,\n        currentEdges,\n        historicalEdges: data.includeHistory ? entityHistory : [],\n        timeline: buildTimeline(allEntityEdges),\n      };\n    },\n  );\n\n  sdk.registerFunction(\"mem::differential-state\", \n    async (data: {\n      entityName: string;\n      from?: string;\n      to?: string;\n    }) => {\n      const allNodes = await kv.list<GraphNode>(KV.graphNodes);\n      const allEdges = await kv.list<GraphEdge>(KV.graphEdges);\n      const historicalEdges = await kv\n        .list<GraphEdge>(KV.graphEdgeHistory)\n        .catch(() => [] as GraphEdge[]);\n\n      const entity = allNodes.find(\n        (n) => n.name.toLowerCase() === data.entityName.toLowerCase(),\n      );\n      if (!entity) return { error: \"Entity not found\" };\n\n      const allEntityEdges = [\n        ...allEdges.filter(\n          (e) =>\n            e.sourceNodeId === entity.id || e.targetNodeId === entity.id,\n        ),\n        ...historicalEdges.filter(\n          (e) =>\n            e.sourceNodeId === entity.id || e.targetNodeId === entity.id,\n        ),\n      ];\n\n      allEntityEdges.sort(\n        (a, b) =>\n          new Date(a.tcommit || a.createdAt).getTime() -\n          new Date(b.tcommit || b.createdAt).getTime(),\n      );\n\n      const fromTime = data.from\n        ? new Date(data.from).getTime()\n        : 0;\n      const toTime = data.to\n        ? new Date(data.to).getTime()\n        : Date.now();\n\n      const filtered = allEntityEdges.filter((e) => {\n        const t = new Date(e.tcommit || e.createdAt).getTime();\n        return t >= fromTime && t <= toTime;\n      });\n\n      const changes = filtered.map((e) => ({\n        type: e.type,\n        target:\n          e.sourceNodeId === entity.id\n            ? e.targetNodeId\n            : e.sourceNodeId,\n        validFrom: e.tvalid || e.createdAt,\n        validTo: e.tvalidEnd,\n        reasoning: e.context?.reasoning,\n        sentiment: e.context?.sentiment,\n        version: e.version || 1,\n        isLatest: e.isLatest !== false,\n      }));\n\n      return {\n        entity: entity.name,\n        totalChanges: changes.length,\n        changes,\n      };\n    },\n  );\n}\n\nfunction getLatestByKey(edges: GraphEdge[]): GraphEdge[] {\n  const byKey = new Map<string, GraphEdge>();\n  for (const e of edges) {\n    const key = `${e.sourceNodeId}|${e.targetNodeId}|${e.type}`;\n    const existing = byKey.get(key);\n    if (\n      !existing ||\n      new Date(e.tcommit || e.createdAt).getTime() >\n        new Date(existing.tcommit || existing.createdAt).getTime()\n    ) {\n      byKey.set(key, e);\n    }\n  }\n  return Array.from(byKey.values());\n}\n\nfunction buildTimeline(\n  edges: GraphEdge[],\n): Array<{\n  edge: GraphEdge;\n  validFrom: string;\n  validTo?: string;\n  context?: EdgeContext;\n}> {\n  const sorted = [...edges].sort(\n    (a, b) =>\n      new Date(a.tcommit || a.createdAt).getTime() -\n      new Date(b.tcommit || b.createdAt).getTime(),\n  );\n\n  return sorted.map((e) => ({\n    edge: e,\n    validFrom: e.tvalid || e.createdAt,\n    validTo: e.tvalidEnd,\n    context: e.context,\n  }));\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type {\n  Memory,\n  SemanticMemory,\n  RetentionScore,\n  DecayConfig,\n} from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport type { AccessLog } from \"./access-tracker.js\";\nimport {\n  emptyAccessLog,\n  deleteAccessLog,\n  normalizeAccessLog,\n} from \"./access-tracker.js\";\nimport { recordAudit } from \"./audit.js\";\nimport { getSearchIndex, vectorIndexRemove, flushIndexSave } from \"./search.js\";\nimport { logger } from \"../logger.js\";\n\nconst DEFAULT_DECAY: DecayConfig = {\n  lambda: 0.01,\n  sigma: 0.3,\n  tierThresholds: {\n    hot: 0.7,\n    warm: 0.4,\n    cold: 0.15,\n  },\n};\n\nfunction resolveDecayConfig(\n  input?: Partial<DecayConfig>,\n): { config: DecayConfig } | { error: string } {\n  const tierThresholds = {\n    ...DEFAULT_DECAY.tierThresholds,\n    ...(input?.tierThresholds ?? {}),\n  };\n  const config: DecayConfig = {\n    lambda:\n      typeof input?.lambda === \"number\" ? input.lambda : DEFAULT_DECAY.lambda,\n    sigma: typeof input?.sigma === \"number\" ? input.sigma : DEFAULT_DECAY.sigma,\n    tierThresholds,\n  };\n\n  if (!Number.isFinite(config.lambda) || config.lambda <= 0) {\n    return { error: \"config.lambda must be a positive number\" };\n  }\n  if (!Number.isFinite(config.sigma) || config.sigma < 0) {\n    return { error: \"config.sigma must be a non-negative number\" };\n  }\n  const { hot, warm, cold } = config.tierThresholds;\n  if (![hot, warm, cold].every((v) => Number.isFinite(v))) {\n    return {\n      error: \"config.tierThresholds.hot/warm/cold must be finite numbers\",\n    };\n  }\n  if (!(hot >= warm && warm >= cold && cold >= 0)) {\n    return {\n      error:\n        \"config.tierThresholds must satisfy hot >= warm >= cold >= 0\",\n    };\n  }\n  return { config };\n}\n\nfunction computeReinforcementBoost(\n  accessTimestamps: number[],\n  sigma: number,\n): number {\n  const now = Date.now();\n  let boost = 0;\n  for (const tAccess of accessTimestamps) {\n    if (!Number.isFinite(tAccess)) continue;\n    const daysSinceAccess = (now - tAccess) / (1000 * 60 * 60 * 24);\n    if (daysSinceAccess > 0) {\n      boost += 1 / daysSinceAccess;\n    }\n  }\n  return boost * sigma;\n}\n\nfunction computeRetention(\n  salience: number,\n  createdAt: string,\n  accessTimestamps: number[],\n  config: DecayConfig,\n): number {\n  const deltaT =\n    (Date.now() - new Date(createdAt).getTime()) / (1000 * 60 * 60 * 24);\n  const temporalDecay = Math.exp(-config.lambda * deltaT);\n  const reinforcementBoost = computeReinforcementBoost(\n    accessTimestamps,\n    config.sigma,\n  );\n  return Math.min(1, salience * temporalDecay + reinforcementBoost);\n}\n\nfunction computeSalience(\n  memory: Memory | SemanticMemory,\n  accessCount: number,\n): number {\n  let baseSalience = 0.5;\n\n  if (\"type\" in memory) {\n    const typeWeights: Record<string, number> = {\n      architecture: 0.9,\n      bug: 0.7,\n      pattern: 0.8,\n      preference: 0.85,\n      workflow: 0.6,\n      fact: 0.5,\n    };\n    baseSalience = typeWeights[(memory as Memory).type] || 0.5;\n  }\n\n  if (\"confidence\" in memory) {\n    baseSalience = Math.max(baseSalience, (memory as SemanticMemory).confidence);\n  }\n\n  const accessBonus = Math.min(0.2, accessCount * 0.02);\n  return Math.min(1, baseSalience + accessBonus);\n}\n\nexport function registerRetentionFunctions(\n  sdk: ISdk,\n  kv: StateKV,\n): void {\n  sdk.registerFunction(\"mem::retention-score\",\n    async (data: { config?: Partial<DecayConfig> }) => {\n      const resolved = resolveDecayConfig(data?.config);\n      if (\"error\" in resolved) {\n        return { success: false, error: resolved.error };\n      }\n      const { config } = resolved;\n\n      const [memories, semanticMems, allLogs] = await Promise.all([\n        kv.list<Memory>(KV.memories),\n        kv.list<SemanticMemory>(KV.semantic),\n        kv.list<unknown>(KV.accessLog).catch(() => [] as unknown[]),\n      ]);\n      const logsById = new Map<string, AccessLog>();\n      for (const raw of allLogs) {\n        const log = normalizeAccessLog(raw);\n        if (log.memoryId) logsById.set(log.memoryId, log);\n      }\n\n      const scores: RetentionScore[] = [];\n\n      const computeDecay = (createdAt: string): number =>\n        Math.exp(\n          -config.lambda *\n            ((Date.now() - new Date(createdAt).getTime()) /\n              (1000 * 60 * 60 * 24)),\n        );\n\n      // Build all entries in memory first, then flush with Promise.all\n      // so a full rescore is one batched KV write instead of N sequential\n      // round-trips. Separate counts for the audit record at the end.\n      const pendingWrites: Array<[string, RetentionScore]> = [];\n      let episodicScored = 0;\n      let semanticScored = 0;\n\n      for (const mem of memories) {\n        if (!mem.isLatest) continue;\n        const log = logsById.get(mem.id) ?? emptyAccessLog(mem.id);\n        const salience = computeSalience(mem, log.count);\n        const temporalDecay = computeDecay(mem.createdAt);\n        const reinforcementBoost = computeReinforcementBoost(\n          log.recent,\n          config.sigma,\n        );\n        const score = Math.min(\n          1,\n          salience * temporalDecay + reinforcementBoost,\n        );\n\n        const entry: RetentionScore = {\n          memoryId: mem.id,\n          source: \"episodic\",\n          score,\n          salience,\n          temporalDecay,\n          reinforcementBoost,\n          lastAccessed: log.lastAt || mem.updatedAt,\n          accessCount: log.count,\n        };\n\n        scores.push(entry);\n        pendingWrites.push([mem.id, entry]);\n        episodicScored++;\n      }\n\n      for (const sem of semanticMems) {\n        const log = logsById.get(sem.id) ?? emptyAccessLog(sem.id);\n\n        // Pre-0.8.3 fallback: use sem.lastAccessedAt only when mem:access is empty.\n        let accessTimestamps: number[];\n        let effectiveCount: number;\n        if (log.recent.length > 0 || log.count > 0) {\n          accessTimestamps = log.recent;\n          effectiveCount = log.count;\n        } else if (sem.lastAccessedAt) {\n          const legacyTs = Date.parse(sem.lastAccessedAt);\n          accessTimestamps = Number.isFinite(legacyTs) ? [legacyTs] : [];\n          effectiveCount = sem.accessCount;\n        } else {\n          accessTimestamps = [];\n          effectiveCount = sem.accessCount;\n        }\n\n        const salience = computeSalience(sem, effectiveCount);\n        const temporalDecay = computeDecay(sem.createdAt);\n        const reinforcementBoost = computeReinforcementBoost(\n          accessTimestamps,\n          config.sigma,\n        );\n        const score = Math.min(\n          1,\n          salience * temporalDecay + reinforcementBoost,\n        );\n\n        const entry: RetentionScore = {\n          memoryId: sem.id,\n          source: \"semantic\",\n          score,\n          salience,\n          temporalDecay,\n          reinforcementBoost,\n          lastAccessed: log.lastAt || sem.lastAccessedAt,\n          accessCount: effectiveCount,\n        };\n\n        scores.push(entry);\n        pendingWrites.push([sem.id, entry]);\n        semanticScored++;\n      }\n\n      // Flush all retention rows in parallel. N sequential writes was\n      // making full rescores O(n) round-trips on stores with 1000+\n      // memories; batching drops that to O(1) wall time on the KV\n      // backends that can pipeline.\n      await Promise.all(\n        pendingWrites.map(([id, entry]) =>\n          kv.set(KV.retentionScores, id, entry),\n        ),\n      );\n\n      scores.sort((a, b) => b.score - a.score);\n\n      const tiers = {\n        hot: scores.filter((s) => s.score >= config.tierThresholds.hot)\n          .length,\n        warm: scores.filter(\n          (s) =>\n            s.score >= config.tierThresholds.warm &&\n            s.score < config.tierThresholds.hot,\n        ).length,\n        cold: scores.filter(\n          (s) =>\n            s.score >= config.tierThresholds.cold &&\n            s.score < config.tierThresholds.warm,\n        ).length,\n        evictable: scores.filter(\n          (s) => s.score < config.tierThresholds.cold,\n        ).length,\n      };\n\n      logger.info(\"Retention scores computed\", {\n        total: scores.length,\n        ...tiers,\n      });\n\n      // Audit the rescore as a single batched event per sweep. We\n      // intentionally pass an empty targetIds array — a mature store\n      // can have 1000+ memory ids per rescore and flooding the audit\n      // log with every memoryId on every cron tick is worse than\n      // recording just the summary. The details payload has enough\n      // context for observability (counts per source + per tier).\n      if (scores.length > 0) {\n        await recordAudit(kv, \"retention_score\", \"mem::retention-score\", [], {\n          total: scores.length,\n          episodic: episodicScored,\n          semantic: semanticScored,\n          tiers,\n          config,\n        });\n      }\n\n      return { success: true, total: scores.length, tiers, scores };\n    },\n  );\n\n  sdk.registerFunction(\"mem::retention-evict\", \n    async (data?: {\n      threshold?: number;\n      dryRun?: boolean;\n      maxEvict?: number;\n    }) => {\n      const threshold =\n        typeof data?.threshold === \"number\" && Number.isFinite(data.threshold)\n          ? data.threshold\n          : DEFAULT_DECAY.tierThresholds.cold;\n      const maxEvictRaw =\n        typeof data?.maxEvict === \"number\" && Number.isInteger(data.maxEvict)\n          ? data.maxEvict\n          : 50;\n      const maxEvict = Math.min(1000, Math.max(0, maxEvictRaw));\n      const { decrementImageRef } = await import(\"./image-refs.js\");\n\n      const allScores = await kv.list<RetentionScore>(KV.retentionScores);\n      const candidates = allScores\n        .filter((s) => s.score < threshold)\n        .sort((a, b) => a.score - b.score)\n        .slice(0, maxEvict);\n\n      if (data?.dryRun) {\n        return {\n          success: true,\n          dryRun: true,\n          wouldEvict: candidates.length,\n          candidates: candidates.map((c) => ({\n            id: c.memoryId,\n            score: c.score,\n          })),\n        };\n      }\n\n      // Branch on source (#124). Pre-0.8.10 rows have no `source` field,\n      // and that includes semantic retention rows that were written by\n      // the old scorer — so we can't just default to episodic, that\n      // would silently no-op the delete and leave the stranded semantic\n      // memory alive (the exact bug #124 is about). When `source` is\n      // missing, probe both namespaces to find where the memoryId\n      // actually lives and route the delete there. After one re-score\n      // (mem::retention-score) every row will have the correct tag.\n      let evicted = 0;\n      let evictedEpisodic = 0;\n      let evictedSemantic = 0;\n      const evictedIds: string[] = [];\n      for (const candidate of candidates) {\n        try {\n          let scope: string | null = null;\n          let resolvedSource: \"episodic\" | \"semantic\" | null = null;\n          if (candidate.source === \"semantic\") {\n            scope = KV.semantic;\n            resolvedSource = \"semantic\";\n          } else if (candidate.source === \"episodic\") {\n            scope = KV.memories;\n            resolvedSource = \"episodic\";\n          } else {\n            const episodic = await kv.get(KV.memories, candidate.memoryId);\n            if (episodic !== null) {\n              scope = KV.memories;\n              resolvedSource = \"episodic\";\n            } else {\n              const semantic = await kv.get(KV.semantic, candidate.memoryId);\n              if (semantic !== null) {\n                scope = KV.semantic;\n                resolvedSource = \"semantic\";\n              }\n            }\n          }\n\n          if (!scope || !resolvedSource) {\n            continue;\n          }\n\n          const mem = await kv.get<Memory>(scope, candidate.memoryId);\n          if (mem && mem.imageRef) {\n            await decrementImageRef(kv, sdk, mem.imageRef);\n          }\n          await kv.delete(scope, candidate.memoryId);\n          await kv.delete(KV.retentionScores, candidate.memoryId);\n          await deleteAccessLog(kv, candidate.memoryId);\n          getSearchIndex().remove(candidate.memoryId);\n          vectorIndexRemove(candidate.memoryId);\n          evicted++;\n          evictedIds.push(candidate.memoryId);\n          if (resolvedSource === \"semantic\") evictedSemantic++;\n          else evictedEpisodic++;\n        } catch {\n          continue;\n        }\n      }\n\n      // Retention eviction is a structural delete path that removes\n      // memories, retention scores, and access logs, so it needs to\n      // emit an audit record per the repo's audit-coverage policy (see\n      // mem::governance-delete for the reference pattern). Batched,\n      // one record per invocation — per-candidate audits would flood\n      // the audit log during normal eviction sweeps.\n      if (evicted > 0) {\n        await flushIndexSave();\n        await recordAudit(kv, \"delete\", \"mem::retention-evict\", evictedIds, {\n          threshold,\n          evicted,\n          evictedEpisodic,\n          evictedSemantic,\n          reason: \"retention score below threshold\",\n        });\n      }\n\n      logger.info(\"Retention-based eviction complete\", {\n        evicted,\n        evictedEpisodic,\n        evictedSemantic,\n        threshold,\n      });\n\n      return { success: true, evicted, evictedEpisodic, evictedSemantic };\n    },\n  );\n}\n","import { constants } from \"node:fs\";\nimport { lstat, open, readFile, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, extname, join, resolve } from \"node:path\";\nimport type { ISdk } from \"iii-sdk\";\nimport type { MemoryProvider } from \"../types.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { recordAudit } from \"./audit.js\";\n\nconst SENSITIVE_PATH_TERMS = [\n  \"secret\",\n  \"credential\",\n  \"private_key\",\n  \".env\",\n  \"id_rsa\",\n  \"token\",\n];\n\nconst COMPRESS_FILE_SYSTEM_PROMPT = `You compress markdown while preserving structure.\nRules:\n- Keep all headings exactly as-is.\n- Keep all URLs exactly as-is.\n- Keep all fenced code blocks exactly as-is.\n- Do not remove sections; shorten prose under each section.\n- Output only markdown, no wrappers or explanations.`;\n\nfunction stripMarkdownFence(text: string): string {\n  const trimmed = text.trim();\n  const match = trimmed.match(/^```(?:markdown|md)?\\s*([\\s\\S]*?)\\s*```$/i);\n  return match ? match[1].trim() : trimmed;\n}\n\nfunction extractUrls(text: string): string[] {\n  return Array.from(new Set(text.match(/https?:\\/\\/[^\\s)]+/g) || []));\n}\n\nfunction extractHeadings(text: string): string[] {\n  return text\n    .split(\"\\n\")\n    .map((line) => line.trim())\n    .filter((line) => /^#{1,6}\\s+/.test(line));\n}\n\nfunction extractCodeBlocks(text: string): string[] {\n  return text.match(/```[\\s\\S]*?```/g) || [];\n}\n\nfunction validateCompression(original: string, compressed: string): string[] {\n  const errors: string[] = [];\n\n  const originalHeadings = extractHeadings(original);\n  const compressedHeadings = extractHeadings(compressed);\n  for (const heading of originalHeadings) {\n    if (!compressedHeadings.includes(heading)) {\n      errors.push(`missing heading: ${heading}`);\n    }\n  }\n\n  const originalUrls = extractUrls(original).sort();\n  const compressedUrls = extractUrls(compressed).sort();\n  if (originalUrls.length !== compressedUrls.length) {\n    errors.push(\"url count changed\");\n  } else {\n    for (let i = 0; i < originalUrls.length; i++) {\n      if (originalUrls[i] !== compressedUrls[i]) {\n        errors.push(\"url set changed\");\n        break;\n      }\n    }\n  }\n\n  const originalBlocks = extractCodeBlocks(original);\n  const compressedBlocks = extractCodeBlocks(compressed);\n  if (originalBlocks.length !== compressedBlocks.length) {\n    errors.push(\"code block count changed\");\n  } else {\n    for (let i = 0; i < originalBlocks.length; i++) {\n      if (originalBlocks[i] !== compressedBlocks[i]) {\n        errors.push(\"code block content changed\");\n        break;\n      }\n    }\n  }\n\n  return errors;\n}\n\nfunction resolveBackupPath(filePath: string): string {\n  const base = basename(filePath, extname(filePath));\n  const name = base.endsWith(\".original\")\n    ? `${base}.backup`\n    : `${base}.original`;\n  return join(dirname(filePath), `${name}.md`);\n}\n\nexport function registerCompressFileFunction(\n  sdk: ISdk,\n  kv: StateKV,\n  provider: MemoryProvider,\n): void {\n  sdk.registerFunction(\n    \"mem::compress-file\",\n    async (data: { filePath: string }) => {\n      if (!data?.filePath || typeof data.filePath !== \"string\") {\n        return { success: false, error: \"filePath is required\" };\n      }\n\n      const absolutePath = resolve(data.filePath);\n      const lowerPath = absolutePath.toLowerCase();\n      if (extname(absolutePath).toLowerCase() !== \".md\") {\n        return { success: false, error: \"filePath must point to a .md file\" };\n      }\n      if (SENSITIVE_PATH_TERMS.some((term) => lowerPath.includes(term))) {\n        return { success: false, error: \"refusing to process sensitive-looking path\" };\n      }\n\n      try {\n        const stat = await lstat(absolutePath);\n        if (stat.isSymbolicLink()) {\n          return { success: false, error: \"symlinks are not supported\" };\n        }\n      } catch {\n        return { success: false, error: \"file not found\" };\n      }\n\n      let original: string;\n      try {\n        original = await readFile(absolutePath, \"utf-8\");\n      } catch {\n        return { success: false, error: \"failed to read file\" };\n      }\n\n      if (!original.trim()) {\n        return { success: true, skipped: true, reason: \"file is empty\" };\n      }\n\n      const response = await provider.summarize(\n        COMPRESS_FILE_SYSTEM_PROMPT,\n        `Compress this markdown file while preserving structure and code blocks:\\n\\n${original}`,\n      );\n      const compressed = stripMarkdownFence(response);\n      const validationErrors = validateCompression(original, compressed);\n      if (validationErrors.length > 0) {\n        return {\n          success: false,\n          error: \"compression validation failed\",\n          details: validationErrors,\n        };\n      }\n\n      const backupPath = resolveBackupPath(absolutePath);\n      await writeFile(backupPath, original, \"utf-8\");\n\n      let fd: Awaited<ReturnType<typeof open>> | null = null;\n      try {\n        fd = await open(\n          absolutePath,\n          constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_NOFOLLOW,\n        );\n        await fd.writeFile(compressed, \"utf-8\");\n      } catch (err: unknown) {\n        const code = (err as NodeJS.ErrnoException).code;\n        if (code === \"ELOOP\" || code === \"EINVAL\") {\n          return { success: false, error: \"symlinks are not supported\" };\n        }\n        return { success: false, error: \"failed to write compressed file\" };\n      } finally {\n        await fd?.close().catch(() => {});\n      }\n\n      try {\n        await recordAudit(kv, \"compress\", \"mem::compress-file\", [], {\n          filePath: absolutePath,\n          backupPath,\n          originalChars: original.length,\n          compressedChars: compressed.length,\n        });\n      } catch {}\n\n      return {\n        success: true,\n        filePath: absolutePath,\n        backupPath,\n        originalChars: original.length,\n        compressedChars: compressed.length,\n      };\n    },\n  );\n}\n","import type { HookType, RawObservation } from \"../types.js\";\nimport { generateId } from \"../state/schema.js\";\n\ninterface JsonlEntry {\n  type?: string;\n  uuid?: string;\n  sessionId?: string;\n  timestamp?: string;\n  cwd?: string;\n  message?: {\n    role?: string;\n    content?: unknown;\n  };\n  toolUseResult?: unknown;\n  [k: string]: unknown;\n}\n\nexport interface ParsedTranscript {\n  sessionId: string;\n  project: string;\n  cwd: string;\n  startedAt: string;\n  endedAt: string;\n  observations: RawObservation[];\n}\n\nfunction deriveProject(cwd: string): string {\n  if (!cwd) return \"unknown\";\n  const parts = cwd.split(\"/\").filter(Boolean);\n  return parts[parts.length - 1] || \"unknown\";\n}\n\nfunction toText(content: unknown): string {\n  if (typeof content === \"string\") return content;\n  if (!Array.isArray(content)) return \"\";\n  const parts: string[] = [];\n  for (const item of content) {\n    if (!item || typeof item !== \"object\") continue;\n    const entry = item as Record<string, unknown>;\n    if (entry.type === \"text\" && typeof entry.text === \"string\") {\n      parts.push(entry.text);\n    }\n  }\n  return parts.join(\"\\n\");\n}\n\nfunction extractToolUses(content: unknown): Array<{ id: string; name: string; input: unknown }> {\n  if (!Array.isArray(content)) return [];\n  const out: Array<{ id: string; name: string; input: unknown }> = [];\n  for (const item of content) {\n    if (!item || typeof item !== \"object\") continue;\n    const entry = item as Record<string, unknown>;\n    if (entry.type === \"tool_use\") {\n      out.push({\n        id: typeof entry.id === \"string\" ? entry.id : \"\",\n        name: typeof entry.name === \"string\" ? entry.name : \"unknown\",\n        input: entry.input,\n      });\n    }\n  }\n  return out;\n}\n\nfunction extractToolResults(content: unknown): Array<{ toolUseId: string; output: unknown; isError: boolean }> {\n  if (!Array.isArray(content)) return [];\n  const out: Array<{ toolUseId: string; output: unknown; isError: boolean }> = [];\n  for (const item of content) {\n    if (!item || typeof item !== \"object\") continue;\n    const entry = item as Record<string, unknown>;\n    if (entry.type === \"tool_result\") {\n      out.push({\n        toolUseId: typeof entry.tool_use_id === \"string\" ? entry.tool_use_id : \"\",\n        output: entry.content,\n        isError: entry.is_error === true,\n      });\n    }\n  }\n  return out;\n}\n\nexport function parseJsonlText(text: string, fallbackSessionId?: string): ParsedTranscript {\n  const lines = text.split(\"\\n\").filter((l) => l.trim().length > 0);\n  const entries: JsonlEntry[] = [];\n  for (const line of lines) {\n    try {\n      const parsed = JSON.parse(line);\n      if (parsed && typeof parsed === \"object\") entries.push(parsed as JsonlEntry);\n    } catch {\n      // skip malformed lines\n    }\n  }\n\n  let sessionId = \"\";\n  let cwd = \"\";\n  let firstTs = \"\";\n  let lastTs = \"\";\n\n  const observations: RawObservation[] = [];\n\n  for (const entry of entries) {\n    if (entry.sessionId && !sessionId) sessionId = entry.sessionId;\n    if (entry.cwd && !cwd) cwd = entry.cwd;\n    const ts = entry.timestamp || new Date().toISOString();\n    if (!firstTs) firstTs = ts;\n    lastTs = ts;\n\n    const role = entry.message?.role;\n    const content = entry.message?.content;\n\n    if (entry.type === \"user\" && role === \"user\") {\n      const toolResults = extractToolResults(content);\n      if (toolResults.length > 0) {\n        for (const result of toolResults) {\n          observations.push({\n            id: generateId(\"obs\"),\n            sessionId: sessionId || \"imported\",\n            timestamp: ts,\n            hookType: (result.isError ? \"post_tool_failure\" : \"post_tool_use\") as HookType,\n            toolName: undefined,\n            toolInput: { toolUseId: result.toolUseId },\n            toolOutput: result.output,\n            raw: entry,\n          });\n        }\n      } else {\n        const text = toText(content);\n        if (text.trim().length > 0) {\n          observations.push({\n            id: generateId(\"obs\"),\n            sessionId: sessionId || \"imported\",\n            timestamp: ts,\n            hookType: \"prompt_submit\" as HookType,\n            userPrompt: text,\n            raw: entry,\n          });\n        }\n      }\n    } else if (entry.type === \"assistant\" && role === \"assistant\") {\n      const text = toText(content);\n      const tools = extractToolUses(content);\n      if (text.trim().length > 0) {\n        observations.push({\n          id: generateId(\"obs\"),\n          sessionId: sessionId || \"imported\",\n          timestamp: ts,\n          hookType: \"stop\" as HookType,\n          assistantResponse: text,\n          raw: entry,\n        });\n      }\n      for (const tool of tools) {\n        observations.push({\n          id: generateId(\"obs\"),\n          sessionId: sessionId || \"imported\",\n          timestamp: ts,\n          hookType: \"pre_tool_use\" as HookType,\n          toolName: tool.name,\n          toolInput: tool.input,\n          raw: { toolUseId: tool.id, entry },\n        });\n      }\n    } else if (entry.type === \"summary\" || entry.type === \"system\") {\n      // ignore meta entries\n    }\n  }\n\n  const effectiveSessionId = sessionId || fallbackSessionId || generateId(\"sess\");\n  for (const obs of observations) {\n    if (obs.sessionId === \"imported\") obs.sessionId = effectiveSessionId;\n  }\n\n  const nowIso = new Date().toISOString();\n  return {\n    sessionId: effectiveSessionId,\n    project: deriveProject(cwd),\n    cwd: cwd || process.cwd(),\n    startedAt: firstTs || nowIso,\n    endedAt: lastTs || nowIso,\n    observations,\n  };\n}\n","import type { RawObservation } from \"../types.js\";\n\nexport type TimelineEventKind =\n  | \"prompt\"\n  | \"response\"\n  | \"tool_call\"\n  | \"tool_result\"\n  | \"tool_error\"\n  | \"hook\"\n  | \"session_start\"\n  | \"session_end\";\n\nexport interface TimelineEvent {\n  id: string;\n  sessionId: string;\n  ts: string;\n  offsetMs: number;\n  durationMs: number;\n  kind: TimelineEventKind;\n  label: string;\n  body?: string;\n  toolName?: string;\n  toolInput?: unknown;\n  toolOutput?: unknown;\n}\n\nexport interface Timeline {\n  sessionId: string;\n  startedAt: string;\n  endedAt: string;\n  totalDurationMs: number;\n  eventCount: number;\n  events: TimelineEvent[];\n}\n\nconst DEFAULT_CHARS_PER_SEC = 40;\nconst MIN_EVENT_MS = 300;\nconst MAX_EVENT_MS = 20_000;\n\nfunction kindFromHook(obs: RawObservation): TimelineEventKind {\n  switch (obs.hookType) {\n    case \"session_start\":\n      return \"session_start\";\n    case \"session_end\":\n      return \"session_end\";\n    case \"prompt_submit\":\n      return \"prompt\";\n    case \"stop\":\n      return obs.assistantResponse ? \"response\" : \"hook\";\n    case \"pre_tool_use\":\n      return \"tool_call\";\n    case \"post_tool_use\":\n      return \"tool_result\";\n    case \"post_tool_failure\":\n      return \"tool_error\";\n    default:\n      return \"hook\";\n  }\n}\n\nfunction labelFor(obs: RawObservation, kind: TimelineEventKind): string {\n  switch (kind) {\n    case \"prompt\":\n      return truncate(obs.userPrompt || \"User prompt\", 80);\n    case \"response\":\n      return truncate(obs.assistantResponse || \"Assistant response\", 80);\n    case \"tool_call\":\n      return `${obs.toolName || \"tool\"} ▸ call`;\n    case \"tool_result\":\n      return `${obs.toolName || \"tool\"} ▸ result`;\n    case \"tool_error\":\n      return `${obs.toolName || \"tool\"} ▸ error`;\n    case \"session_start\":\n      return \"Session start\";\n    case \"session_end\":\n      return \"Session end\";\n    default:\n      return obs.hookType;\n  }\n}\n\nfunction truncate(text: string, max: number): string {\n  if (text.length <= max) return text;\n  return text.slice(0, max - 1) + \"…\";\n}\n\nfunction bodyFor(obs: RawObservation, kind: TimelineEventKind): string | undefined {\n  if (kind === \"prompt\") return obs.userPrompt;\n  if (kind === \"response\") return obs.assistantResponse;\n  return undefined;\n}\n\nfunction estimateDurationMs(ev: TimelineEvent): number {\n  const chars =\n    (ev.body?.length || 0) +\n    (typeof ev.toolInput === \"string\" ? ev.toolInput.length : 0) +\n    (typeof ev.toolOutput === \"string\" ? ev.toolOutput.length : 0);\n  if (chars === 0) return MIN_EVENT_MS;\n  const ms = Math.round((chars / DEFAULT_CHARS_PER_SEC) * 1000);\n  return Math.max(MIN_EVENT_MS, Math.min(MAX_EVENT_MS, ms));\n}\n\nexport function projectTimeline(observations: RawObservation[]): Timeline {\n  if (observations.length === 0) {\n    const now = new Date().toISOString();\n    return {\n      sessionId: \"\",\n      startedAt: now,\n      endedAt: now,\n      totalDurationMs: 0,\n      eventCount: 0,\n      events: [],\n    };\n  }\n\n  const sorted = [...observations].sort((a, b) =>\n    a.timestamp.localeCompare(b.timestamp),\n  );\n\n  const startedAt = sorted[0].timestamp;\n  const startMs = Date.parse(startedAt);\n  const events: TimelineEvent[] = [];\n\n  let syntheticOffset = 0;\n  const allSameTs = sorted.every((o) => o.timestamp === startedAt);\n\n  for (const obs of sorted) {\n    const kind = kindFromHook(obs);\n    const body = bodyFor(obs, kind);\n    const obsMs = Date.parse(obs.timestamp);\n    const offsetMs = allSameTs\n      ? syntheticOffset\n      : Number.isFinite(obsMs) && Number.isFinite(startMs)\n        ? Math.max(0, obsMs - startMs)\n        : syntheticOffset;\n\n    const event: TimelineEvent = {\n      id: obs.id,\n      sessionId: obs.sessionId,\n      ts: obs.timestamp,\n      offsetMs,\n      durationMs: 0,\n      kind,\n      label: labelFor(obs, kind),\n      body,\n      toolName: obs.toolName,\n      toolInput: obs.toolInput,\n      toolOutput: obs.toolOutput,\n    };\n    event.durationMs = estimateDurationMs(event);\n    events.push(event);\n    syntheticOffset += event.durationMs;\n  }\n\n  const last = events[events.length - 1];\n  const totalDurationMs = last.offsetMs + last.durationMs;\n\n  return {\n    sessionId: sorted[0].sessionId,\n    startedAt,\n    endedAt: sorted[sorted.length - 1].timestamp,\n    totalDurationMs,\n    eventCount: events.length,\n    events,\n  };\n}\n","import { homedir } from \"node:os\";\nimport { lstat, readFile, readdir } from \"node:fs/promises\";\nimport { resolve, join } from \"node:path\";\nimport type { ISdk } from \"iii-sdk\";\nimport type {\n  CompressedObservation,\n  Crystal,\n  Lesson,\n  RawObservation,\n  Session,\n} from \"../types.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV, generateId, fingerprintId } from \"../state/schema.js\";\nimport { parseJsonlText } from \"../replay/jsonl-parser.js\";\nimport { projectTimeline, type Timeline } from \"../replay/timeline.js\";\nimport { safeAudit } from \"./audit.js\";\nimport { buildSyntheticCompression } from \"./compress-synthetic.js\";\nimport { getSearchIndex } from \"./search.js\";\nimport { logger } from \"../logger.js\";\n\nexport const MAX_FILES_DEFAULT = 200;\nexport const MAX_FILES_UPPER_BOUND = 1000;\n\nconst SENSITIVE_PATH_PATTERNS: RegExp[] = [\n  /(^|[\\\\/_.-])secret([\\\\/_.-]|s?$)/i,\n  /(^|[\\\\/_.-])credentials?([\\\\/_.-]|$)/i,\n  /(^|[\\\\/_.-])private[_-]?key([\\\\/_.-]|$)/i,\n  /(^|[\\\\/])\\.env(\\.[\\w-]+)?$/i,\n  /(^|[\\\\/_.-])id_rsa([\\\\/_.-]|$)/i,\n  /(^|[\\\\/])auth[_-]?token([\\\\/_.-]|$)/i,\n  /(^|[\\\\/])bearer[_-]?token([\\\\/_.-]|$)/i,\n  /(^|[\\\\/])access[_-]?token([\\\\/_.-]|$)/i,\n  /(^|[\\\\/])api[_-]?token([\\\\/_.-]|$)/i,\n];\n\nexport function isSensitive(path: string): boolean {\n  return SENSITIVE_PATH_PATTERNS.some((re) => re.test(path));\n}\n\nasync function isSymlink(path: string): Promise<boolean> {\n  try {\n    const st = await lstat(path);\n    return st.isSymbolicLink();\n  } catch {\n    return false;\n  }\n}\n\nfunction rawFromCompressed(obs: CompressedObservation): RawObservation {\n  return {\n    id: obs.id,\n    sessionId: obs.sessionId,\n    timestamp: obs.timestamp,\n    hookType: \"post_tool_use\",\n    toolName: undefined,\n    toolInput: undefined,\n    toolOutput: undefined,\n    userPrompt: obs.type === \"conversation\" ? obs.narrative : undefined,\n    assistantResponse: undefined,\n    raw: { title: obs.title, narrative: obs.narrative, facts: obs.facts },\n  };\n}\n\nconst LESSON_PATTERNS: RegExp[] = [\n  /\\b(always|never|don'?t|do not|make sure|remember to|note:|caveat:|warning:)\\b[^.\\n]{10,200}[.!\\n]/gi,\n  /\\b(prefer|avoid)\\s[^.\\n]{10,200}[.!\\n]/gi,\n];\n\nasync function deriveCrystalAndLessons(\n  kv: StateKV,\n  sessionId: string,\n  project: string,\n  rawObs: RawObservation[],\n  compressed: CompressedObservation[],\n  firstPrompt: string | undefined,\n): Promise<void> {\n  if (rawObs.length === 0) return;\n  const createdAt = new Date().toISOString();\n\n  const files = new Set<string>();\n  const tools = new Set<string>();\n  for (const c of compressed) {\n    for (const f of c.files || []) files.add(f);\n    if (c.type && c.type !== \"conversation\" && c.title) tools.add(c.title);\n  }\n\n  const assistantTexts: string[] = [];\n  const userPrompts: string[] = [];\n  for (const r of rawObs) {\n    if (typeof r.assistantResponse === \"string\" && r.assistantResponse.trim()) {\n      assistantTexts.push(r.assistantResponse);\n    }\n    if (typeof r.userPrompt === \"string\" && r.userPrompt.trim()) {\n      userPrompts.push(r.userPrompt);\n    }\n  }\n\n  const lessonMatches = new Map<string, string>();\n  for (const text of assistantTexts.concat(userPrompts).slice(0, 200)) {\n    for (const pat of LESSON_PATTERNS) {\n      pat.lastIndex = 0;\n      let m: RegExpExecArray | null;\n      while ((m = pat.exec(text)) !== null && lessonMatches.size < 40) {\n        const snippet = m[0].replace(/\\s+/g, \" \").trim();\n        if (snippet.length >= 20 && snippet.length <= 220) {\n          const key = snippet.toLowerCase();\n          if (!lessonMatches.has(key)) lessonMatches.set(key, snippet);\n        }\n      }\n    }\n  }\n\n  const lessonEntries = Array.from(lessonMatches.values()).slice(0, 20);\n  const lessonIds: string[] = [];\n  for (const content of lessonEntries) {\n    // Content-addressed ID so re-importing the same JSONL does not\n    // duplicate lessons. fingerprintId hashes the normalized content,\n    // giving a stable lesson_xxx for identical text.\n    const lessonId = fingerprintId(\"lesson\", content.trim().toLowerCase());\n    try {\n      const existing = await kv.get<Lesson>(KV.lessons, lessonId);\n      if (existing) {\n        const existingSources = existing.sourceIds || [];\n        const mergedSources = existingSources.includes(sessionId)\n          ? existingSources\n          : [...existingSources, sessionId];\n        const existingTags = existing.tags || [];\n        const mergedTags = existingTags.includes(\"auto-import\")\n          ? existingTags\n          : [...existingTags, \"auto-import\"];\n        const merged: Lesson = {\n          ...existing,\n          sourceIds: mergedSources,\n          tags: mergedTags,\n          reinforcements: (existing.reinforcements || 0) + 1,\n          updatedAt: createdAt,\n          lastReinforcedAt: createdAt,\n        };\n        await kv.set(KV.lessons, lessonId, merged);\n      } else {\n        const lesson: Lesson = {\n          id: lessonId,\n          content,\n          context: firstPrompt || project,\n          confidence: 0.4,\n          reinforcements: 0,\n          source: \"consolidation\",\n          sourceIds: [sessionId],\n          project,\n          tags: [\"auto-import\"],\n          createdAt,\n          updatedAt: createdAt,\n          decayRate: 0.05,\n        };\n        await kv.set(KV.lessons, lessonId, lesson);\n      }\n      lessonIds.push(lessonId);\n    } catch {}\n  }\n\n  // Content-addressed on sessionId so re-importing the same session\n  // upserts the crystal in place instead of creating a new one.\n  const crystalId = fingerprintId(\"crystal\", sessionId);\n  const narrativePreview = firstPrompt\n    ? firstPrompt.slice(0, 300)\n    : compressed\n        .slice(0, 5)\n        .map((c) => c.narrative || c.title)\n        .filter(Boolean)\n        .join(\" · \")\n        .slice(0, 300);\n\n  try {\n    const existingCrystal = await kv.get<Crystal>(KV.crystals, crystalId);\n    const crystal: Crystal = {\n      id: crystalId,\n      narrative: narrativePreview || `Session ${sessionId.slice(0, 12)} (${rawObs.length} observations)`,\n      keyOutcomes: Array.from(tools).slice(0, 8),\n      filesAffected: Array.from(files).slice(0, 20),\n      lessons: lessonIds,\n      sourceActionIds: existingCrystal?.sourceActionIds ?? [],\n      sessionId,\n      project,\n      createdAt: existingCrystal?.createdAt ?? createdAt,\n    };\n    await kv.set(KV.crystals, crystalId, crystal);\n  } catch {}\n}\n\nfunction isRawShape(o: unknown): o is RawObservation {\n  if (!o || typeof o !== \"object\") return false;\n  const r = o as Record<string, unknown>;\n  return typeof r.hookType === \"string\";\n}\n\nasync function loadObservations(\n  kv: StateKV,\n  sessionId: string,\n): Promise<RawObservation[]> {\n  const rows = await kv.list<RawObservation | CompressedObservation>(\n    KV.observations(sessionId),\n  );\n  return rows.map((r) => (isRawShape(r) ? r : rawFromCompressed(r as CompressedObservation)));\n}\n\nasync function findJsonlFiles(\n  root: string,\n  limit = 200,\n): Promise<{\n  files: string[];\n  truncated: boolean;\n  discovered: number;\n  traversalCapped: boolean;\n}> {\n  const out: string[] = [];\n  let discovered = 0;\n  let walked = 0;\n  // Hard bound on entries visited (regardless of extension) so trees\n  // dominated by non-jsonl files (node_modules, lockfiles, etc.) cannot\n  // lock the 30s function timeout. `discovered` may underrepresent the\n  // true count when traversalCapped fires — callers should surface that\n  // distinction to the user.\n  const traversalCap = Math.max(limit * 50, 50_000);\n  async function walk(dir: string) {\n    if (walked >= traversalCap) return;\n    let names: string[];\n    try {\n      names = await readdir(dir);\n    } catch {\n      return;\n    }\n    for (const name of names) {\n      if (walked >= traversalCap) return;\n      walked++;\n      const full = join(dir, name);\n      let st;\n      try {\n        st = await lstat(full);\n      } catch {\n        continue;\n      }\n      if (st.isSymbolicLink()) continue;\n      if (st.isDirectory()) {\n        await walk(full);\n      } else if (st.isFile() && name.endsWith(\".jsonl\")) {\n        discovered++;\n        if (out.length < limit) out.push(full);\n      }\n    }\n  }\n  await walk(root);\n  const traversalCapped = walked >= traversalCap;\n  return {\n    files: out,\n    truncated: discovered > out.length || traversalCapped,\n    discovered,\n    traversalCapped,\n  };\n}\n\nexport function registerReplayFunctions(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\n    \"mem::replay::load\",\n    async (data: { sessionId: string }): Promise<\n      | { success: true; timeline: Timeline; session: Session | null }\n      | { success: false; error: string }\n    > => {\n      if (!data?.sessionId || typeof data.sessionId !== \"string\") {\n        return { success: false, error: \"sessionId is required\" };\n      }\n      const session = await kv.get<Session>(KV.sessions, data.sessionId);\n      const observations = await loadObservations(kv, data.sessionId);\n      const timeline = projectTimeline(observations);\n      return { success: true, timeline, session };\n    },\n  );\n\n  sdk.registerFunction(\n    \"mem::replay::sessions\",\n    async (): Promise<{ success: true; sessions: Session[] }> => {\n      const sessions = await kv.list<Session>(KV.sessions);\n      sessions.sort((a, b) => (b.startedAt || \"\").localeCompare(a.startedAt || \"\"));\n      return { success: true, sessions };\n    },\n  );\n\n  sdk.registerFunction(\n    \"mem::replay::import-jsonl\",\n    async (\n      data: { path?: string; maxFiles?: number } = {},\n    ): Promise<\n      | {\n          success: true;\n          imported: number;\n          sessionIds: string[];\n          observations: number;\n          discovered: number;\n          truncated: boolean;\n          traversalCapped: boolean;\n          maxFiles: number;\n          maxFilesUpperBound: number;\n        }\n      | { success: false; error: string }\n    > => {\n      const defaultRoot = join(homedir(), \".claude\", \"projects\");\n      const rawPath = data.path || defaultRoot;\n      if (typeof rawPath !== \"string\" || rawPath.length === 0) {\n        return { success: false, error: \"path must be a non-empty string\" };\n      }\n      const expanded = rawPath.startsWith(\"~\")\n        ? join(homedir(), rawPath.slice(1))\n        : rawPath;\n      const abs = resolve(expanded);\n      if (isSensitive(abs)) {\n        return { success: false, error: \"refusing to process sensitive-looking path\" };\n      }\n      if (await isSymlink(abs)) {\n        return { success: false, error: \"symlinks are not supported\" };\n      }\n\n      let stat;\n      try {\n        stat = await lstat(abs);\n      } catch {\n        return { success: false, error: \"path not found\" };\n      }\n\n      // Valid integer requests are clamped to MAX_FILES_UPPER_BOUND so\n      // callers see a stable maxFiles in the response. Non-integer or\n      // <= 0 falls back to the safe default. The HTTP layer rejects\n      // out-of-range up front; this is the SDK-callable safety net.\n      const maxFiles =\n        Number.isInteger(data.maxFiles) && (data.maxFiles as number) > 0\n          ? Math.min(data.maxFiles as number, MAX_FILES_UPPER_BOUND)\n          : MAX_FILES_DEFAULT;\n      let files: string[] = [];\n      let truncated = false;\n      let discovered = 0;\n      let traversalCapped = false;\n      if (stat.isDirectory()) {\n        const found = await findJsonlFiles(abs, maxFiles);\n        files = found.files;\n        truncated = found.truncated;\n        discovered = found.discovered;\n        traversalCapped = found.traversalCapped;\n      } else if (stat.isFile() && abs.endsWith(\".jsonl\")) {\n        files = [abs];\n        discovered = 1;\n      } else {\n        return { success: false, error: \"path must be a .jsonl file or directory\" };\n      }\n\n      if (files.length === 0) {\n        return {\n          success: true,\n          imported: 0,\n          sessionIds: [],\n          observations: 0,\n          discovered,\n          truncated,\n          traversalCapped,\n          maxFiles,\n          maxFilesUpperBound: MAX_FILES_UPPER_BOUND,\n        };\n      }\n\n      const sessionIds: string[] = [];\n      let observationCount = 0;\n\n      for (const file of files) {\n        if (isSensitive(file)) continue;\n        if (await isSymlink(file)) continue;\n        let text: string;\n        try {\n          text = await readFile(file, \"utf-8\");\n        } catch (err) {\n          logger.warn(\"replay: failed to read jsonl\", {\n            file,\n            error: err instanceof Error ? err.message : String(err),\n          });\n          continue;\n        }\n\n        const parsed = parseJsonlText(text, generateId(\"sess\"));\n        if (parsed.observations.length === 0) continue;\n\n        const firstPromptObs = parsed.observations.find(\n          (o) => typeof o.userPrompt === \"string\" && o.userPrompt.trim().length > 0,\n        );\n        const firstPrompt = firstPromptObs?.userPrompt\n          ? firstPromptObs.userPrompt.replace(/\\s+/g, \" \").trim().slice(0, 200)\n          : undefined;\n\n        const existing = await kv.get<Session>(KV.sessions, parsed.sessionId);\n        if (existing) {\n          existing.observationCount =\n            (existing.observationCount || 0) + parsed.observations.length;\n          if (parsed.endedAt > (existing.endedAt || \"\")) {\n            existing.endedAt = parsed.endedAt;\n          }\n          if (existing.status === \"active\") existing.status = \"completed\";\n          const existingTags = existing.tags || [];\n          if (!existingTags.includes(\"jsonl-import\")) {\n            existing.tags = [...existingTags, \"jsonl-import\"];\n          }\n          if (!existing.firstPrompt && firstPrompt) {\n            existing.firstPrompt = firstPrompt;\n          }\n          // #775: re-key on parsed.sessionId, not existing.id. Older\n          // session rows may be missing the `id` field; existing.id\n          // would then be undefined, JSON.stringify would drop the\n          // `key` from the state::set payload, and the engine would\n          // reject the call with `missing field \\`key\\``. Because the\n          // rejection aborts the whole import handler, a single\n          // legacy row killed the entire batch. parsed.sessionId is\n          // always populated (parseJsonlText has a three-level\n          // fallback) and is what we just used to read the row.\n          if (!existing.id) existing.id = parsed.sessionId;\n          await kv.set(KV.sessions, parsed.sessionId, existing);\n        } else {\n          const session: Session = {\n            id: parsed.sessionId,\n            project: parsed.project,\n            cwd: parsed.cwd,\n            startedAt: parsed.startedAt,\n            endedAt: parsed.endedAt,\n            status: \"completed\",\n            observationCount: parsed.observations.length,\n            tags: [\"jsonl-import\"],\n            firstPrompt,\n          };\n          await kv.set(KV.sessions, session.id, session);\n        }\n\n        const searchIndex = getSearchIndex();\n        const compressed: CompressedObservation[] = [];\n        await Promise.all(\n          parsed.observations.map(async (obs) => {\n            const synthetic = buildSyntheticCompression(obs);\n            compressed.push(synthetic);\n            await kv.set(KV.observations(parsed.sessionId), obs.id, synthetic);\n            searchIndex.add(synthetic);\n          }),\n        );\n        observationCount += parsed.observations.length;\n        sessionIds.push(parsed.sessionId);\n\n        await deriveCrystalAndLessons(\n          kv,\n          parsed.sessionId,\n          parsed.project,\n          parsed.observations,\n          compressed,\n          firstPrompt,\n        );\n      }\n\n      await safeAudit(kv, \"import\", \"mem::replay::import-jsonl\", sessionIds, {\n        source: \"jsonl\",\n        path: abs,\n        files: files.length,\n        observations: observationCount,\n      });\n\n      return {\n        success: true,\n        imported: files.length,\n        sessionIds,\n        observations: observationCount,\n        discovered,\n        truncated,\n        traversalCapped,\n        maxFiles,\n        maxFilesUpperBound: MAX_FILES_UPPER_BOUND,\n      };\n    },\n  );\n}\n","import type { HealthSnapshot } from \"../types.js\";\n\ninterface ThresholdConfig {\n  eventLoopLagWarnMs: number;\n  eventLoopLagCriticalMs: number;\n  cpuWarnPercent: number;\n  cpuCriticalPercent: number;\n  memoryWarnPercent: number;\n  memoryCriticalPercent: number;\n  memoryRssFloorBytes: number;\n}\n\nconst DEFAULTS: ThresholdConfig = {\n  eventLoopLagWarnMs: 100,\n  eventLoopLagCriticalMs: 500,\n  cpuWarnPercent: 80,\n  cpuCriticalPercent: 90,\n  memoryWarnPercent: 80,\n  memoryCriticalPercent: 95,\n  memoryRssFloorBytes: 512 * 1024 * 1024,\n};\n\nexport function evaluateHealth(\n  snapshot: HealthSnapshot,\n  config: Partial<ThresholdConfig> = {},\n): { status: \"healthy\" | \"degraded\" | \"critical\"; alerts: string[]; notes: string[] } {\n  const cfg = { ...DEFAULTS, ...config };\n  const alerts: string[] = [];\n  const notes: string[] = [];\n  let critical = false;\n  let degraded = false;\n\n  if (\n    snapshot.connectionState === \"disconnected\" ||\n    snapshot.connectionState === \"failed\"\n  ) {\n    alerts.push(`connection_${snapshot.connectionState}`);\n    critical = true;\n  } else if (snapshot.connectionState === \"reconnecting\") {\n    alerts.push(\"connection_reconnecting\");\n    degraded = true;\n  }\n\n  if (snapshot.eventLoopLagMs > cfg.eventLoopLagCriticalMs) {\n    alerts.push(\n      `event_loop_lag_critical_${Math.round(snapshot.eventLoopLagMs)}ms`,\n    );\n    critical = true;\n  } else if (snapshot.eventLoopLagMs > cfg.eventLoopLagWarnMs) {\n    alerts.push(`event_loop_lag_warn_${Math.round(snapshot.eventLoopLagMs)}ms`);\n    degraded = true;\n  }\n\n  if (snapshot.cpu.percent > cfg.cpuCriticalPercent) {\n    alerts.push(`cpu_critical_${Math.round(snapshot.cpu.percent)}%`);\n    critical = true;\n  } else if (snapshot.cpu.percent > cfg.cpuWarnPercent) {\n    alerts.push(`cpu_warn_${Math.round(snapshot.cpu.percent)}%`);\n    degraded = true;\n  }\n\n  const memPercent =\n    snapshot.memory.heapTotal > 0\n      ? (snapshot.memory.heapUsed / snapshot.memory.heapTotal) * 100\n      : 0;\n  const rss = snapshot.memory.rss ?? 0;\n  const rssAboveFloor = rss >= cfg.memoryRssFloorBytes;\n  const memMb = Math.round(rss / (1024 * 1024));\n  if (memPercent > cfg.memoryCriticalPercent && rssAboveFloor) {\n    alerts.push(`memory_critical_${Math.round(memPercent)}%_rss${memMb}mb`);\n    critical = true;\n  } else if (memPercent > cfg.memoryWarnPercent && rssAboveFloor) {\n    alerts.push(`memory_warn_${Math.round(memPercent)}%_rss${memMb}mb`);\n    degraded = true;\n  } else if (memPercent > cfg.memoryWarnPercent) {\n    notes.push(`memory_heap_tight_${Math.round(memPercent)}%_rss${memMb}mb`);\n  }\n\n  const status = critical ? \"critical\" : degraded ? \"degraded\" : \"healthy\";\n  return { status, alerts, notes };\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { HealthSnapshot } from \"../types.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport { evaluateHealth } from \"./thresholds.js\";\n\nexport function registerHealthMonitor(\n  sdk: ISdk,\n  kv: StateKV,\n): { stop: () => void } {\n  let connectionState = \"connected\";\n  let prevCpuUsage = process.cpuUsage();\n  let prevCpuTime = Date.now();\n\n  if (typeof sdk.on === \"function\") {\n    sdk.on(\"connection_state\", (state?: unknown) => {\n      connectionState = state as string;\n    });\n  }\n\n  async function collectHealth(): Promise<HealthSnapshot> {\n    const mem = process.memoryUsage();\n    const currentCpu = process.cpuUsage();\n    const now = Date.now();\n    const uptime = process.uptime();\n\n    const elapsedMs = now - prevCpuTime;\n    const userDelta = currentCpu.user - prevCpuUsage.user;\n    const systemDelta = currentCpu.system - prevCpuUsage.system;\n    const cpuPercent =\n      elapsedMs > 0 ? ((userDelta + systemDelta) / 1000 / elapsedMs) * 100 : 0;\n    prevCpuUsage = currentCpu;\n    prevCpuTime = now;\n\n    const startMark = performance.now();\n    await new Promise((resolve) => setImmediate(resolve));\n    const eventLoopLagMs = performance.now() - startMark;\n\n    let workers: HealthSnapshot[\"workers\"] = [];\n    try {\n      const result = await sdk.trigger<\n        unknown,\n        { workers?: HealthSnapshot[\"workers\"] }\n      >({ function_id: \"engine::workers::list\", payload: {} });\n      if (result?.workers) workers = result.workers;\n    } catch {}\n\n    const KV_PROBE_TIMEOUT = 5000;\n    let kvConnectivity: { status: string; latencyMs?: number; error?: string };\n    const kvStart = performance.now();\n    try {\n      await Promise.race([\n        (async () => {\n          await kv.set(KV.health, \"_probe\", { ts: Date.now() });\n          await kv.get(KV.health, \"_probe\");\n        })(),\n        new Promise<never>((_, reject) =>\n          setTimeout(() => reject(new Error(\"timeout\")), KV_PROBE_TIMEOUT),\n        ),\n      ]);\n      kvConnectivity = { status: \"ok\", latencyMs: Math.round((performance.now() - kvStart) * 100) / 100 };\n    } catch {\n      kvConnectivity = { status: \"error\", error: \"kv_probe_failed\", latencyMs: Math.round((performance.now() - kvStart) * 100) / 100 };\n    }\n\n    const snapshot: HealthSnapshot = {\n      connectionState,\n      workers,\n      memory: {\n        heapUsed: mem.heapUsed,\n        heapTotal: mem.heapTotal,\n        rss: mem.rss,\n        external: mem.external,\n      },\n      cpu: {\n        userMicros: currentCpu.user,\n        systemMicros: currentCpu.system,\n        percent: Math.round(cpuPercent * 100) / 100,\n      },\n      eventLoopLagMs,\n      uptimeSeconds: uptime,\n      kvConnectivity,\n      status: \"healthy\",\n      alerts: [],\n    };\n\n    const evaluated = evaluateHealth(snapshot);\n    snapshot.status = evaluated.status;\n    snapshot.alerts = evaluated.alerts;\n    snapshot.notes = evaluated.notes;\n\n    await kv.set(KV.health, \"latest\", snapshot).catch(() => {});\n    return snapshot;\n  }\n\n  collectHealth().catch(() => {});\n  const interval = setInterval(() => {\n    collectHealth().catch(() => {});\n  }, 30_000);\n  interval.unref();\n\n  return {\n    stop: () => clearInterval(interval),\n  };\n}\n\nexport async function getLatestHealth(\n  kv: StateKV,\n): Promise<HealthSnapshot | null> {\n  return kv.get<HealthSnapshot>(KV.health, \"latest\");\n}\n","import { timingSafeEqual, createHmac, randomBytes } from \"node:crypto\";\n\nconst hmacKey = randomBytes(32);\nexport const VIEWER_NONCE_PLACEHOLDER = \"__AGENTMEMORY_VIEWER_NONCE__\";\n\nexport function timingSafeCompare(a: string, b: string): boolean {\n  const hmacA = createHmac(\"sha256\", hmacKey).update(a).digest();\n  const hmacB = createHmac(\"sha256\", hmacKey).update(b).digest();\n  return timingSafeEqual(hmacA, hmacB);\n}\n\nexport function createViewerNonce(): string {\n  return randomBytes(16).toString(\"base64url\");\n}\n\nexport function buildViewerCsp(nonce: string): string {\n  return [\n    \"default-src 'none'\",\n    \"base-uri 'none'\",\n    \"frame-ancestors 'none'\",\n    \"object-src 'none'\",\n    \"form-action 'none'\",\n    `script-src 'nonce-${nonce}'`,\n    \"script-src-attr 'none'\",\n    \"style-src 'unsafe-inline'\",\n    \"connect-src 'self' http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:* wss://localhost:* wss://127.0.0.1:*\",\n    \"img-src 'self'\",\n    \"font-src 'self'\",\n  ].join(\"; \");\n}\n","import { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n  VIEWER_NONCE_PLACEHOLDER,\n  createViewerNonce,\n  buildViewerCsp,\n} from \"../auth.js\";\nimport { VERSION } from \"../version.js\";\n\nconst VIEWER_VERSION_PLACEHOLDER = \"__AGENTMEMORY_VERSION__\";\n\nfunction loadViewerTemplate(): string | null {\n  const base = dirname(fileURLToPath(import.meta.url));\n  const candidates = [\n    join(base, \"..\", \"src\", \"viewer\", \"index.html\"),\n    join(base, \"..\", \"viewer\", \"index.html\"),\n    join(base, \"viewer\", \"index.html\"),\n  ];\n  for (const path of candidates) {\n    try {\n      return readFileSync(path, \"utf-8\");\n    } catch {}\n  }\n  return null;\n}\n\nexport function renderViewerDocument():\n  | { found: true; html: string; csp: string }\n  | { found: false } {\n  const template = loadViewerTemplate();\n  if (!template) {\n    return { found: false };\n  }\n\n  const nonce = createViewerNonce();\n  const html = template\n    .replaceAll(VIEWER_NONCE_PLACEHOLDER, nonce)\n    .replaceAll(VIEWER_VERSION_PLACEHOLDER, VERSION);\n  return {\n    found: true,\n    html,\n    csp: buildViewerCsp(nonce),\n  };\n}\n","import {\n  createServer,\n  type Server,\n  type IncomingMessage,\n  type ServerResponse,\n} from \"node:http\";\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { renderViewerDocument } from \"./document.js\";\nimport { timingSafeCompare } from \"../auth.js\";\n\n// Self-host the viewer favicon at /favicon.svg instead of an inline\n// data: URI so the viewer CSP can stay tight at `img-src 'self'`.\n// Mirrors loadViewerTemplate() in document.ts — same candidate paths so\n// it resolves both from source (vitest) and from dist/ (npm run start).\nfunction loadViewerFavicon(): Buffer | null {\n  const base = dirname(fileURLToPath(import.meta.url));\n  const candidates = [\n    join(base, \"..\", \"src\", \"viewer\", \"favicon.svg\"),\n    join(base, \"..\", \"viewer\", \"favicon.svg\"),\n    join(base, \"viewer\", \"favicon.svg\"),\n  ];\n  for (const path of candidates) {\n    try {\n      return readFileSync(path);\n    } catch {}\n  }\n  return null;\n}\n\n// Favicon is static — load once at module init instead of one synchronous\n// disk read per /favicon.svg request.\nconst VIEWER_FAVICON: Buffer | null = loadViewerFavicon();\n\nconst ALLOWED_ORIGINS = (\n  process.env.VIEWER_ALLOWED_ORIGINS ||\n  \"http://localhost:3111,http://localhost:3113,http://127.0.0.1:3111,http://127.0.0.1:3113\"\n)\n  .split(\",\")\n  .map((o) => o.trim());\n\n// Hosts the viewer will accept in the Host header. Restricting this is the\n// defence against DNS rebinding: a browser visiting `attacker.com` whose\n// authoritative DNS rebinds to 127.0.0.1 hits the viewer's listening socket\n// directly, the Origin header reads `http://attacker.com` (same-origin from\n// the browser's perspective on a same-port attacker page, so no preflight\n// fires), and the request body is whatever the page wants. The viewer\n// proxies it to the local REST API with the AGENTMEMORY_SECRET bearer\n// attached, so the response stream is fully privileged. Rejecting any Host\n// not in this allowlist closes that path before the proxy runs.\n//\n// Explicit override via VIEWER_ALLOWED_HOSTS for the rare case of a\n// reverse-proxy in front of the viewer; defaults are computed from the\n// listen port at server-create time. Read on each call (no module-level\n// caching) so tests can rotate the env var between startViewerServer()\n// and the first request. Note: `buildAllowedHosts` only re-runs on a\n// cache miss for the in-process `allowedHosts` set, so production env\n// changes after the first request require a restart.\nfunction readAllowedHostsOverride(): string[] {\n  return (process.env.VIEWER_ALLOWED_HOSTS || \"\")\n    .split(\",\")\n    .map((h) => h.trim().toLowerCase())\n    .filter(Boolean);\n}\n\nexport function resolveViewerHost(): string {\n  return process.env.AGENTMEMORY_VIEWER_HOST?.trim() || \"127.0.0.1\";\n}\n\nexport function isLoopbackHost(host: string): boolean {\n  const h = host.trim().toLowerCase();\n  return h === \"127.0.0.1\" || h === \"::1\" || h === \"localhost\";\n}\n\nexport function buildAllowedHosts(\n  origins: string[],\n  listenPort: number,\n  bindHost: string = \"127.0.0.1\",\n): Set<string> {\n  const hosts = new Set<string>();\n  // When bind is loopback the listening socket is unreachable from the\n  // network, so it's safe to seed the allowlist from the CORS origins\n  // (which by default are localhost-based) plus the standard loopback\n  // hostnames on the actual listen port. When bind is non-loopback the\n  // listening socket is reachable from anywhere TCP can reach the\n  // process, and any of those loopback names becomes a spoofable Host\n  // header — so only explicit VIEWER_ALLOWED_HOSTS entries are trusted.\n  if (isLoopbackHost(bindHost)) {\n    for (const o of origins) {\n      try {\n        const parsed = new URL(o);\n        if (parsed.host) hosts.add(parsed.host.toLowerCase());\n      } catch {\n        // Skip invalid origin entries — the existing CORS path already\n        // tolerates them by simply not matching; mirror that here.\n      }\n    }\n    hosts.add(`localhost:${listenPort}`);\n    hosts.add(`127.0.0.1:${listenPort}`);\n    hosts.add(`[::1]:${listenPort}`);\n  }\n  for (const h of readAllowedHostsOverride()) hosts.add(h);\n  return hosts;\n}\n\nexport function isHostAllowed(\n  headerHost: string | string[] | undefined,\n  allowed: Set<string>,\n): boolean {\n  if (typeof headerHost !== \"string\") return false;\n  const lower = headerHost.toLowerCase().trim();\n  if (!lower) return false;\n  return allowed.has(lower);\n}\n\n// When bind is non-loopback the viewer is a bearer-authorized proxy\n// reachable from the network, so every request that would forward\n// upstream must also present the same bearer. Static routes (HTML,\n// favicon) stay open so a browser can fetch the shell — the JS inside\n// then has to provide a bearer for the API calls.\nexport function requireInboundBearer(\n  authHeader: string | string[] | undefined,\n  secret: string,\n): boolean {\n  if (typeof authHeader !== \"string\") return false;\n  const match = /^Bearer\\s+(\\S+)\\s*$/i.exec(authHeader);\n  if (!match) return false;\n  return timingSafeCompare(match[1], secret);\n}\n\nfunction corsHeaders(req: IncomingMessage): Record<string, string> {\n  const origin = req.headers.origin || \"\";\n  const allowed = ALLOWED_ORIGINS.includes(origin)\n    ? origin\n    : ALLOWED_ORIGINS[0];\n  return {\n    \"Access-Control-Allow-Origin\": allowed,\n    \"Access-Control-Allow-Methods\": \"GET, POST, DELETE, OPTIONS\",\n    \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n    Vary: \"Origin\",\n  };\n}\n\nfunction json(\n  res: ServerResponse,\n  status: number,\n  data: unknown,\n  req?: IncomingMessage,\n): void {\n  const body = JSON.stringify(data);\n  const cors = req\n    ? corsHeaders(req)\n    : { \"Access-Control-Allow-Origin\": ALLOWED_ORIGINS[0], Vary: \"Origin\" };\n  res.writeHead(status, { ...cors, \"Content-Type\": \"application/json\" });\n  res.end(body);\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n  return new Promise((resolve, reject) => {\n    let data = \"\";\n    let size = 0;\n    req.on(\"data\", (chunk: Buffer) => {\n      size += chunk.length;\n      if (size > 1_000_000) {\n        req.destroy();\n        reject(new Error(\"too large\"));\n        return;\n      }\n      data += chunk.toString();\n    });\n    req.on(\"end\", () => resolve(data));\n    req.on(\"error\", reject);\n  });\n}\n\nconst MAX_VIEWER_PORT_RETRIES = 10;\n\nlet boundViewerPort: number | null = null;\nlet viewerSkipped = false;\n\nexport function getBoundViewerPort(): number | null {\n  return boundViewerPort;\n}\nexport function getViewerSkipped(): boolean {\n  return viewerSkipped;\n}\n\nexport class ViewerConfigError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"ViewerConfigError\";\n  }\n}\n\nexport function startViewerServer(\n  port: number,\n  _kv: unknown,\n  _sdk: unknown,\n  secret?: string,\n  restPort?: number,\n): Server {\n  // Reset exported runtime state for each start attempt.\n  boundViewerPort = null;\n  viewerSkipped = false;\n\n  const resolvedRestPort = restPort ?? port - 2;\n  const requestedPort = port;\n  const host = resolveViewerHost();\n  let inboundSecret: string | null = null;\n\n  // Non-loopback bind turns the viewer into a network-reachable\n  // bearer-authorized proxy. Refuse to start unless the operator has\n  // both an inbound secret to authenticate callers against and an\n  // explicit Host header allowlist; otherwise the listening socket\n  // becomes an open relay to the local REST API.\n  if (!isLoopbackHost(host)) {\n    if (!secret) {\n      throw new ViewerConfigError(\n        `AGENTMEMORY_VIEWER_HOST=${host} requires AGENTMEMORY_SECRET to be set so the viewer can validate inbound bearer tokens. To fix: unset AGENTMEMORY_VIEWER_HOST to keep the safe loopback bind, or set AGENTMEMORY_SECRET. For Fly images, it is printed on first boot; see deploy/fly/README.md.`,\n      );\n    }\n    if (readAllowedHostsOverride().length === 0) {\n      throw new ViewerConfigError(\n        `AGENTMEMORY_VIEWER_HOST=${host} requires VIEWER_ALLOWED_HOSTS because non-loopback viewer binds only trust explicit Host headers. To fix: set VIEWER_ALLOWED_HOSTS to a comma-separated list of trusted Host header values (e.g. \"localhost:3113\" for fly proxy), or unset AGENTMEMORY_VIEWER_HOST to keep the safe loopback bind.`,\n      );\n    }\n    inboundSecret = secret;\n  }\n\n  // Computed lazily on first request — `port` may be 0 here (OS-assigned)\n  // or the EADDRINUSE retry loop below may bump us to a different port,\n  // so we read the actual bound port from server.address() on first hit.\n  let allowedHosts: Set<string> | null = null;\n\n  const server = createServer(async (req, res) => {\n    if (!allowedHosts) {\n      const addr = server.address();\n      const actualPort =\n        addr && typeof addr === \"object\" && \"port\" in addr\n          ? (addr.port as number)\n          : port;\n      allowedHosts = buildAllowedHosts(ALLOWED_ORIGINS, actualPort, host);\n    }\n    if (!isHostAllowed(req.headers.host, allowedHosts)) {\n      res.writeHead(403, { \"Content-Type\": \"text/plain\" });\n      res.end(\"forbidden host\");\n      return;\n    }\n\n    const raw = req.url || \"/\";\n    const qIdx = raw.indexOf(\"?\");\n    const pathname = qIdx >= 0 ? raw.slice(0, qIdx) : raw;\n    const qs = qIdx >= 0 ? raw.slice(qIdx + 1) : \"\";\n    const method = req.method || \"GET\";\n\n    if (method === \"OPTIONS\") {\n      res.writeHead(204, {\n        ...corsHeaders(req),\n        \"Access-Control-Max-Age\": \"86400\",\n      });\n      res.end();\n      return;\n    }\n\n    if (\n      method === \"GET\" &&\n      (pathname === \"/\" ||\n        pathname === \"/viewer\" ||\n        pathname === \"/agentmemory/viewer\")\n    ) {\n      const rendered = renderViewerDocument();\n      if (rendered.found) {\n        res.writeHead(200, {\n          \"Content-Type\": \"text/html; charset=utf-8\",\n          \"Content-Security-Policy\": rendered.csp,\n          \"Cache-Control\": \"no-cache\",\n        });\n        res.end(rendered.html);\n        return;\n      }\n      res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n      res.end(\"viewer not found\");\n      return;\n    }\n\n    if (method === \"GET\" && pathname === \"/favicon.svg\") {\n      if (VIEWER_FAVICON) {\n        res.writeHead(200, {\n          \"Content-Type\": \"image/svg+xml\",\n          \"Cache-Control\": \"public, max-age=3600\",\n        });\n        res.end(VIEWER_FAVICON);\n        return;\n      }\n      res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n      res.end(\"favicon not found\");\n      return;\n    }\n\n    if (\n      inboundSecret !== null &&\n      !requireInboundBearer(req.headers.authorization, inboundSecret)\n    ) {\n      res.writeHead(401, {\n        \"Content-Type\": \"text/plain\",\n        \"WWW-Authenticate\": 'Bearer realm=\"agentmemory-viewer\"',\n      });\n      res.end(\"unauthorized\");\n      return;\n    }\n\n    try {\n      await proxyToRestApi(resolvedRestPort, pathname, qs, method, req, res, secret);\n    } catch (err) {\n      console.error(`[viewer] proxy error on ${method} ${pathname}:`, err);\n      json(res, 502, { error: \"upstream error\" }, req);\n    }\n  });\n\n  let attempt = 0;\n  let currentPort = requestedPort;\n\n  const tryListen = (): void => {\n    server.listen(currentPort, host);\n  };\n\n  server.on(\"listening\", () => {\n    const addr = server.address();\n    // `currentPort` is the value passed to `listen()` and stays 0 for\n    // ephemeral-port callers (tests, port=0). `server.address()` exposes\n    // the OS-assigned port — log that so the startup line is accurate.\n    const actualPort =\n      addr && typeof addr === \"object\" && \"port\" in addr\n        ? addr.port\n        : currentPort;\n    boundViewerPort = actualPort;\n    viewerSkipped = false;\n    if (inboundSecret !== null) {\n      const allowedHosts = readAllowedHostsOverride().join(\", \");\n      console.log(\n        `[agentmemory] Viewer: http://localhost:${actualPort} (bound to ${host}; inbound Bearer required; allowed Host headers: ${allowedHosts})`,\n      );\n      return;\n    }\n    if (actualPort === requestedPort) {\n      console.log(`[agentmemory] Viewer: http://localhost:${actualPort}`);\n    } else {\n      console.log(\n        `[agentmemory] Viewer started on http://localhost:${actualPort} (fallback from ${requestedPort})`,\n      );\n    }\n  });\n\n  server.on(\"error\", (err: NodeJS.ErrnoException) => {\n    if (\n      err.code === \"EADDRINUSE\" &&\n      inboundSecret === null &&\n      attempt < MAX_VIEWER_PORT_RETRIES\n    ) {\n      attempt++;\n      currentPort = requestedPort + attempt;\n      setImmediate(tryListen);\n      return;\n    }\n    if (err.code === \"EADDRINUSE\") {\n      boundViewerPort = null;\n      viewerSkipped = true;\n      if (inboundSecret !== null) {\n        console.warn(\n          `[agentmemory] Viewer port ${requestedPort} is in use while bound to ${host}; not retrying because non-loopback viewer binds require VIEWER_ALLOWED_HOSTS to match the exact port. Free the port, choose another viewer port, or unset AGENTMEMORY_VIEWER_HOST to keep the safe loopback bind.`,\n        );\n      } else {\n        console.warn(\n          `[agentmemory] Viewer ports ${requestedPort}-${requestedPort + MAX_VIEWER_PORT_RETRIES} all in use, skipping viewer.`,\n        );\n      }\n    } else {\n      boundViewerPort = null;\n      viewerSkipped = true;\n      console.error(`[agentmemory] Viewer error:`, err.message);\n    }\n  });\n\n  tryListen();\n\n  return server;\n}\n\nasync function proxyToRestApi(\n  restPort: number,\n  pathname: string,\n  qs: string,\n  method: string,\n  req: IncomingMessage,\n  res: ServerResponse,\n  secret?: string,\n): Promise<void> {\n  const upstreamPath = pathname.startsWith(\"/agentmemory/\")\n    ? pathname\n    : `/agentmemory${pathname.startsWith(\"/\") ? pathname : \"/\" + pathname}`;\n\n  const upstreamUrl = `http://127.0.0.1:${restPort}${upstreamPath}${qs ? \"?\" + qs : \"\"}`;\n\n  const headers: Record<string, string> = {};\n  if (secret) {\n    headers[\"Authorization\"] = `Bearer ${secret}`;\n  }\n  const ct = req.headers[\"content-type\"];\n  if (ct) {\n    headers[\"Content-Type\"] = ct;\n  }\n\n  let body: string | undefined;\n  if (method === \"POST\" || method === \"PUT\" || method === \"DELETE\" || method === \"PATCH\") {\n    body = await readBody(req);\n  }\n\n  const controller = new AbortController();\n  const fetchTimeout = setTimeout(() => controller.abort(), 10000);\n  let upstream: Response;\n  try {\n    upstream = await fetch(upstreamUrl, {\n      method,\n      headers,\n      body: body || undefined,\n      signal: controller.signal,\n    });\n    clearTimeout(fetchTimeout);\n  } catch (err) {\n    clearTimeout(fetchTimeout);\n    if (err instanceof Error && err.name === \"AbortError\") {\n      json(res, 504, { error: \"upstream timeout\" }, req);\n      return;\n    }\n    throw err;\n  }\n\n  const cors = corsHeaders(req);\n  const responseBody = await upstream.text();\n  const responseHeaders: Record<string, string> = {\n    ...cors,\n  };\n  const upstreamCt = upstream.headers.get(\"content-type\");\n  if (upstreamCt) {\n    responseHeaders[\"Content-Type\"] = upstreamCt;\n  }\n\n  res.writeHead(upstream.status, responseHeaders);\n  res.end(responseBody);\n}\n","import { TriggerAction, type ISdk, type ApiRequest } from \"iii-sdk\";\nimport type { Session, CompressedObservation, HookPayload, CommitLink, SessionSummary } from \"../types.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { getLatestHealth } from \"../health/monitor.js\";\nimport type { MetricsStore } from \"../eval/metrics-store.js\";\nimport type { ResilientProvider } from \"../providers/resilient.js\";\nimport { VERSION } from \"../version.js\";\nimport { timingSafeCompare } from \"../auth.js\";\nimport { isSlotsEnabled, isReflectEnabled } from \"../functions/slots.js\";\nimport { renderViewerDocument } from \"../viewer/document.js\";\nimport { getBoundViewerPort, getViewerSkipped } from \"../viewer/server.js\";\nimport { MAX_FILES_UPPER_BOUND } from \"../functions/replay.js\";\nimport { logger } from \"../logger.js\";\nimport {\n  isGraphExtractionEnabled,\n  isConsolidationEnabled,\n  isAutoCompressEnabled,\n  isContextInjectionEnabled,\n  detectEmbeddingProvider,\n  detectLlmProviderKind,\n  getAgentId,\n  isAgentScopeIsolated,\n} from \"../config.js\";\n\ntype Response = {\n  status_code: number;\n  headers?: Record<string, string>;\n  body: unknown;\n};\n\nfunction parseOptionalInt(raw: unknown): number | undefined {\n  if (raw === undefined || raw === null || raw === \"\") return undefined;\n  const n = typeof raw === \"number\" ? raw : parseInt(String(raw), 10);\n  return Number.isFinite(n) ? n : undefined;\n}\n\nfunction checkAuth(\n  req: ApiRequest,\n  secret: string | undefined,\n): Response | null {\n  if (!secret) return null;\n  const auth = req.headers?.[\"authorization\"] || req.headers?.[\"Authorization\"];\n  if (\n    typeof auth !== \"string\" ||\n    !timingSafeCompare(auth, `Bearer ${secret}`)\n  ) {\n    return { status_code: 401, body: { error: \"unauthorized\" } };\n  }\n  return null;\n}\n\nfunction requireConfiguredSecret(\n  secret: string | undefined,\n  feature: string,\n): Response | null {\n  if (secret) return null;\n  return {\n    status_code: 503,\n    body: { error: `${feature} requires AGENTMEMORY_SECRET` },\n  };\n}\n\nfunction flagDisabledResponse(opts: {\n  error: string;\n  flag: string;\n  enableHow: string;\n  docsHref: string;\n}): Response {\n  return {\n    status_code: 503,\n    body: opts,\n  };\n}\n\nfunction graphDisabledResponse(): Response {\n  return flagDisabledResponse({\n    error: \"Knowledge graph not enabled\",\n    flag: \"GRAPH_EXTRACTION_ENABLED\",\n    enableHow: \"Set GRAPH_EXTRACTION_ENABLED=true and restart. Requires an LLM provider key.\",\n    docsHref: \"https://github.com/rohitg00/agentmemory#knowledge-graph\",\n  });\n}\n\nfunction consolidationDisabledResponse(): Response {\n  return flagDisabledResponse({\n    error: \"Consolidation pipeline not enabled\",\n    flag: \"CONSOLIDATION_ENABLED\",\n    enableHow: \"Set CONSOLIDATION_ENABLED=true and restart. Requires an LLM provider key.\",\n    docsHref: \"https://github.com/rohitg00/agentmemory#consolidation\",\n  });\n}\n\nfunction slotsDisabledResponse(): Response {\n  return flagDisabledResponse({\n    error: \"Memory slots not enabled\",\n    flag: \"AGENTMEMORY_SLOTS\",\n    enableHow: \"Set AGENTMEMORY_SLOTS=true (in ~/.agentmemory/.env or the shell) and restart.\",\n    docsHref: \"https://github.com/rohitg00/agentmemory#memory-slots\",\n  });\n}\n\nfunction reflectDisabledResponse(): Response {\n  return flagDisabledResponse({\n    error: \"Slot reflection not enabled\",\n    flag: \"AGENTMEMORY_REFLECT\",\n    enableHow: \"Set AGENTMEMORY_REFLECT=true (in ~/.agentmemory/.env or the shell) and restart. Requires AGENTMEMORY_SLOTS=true.\",\n    docsHref: \"https://github.com/rohitg00/agentmemory#memory-slots\",\n  });\n}\n\nfunction asNonEmptyString(value: unknown): string | null {\n  if (typeof value !== \"string\") return null;\n  const trimmed = value.trim();\n  return trimmed ? trimmed : null;\n}\n\nfunction parseOptionalFiniteNumber(value: unknown): number | undefined | null {\n  if (value === undefined || value === null) return undefined;\n  if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\n  if (typeof value === \"string\") {\n    const trimmed = value.trim();\n    if (!trimmed) return undefined;\n    const parsed = Number(trimmed);\n    return Number.isFinite(parsed) ? parsed : null;\n  }\n  return null;\n}\n\nfunction parseOptionalPositiveInt(value: unknown): number | undefined | null {\n  const parsed = parseOptionalFiniteNumber(value);\n  if (parsed === undefined || parsed === null) return parsed;\n  if (!Number.isInteger(parsed) || parsed < 1) return null;\n  return parsed;\n}\n\nexport function registerApiTriggers(\n  sdk: ISdk,\n  kv: StateKV,\n  secret?: string,\n  metricsStore?: MetricsStore,\n  provider?: ResilientProvider | { circuitState?: unknown },\n): void {\n  sdk.registerFunction(\n    \"middleware::api-auth\",\n    async (input: {\n      request?: { headers?: Record<string, string | undefined> };\n    }) => {\n      if (!secret) return { action: \"continue\" };\n      const headers = input?.request?.headers || {};\n      const auth = headers[\"authorization\"] || headers[\"Authorization\"];\n      if (\n        typeof auth !== \"string\" ||\n        !timingSafeCompare(auth, `Bearer ${secret}`)\n      ) {\n        return {\n          action: \"respond\",\n          response: { status_code: 401, body: { error: \"unauthorized\" } },\n        };\n      }\n      return { action: \"continue\" };\n    },\n  );\n\n  sdk.registerFunction(\"api::liveness\",\n    async (): Promise<Response> => ({\n      status_code: 200,\n      body: { status: \"ok\", service: \"agentmemory\", viewerPort: getBoundViewerPort(), viewerSkipped: getViewerSkipped() },\n    }),\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::liveness\",\n    config: { api_path: \"/agentmemory/livez\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::config-flags\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const providerKind = detectLlmProviderKind();\n      const embeddingProvider = detectEmbeddingProvider() ? \"embeddings\" : \"none\";\n      const flags = [\n        {\n          key: \"GRAPH_EXTRACTION_ENABLED\",\n          label: \"Knowledge graph extraction\",\n          enabled: isGraphExtractionEnabled(),\n          default: false,\n          affects: [\"Graph\", \"Dashboard\"],\n          needsLlm: true,\n          description: \"Extracts entities and relations from observations into a knowledge graph.\",\n          enableHow: \"Set GRAPH_EXTRACTION_ENABLED=true and provide an LLM key, then restart.\",\n          docsHref: \"https://github.com/rohitg00/agentmemory#knowledge-graph\",\n        },\n        {\n          key: \"CONSOLIDATION_ENABLED\",\n          label: \"Memory consolidation\",\n          enabled: isConsolidationEnabled(),\n          default: false,\n          affects: [\"Dashboard\", \"Memories\", \"Crystals\"],\n          needsLlm: true,\n          description: \"Periodically summarizes sessions into semantic facts + procedures.\",\n          enableHow: \"Set CONSOLIDATION_ENABLED=true and provide an LLM key, then restart.\",\n          docsHref: \"https://github.com/rohitg00/agentmemory#consolidation\",\n        },\n        {\n          key: \"AGENTMEMORY_AUTO_COMPRESS\",\n          label: \"LLM-powered observation compression\",\n          enabled: isAutoCompressEnabled(),\n          default: false,\n          affects: [\"Memories\", \"Timeline\"],\n          needsLlm: true,\n          description: \"Every observation is compressed by the LLM for richer summaries (costs tokens). OFF uses zero-LLM synthetic compression.\",\n          enableHow: \"Set AGENTMEMORY_AUTO_COMPRESS=true and provide an LLM key.\",\n          docsHref: \"https://github.com/rohitg00/agentmemory/issues/138\",\n        },\n        {\n          key: \"AGENTMEMORY_INJECT_CONTEXT\",\n          label: \"In-conversation context injection\",\n          enabled: isContextInjectionEnabled(),\n          default: false,\n          affects: [\"Hooks\"],\n          needsLlm: false,\n          description: \"Hooks write recalled context into Claude Code's conversation. OFF captures in the background without injecting.\",\n          enableHow: \"Set AGENTMEMORY_INJECT_CONTEXT=true and restart.\",\n          docsHref: \"https://github.com/rohitg00/agentmemory/issues/143\",\n        },\n      ];\n      return {\n        status_code: 200,\n        body: {\n          version: VERSION,\n          provider: providerKind,\n          embeddingProvider,\n          flags,\n        },\n      };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::config-flags\",\n    config: {\n      api_path: \"/agentmemory/config/flags\",\n      http_method: \"GET\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::health\", \n    async (req: ApiRequest): Promise<Response> => {\n      const health = await getLatestHealth(kv);\n      const functionMetrics = metricsStore ? await metricsStore.getAll() : [];\n      const circuitBreaker =\n        provider && \"circuitState\" in provider ? provider.circuitState : null;\n\n      const status = health?.status || \"healthy\";\n      const statusCode = status === \"critical\" ? 503 : 200;\n\n      return {\n        status_code: statusCode,\n        body: {\n          status,\n          service: \"agentmemory\",\n          version: VERSION,\n          health: health || null,\n          functionMetrics,\n          circuitBreaker,\n          viewerPort: getBoundViewerPort(),\n          viewerSkipped: getViewerSkipped(),\n        },\n      };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::health\",\n    config: {\n      api_path: \"/agentmemory/health\",\n      http_method: \"GET\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::observe\",\n    async (req: ApiRequest<HookPayload>): Promise<Response> => {\n      const body = (req.body ?? {}) as Record<string, unknown>;\n      const hookType = asNonEmptyString(body.hookType);\n      const sessionId = asNonEmptyString(body.sessionId);\n      const project = asNonEmptyString(body.project);\n      const cwd = asNonEmptyString(body.cwd);\n      const timestamp = asNonEmptyString(body.timestamp);\n      if (!hookType || !sessionId || !project || !cwd || !timestamp) {\n        return {\n          status_code: 400,\n          body: {\n            error:\n              \"hookType, sessionId, project, cwd, and timestamp are required strings\",\n          },\n        };\n      }\n      const payload: HookPayload = {\n        hookType: hookType as HookPayload[\"hookType\"],\n        sessionId,\n        project,\n        cwd,\n        timestamp,\n        data: body.data,\n      };\n      const result = await sdk.trigger({ function_id: \"mem::observe\", payload });\n      return { status_code: 201, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::observe\",\n    config: {\n      api_path: \"/agentmemory/observe\",\n      http_method: \"POST\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::context\",\n    async (\n      req: ApiRequest<{ sessionId: string; project: string; budget?: number }>,\n    ): Promise<Response> => {\n      const body = (req.body ?? {}) as Record<string, unknown>;\n      const sessionId = asNonEmptyString(body.sessionId);\n      const project = asNonEmptyString(body.project);\n      if (!sessionId || !project) {\n        return {\n          status_code: 400,\n          body: { error: \"sessionId and project are required strings\" },\n        };\n      }\n      const budget = parseOptionalPositiveInt(body.budget);\n      if (budget === null) {\n        return {\n          status_code: 400,\n          body: { error: \"budget must be a positive integer\" },\n        };\n      }\n      const payload: { sessionId: string; project: string; budget?: number } = {\n        sessionId,\n        project,\n      };\n      if (budget !== undefined) payload.budget = budget;\n      const result = await sdk.trigger({ function_id: \"mem::context\", payload });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::context\",\n    config: {\n      api_path: \"/agentmemory/context\",\n      http_method: \"POST\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::search\",\n    async (\n      req: ApiRequest<{\n        query: string;\n        limit?: number;\n        project?: string;\n        cwd?: string;\n        format?: string;\n        token_budget?: number;\n        agentId?: string;\n      }>,\n    ): Promise<Response> => {\n      const body = (req.body ?? {}) as Record<string, unknown>;\n      const queryAgentId =\n        typeof (req as { query_params?: Record<string, string> })\n          .query_params?.[\"agentId\"] === \"string\"\n          ? (req as { query_params: Record<string, string> })\n              .query_params[\"agentId\"]\n          : undefined;\n      if (typeof body.query !== \"string\" || !body.query.trim()) {\n        return { status_code: 400, body: { error: \"query is required and must be a non-empty string\" } };\n      }\n      if (\n        body.limit !== undefined &&\n        (!Number.isInteger(body.limit) || (body.limit as number) < 1)\n      ) {\n        return { status_code: 400, body: { error: \"limit must be a positive integer\" } };\n      }\n      if (body.project !== undefined && typeof body.project !== \"string\") {\n        return { status_code: 400, body: { error: \"project must be a string\" } };\n      }\n      if (body.cwd !== undefined && typeof body.cwd !== \"string\") {\n        return { status_code: 400, body: { error: \"cwd must be a string\" } };\n      }\n      if (\n        body.format !== undefined &&\n        (typeof body.format !== \"string\" ||\n          ![\"full\", \"compact\", \"narrative\"].includes(body.format.trim().toLowerCase()))\n      ) {\n        return {\n          status_code: 400,\n          body: { error: \"format must be one of: full, compact, narrative\" },\n        };\n      }\n      if (\n        body.token_budget !== undefined &&\n        (!Number.isInteger(body.token_budget) || (body.token_budget as number) < 1)\n      ) {\n        return {\n          status_code: 400,\n          body: { error: \"token_budget must be a positive integer\" },\n        };\n      }\n      // #817: propagate agentId so the upstream isolation filter\n      // applies. Honors body.agentId (POST body), ?agentId=... query\n      // param, or implicit fallback to the worker's AGENT_ID when\n      // AGENTMEMORY_AGENT_SCOPE=isolated.\n      const bodyAgentId =\n        typeof body.agentId === \"string\" && body.agentId.trim().length > 0\n          ? (body.agentId as string).trim()\n          : undefined;\n      const payload = {\n        query: body.query.trim(),\n        limit: body.limit as number | undefined,\n        project: body.project as string | undefined,\n        cwd: body.cwd as string | undefined,\n        format:\n          typeof body.format === \"string\"\n            ? body.format.trim().toLowerCase()\n            : undefined,\n        token_budget: body.token_budget as number | undefined,\n        agentId: bodyAgentId ?? queryAgentId,\n      };\n      const result = await sdk.trigger({ function_id: \"mem::search\", payload: payload });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::search\",\n    config: {\n      api_path: \"/agentmemory/search\",\n      http_method: \"POST\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::compress-file\", \n    async (req: ApiRequest<{ filePath: string }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const body = (req.body ?? {}) as Record<string, unknown>;\n      const filePath = asNonEmptyString(body.filePath);\n      if (!filePath) {\n        return {\n          status_code: 400,\n          body: { error: \"filePath is required and must be a non-empty string\" },\n        };\n      }\n      const result = await sdk.trigger({\n        function_id: \"mem::compress-file\",\n        payload: { filePath },\n      });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::compress-file\",\n    config: { api_path: \"/agentmemory/compress-file\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::replay::load\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const sessionId = asNonEmptyString(req.query_params?.[\"sessionId\"]);\n      if (!sessionId) {\n        return { status_code: 400, body: { error: \"sessionId is required\" } };\n      }\n      const result = await sdk.trigger({\n        function_id: \"mem::replay::load\",\n        payload: { sessionId },\n      });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::replay::load\",\n    config: { api_path: \"/agentmemory/replay/load\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::replay::sessions\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const sessions = await kv.list<Session>(KV.sessions);\n      sessions.sort((a, b) =>\n        (b.startedAt || \"\").localeCompare(a.startedAt || \"\"),\n      );\n      return { status_code: 200, body: { success: true, sessions } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::replay::sessions\",\n    config: { api_path: \"/agentmemory/replay/sessions\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::replay::import\",\n    async (\n      req: ApiRequest<{ path?: string; maxFiles?: number }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const body = (req.body ?? {}) as Record<string, unknown>;\n      const payload: { path?: string; maxFiles?: number } = {};\n      if (body.path !== undefined) {\n        if (typeof body.path !== \"string\" || body.path.trim().length === 0) {\n          return {\n            status_code: 400,\n            body: { error: \"path must be a non-empty string\" },\n          };\n        }\n        payload.path = body.path.trim();\n      }\n      if (body.maxFiles !== undefined) {\n        const n = body.maxFiles as number;\n        if (\n          !Number.isInteger(n) ||\n          n < 1 ||\n          n > MAX_FILES_UPPER_BOUND\n        ) {\n          return {\n            status_code: 400,\n            body: {\n              error: `maxFiles must be an integer between 1 and ${MAX_FILES_UPPER_BOUND}`,\n            },\n          };\n        }\n        payload.maxFiles = n;\n      }\n      const result = await sdk.trigger({\n        function_id: \"mem::replay::import-jsonl\",\n        payload,\n      });\n      return { status_code: 202, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::replay::import\",\n    config: { api_path: \"/agentmemory/replay/import-jsonl\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::session::start\",\n    async (\n      req: ApiRequest<{ sessionId: string; project: string; cwd: string }>,\n    ): Promise<Response> => {\n      const body = (req.body ?? {}) as Record<string, unknown>;\n      const sessionId = asNonEmptyString(body.sessionId);\n      const project = asNonEmptyString(body.project);\n      const cwd = asNonEmptyString(body.cwd);\n      if (!sessionId || !project || !cwd) {\n        return {\n          status_code: 400,\n          body: {\n            error: \"sessionId, project, and cwd are required non-empty strings\",\n          },\n        };\n      }\n      const title = typeof body.title === \"string\" ? body.title.trim() : undefined;\n      // allow session/start to override AGENT_ID from request body\n      // (multi-agent runtimes that route many roles through one server\n      // process). Falls back to the AGENT_ID env on the server.\n      const requestAgentId =\n        typeof body.agentId === \"string\" && body.agentId.trim().length > 0\n          ? body.agentId.trim().slice(0, 128)\n          : undefined;\n      const agentId = requestAgentId ?? getAgentId();\n      const session: Session = {\n        id: sessionId,\n        project,\n        cwd,\n        startedAt: new Date().toISOString(),\n        status: \"active\",\n        observationCount: 0,\n        ...(title ? { summary: title.slice(0, 200) } : {}),\n        ...(title ? { firstPrompt: title.slice(0, 200) } : {}),\n        ...(agentId ? { agentId } : {}),\n      };\n      await kv.set(KV.sessions, sessionId, session);\n      const contextResult = await sdk.trigger<\n        { sessionId: string; project: string },\n        { context: string }\n      >({ function_id: \"mem::context\", payload: { sessionId, project } });\n      return {\n        status_code: 200,\n        body: { session, context: contextResult.context },\n      };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::session::start\",\n    config: {\n      api_path: \"/agentmemory/session/start\",\n      http_method: \"POST\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::session::end\",\n    async (req: ApiRequest<{ sessionId: string }>): Promise<Response> => {\n      const sessionId = asNonEmptyString((req.body as Record<string, unknown>)?.sessionId);\n      if (!sessionId) {\n        return {\n          status_code: 400,\n          body: { error: \"sessionId is required and must be a non-empty string\" },\n        };\n      }\n      await kv.update(KV.sessions, sessionId, [\n        { type: \"set\", path: \"endedAt\", value: new Date().toISOString() },\n        { type: \"set\", path: \"status\", value: \"completed\" },\n      ]);\n      // Fan out session-stopped lifecycle (non-blocking).\n      try {\n        sdk.trigger({\n          function_id: \"event::session::stopped\",\n          payload: { sessionId },\n          action: TriggerAction.Void(),\n        });\n      } catch (err) {\n        logger.warn(\"event::session::stopped trigger failed\", {\n          sessionId,\n          error: err instanceof Error ? err.message : String(err),\n        });\n      }\n      return { status_code: 200, body: { success: true } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::session::end\",\n    config: {\n      api_path: \"/agentmemory/session/end\",\n      http_method: \"POST\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::summarize\", \n    async (req: ApiRequest<{ sessionId: string }>): Promise<Response> => {\n      const sessionId = asNonEmptyString((req.body as Record<string, unknown>)?.sessionId);\n      if (!sessionId) {\n        return { status_code: 400, body: { error: \"sessionId is required\" } };\n      }\n      const result = await sdk.trigger({\n        function_id: \"mem::summarize\",\n        payload: { sessionId },\n      });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::summarize\",\n    config: {\n      api_path: \"/agentmemory/summarize\",\n      http_method: \"POST\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::session::commit\",\n    async (req: ApiRequest): Promise<Response> => {\n      const body = (req.body ?? {}) as Record<string, unknown>;\n      const sha = asNonEmptyString(body.sha);\n      if (!sha) {\n        return {\n          status_code: 400,\n          body: { error: \"sha is required and must be a non-empty string\" },\n        };\n      }\n      const sessionId = asNonEmptyString(body.sessionId) ?? undefined;\n      const branch = asNonEmptyString(body.branch) ?? undefined;\n      const repo = asNonEmptyString(body.repo) ?? undefined;\n      const message = asNonEmptyString(body.message) ?? undefined;\n      const author = asNonEmptyString(body.author) ?? undefined;\n      const authoredAt = asNonEmptyString(body.authoredAt) ?? undefined;\n      const files = Array.isArray(body.files)\n        ? (body.files as unknown[]).filter(\n            (f): f is string => typeof f === \"string\" && f.length > 0,\n          )\n        : undefined;\n\n      const link = await withKeyedLock(`commit:${sha}`, async () => {\n        const existing = await kv.get<CommitLink>(KV.commits, sha);\n        const sessionSet = new Set<string>(existing?.sessionIds ?? []);\n        if (sessionId) sessionSet.add(sessionId);\n        const merged: CommitLink = {\n          sha,\n          shortSha: existing?.shortSha ?? sha.slice(0, 7),\n          branch: branch ?? existing?.branch,\n          repo: repo ?? existing?.repo,\n          message: message ?? existing?.message,\n          author: author ?? existing?.author,\n          authoredAt: authoredAt ?? existing?.authoredAt,\n          files: files ?? existing?.files,\n          sessionIds: Array.from(sessionSet),\n          linkedAt: existing?.linkedAt ?? new Date().toISOString(),\n        };\n        await kv.set(KV.commits, sha, merged);\n        return merged;\n      });\n\n      if (sessionId) {\n        await withKeyedLock(`session:${sessionId}`, async () => {\n          const session = await kv.get<Session>(KV.sessions, sessionId);\n          if (!session) return;\n          const shaSet = new Set<string>(session.commitShas ?? []);\n          shaSet.add(sha);\n          session.commitShas = Array.from(shaSet);\n          await kv.set(KV.sessions, sessionId, session);\n        });\n      }\n\n      return { status_code: 200, body: { commit: link } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::session::commit\",\n    config: {\n      api_path: \"/agentmemory/session/commit\",\n      http_method: \"POST\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::session::by-commit\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const sha = asNonEmptyString(req.query_params?.[\"sha\"]);\n      if (!sha) {\n        return {\n          status_code: 400,\n          body: { error: \"sha is required and must be a non-empty string\" },\n        };\n      }\n      const link = await kv.get<CommitLink>(KV.commits, sha);\n      if (!link) {\n        return {\n          status_code: 404,\n          body: { error: \"no sessions linked to this commit\" },\n        };\n      }\n      const fetched = await Promise.all(\n        (link.sessionIds ?? []).map((sid) => kv.get<Session>(KV.sessions, sid)),\n      );\n      const sessions = fetched.filter((s): s is Session => s !== null);\n      return { status_code: 200, body: { commit: link, sessions } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::session::by-commit\",\n    config: {\n      api_path: \"/agentmemory/session/by-commit\",\n      http_method: \"GET\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::commits\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const branch = asNonEmptyString(req.query_params?.[\"branch\"]);\n      const repo = asNonEmptyString(req.query_params?.[\"repo\"]);\n      const rawLimit = parseOptionalInt(req.query_params?.[\"limit\"]);\n      const limit = Math.max(1, Math.min(500, rawLimit ?? 100));\n      const all = await kv.list<CommitLink>(KV.commits);\n      const filtered = all\n        .filter((c) => !branch || c.branch === branch)\n        .filter((c) => !repo || c.repo === repo)\n        .sort((a, b) => ((a.linkedAt ?? \"\") < (b.linkedAt ?? \"\") ? 1 : -1))\n        .slice(0, limit);\n      return { status_code: 200, body: { commits: filtered } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::commits\",\n    config: {\n      api_path: \"/agentmemory/commits\",\n      http_method: \"GET\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::sessions\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const sessions = await kv.list<Session>(KV.sessions);\n      const normalizedAgentId =\n        typeof req.query_params?.[\"agentId\"] === \"string\"\n          ? req.query_params[\"agentId\"].trim()\n          : undefined;\n      const wildcardAgent = normalizedAgentId === \"*\";\n      const explicitAgentId =\n        normalizedAgentId && !wildcardAgent ? normalizedAgentId : undefined;\n      const filterAgentId = wildcardAgent\n        ? undefined\n        : explicitAgentId ??\n          (isAgentScopeIsolated() ? getAgentId() : undefined);\n      const filtered = filterAgentId\n        ? sessions.filter((s) => s.agentId === filterAgentId)\n        : sessions;\n      const summaries = await Promise.all(\n        filtered.map((s) =>\n          kv.get<SessionSummary>(KV.summaries, s.id).catch(() => null),\n        ),\n      );\n      const withSummary = filtered.map((s, i) =>\n        summaries[i] ? { ...s, summary: summaries[i] } : s,\n      );\n      return { status_code: 200, body: { sessions: withSummary } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::sessions\",\n    config: { api_path: \"/agentmemory/sessions\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::observations\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const sessionId = asNonEmptyString(req.query_params?.[\"sessionId\"]);\n      if (!sessionId)\n        return { status_code: 400, body: { error: \"sessionId required\" } };\n      const observations = await kv.list<CompressedObservation>(\n        KV.observations(sessionId),\n      );\n      const normalizedAgentId =\n        typeof req.query_params?.[\"agentId\"] === \"string\"\n          ? req.query_params[\"agentId\"].trim()\n          : undefined;\n      const wildcardAgent = normalizedAgentId === \"*\";\n      const explicitAgentId =\n        normalizedAgentId && !wildcardAgent ? normalizedAgentId : undefined;\n      const filterAgentId = wildcardAgent\n        ? undefined\n        : explicitAgentId ??\n          (isAgentScopeIsolated() ? getAgentId() : undefined);\n      const filtered = filterAgentId\n        ? observations.filter((o) => o.agentId === filterAgentId)\n        : observations;\n      return { status_code: 200, body: { observations: filtered } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::observations\",\n    config: { api_path: \"/agentmemory/observations\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::file-context\", \n    async (\n      req: ApiRequest<{ sessionId: string; files: string[] }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::file-context\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::file-context\",\n    config: { api_path: \"/agentmemory/file-context\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::enrich\",\n    async (\n      req: ApiRequest<{\n        sessionId: string;\n        files: string[];\n        terms?: string[];\n        toolName?: string;\n        project?: string;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (\n        !req.body?.sessionId ||\n        typeof req.body.sessionId !== \"string\" ||\n        !Array.isArray(req.body?.files) ||\n        req.body.files.length === 0 ||\n        !req.body.files.every((f: unknown) => typeof f === \"string\")\n      ) {\n        return {\n          status_code: 400,\n          body: {\n            error: \"sessionId (string) and files (string[]) are required\",\n          },\n        };\n      }\n      if (\n        req.body.terms !== undefined &&\n        (!Array.isArray(req.body.terms) ||\n          !req.body.terms.every((t: unknown) => typeof t === \"string\"))\n      ) {\n        return {\n          status_code: 400,\n          body: { error: \"terms must be an array of strings\" },\n        };\n      }\n      if (\n        req.body.project !== undefined &&\n        (typeof req.body.project !== \"string\" || !req.body.project.trim())\n      ) {\n        return {\n          status_code: 400,\n          body: { error: \"project must be a non-empty string\" },\n        };\n      }\n      const result = await sdk.trigger({\n        function_id: \"mem::enrich\",\n        payload: {\n          sessionId: req.body.sessionId,\n          files: req.body.files,\n          ...(req.body.terms !== undefined && { terms: req.body.terms }),\n          ...(req.body.toolName !== undefined && { toolName: req.body.toolName }),\n          ...(req.body.project !== undefined && { project: req.body.project }),\n        },\n      });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::enrich\",\n    config: { api_path: \"/agentmemory/enrich\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::remember\",\n    async (\n      req: ApiRequest<{\n        content: string;\n        type?: string;\n        concepts?: string[];\n        files?: string[];\n        ttlDays?: number;\n        sourceObservationIds?: string[];\n        project?: string;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (\n        !req.body?.content ||\n        typeof req.body.content !== \"string\" ||\n        !req.body.content.trim()\n      ) {\n        return { status_code: 400, body: { error: \"content is required\" } };\n      }\n      if (\n        req.body.project !== undefined &&\n        (typeof req.body.project !== \"string\" || !req.body.project.trim())\n      ) {\n        return { status_code: 400, body: { error: \"project must be a non-empty string\" } };\n      }\n      const result = await sdk.trigger({\n        function_id: \"mem::remember\",\n        payload: {\n          content: req.body.content,\n          ...(req.body.type !== undefined && { type: req.body.type }),\n          ...(req.body.concepts !== undefined && { concepts: req.body.concepts }),\n          ...(req.body.files !== undefined && { files: req.body.files }),\n          ...(req.body.ttlDays !== undefined && { ttlDays: req.body.ttlDays }),\n          ...(req.body.sourceObservationIds !== undefined && { sourceObservationIds: req.body.sourceObservationIds }),\n          ...(req.body.project !== undefined && { project: req.body.project }),\n        },\n      });\n      return { status_code: 201, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::remember\",\n    config: { api_path: \"/agentmemory/remember\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::forget\", \n    async (\n      req: ApiRequest<{\n        sessionId?: string;\n        observationIds?: string[];\n        memoryId?: string;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.sessionId && !req.body?.memoryId) {\n        return {\n          status_code: 400,\n          body: { error: \"sessionId or memoryId is required\" },\n        };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::forget\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::forget\",\n    config: { api_path: \"/agentmemory/forget\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::consolidate\", \n    async (\n      req: ApiRequest<{ project?: string; minObservations?: number }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::consolidate\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::consolidate\",\n    config: { api_path: \"/agentmemory/consolidate\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::patterns\", \n    async (req: ApiRequest<{ project?: string }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::patterns\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::patterns\",\n    config: { api_path: \"/agentmemory/patterns\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::generate-rules\", \n    async (req: ApiRequest<{ project?: string }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::generate-rules\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::generate-rules\",\n    config: { api_path: \"/agentmemory/generate-rules\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::migrate\",\n    async (\n      req: ApiRequest<{ dbPath?: string; step?: string; dryRun?: boolean }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const hasStep =\n        typeof req.body?.step === \"string\" && req.body.step.trim().length > 0;\n      const hasDbPath =\n        typeof req.body?.dbPath === \"string\" && req.body.dbPath.trim().length > 0;\n      if (!hasStep && !hasDbPath) {\n        return {\n          status_code: 400,\n          body: { error: \"Either step (string) or dbPath (string) is required\" },\n        };\n      }\n      const result = await sdk.trigger({\n        function_id: \"mem::migrate\",\n        payload: {\n          ...(req.body.step !== undefined && { step: req.body.step }),\n          ...(req.body.dbPath !== undefined && { dbPath: req.body.dbPath }),\n          ...(req.body.dryRun !== undefined && { dryRun: req.body.dryRun }),\n        },\n      });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::migrate\",\n    config: { api_path: \"/agentmemory/migrate\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::evict\", \n    async (req: ApiRequest<{ dryRun?: boolean }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const dryRun =\n        req.query_params?.[\"dryRun\"] === \"true\" || req.body?.dryRun === true;\n      const result = await sdk.trigger({ function_id: \"mem::evict\", payload: { dryRun } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::evict\",\n    config: { api_path: \"/agentmemory/evict\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::smart-search\",\n    async (\n      req: ApiRequest<{\n        query?: string;\n        expandIds?: Array<string | { obsId: string; sessionId: string }>;\n        limit?: number;\n        project?: string;\n        includeLessons?: boolean;\n        agentId?: string;\n        sessionId?: string;\n        source?: string;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (\n        !req.body?.query &&\n        (!req.body?.expandIds || req.body.expandIds.length === 0)\n      ) {\n        return {\n          status_code: 400,\n          body: { error: \"query or expandIds is required\" },\n        };\n      }\n      // #771: route the X-Agentmemory-Source header into the payload so\n      // the followup-rate diagnostic can skip viewer-originated calls.\n      // Body wins if both are set (advanced callers explicitly override).\n      const headers = (req.headers || {}) as Record<string, string | string[] | undefined>;\n      const sourceHeader = headers[\"x-agentmemory-source\"] ?? headers[\"X-Agentmemory-Source\"];\n      const sourceFromHeader = Array.isArray(sourceHeader) ? sourceHeader[0] : sourceHeader;\n      // Whitelist payload fields explicitly — REST endpoints never pass\n      // the raw request body through to sdk.trigger (AGENTS.md security\n      // section). Drops unknown fields so a misbehaving client can't\n      // inject downstream-only options.\n      const payload = {\n        query: req.body?.query,\n        expandIds: req.body?.expandIds,\n        limit: req.body?.limit,\n        project: req.body?.project,\n        includeLessons: req.body?.includeLessons,\n        agentId: req.body?.agentId,\n        sessionId: req.body?.sessionId,\n        source: req.body?.source ?? sourceFromHeader,\n      };\n      const result = await sdk.trigger({ function_id: \"mem::smart-search\", payload });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::smart-search\",\n    config: { api_path: \"/agentmemory/smart-search\", http_method: \"POST\" },\n  });\n\n  // #771: read-back endpoint for the followup-rate diagnostic. Returns\n  // a directional signal — overcounts on legitimate query refinement —\n  // so help text + the CLI status line carry the same caveat.\n  sdk.registerFunction(\"api::diagnostic-followup\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({\n        function_id: \"mem::diagnostic::followup-stats\",\n        payload: {},\n      });\n      return {\n        status_code: 200,\n        body: {\n          ...(result as Record<string, unknown>),\n          caveat:\n            \"Directional signal: overcounts on legitimate query refinement. \" +\n            \"Tune via AGENTMEMORY_FOLLOWUP_WINDOW_SECONDS.\",\n        },\n      };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::diagnostic-followup\",\n    config: {\n      api_path: \"/agentmemory/diagnostics/followup\",\n      http_method: \"GET\",\n      middleware_function_ids: [\"middleware::api-auth\"],\n    },\n  });\n\n  sdk.registerFunction(\"api::timeline\", \n    async (\n      req: ApiRequest<{\n        anchor: string;\n        project?: string;\n        before?: number;\n        after?: number;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.anchor) {\n        return { status_code: 400, body: { error: \"anchor is required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::timeline\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::timeline\",\n    config: { api_path: \"/agentmemory/timeline\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::profile\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const project = req.query_params[\"project\"] as string;\n      if (!project) {\n        return {\n          status_code: 400,\n          body: { error: \"project query param is required\" },\n        };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::profile\", payload: { project } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::profile\",\n    config: { api_path: \"/agentmemory/profile\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::export\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      // mem::export already supports maxSessions/offset internally,\n      // but the HTTP endpoint hardcoded an empty payload — so /export on a\n      // real corpus (40 sessions × 34K observations × 8K memories) hit the\n      // iii engine invocation timeout and `agentmemory status` reported 0.\n      // Pass through the query-string pagination so callers can chunk.\n      const rawMax = req.query_params?.[\"maxSessions\"];\n      const rawOffset = req.query_params?.[\"offset\"];\n      const payload: { maxSessions?: number; offset?: number } = {};\n      if (typeof rawMax === \"string\") {\n        const n = Number(rawMax);\n        if (Number.isInteger(n) && n > 0) payload.maxSessions = n;\n      }\n      if (typeof rawOffset === \"string\") {\n        const n = Number(rawOffset);\n        if (Number.isInteger(n) && n >= 0) payload.offset = n;\n      }\n      const result = await sdk.trigger({\n        function_id: \"mem::export\",\n        payload,\n      });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::export\",\n    config: { api_path: \"/agentmemory/export\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::import\", \n    async (\n      req: ApiRequest<{\n        exportData: unknown;\n        strategy?: \"merge\" | \"replace\" | \"skip\";\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.exportData) {\n        return { status_code: 400, body: { error: \"exportData is required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::import\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::import\",\n    config: { api_path: \"/agentmemory/import\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::relations\", \n    async (\n      req: ApiRequest<{ sourceId: string; targetId: string; type: string }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.sourceId || !req.body?.targetId || !req.body?.type) {\n        return {\n          status_code: 400,\n          body: { error: \"sourceId, targetId, and type are required\" },\n        };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::relate\", payload: req.body });\n      return { status_code: 201, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::relations\",\n    config: { api_path: \"/agentmemory/relations\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::evolve\", \n    async (\n      req: ApiRequest<{\n        memoryId: string;\n        newContent: string;\n        newTitle?: string;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.memoryId || !req.body?.newContent) {\n        return {\n          status_code: 400,\n          body: { error: \"memoryId and newContent are required\" },\n        };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::evolve\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::evolve\",\n    config: { api_path: \"/agentmemory/evolve\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::auto-forget\", \n    async (req: ApiRequest<{ dryRun?: boolean }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const dryRun =\n        req.query_params?.[\"dryRun\"] === \"true\" || req.body?.dryRun === true;\n      const result = await sdk.trigger({ function_id: \"mem::auto-forget\", payload: { dryRun } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::auto-forget\",\n    config: { api_path: \"/agentmemory/auto-forget\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::claude-bridge-read\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::claude-bridge-read\", payload: {} });\n        return { status_code: 200, body: result };\n      } catch {\n        return {\n          status_code: 404,\n          body: { error: \"Claude bridge not enabled\" },\n        };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::claude-bridge-read\",\n    config: { api_path: \"/agentmemory/claude-bridge/read\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::claude-bridge-sync\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::claude-bridge-sync\", payload: {} });\n        return { status_code: 200, body: result };\n      } catch {\n        return {\n          status_code: 404,\n          body: { error: \"Claude bridge not enabled\" },\n        };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::claude-bridge-sync\",\n    config: {\n      api_path: \"/agentmemory/claude-bridge/sync\",\n      http_method: \"POST\",\n    },\n  });\n\n  sdk.registerFunction(\"api::graph-query\",\n    async (\n      req: ApiRequest<{\n        startNodeId?: string;\n        nodeType?: string;\n        maxDepth?: number;\n        query?: string;\n        limit?: number;\n        offset?: number;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      // Whitelist payload fields explicitly; AGENTS.md security rule:\n      // REST endpoints never pass raw req.body through to sdk.trigger.\n      const payload = {\n        startNodeId: req.body?.startNodeId,\n        nodeType: req.body?.nodeType,\n        maxDepth: req.body?.maxDepth,\n        query: req.body?.query,\n        limit: req.body?.limit,\n        offset: req.body?.offset,\n      };\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::graph-query\", payload });\n        return { status_code: 200, body: result };\n      } catch {\n        return graphDisabledResponse();\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::graph-query\",\n    config: { api_path: \"/agentmemory/graph/query\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::graph-stats\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::graph-stats\", payload: {} });\n        return { status_code: 200, body: result };\n      } catch {\n        return graphDisabledResponse();\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::graph-stats\",\n    config: { api_path: \"/agentmemory/graph/stats\", http_method: \"GET\" },\n  });\n\n  // #814: explicit snapshot rebuild endpoint. Pays the full graph\n  // enumeration once and persists a top-degree subgraph + aggregate\n  // counts so subsequent /graph/query and /graph/stats calls skip the\n  // unbounded kv.list. Operator-grade endpoint exposed for the viewer\n  // banner action and CLI repair.\n  sdk.registerFunction(\"api::graph-snapshot-rebuild\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const result = await sdk.trigger({\n          function_id: \"mem::graph-snapshot-rebuild\",\n          payload: {},\n        });\n        return { status_code: 200, body: result };\n      } catch {\n        return graphDisabledResponse();\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::graph-snapshot-rebuild\",\n    config: { api_path: \"/agentmemory/graph/snapshot-rebuild\", http_method: \"POST\" },\n  });\n\n  // #814 v2: clean-restart endpoint for legacy corpora too large for\n  // safe rebuild. Wipes graph state without touching observations, so\n  // recall + history stay intact while the graph rebuilds incrementally\n  // from new extracts (or a one-shot /graph/build replay).\n  sdk.registerFunction(\"api::graph-reset\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const result = await sdk.trigger({\n          function_id: \"mem::graph-reset\",\n          payload: {},\n        });\n        return { status_code: 200, body: result };\n      } catch {\n        return graphDisabledResponse();\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::graph-reset\",\n    config: { api_path: \"/agentmemory/graph/reset\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::graph-extract\",\n    async (req: ApiRequest<{ observations: unknown[] }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (\n        !Array.isArray(req.body?.observations) ||\n        req.body.observations.length === 0\n      ) {\n        return {\n          status_code: 400,\n          body: { error: \"observations array is required\" },\n        };\n      }\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::graph-extract\", payload: req.body });\n        return { status_code: 200, body: result };\n      } catch {\n        return graphDisabledResponse();\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::graph-extract\",\n    config: { api_path: \"/agentmemory/graph/extract\", http_method: \"POST\" },\n  });\n\n  // Backfill the knowledge graph from existing compressed observations.\n  // Viewer calls this when the graph is empty (#666). Iterates every\n  // session, collects observations that have a `title` (compressed only),\n  // and feeds them through `mem::graph-extract` in batches.\n  sdk.registerFunction(\"api::graph-build\",\n    async (req: ApiRequest<{ batchSize?: number }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const batchSize = Math.max(\n        1,\n        Math.min(100, Number((req.body as { batchSize?: number })?.batchSize) || 25),\n      );\n      try {\n        const sessions = await kv.list<Session>(KV.sessions);\n        let totalNodes = 0;\n        let totalEdges = 0;\n        let batchesRun = 0;\n        for (const session of sessions) {\n          const sid = session?.id;\n          if (typeof sid !== \"string\" || sid.length === 0) continue;\n          const observations = await kv.list<CompressedObservation>(KV.observations(sid));\n          const compressed = observations.filter((o) => o && typeof o.title === \"string\" && o.title.length > 0);\n          if (compressed.length === 0) continue;\n          for (let i = 0; i < compressed.length; i += batchSize) {\n            const batch = compressed.slice(i, i + batchSize);\n            try {\n              const result = (await sdk.trigger({\n                function_id: \"mem::graph-extract\",\n                payload: { observations: batch },\n              })) as { success?: boolean; nodesAdded?: number; edgesAdded?: number };\n              if (result?.success) {\n                totalNodes += Number(result.nodesAdded) || 0;\n                totalEdges += Number(result.edgesAdded) || 0;\n              }\n              batchesRun++;\n            } catch (err) {\n              logger.warn(\"graph-build batch failed\", {\n                sessionId: sid,\n                batchIndex: Math.floor(i / batchSize),\n                error: err instanceof Error ? err.message : String(err),\n              });\n            }\n          }\n        }\n        return {\n          status_code: 200,\n          body: {\n            success: true,\n            sessions: sessions.length,\n            batches: batchesRun,\n            nodes: totalNodes,\n            edges: totalEdges,\n          },\n        };\n      } catch {\n        return graphDisabledResponse();\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::graph-build\",\n    config: { api_path: \"/agentmemory/graph/build\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::consolidate-pipeline\",\n    async (req: ApiRequest<{ tier?: string }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::consolidate-pipeline\", payload: req.body || {},\n         });\n        return { status_code: 200, body: result };\n      } catch {\n        return consolidationDisabledResponse();\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::consolidate-pipeline\",\n    config: {\n      api_path: \"/agentmemory/consolidate-pipeline\",\n      http_method: \"POST\",\n    },\n  });\n\n  sdk.registerFunction(\"api::team-share\", \n    async (\n      req: ApiRequest<{ itemId: string; itemType: string; project?: string }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.itemId || !req.body?.itemType) {\n        return {\n          status_code: 400,\n          body: { error: \"itemId and itemType are required\" },\n        };\n      }\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::team-share\", payload: req.body });\n        return { status_code: 201, body: result };\n      } catch {\n        return { status_code: 404, body: { error: \"Team memory not enabled\" } };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::team-share\",\n    config: { api_path: \"/agentmemory/team/share\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::team-feed\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const parsedLimit = parseOptionalInt(req.query_params?.[\"limit\"]);\n        const limit = parsedLimit ?? 20;\n        const result = await sdk.trigger({ function_id: \"mem::team-feed\", payload: { limit } });\n        return { status_code: 200, body: result };\n      } catch {\n        return { status_code: 404, body: { error: \"Team memory not enabled\" } };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::team-feed\",\n    config: { api_path: \"/agentmemory/team/feed\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::team-profile\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::team-profile\", payload: {} });\n        return { status_code: 200, body: result };\n      } catch {\n        return { status_code: 404, body: { error: \"Team memory not enabled\" } };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::team-profile\",\n    config: { api_path: \"/agentmemory/team/profile\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::audit\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const parsedLimit = parseOptionalInt(req.query_params?.[\"limit\"]);\n      const entries = await sdk.trigger({ function_id: \"mem::audit-query\", payload: {\n        operation: req.query_params?.[\"operation\"],\n        limit: parsedLimit ?? 50,\n      } });\n      return { status_code: 200, body: { entries, success: true } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::audit\",\n    config: { api_path: \"/agentmemory/audit\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::governance-delete\", \n    async (\n      req: ApiRequest<{ memoryIds: string[]; reason?: string }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.memoryIds || !Array.isArray(req.body.memoryIds)) {\n        return {\n          status_code: 400,\n          body: { error: \"memoryIds array is required\" },\n        };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::governance-delete\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::governance-delete\",\n    config: {\n      api_path: \"/agentmemory/governance/memories\",\n      http_method: \"DELETE\",\n    },\n  });\n\n  sdk.registerFunction(\"api::governance-bulk\", \n    async (\n      req: ApiRequest<{\n        type?: string[];\n        dateFrom?: string;\n        dateTo?: string;\n        qualityBelow?: number;\n        dryRun?: boolean;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::governance-bulk\", payload: req.body || {} });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::governance-bulk\",\n    config: {\n      api_path: \"/agentmemory/governance/bulk-delete\",\n      http_method: \"POST\",\n    },\n  });\n\n  sdk.registerFunction(\"api::snapshots\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::snapshot-list\", payload: {} });\n        return { status_code: 200, body: result };\n      } catch {\n        return { status_code: 404, body: { error: \"Snapshots not enabled\" } };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::snapshots\",\n    config: { api_path: \"/agentmemory/snapshots\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::snapshot-create\", \n    async (req: ApiRequest<{ message?: string }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::snapshot-create\", payload: req.body || {},\n         });\n        return { status_code: 201, body: result };\n      } catch {\n        return { status_code: 404, body: { error: \"Snapshots not enabled\" } };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::snapshot-create\",\n    config: { api_path: \"/agentmemory/snapshot/create\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::snapshot-restore\", \n    async (req: ApiRequest<{ commitHash: string }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.commitHash) {\n        return { status_code: 400, body: { error: \"commitHash is required\" } };\n      }\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::snapshot-restore\", payload: req.body });\n        return { status_code: 200, body: result };\n      } catch {\n        return { status_code: 404, body: { error: \"Snapshots not enabled\" } };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::snapshot-restore\",\n    config: { api_path: \"/agentmemory/snapshot/restore\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::memories\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const memories = await kv.list<import(\"../types.js\").Memory>(KV.memories);\n      const latest = req.query_params?.[\"latest\"] === \"true\";\n      // agentId filter. Request param wins, env AGENT_ID (when\n      // scope=isolated) is the fallback. Shared mode keeps the tag but\n      // does not restrict the list endpoint. Pass agentId=* to opt out\n      // of the env scope entirely. includeOrphans=true surfaces\n      // pre-AGENT_ID memories whose agentId is undefined.\n      const normalizedAgentId =\n        typeof req.query_params?.[\"agentId\"] === \"string\"\n          ? req.query_params[\"agentId\"].trim()\n          : undefined;\n      const wildcardAgent = normalizedAgentId === \"*\";\n      const explicitAgentId =\n        normalizedAgentId && !wildcardAgent ? normalizedAgentId : undefined;\n      const includeOrphans =\n        req.query_params?.[\"includeOrphans\"] === \"true\";\n      const filterAgentId = wildcardAgent\n        ? undefined\n        : explicitAgentId ?? (isAgentScopeIsolated() ? getAgentId() : undefined);\n      let filtered = latest ? memories.filter((m) => m.isLatest) : memories;\n      if (filterAgentId) {\n        filtered = filtered.filter(\n          (m) =>\n            m.agentId === filterAgentId ||\n            (includeOrphans && m.agentId === undefined),\n        );\n      }\n\n      // viewer + `agentmemory status` were hitting this endpoint to\n      // count memories. On a real corpus (8K+ memories) the unbounded\n      // response either timed out at the iii engine boundary (\"Invocation\n      // stopped\") or arrived too large for the viewer to render — so the\n      // UI showed 0 memories despite a healthy store. Two opt-in modes:\n      //   ?count=true       — totals only, no payload\n      //   ?limit=N&offset=M — page slice (default unlimited for back-compat)\n      if (req.query_params?.[\"count\"] === \"true\") {\n        // Match the SAME scope that the list path applies — returning\n        // unfiltered totals here would leak cross-agent counts to a\n        // caller that's blocked from the underlying rows.\n        return {\n          status_code: 200,\n          body: {\n            total: filtered.length,\n            latestCount: filtered.filter((m) => m.isLatest).length,\n          },\n        };\n      }\n\n      const rawLimit = req.query_params?.[\"limit\"];\n      const rawOffset = req.query_params?.[\"offset\"];\n      const parsedLimit =\n        typeof rawLimit === \"string\" ? Number(rawLimit) : Number.NaN;\n      const parsedOffset =\n        typeof rawOffset === \"string\" ? Number(rawOffset) : Number.NaN;\n      const limit =\n        Number.isInteger(parsedLimit) && parsedLimit > 0\n          ? Math.min(parsedLimit, 5000)\n          : undefined;\n      const offset =\n        Number.isInteger(parsedOffset) && parsedOffset >= 0 ? parsedOffset : 0;\n      const sliced =\n        limit !== undefined ? filtered.slice(offset, offset + limit) : filtered;\n\n      return {\n        status_code: 200,\n        body: {\n          memories: sliced,\n          total: filtered.length,\n          offset,\n          limit: limit ?? null,\n        },\n      };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::memories\",\n    config: { api_path: \"/agentmemory/memories\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::memory-by-id\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const id = req.path_params?.[\"id\"];\n      if (!id || typeof id !== \"string\") {\n        return { status_code: 400, body: { error: \"id path parameter is required\" } };\n      }\n      const memory = await kv.get<import(\"../types.js\").Memory>(KV.memories, id);\n      if (!memory) {\n        return { status_code: 404, body: { error: `memory not found: ${id}` } };\n      }\n      return { status_code: 200, body: { memory } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::memory-by-id\",\n    config: { api_path: \"/agentmemory/memories/:id\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::semantic-list\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const semantic = await kv.list<import(\"../types.js\").SemanticMemory>(KV.semantic);\n      return { status_code: 200, body: { semantic } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::semantic-list\",\n    config: { api_path: \"/agentmemory/semantic\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::procedural-list\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const procedural = await kv.list<import(\"../types.js\").ProceduralMemory>(KV.procedural);\n      return { status_code: 200, body: { procedural } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::procedural-list\",\n    config: { api_path: \"/agentmemory/procedural\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::relations-list\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const relations = await kv.list<import(\"../types.js\").MemoryRelation>(KV.relations);\n      return { status_code: 200, body: { relations } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::relations-list\",\n    config: { api_path: \"/agentmemory/relations\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::vision-search\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const body = (req.body ?? {}) as Record<string, unknown>;\n      const queryText = asNonEmptyString(body[\"queryText\"]);\n      const queryImageRef = asNonEmptyString(body[\"queryImageRef\"]);\n      const queryImageBase64 = asNonEmptyString(body[\"queryImageBase64\"]);\n      const sessionId = asNonEmptyString(body[\"sessionId\"]);\n      if (!queryText && !queryImageRef && !queryImageBase64) {\n        return {\n          status_code: 400,\n          body: { error: \"queryText, queryImageRef, or queryImageBase64 required\" },\n        };\n      }\n      const topKParsed = parseOptionalPositiveInt(body[\"topK\"]);\n      if (topKParsed === null) {\n        return { status_code: 400, body: { error: \"topK must be a positive integer\" } };\n      }\n      const payload: Record<string, unknown> = {};\n      if (queryText) payload[\"queryText\"] = queryText;\n      if (queryImageRef) payload[\"queryImageRef\"] = queryImageRef;\n      if (queryImageBase64) payload[\"queryImageBase64\"] = queryImageBase64;\n      if (sessionId) payload[\"sessionId\"] = sessionId;\n      if (topKParsed !== undefined) payload[\"topK\"] = Math.min(50, topKParsed);\n      const result = await sdk.trigger({ function_id: \"mem::vision-search\", payload });\n      const resp = result as { success?: boolean; error?: string };\n      if (resp?.success === false) {\n        return { status_code: resp.error?.includes(\"disabled\") ? 503 : 400, body: resp };\n      }\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::vision-search\",\n    config: { api_path: \"/agentmemory/vision-search\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::vision-embed\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const body = (req.body ?? {}) as Record<string, unknown>;\n      const imageRef = asNonEmptyString(body[\"imageRef\"]);\n      const sessionId = asNonEmptyString(body[\"sessionId\"]);\n      const observationId = asNonEmptyString(body[\"observationId\"]);\n      if (!imageRef) {\n        return { status_code: 400, body: { error: \"imageRef is required\" } };\n      }\n      const payload: Record<string, unknown> = { imageRef };\n      if (sessionId) payload[\"sessionId\"] = sessionId;\n      if (observationId) payload[\"observationId\"] = observationId;\n      const result = await sdk.trigger({ function_id: \"mem::vision-embed\", payload });\n      const resp = result as { success?: boolean; error?: string };\n      if (resp?.success === false) {\n        return { status_code: resp.error?.includes(\"disabled\") ? 503 : 400, body: resp };\n      }\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::vision-embed\",\n    config: { api_path: \"/agentmemory/vision-embed\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::slot-list\", async (req: ApiRequest): Promise<Response> => {\n    const authErr = checkAuth(req, secret);\n    if (authErr) return authErr;\n    if (!isSlotsEnabled()) return slotsDisabledResponse();\n    const result = await sdk.trigger({ function_id: \"mem::slot-list\", payload: {} });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::slot-list\",\n    config: { api_path: \"/agentmemory/slots\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::slot-get\", async (req: ApiRequest): Promise<Response> => {\n    const authErr = checkAuth(req, secret);\n    if (authErr) return authErr;\n    if (!isSlotsEnabled()) return slotsDisabledResponse();\n    const label = asNonEmptyString(req.query_params?.[\"label\"]);\n    if (!label) return { status_code: 400, body: { error: \"label query param required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::slot-get\", payload: { label } });\n    const resp = result as { success?: boolean; error?: string };\n    if (resp?.success === false) {\n      return { status_code: resp.error?.includes(\"not found\") ? 404 : 400, body: resp };\n    }\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::slot-get\",\n    config: { api_path: \"/agentmemory/slot\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::slot-create\", async (req: ApiRequest): Promise<Response> => {\n    const authErr = checkAuth(req, secret);\n    if (authErr) return authErr;\n    if (!isSlotsEnabled()) return slotsDisabledResponse();\n    const body = (req.body ?? {}) as Record<string, unknown>;\n    const label = asNonEmptyString(body[\"label\"]);\n    if (!label) return { status_code: 400, body: { error: \"label required\" } };\n    // Reject malformed inputs instead of silently dropping them.\n    if (body[\"content\"] !== undefined && typeof body[\"content\"] !== \"string\") {\n      return { status_code: 400, body: { error: \"content must be a string\" } };\n    }\n    if (body[\"description\"] !== undefined && typeof body[\"description\"] !== \"string\") {\n      return { status_code: 400, body: { error: \"description must be a string\" } };\n    }\n    if (body[\"pinned\"] !== undefined && typeof body[\"pinned\"] !== \"boolean\") {\n      return { status_code: 400, body: { error: \"pinned must be a boolean\" } };\n    }\n    if (\n      body[\"scope\"] !== undefined &&\n      body[\"scope\"] !== \"project\" &&\n      body[\"scope\"] !== \"global\"\n    ) {\n      return { status_code: 400, body: { error: \"scope must be 'project' or 'global'\" } };\n    }\n    const sizeLimit = parseOptionalPositiveInt(body[\"sizeLimit\"]);\n    if (sizeLimit === null) {\n      return { status_code: 400, body: { error: \"sizeLimit must be a positive integer\" } };\n    }\n    if (sizeLimit !== undefined && sizeLimit > 20000) {\n      return { status_code: 400, body: { error: \"sizeLimit must be <= 20000\" } };\n    }\n    const payload: Record<string, unknown> = { label };\n    if (typeof body[\"content\"] === \"string\") payload[\"content\"] = body[\"content\"];\n    if (typeof body[\"description\"] === \"string\") payload[\"description\"] = body[\"description\"];\n    if (sizeLimit !== undefined) payload[\"sizeLimit\"] = sizeLimit;\n    if (typeof body[\"pinned\"] === \"boolean\") payload[\"pinned\"] = body[\"pinned\"];\n    if (body[\"scope\"] === \"project\" || body[\"scope\"] === \"global\") payload[\"scope\"] = body[\"scope\"];\n    const result = await sdk.trigger({ function_id: \"mem::slot-create\", payload });\n    const resp = result as { success?: boolean; error?: string };\n    if (resp?.success === false) {\n      return { status_code: resp.error?.includes(\"exists\") ? 409 : 400, body: resp };\n    }\n    return { status_code: 201, body: result };\n  });\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::slot-create\",\n    config: { api_path: \"/agentmemory/slot\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::slot-append\", async (req: ApiRequest): Promise<Response> => {\n    const authErr = checkAuth(req, secret);\n    if (authErr) return authErr;\n    if (!isSlotsEnabled()) return slotsDisabledResponse();\n    const body = (req.body ?? {}) as Record<string, unknown>;\n    const label = asNonEmptyString(body[\"label\"]);\n    const text = typeof body[\"text\"] === \"string\" ? body[\"text\"] : null;\n    if (!label || !text) return { status_code: 400, body: { error: \"label and text required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::slot-append\", payload: { label, text } });\n    const resp = result as { success?: boolean; error?: string };\n    if (resp?.success === false) {\n      const notFound = resp.error?.includes(\"not found\");\n      const overLimit = resp.error?.includes(\"exceed\");\n      return { status_code: notFound ? 404 : overLimit ? 413 : 400, body: resp };\n    }\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::slot-append\",\n    config: { api_path: \"/agentmemory/slot/append\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::slot-replace\", async (req: ApiRequest): Promise<Response> => {\n    const authErr = checkAuth(req, secret);\n    if (authErr) return authErr;\n    if (!isSlotsEnabled()) return slotsDisabledResponse();\n    const body = (req.body ?? {}) as Record<string, unknown>;\n    const label = asNonEmptyString(body[\"label\"]);\n    const content = body[\"content\"];\n    if (!label || typeof content !== \"string\") {\n      return { status_code: 400, body: { error: \"label and content (string) required\" } };\n    }\n    const result = await sdk.trigger({ function_id: \"mem::slot-replace\", payload: { label, content } });\n    const resp = result as { success?: boolean; error?: string };\n    if (resp?.success === false) {\n      const notFound = resp.error?.includes(\"not found\");\n      const overLimit = resp.error?.includes(\"exceed\");\n      return { status_code: notFound ? 404 : overLimit ? 413 : 400, body: resp };\n    }\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::slot-replace\",\n    config: { api_path: \"/agentmemory/slot/replace\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::slot-delete\", async (req: ApiRequest): Promise<Response> => {\n    const authErr = checkAuth(req, secret);\n    if (authErr) return authErr;\n    if (!isSlotsEnabled()) return slotsDisabledResponse();\n    const label = asNonEmptyString(req.query_params?.[\"label\"]);\n    if (!label) return { status_code: 400, body: { error: \"label query param required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::slot-delete\", payload: { label } });\n    const resp = result as { success?: boolean; error?: string };\n    if (resp?.success === false) {\n      return { status_code: resp.error?.includes(\"not found\") ? 404 : 400, body: resp };\n    }\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::slot-delete\",\n    config: { api_path: \"/agentmemory/slot\", http_method: \"DELETE\" },\n  });\n\n  sdk.registerFunction(\"api::slot-reflect\", async (req: ApiRequest): Promise<Response> => {\n    const authErr = checkAuth(req, secret);\n    if (authErr) return authErr;\n    if (!isSlotsEnabled()) return slotsDisabledResponse();\n    if (!isReflectEnabled()) return reflectDisabledResponse();\n    const body = (req.body ?? {}) as Record<string, unknown>;\n    const sessionId = asNonEmptyString(body[\"sessionId\"]);\n    if (!sessionId) return { status_code: 400, body: { error: \"sessionId required\" } };\n    const maxObservations = parseOptionalPositiveInt(body[\"maxObservations\"]);\n    if (maxObservations === null) return { status_code: 400, body: { error: \"maxObservations must be a positive integer\" } };\n    const payload: Record<string, unknown> = { sessionId };\n    if (maxObservations !== undefined) payload[\"maxObservations\"] = maxObservations;\n    const result = await sdk.trigger({ function_id: \"mem::slot-reflect\", payload });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::slot-reflect\",\n    config: { api_path: \"/agentmemory/slot/reflect\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::action-create\",\n    async (\n      req: ApiRequest<{\n        title: string;\n        description?: string;\n        priority?: number;\n        createdBy?: string;\n        project?: string;\n        tags?: string[];\n        parentId?: string;\n        edges?: Array<{ type: string; targetActionId: string }>;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.title) {\n        return { status_code: 400, body: { error: \"title is required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::action-create\", payload: req.body });\n      return { status_code: 201, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::action-create\",\n    config: { api_path: \"/agentmemory/actions\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::action-update\", \n    async (\n      req: ApiRequest<{\n        actionId: string;\n        status?: string;\n        title?: string;\n        description?: string;\n        priority?: number;\n        result?: string;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.actionId) {\n        return { status_code: 400, body: { error: \"actionId is required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::action-update\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::action-update\",\n    config: { api_path: \"/agentmemory/actions/update\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::action-list\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::action-list\", payload: {\n        status: req.query_params?.[\"status\"],\n        project: req.query_params?.[\"project\"],\n        parentId: req.query_params?.[\"parentId\"],\n      } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::action-list\",\n    config: { api_path: \"/agentmemory/actions\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::action-get\", \n    async (req: ApiRequest<{ actionId: string }>): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const actionId = req.query_params?.[\"actionId\"] as string;\n      if (!actionId) {\n        return { status_code: 400, body: { error: \"actionId required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::action-get\", payload: { actionId } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::action-get\",\n    config: { api_path: \"/agentmemory/actions/get\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::action-edge\", \n    async (\n      req: ApiRequest<{\n        sourceActionId: string;\n        targetActionId: string;\n        type: string;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.sourceActionId || !req.body?.targetActionId || !req.body?.type) {\n        return { status_code: 400, body: { error: \"sourceActionId, targetActionId, and type are required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::action-edge-create\", payload: req.body });\n      return { status_code: 201, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::action-edge\",\n    config: { api_path: \"/agentmemory/actions/edges\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::frontier\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const parsedLimit = parseOptionalInt(req.query_params?.[\"limit\"]);\n      const result = await sdk.trigger({ function_id: \"mem::frontier\", payload: {\n        project: req.query_params?.[\"project\"],\n        agentId: req.query_params?.[\"agentId\"],\n        limit: parsedLimit,\n      } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::frontier\",\n    config: { api_path: \"/agentmemory/frontier\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::next\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::next\", payload: {\n        project: req.query_params?.[\"project\"],\n        agentId: req.query_params?.[\"agentId\"],\n      } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::next\",\n    config: { api_path: \"/agentmemory/next\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::lease-acquire\", \n    async (\n      req: ApiRequest<{ actionId: string; agentId: string; ttlMs?: number }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.actionId || !req.body?.agentId) {\n        return { status_code: 400, body: { error: \"actionId and agentId are required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::lease-acquire\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::lease-acquire\",\n    config: { api_path: \"/agentmemory/leases/acquire\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::lease-release\", \n    async (\n      req: ApiRequest<{ actionId: string; agentId: string; result?: string }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.actionId || !req.body?.agentId) {\n        return { status_code: 400, body: { error: \"actionId and agentId are required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::lease-release\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::lease-release\",\n    config: { api_path: \"/agentmemory/leases/release\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::lease-renew\", \n    async (\n      req: ApiRequest<{ actionId: string; agentId: string; ttlMs?: number }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.actionId || !req.body?.agentId) {\n        return { status_code: 400, body: { error: \"actionId and agentId are required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::lease-renew\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::lease-renew\",\n    config: { api_path: \"/agentmemory/leases/renew\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::routine-create\",\n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.name || !req.body?.steps) {\n        return {\n          status_code: 400,\n          body: { error: \"name and steps are required\" },\n        };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::routine-create\", payload: req.body });\n      return { status_code: 201, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::routine-create\",\n    config: { api_path: \"/agentmemory/routines\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::routine-list\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::routine-list\", payload: {\n        frozen: req.query_params?.[\"frozen\"] === \"true\" ? true : undefined,\n      } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::routine-list\",\n    config: { api_path: \"/agentmemory/routines\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::routine-run\", \n    async (\n      req: ApiRequest<{ routineId: string; project?: string; initiatedBy?: string }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.routineId) {\n        return { status_code: 400, body: { error: \"routineId is required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::routine-run\", payload: req.body });\n      return { status_code: 201, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::routine-run\",\n    config: { api_path: \"/agentmemory/routines/run\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::routine-status\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const runId = req.query_params?.[\"runId\"] as string;\n      if (!runId) {\n        return { status_code: 400, body: { error: \"runId query param required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::routine-status\", payload: { runId } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::routine-status\",\n    config: { api_path: \"/agentmemory/routines/status\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::signal-send\", \n    async (\n      req: ApiRequest<{\n        from: string;\n        to?: string;\n        content: string;\n        type?: string;\n        replyTo?: string;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.from || !req.body?.content) {\n        return { status_code: 400, body: { error: \"from and content are required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::signal-send\", payload: req.body });\n      return { status_code: 201, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::signal-send\",\n    config: { api_path: \"/agentmemory/signals/send\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::signal-read\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const agentId = req.query_params?.[\"agentId\"] as string;\n      if (!agentId) {\n        return { status_code: 400, body: { error: \"agentId query param required\" } };\n      }\n      const parsedLimit = parseOptionalInt(req.query_params?.[\"limit\"]);\n      const result = await sdk.trigger({ function_id: \"mem::signal-read\", payload: {\n        agentId,\n        unreadOnly: req.query_params?.[\"unreadOnly\"] === \"true\",\n        threadId: req.query_params?.[\"threadId\"],\n        limit: parsedLimit,\n      } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::signal-read\",\n    config: { api_path: \"/agentmemory/signals\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::checkpoint-create\", \n    async (\n      req: ApiRequest<{\n        name: string;\n        description?: string;\n        type?: string;\n        linkedActionIds?: string[];\n        expiresInMs?: number;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.name) {\n        return { status_code: 400, body: { error: \"name is required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::checkpoint-create\", payload: req.body });\n      return { status_code: 201, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::checkpoint-create\",\n    config: { api_path: \"/agentmemory/checkpoints\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::checkpoint-resolve\", \n    async (\n      req: ApiRequest<{\n        checkpointId: string;\n        status: string;\n        resolvedBy?: string;\n        result?: unknown;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.checkpointId || !req.body?.status) {\n        return { status_code: 400, body: { error: \"checkpointId and status are required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::checkpoint-resolve\", payload: req.body });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::checkpoint-resolve\",\n    config: { api_path: \"/agentmemory/checkpoints/resolve\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::checkpoint-list\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::checkpoint-list\", payload: {\n        status: req.query_params?.[\"status\"],\n        type: req.query_params?.[\"type\"],\n      } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::checkpoint-list\",\n    config: { api_path: \"/agentmemory/checkpoints\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::mesh-register\", \n    async (\n      req: ApiRequest<{ url: string; name: string; sharedScopes?: string[] }>,\n    ): Promise<Response> => {\n      const secretErr = requireConfiguredSecret(secret, \"mesh\");\n      if (secretErr) return secretErr;\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      if (!req.body?.url || !req.body?.name) {\n        return { status_code: 400, body: { error: \"url and name are required\" } };\n      }\n      const result = await sdk.trigger({ function_id: \"mem::mesh-register\", payload: req.body });\n      return { status_code: 201, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::mesh-register\",\n    config: { api_path: \"/agentmemory/mesh/peers\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::mesh-list\", \n    async (req: ApiRequest): Promise<Response> => {\n      const secretErr = requireConfiguredSecret(secret, \"mesh\");\n      if (secretErr) return secretErr;\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::mesh-list\", payload: {} });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::mesh-list\",\n    config: { api_path: \"/agentmemory/mesh/peers\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::mesh-sync\", \n    async (\n      req: ApiRequest<{ peerId?: string; direction?: string }>,\n    ): Promise<Response> => {\n      const secretErr = requireConfiguredSecret(secret, \"mesh\");\n      if (secretErr) return secretErr;\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::mesh-sync\", payload: req.body || {} });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::mesh-sync\",\n    config: { api_path: \"/agentmemory/mesh/sync\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::mesh-receive\", \n    async (req: ApiRequest): Promise<Response> => {\n      const secretErr = requireConfiguredSecret(secret, \"mesh\");\n      if (secretErr) return secretErr;\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const result = await sdk.trigger({ function_id: \"mem::mesh-receive\", payload: req.body || {} });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::mesh-receive\",\n    config: { api_path: \"/agentmemory/mesh/receive\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::mesh-export\", \n    async (req: ApiRequest): Promise<Response> => {\n      const secretErr = requireConfiguredSecret(secret, \"mesh\");\n      if (secretErr) return secretErr;\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const since = req.query_params?.[\"since\"] as string;\n      if (since) {\n        const parsed = new Date(since).getTime();\n        if (Number.isNaN(parsed)) {\n          return { status_code: 400, body: { error: \"Invalid 'since' date format\" } };\n        }\n      }\n      const project = req.query_params?.[\"project\"] as string | undefined;\n      const sinceTime = since ? new Date(since).getTime() : 0;\n      const df = <T>(items: T[], field: \"updatedAt\" | \"createdAt\") =>\n        items.filter((i) => new Date((i as Record<string, unknown>)[field] as string).getTime() > sinceTime);\n      const memories = await kv.list<import(\"../types.js\").Memory>(KV.memories);\n      let actions = await kv.list<import(\"../types.js\").Action>(KV.actions);\n      if (project) {\n        actions = actions.filter((a) => a.project === project);\n      }\n      const body: Record<string, unknown> = {\n        memories: df(memories, \"updatedAt\"),\n        actions: df(actions, \"updatedAt\"),\n      };\n      if (!project) {\n        const semantic = await kv.list<import(\"../types.js\").SemanticMemory>(KV.semantic);\n        const procedural = await kv.list<import(\"../types.js\").ProceduralMemory>(KV.procedural);\n        const relations = await kv.list<import(\"../types.js\").MemoryRelation>(KV.relations);\n        const graphNodes = await kv.list<import(\"../types.js\").GraphNode>(KV.graphNodes);\n        const graphEdges = await kv.list<import(\"../types.js\").GraphEdge>(KV.graphEdges);\n        body.semantic = df(semantic, \"updatedAt\");\n        body.procedural = df(procedural, \"updatedAt\");\n        body.relations = df(relations, \"createdAt\");\n        body.graphNodes = graphNodes.filter(\n          (n) => new Date(n.updatedAt || n.createdAt).getTime() > sinceTime,\n        );\n        body.graphEdges = df(graphEdges, \"createdAt\");\n      }\n      return { status_code: 200, body };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::mesh-export\",\n    config: { api_path: \"/agentmemory/mesh/export\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::flow-compress\", \n    async (\n      req: ApiRequest<{\n        runId?: string;\n        actionIds?: string[];\n        project?: string;\n      }>,\n    ): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      try {\n        const result = await sdk.trigger({ function_id: \"mem::flow-compress\", payload: req.body || {} });\n        return { status_code: 200, body: result };\n      } catch {\n        return {\n          status_code: 404,\n          body: { error: \"Flow compression requires a provider\" },\n        };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::flow-compress\",\n    config: { api_path: \"/agentmemory/flow/compress\", http_method: \"POST\" },\n  });\n\n  sdk.registerFunction(\"api::branch-detect\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const cwd = (req.query_params?.[\"cwd\"] as string) || process.cwd();\n      const result = await sdk.trigger({ function_id: \"mem::detect-worktree\", payload: { cwd } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::branch-detect\",\n    config: { api_path: \"/agentmemory/branch/detect\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::branch-worktrees\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const cwd = (req.query_params?.[\"cwd\"] as string) || process.cwd();\n      const result = await sdk.trigger({ function_id: \"mem::list-worktrees\", payload: { cwd } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::branch-worktrees\",\n    config: { api_path: \"/agentmemory/branch/worktrees\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::branch-sessions\", \n    async (req: ApiRequest): Promise<Response> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      const cwd = (req.query_params?.[\"cwd\"] as string) || process.cwd();\n      const result = await sdk.trigger({ function_id: \"mem::branch-sessions\", payload: { cwd } });\n      return { status_code: 200, body: result };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::branch-sessions\",\n    config: { api_path: \"/agentmemory/branch/sessions\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::viewer\", \n    async (req: ApiRequest): Promise<Response> => {\n      const denied = checkAuth(req, secret);\n      if (denied) return denied;\n      const rendered = renderViewerDocument();\n      if (rendered.found) {\n        return {\n          status_code: 200,\n          headers: {\n            \"Content-Type\": \"text/html\",\n            \"Content-Security-Policy\": rendered.csp,\n          },\n          body: rendered.html,\n        };\n      }\n      return {\n        status_code: 404,\n        headers: {\n          \"Content-Type\": \"text/html\",\n        },\n        body: \"<!DOCTYPE html><html><body><h1>agentmemory</h1><p>viewer not found</p></body></html>\",\n      };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"api::viewer\",\n    config: { api_path: \"/agentmemory/viewer\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"api::sentinel-create\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.name) return { status_code: 400, body: { error: \"name is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::sentinel-create\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sentinel-create\", config: { api_path: \"/agentmemory/sentinels\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::sentinel-trigger\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.sentinelId) return { status_code: 400, body: { error: \"sentinelId is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::sentinel-trigger\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sentinel-trigger\", config: { api_path: \"/agentmemory/sentinels/trigger\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::sentinel-check\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const result = await sdk.trigger({ function_id: \"mem::sentinel-check\", payload: {} });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sentinel-check\", config: { api_path: \"/agentmemory/sentinels/check\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::sentinel-cancel\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.sentinelId) return { status_code: 400, body: { error: \"sentinelId is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::sentinel-cancel\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sentinel-cancel\", config: { api_path: \"/agentmemory/sentinels/cancel\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::sentinel-list\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const params = req.query_params || {};\n    const result = await sdk.trigger({ function_id: \"mem::sentinel-list\", payload: { status: params.status, type: params.type } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sentinel-list\", config: { api_path: \"/agentmemory/sentinels\", http_method: \"GET\" } });\n\n  sdk.registerFunction(\"api::sketch-create\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.title) return { status_code: 400, body: { error: \"title is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::sketch-create\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sketch-create\", config: { api_path: \"/agentmemory/sketches\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::sketch-add\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.sketchId || !body?.title) return { status_code: 400, body: { error: \"sketchId and title are required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::sketch-add\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sketch-add\", config: { api_path: \"/agentmemory/sketches/add\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::sketch-promote\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.sketchId) return { status_code: 400, body: { error: \"sketchId is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::sketch-promote\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sketch-promote\", config: { api_path: \"/agentmemory/sketches/promote\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::sketch-discard\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.sketchId) return { status_code: 400, body: { error: \"sketchId is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::sketch-discard\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sketch-discard\", config: { api_path: \"/agentmemory/sketches/discard\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::sketch-list\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const params = req.query_params || {};\n    const result = await sdk.trigger({ function_id: \"mem::sketch-list\", payload: { status: params.status, project: params.project } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sketch-list\", config: { api_path: \"/agentmemory/sketches\", http_method: \"GET\" } });\n\n  sdk.registerFunction(\"api::sketch-gc\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const result = await sdk.trigger({ function_id: \"mem::sketch-gc\", payload: {} });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::sketch-gc\", config: { api_path: \"/agentmemory/sketches/gc\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::crystallize\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.actionIds) return { status_code: 400, body: { error: \"actionIds is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::crystallize\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::crystallize\", config: { api_path: \"/agentmemory/crystals/create\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::crystal-list\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const params = req.query_params || {};\n    const limit = parseOptionalPositiveInt(params.limit);\n    if (limit === null) {\n      return {\n        status_code: 400,\n        body: { error: \"invalid numeric parameter: limit\" },\n      };\n    }\n    const result = await sdk.trigger({ function_id: \"mem::crystal-list\", payload: { project: params.project, sessionId: params.sessionId, limit } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::crystal-list\", config: { api_path: \"/agentmemory/crystals\", http_method: \"GET\" } });\n\n  sdk.registerFunction(\"api::auto-crystallize\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    const result = await sdk.trigger({ function_id: \"mem::auto-crystallize\", payload: body || {} });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::auto-crystallize\", config: { api_path: \"/agentmemory/crystals/auto\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::diagnose\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    const result = await sdk.trigger({ function_id: \"mem::diagnose\", payload: body || {} });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::diagnose\", config: { api_path: \"/agentmemory/diagnostics\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::heal\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    const result = await sdk.trigger({ function_id: \"mem::heal\", payload: body || {} });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::heal\", config: { api_path: \"/agentmemory/diagnostics/heal\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::facet-tag\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.targetId || !body?.dimension || !body?.value) return { status_code: 400, body: { error: \"targetId, dimension, and value are required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::facet-tag\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::facet-tag\", config: { api_path: \"/agentmemory/facets\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::facet-untag\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.targetId || !body?.dimension) return { status_code: 400, body: { error: \"targetId and dimension are required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::facet-untag\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::facet-untag\", config: { api_path: \"/agentmemory/facets/remove\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::facet-query\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    const result = await sdk.trigger({ function_id: \"mem::facet-query\", payload: body || {} });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::facet-query\", config: { api_path: \"/agentmemory/facets/query\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::facet-get\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const params = req.query_params || {};\n    if (!params.targetId) return { status_code: 400, body: { error: \"targetId query param is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::facet-get\", payload: { targetId: params.targetId } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::facet-get\", config: { api_path: \"/agentmemory/facets\", http_method: \"GET\" } });\n\n  sdk.registerFunction(\"api::facet-stats\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const params = req.query_params || {};\n    const result = await sdk.trigger({ function_id: \"mem::facet-stats\", payload: { targetType: params.targetType } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::facet-stats\", config: { api_path: \"/agentmemory/facets/stats\", http_method: \"GET\" } });\n\n  sdk.registerFunction(\"api::verify\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.id || typeof body.id !== \"string\") return { status_code: 400, body: { error: \"id is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::verify\", payload: { id: body.id } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::verify\", config: { api_path: \"/agentmemory/verify\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::cascade-update\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.supersededMemoryId || typeof body.supersededMemoryId !== \"string\") {\n      return { status_code: 400, body: { error: \"supersededMemoryId is required\" } };\n    }\n    const result = await sdk.trigger({ function_id: \"mem::cascade-update\", payload: { supersededMemoryId: body.supersededMemoryId } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::cascade-update\", config: { api_path: \"/agentmemory/cascade-update\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::lesson-save\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.content || typeof body.content !== \"string\") return { status_code: 400, body: { error: \"content is required\" } };\n    const tags = typeof body.tags === \"string\" ? (body.tags as string).split(\",\").map((t: string) => t.trim()).filter(Boolean) : Array.isArray(body.tags) ? body.tags : [];\n    const result = (await sdk.trigger({\n      function_id: \"mem::lesson-save\",\n      payload: {\n        content: body.content,\n        context: body.context || \"\",\n        confidence: typeof body.confidence === \"number\" ? body.confidence : undefined,\n        project: typeof body.project === \"string\" ? body.project : undefined,\n        tags,\n        source: \"manual\",\n      },\n    })) as { action?: string };\n    const statusCode = result?.action === \"created\" ? 201 : 200;\n    return { status_code: statusCode, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::lesson-save\", config: { api_path: \"/agentmemory/lessons\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::lesson-list\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const params = req.query_params || {};\n    const minConfidence = parseOptionalFiniteNumber(params.minConfidence);\n    if (minConfidence === null) {\n      return {\n        status_code: 400,\n        body: { error: \"invalid numeric parameter: minConfidence\" },\n      };\n    }\n    const limit = parseOptionalPositiveInt(params.limit);\n    if (limit === null) {\n      return {\n        status_code: 400,\n        body: { error: \"invalid numeric parameter: limit\" },\n      };\n    }\n    const result = await sdk.trigger({ function_id: \"mem::lesson-list\", payload: {\n      project: params.project,\n      source: params.source,\n      minConfidence,\n      limit,\n    } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::lesson-list\", config: { api_path: \"/agentmemory/lessons\", http_method: \"GET\" } });\n\n  sdk.registerFunction(\"api::lesson-search\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.query || typeof body.query !== \"string\") return { status_code: 400, body: { error: \"query is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::lesson-recall\", payload: body });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::lesson-search\", config: { api_path: \"/agentmemory/lessons/search\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::lesson-strengthen\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.lessonId || typeof body.lessonId !== \"string\") return { status_code: 400, body: { error: \"lessonId is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::lesson-strengthen\", payload: { lessonId: body.lessonId } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::lesson-strengthen\", config: { api_path: \"/agentmemory/lessons/strengthen\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::obsidian-export\", async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = (req.body as Record<string, unknown>) || {};\n    const vaultDir = asNonEmptyString(body.vaultDir);\n    if (!vaultDir) {\n      return {\n        status_code: 400,\n        body: { error: \"vaultDir must be a non-empty string\" },\n      };\n    }\n    const types = typeof body.types === \"string\" ? body.types.split(\",\").map((t: string) => t.trim()).filter(Boolean) : undefined;\n    const result = await sdk.trigger({ function_id: \"mem::obsidian-export\", payload: { vaultDir, types } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::obsidian-export\", config: { api_path: \"/agentmemory/obsidian/export\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::reflect\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = (req.body as Record<string, unknown>) || {};\n    const result = await sdk.trigger({ function_id: \"mem::reflect\", payload: {\n      project: typeof body.project === \"string\" ? body.project : undefined,\n      maxClusters: typeof body.maxClusters === \"number\" ? body.maxClusters : undefined,\n    } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::reflect\", config: { api_path: \"/agentmemory/reflect\", http_method: \"POST\" } });\n\n  sdk.registerFunction(\"api::insight-list\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const params = req.query_params || {};\n    const minConfidence = parseOptionalFiniteNumber(params.minConfidence);\n    if (minConfidence === null) {\n      return {\n        status_code: 400,\n        body: { error: \"invalid numeric parameter: minConfidence\" },\n      };\n    }\n    const limit = parseOptionalPositiveInt(params.limit);\n    if (limit === null) {\n      return {\n        status_code: 400,\n        body: { error: \"invalid numeric parameter: limit\" },\n      };\n    }\n    const result = await sdk.trigger({ function_id: \"mem::insight-list\", payload: {\n      project: params.project,\n      minConfidence,\n      limit,\n    } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::insight-list\", config: { api_path: \"/agentmemory/insights\", http_method: \"GET\" } });\n\n  sdk.registerFunction(\"api::insight-search\",  async (req: ApiRequest) => {\n    const denied = checkAuth(req, secret);\n    if (denied) return denied;\n    const body = req.body as Record<string, unknown>;\n    if (!body?.query || typeof body.query !== \"string\") return { status_code: 400, body: { error: \"query is required\" } };\n    const result = await sdk.trigger({ function_id: \"mem::insight-search\", payload: {\n      query: body.query,\n      project: typeof body.project === \"string\" ? body.project : undefined,\n      minConfidence: typeof body.minConfidence === \"number\" ? body.minConfidence : undefined,\n      limit: typeof body.limit === \"number\" ? body.limit : undefined,\n    } });\n    return { status_code: 200, body: result };\n  });\n  sdk.registerTrigger({ type: \"http\", function_id: \"api::insight-search\", config: { api_path: \"/agentmemory/insights/search\", http_method: \"POST\" } });\n}\n","import { TriggerAction, type ISdk } from \"iii-sdk\";\nimport type { CompressedObservation, HookPayload, Session } from \"../types.js\";\nimport { KV, STREAM } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { isReflectEnabled } from \"../functions/slots.js\";\nimport { isGraphExtractionEnabled } from \"../config.js\";\nimport { logger } from \"../logger.js\";\n\nexport function registerEventTriggers(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\n    \"event::session::started\",\n    async (data: { sessionId: string; project: string; cwd: string }) => {\n      const session: Session = {\n        id: data.sessionId,\n        project: data.project,\n        cwd: data.cwd,\n        startedAt: new Date().toISOString(),\n        status: \"active\",\n        observationCount: 0,\n      };\n      await kv.set(KV.sessions, data.sessionId, session);\n      const contextResult = await sdk.trigger<\n        { sessionId: string; project: string },\n        { context: string }\n      >({\n        function_id: \"mem::context\",\n        payload: { sessionId: data.sessionId, project: data.project },\n      });\n      return { session, context: contextResult.context };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"durable:subscriber\",\n    function_id: \"event::session::started\",\n    config: { topic: \"agentmemory.session.started\" },\n  });\n\n  sdk.registerFunction(\"event::observation\", async (data: HookPayload) =>\n    sdk.trigger({ function_id: \"mem::observe\", payload: data }),\n  );\n  sdk.registerTrigger({\n    type: \"durable:subscriber\",\n    function_id: \"event::observation\",\n    config: { topic: \"agentmemory.observation\" },\n  });\n\n  sdk.registerFunction(\"event::session::stopped\", async (data: { sessionId: string }) => {\n    const summary = await sdk.trigger({ function_id: \"mem::summarize\", payload: data });\n    if (isReflectEnabled()) {\n      try {\n        sdk.trigger({\n          function_id: \"mem::slot-reflect\",\n          payload: { sessionId: data.sessionId },\n          action: TriggerAction.Void(),\n        });\n      } catch (err) {\n        logger.warn(\"slot-reflect trigger failed\", {\n          sessionId: data.sessionId,\n          error: err instanceof Error ? err.message : String(err),\n        });\n      }\n    }\n    if (isGraphExtractionEnabled()) {\n      try {\n        const observations = await kv.list<CompressedObservation>(\n          KV.observations(data.sessionId),\n        );\n        const compressed = observations.filter((o) => o.title);\n        if (compressed.length > 0) {\n          sdk.trigger({\n            function_id: \"mem::graph-extract\",\n            payload: { observations: compressed },\n            action: TriggerAction.Void(),\n          });\n        }\n      } catch (err) {\n        logger.warn(\"graph-extract trigger failed\", {\n          sessionId: data.sessionId,\n          error: err instanceof Error ? err.message : String(err),\n        });\n      }\n    }\n    return summary;\n  });\n  sdk.registerTrigger({\n    type: \"durable:subscriber\",\n    function_id: \"event::session::stopped\",\n    config: { topic: \"agentmemory.session.stopped\" },\n  });\n\n  sdk.registerFunction(\n    \"event::session::ended\",\n    async (data: { sessionId: string }) => {\n      await kv.update(KV.sessions, data.sessionId, [\n        { type: \"set\", path: \"endedAt\", value: new Date().toISOString() },\n        { type: \"set\", path: \"status\", value: \"completed\" },\n      ]);\n      return { success: true };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"durable:subscriber\",\n    function_id: \"event::session::ended\",\n    config: { topic: \"agentmemory.session.ended\" },\n  });\n\n  // React to observation count changes and emit a lightweight live event for dashboards/viewer.\n  sdk.registerFunction(\n    \"event::session::observation-count-changed\",\n    async (payload: {\n      key: string;\n      event_type: string;\n      old_value?: Session;\n      new_value?: Session;\n    }) => {\n      if (payload.event_type === \"delete\") return { skipped: true };\n      const oldCount = payload.old_value?.observationCount ?? 0;\n      const newCount = payload.new_value?.observationCount ?? 0;\n      if (newCount <= oldCount) return { skipped: true };\n\n      await sdk.trigger({\n        function_id: \"stream::send\",\n        payload: {\n          stream_name: STREAM.name,\n          group_id: STREAM.viewerGroup,\n          id: `session-activity-${payload.key}-${Date.now()}`,\n          type: \"session.activity\",\n          data: {\n            sessionId: payload.key,\n            observationCount: newCount,\n            delta: newCount - oldCount,\n            updatedAt: payload.new_value?.updatedAt ?? new Date().toISOString(),\n          },\n        },\n        action: TriggerAction.Void(),\n      });\n\n      return { emitted: true };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"state\",\n    function_id: \"event::session::observation-count-changed\",\n    config: { scope: KV.sessions },\n  });\n}\n","import type { ISdk, ApiRequest } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport type {\n  SessionSummary,\n  Memory,\n  Session,\n  GraphNode,\n  GraphEdge,\n} from \"../types.js\";\nimport { getVisibleTools } from \"./tools-registry.js\";\nimport { timingSafeCompare } from \"../auth.js\";\nimport { getAgentId, isAgentScopeIsolated } from \"../config.js\";\n\ntype McpResponse = {\n  status_code: number;\n  headers?: Record<string, string>;\n  body: unknown;\n};\n\nfunction asNonEmptyString(value: unknown): string | undefined {\n  return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction asNumber(value: unknown, fallback?: number): number | undefined {\n  const n = Number(value);\n  if (Number.isFinite(n)) return n;\n  return fallback;\n}\n\nfunction parseCsvList(value: unknown): string[] {\n  if (typeof value === \"string\") {\n    return value.split(\",\").map((v) => v.trim()).filter(Boolean);\n  }\n  if (Array.isArray(value)) {\n    return value\n      .map((v) => (typeof v === \"string\" ? v.trim() : \"\"))\n      .filter(Boolean);\n  }\n  return [];\n}\n\nexport function registerMcpEndpoints(\n  sdk: ISdk,\n  kv: StateKV,\n  secret?: string,\n): void {\n  function checkAuth(\n    req: ApiRequest,\n    sec: string | undefined,\n  ): McpResponse | null {\n    if (!sec) return null;\n    const auth =\n      req.headers?.[\"authorization\"] || req.headers?.[\"Authorization\"];\n    if (typeof auth !== \"string\" || !timingSafeCompare(auth, `Bearer ${sec}`)) {\n      return { status_code: 401, body: { error: \"unauthorized\" } };\n    }\n    return null;\n  }\n\n  sdk.registerFunction(\"mcp::tools::list\", \n    async (req: ApiRequest): Promise<McpResponse> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      return { status_code: 200, body: { tools: getVisibleTools() } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"mcp::tools::list\",\n    config: { api_path: \"/agentmemory/mcp/tools\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"mcp::tools::call\", \n    async (\n      req: ApiRequest<{ name: string; arguments: Record<string, unknown> }>,\n    ): Promise<McpResponse> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n\n      if (!req.body || typeof req.body.name !== \"string\") {\n        return { status_code: 400, body: { error: \"name is required\" } };\n      }\n\n      const { name, arguments: args = {} } = req.body;\n\n      try {\n        switch (name) {\n          case \"memory_recall\": {\n            if (typeof args.query !== \"string\" || !args.query.trim()) {\n              return {\n                status_code: 400,\n                body: { error: \"query is required for memory_recall\" },\n              };\n            }\n            const format =\n              typeof args.format === \"string\" ? args.format.trim().toLowerCase() : \"full\";\n            if (![\"full\", \"compact\", \"narrative\"].includes(format)) {\n              return {\n                status_code: 400,\n                body: {\n                  error: \"format must be one of: full, compact, narrative\",\n                },\n              };\n            }\n            const tokenBudget = asNumber(args.token_budget);\n            if (\n              args.token_budget !== undefined &&\n              (!Number.isInteger(tokenBudget) || (tokenBudget ?? 0) < 1)\n            ) {\n              return {\n                status_code: 400,\n                body: { error: \"token_budget must be a positive integer\" },\n              };\n            }\n            // #817: forward agentId so mem::search applies the same\n            // isolation filter smart-search uses. Default behavior is\n            // unchanged (no agentId → falls back to env AGENT_ID when\n            // AGENTMEMORY_AGENT_SCOPE=isolated; \"*\" wildcard bypasses).\n            const recallAgentId =\n              typeof args.agentId === \"string\" && args.agentId.trim().length > 0\n                ? (args.agentId as string).trim()\n                : undefined;\n            const result = await sdk.trigger({ function_id: \"mem::search\", payload: {\n              query: args.query,\n              limit: typeof args.limit === \"number\" ? args.limit : 10,\n              format,\n              token_budget: tokenBudget,\n              agentId: recallAgentId,\n            } });\n            const text =\n              format === \"narrative\" &&\n              result &&\n              typeof result === \"object\" &&\n              \"text\" in (result as Record<string, unknown>) &&\n              typeof (result as { text?: unknown }).text === \"string\"\n                ? (result as { text: string }).text\n                : JSON.stringify(result, null, 2);\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text },\n                ],\n              },\n            };\n          }\n\n          case \"memory_compress_file\": {\n            if (typeof args.filePath !== \"string\" || !args.filePath.trim()) {\n              return {\n                status_code: 400,\n                body: { error: \"filePath is required for memory_compress_file\" },\n              };\n            }\n            const result = await sdk.trigger({\n              function_id: \"mem::compress-file\",\n              payload: { filePath: args.filePath.trim() },\n            });\n            return {\n              status_code: 200,\n              body: {\n                content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n              },\n            };\n          }\n\n          case \"memory_save\": {\n            if (typeof args.content !== \"string\" || !args.content.trim()) {\n              return {\n                status_code: 400,\n                body: { error: \"content is required for memory_save\" },\n              };\n            }\n            const type = (args.type as string) || \"fact\";\n            const concepts =\n              typeof args.concepts === \"string\"\n                ? args.concepts.split(\",\").map((c: string) => c.trim()).filter(Boolean)\n                : [];\n            const files =\n              typeof args.files === \"string\"\n                ? args.files.split(\",\").map((f: string) => f.trim()).filter(Boolean)\n                : [];\n\n            const project =\n              typeof args.project === \"string\" && args.project.trim().length > 0\n                ? args.project.trim()\n                : undefined;\n\n            const result = await sdk.trigger({ function_id: \"mem::remember\", payload: {\n              content: args.content,\n              type,\n              concepts,\n              files,\n              ...(project !== undefined && { project }),\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [{ type: \"text\", text: JSON.stringify(result) }],\n              },\n            };\n          }\n\n          case \"memory_file_history\": {\n            if (typeof args.files !== \"string\" || !args.files.trim()) {\n              return {\n                status_code: 400,\n                body: { error: \"files is required for memory_file_history\" },\n              };\n            }\n            const fileList = parseCsvList(args.files);\n            if (!fileList.length) {\n              return {\n                status_code: 400,\n                body: { error: \"files must contain at least one valid path\" },\n              };\n            }\n            const payload: { sessionId?: string; files: string[] } = { files: fileList };\n            const sessionId = asNonEmptyString(args.sessionId);\n            if (sessionId) payload.sessionId = sessionId;\n            const result = await sdk.trigger({\n              function_id: \"mem::file-context\",\n              payload,\n            });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  {\n                    type: \"text\",\n                    text:\n                      (result as { context: string }).context ||\n                      \"No history found.\",\n                  },\n                ],\n              },\n            };\n          }\n\n          case \"memory_patterns\": {\n            const result = await sdk.trigger({ function_id: \"mem::patterns\", payload: {\n              project: args.project as string,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(result, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_sessions\": {\n            const sessions = await kv.list(KV.sessions);\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify({ sessions }, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_smart_search\": {\n            if (typeof args.query !== \"string\" || !args.query.trim()) {\n              return {\n                status_code: 400,\n                body: { error: \"query is required for memory_smart_search\" },\n              };\n            }\n            const expandIds = parseCsvList(args.expandIds).slice(0, 20);\n            const limit = Math.max(1, Math.min(100, asNumber(args.limit, 10) ?? 10));\n            const result = await sdk.trigger({\n              function_id: \"mem::smart-search\",\n              payload: {\n                query: args.query,\n                expandIds,\n                limit,\n              },\n            });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(result, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_vision_search\": {\n            const queryText = typeof args.queryText === \"string\" ? args.queryText : undefined;\n            const queryImageRef = typeof args.queryImageRef === \"string\" ? args.queryImageRef : undefined;\n            const queryImageBase64 = typeof args.queryImageBase64 === \"string\" ? args.queryImageBase64 : undefined;\n            if (!queryText && !queryImageRef && !queryImageBase64) {\n              return {\n                status_code: 400,\n                body: { error: \"queryText, queryImageRef, or queryImageBase64 required\" },\n              };\n            }\n            const topK = Math.max(1, Math.min(50, asNumber(args.topK, 10) ?? 10));\n            const sessionId = typeof args.sessionId === \"string\" ? args.sessionId : undefined;\n            const result = await sdk.trigger({\n              function_id: \"mem::vision-search\",\n              payload: { queryText, queryImageRef, queryImageBase64, topK, sessionId },\n            });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(result, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_timeline\": {\n            if (typeof args.anchor !== \"string\" || !args.anchor.trim()) {\n              return {\n                status_code: 400,\n                body: { error: \"anchor is required for memory_timeline\" },\n              };\n            }\n            const result = await sdk.trigger({ function_id: \"mem::timeline\", payload: {\n              anchor: args.anchor,\n              project: (args.project as string) || undefined,\n              before: (args.before as number) || 5,\n              after: (args.after as number) || 5,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(result, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_profile\": {\n            if (typeof args.project !== \"string\" || !args.project.trim()) {\n              return {\n                status_code: 400,\n                body: { error: \"project is required for memory_profile\" },\n              };\n            }\n            const result = await sdk.trigger({ function_id: \"mem::profile\", payload: {\n              project: args.project,\n              refresh: args.refresh === true || args.refresh === \"true\",\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(result, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_export\": {\n            const result = await sdk.trigger({ function_id: \"mem::export\", payload: {} });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(result, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_relations\": {\n            if (typeof args.memoryId !== \"string\" || !args.memoryId.trim()) {\n              return {\n                status_code: 400,\n                body: { error: \"memoryId is required for memory_relations\" },\n              };\n            }\n            const rawMaxHops = Number(args.maxHops);\n            const rawMinConf = Number(args.minConfidence);\n            const result = await sdk.trigger({ function_id: \"mem::get-related\", payload: {\n              memoryId: args.memoryId,\n              maxHops: Number.isFinite(rawMaxHops) ? rawMaxHops : 2,\n              minConfidence: Number.isFinite(rawMinConf)\n                ? Math.max(0, Math.min(1, rawMinConf))\n                : 0,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(result, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_claude_bridge_sync\": {\n            const direction = (args.direction as string) || \"write\";\n            const funcId =\n              direction === \"read\"\n                ? \"mem::claude-bridge-read\"\n                : \"mem::claude-bridge-sync\";\n            try {\n              const result = await sdk.trigger({\n                function_id: funcId,\n                payload: {},\n              });\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    { type: \"text\", text: JSON.stringify(result, null, 2) },\n                  ],\n                },\n              };\n            } catch {\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    {\n                      type: \"text\",\n                      text: \"Claude bridge not enabled. Set CLAUDE_MEMORY_BRIDGE=true\",\n                    },\n                  ],\n                },\n              };\n            }\n          }\n\n          case \"memory_graph_query\": {\n            try {\n              const payload: {\n                startNodeId?: string;\n                nodeType?: string;\n                maxDepth?: number;\n                query?: string;\n              } = {};\n              const startNodeId = asNonEmptyString(args.startNodeId);\n              const nodeType = asNonEmptyString(args.nodeType);\n              const query = asNonEmptyString(args.query);\n              const maxDepth = asNumber(args.maxDepth);\n              if (startNodeId) payload.startNodeId = startNodeId;\n              if (nodeType) payload.nodeType = nodeType;\n              if (query) payload.query = query;\n              if (maxDepth !== undefined) payload.maxDepth = Math.max(1, Math.min(8, maxDepth));\n              const result = await sdk.trigger({\n                function_id: \"mem::graph-query\",\n                payload,\n              });\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    { type: \"text\", text: JSON.stringify(result, null, 2) },\n                  ],\n                },\n              };\n            } catch {\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    {\n                      type: \"text\",\n                      text: \"Knowledge graph not enabled. Set GRAPH_EXTRACTION_ENABLED=true\",\n                    },\n                  ],\n                },\n              };\n            }\n          }\n\n          case \"memory_consolidate\": {\n            try {\n              const result = await sdk.trigger({ function_id: \"mem::consolidate-pipeline\", payload: {\n                tier: args.tier as string,\n              } });\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    { type: \"text\", text: JSON.stringify(result, null, 2) },\n                  ],\n                },\n              };\n            } catch {\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    {\n                      type: \"text\",\n                      text: \"Consolidation not enabled. Set CONSOLIDATION_ENABLED=true\",\n                    },\n                  ],\n                },\n              };\n            }\n          }\n\n          case \"memory_team_share\": {\n            if (\n              typeof args.itemId !== \"string\" ||\n              typeof args.itemType !== \"string\"\n            ) {\n              return {\n                status_code: 400,\n                body: { error: \"itemId and itemType are required\" },\n              };\n            }\n            try {\n              const result = await sdk.trigger({ function_id: \"mem::team-share\", payload: {\n                itemId: args.itemId,\n                itemType: args.itemType,\n              } });\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    { type: \"text\", text: JSON.stringify(result, null, 2) },\n                  ],\n                },\n              };\n            } catch {\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    {\n                      type: \"text\",\n                      text: \"Team memory not enabled. Set TEAM_ID and USER_ID\",\n                    },\n                  ],\n                },\n              };\n            }\n          }\n\n          case \"memory_team_feed\": {\n            try {\n              const result = await sdk.trigger({ function_id: \"mem::team-feed\", payload: {\n                limit: typeof args.limit === \"number\" ? args.limit : 20,\n              } });\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    { type: \"text\", text: JSON.stringify(result, null, 2) },\n                  ],\n                },\n              };\n            } catch {\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    {\n                      type: \"text\",\n                      text: \"Team memory not enabled. Set TEAM_ID and USER_ID\",\n                    },\n                  ],\n                },\n              };\n            }\n          }\n\n          case \"memory_audit\": {\n            try {\n              const result = await sdk.trigger({ function_id: \"mem::audit-query\", payload: {\n                operation: args.operation as string,\n                limit: typeof args.limit === \"number\" ? args.limit : 50,\n              } });\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    { type: \"text\", text: JSON.stringify(result, null, 2) },\n                  ],\n                },\n              };\n            } catch {\n              return {\n                status_code: 200,\n                body: {\n                  content: [{ type: \"text\", text: \"Audit query failed\" }],\n                  isError: true,\n                },\n              };\n            }\n          }\n\n          case \"memory_governance_delete\": {\n            if (typeof args.memoryIds !== \"string\") {\n              return {\n                status_code: 400,\n                body: { error: \"memoryIds is required\" },\n              };\n            }\n            const ids = (args.memoryIds as string)\n              .split(\",\")\n              .map((id) => id.trim())\n              .filter(Boolean);\n            try {\n              const result = await sdk.trigger({ function_id: \"mem::governance-delete\", payload: {\n                memoryIds: ids,\n                reason: args.reason as string,\n              } });\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    { type: \"text\", text: JSON.stringify(result, null, 2) },\n                  ],\n                },\n              };\n            } catch {\n              return {\n                status_code: 200,\n                body: {\n                  content: [{ type: \"text\", text: \"Governance delete failed\" }],\n                  isError: true,\n                },\n              };\n            }\n          }\n\n          case \"memory_snapshot_create\": {\n            try {\n              const result = await sdk.trigger({ function_id: \"mem::snapshot-create\", payload: {\n                message: args.message as string,\n              } });\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    { type: \"text\", text: JSON.stringify(result, null, 2) },\n                  ],\n                },\n              };\n            } catch {\n              return {\n                status_code: 200,\n                body: {\n                  content: [\n                    {\n                      type: \"text\",\n                      text: \"Snapshots not enabled. Set SNAPSHOT_ENABLED=true\",\n                    },\n                  ],\n                },\n              };\n            }\n          }\n\n          case \"memory_action_create\": {\n            if (typeof args.title !== \"string\" || !args.title.trim()) {\n              return {\n                status_code: 400,\n                body: { error: \"title is required\" },\n              };\n            }\n            const edges: Array<{ type: string; targetActionId: string }> = [];\n            if (typeof args.requires === \"string\" && args.requires.trim()) {\n              for (const id of args.requires.split(\",\").map((s: string) => s.trim()).filter(Boolean)) {\n                edges.push({ type: \"requires\", targetActionId: id });\n              }\n            }\n            const tags = typeof args.tags === \"string\" && args.tags.trim()\n              ? args.tags.split(\",\").map((t: string) => t.trim()).filter(Boolean)\n              : [];\n            const actionResult = await sdk.trigger({ function_id: \"mem::action-create\", payload: {\n              title: args.title,\n              description: args.description,\n              priority: args.priority,\n              project: args.project,\n              tags,\n              parentId: args.parentId,\n              edges: edges.length > 0 ? edges : undefined,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(actionResult, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_action_update\": {\n            if (typeof args.actionId !== \"string\" || !args.actionId.trim()) {\n              return {\n                status_code: 400,\n                body: { error: \"actionId is required\" },\n              };\n            }\n            const updateResult = await sdk.trigger({ function_id: \"mem::action-update\", payload: {\n              actionId: args.actionId,\n              status: args.status,\n              result: args.result,\n              priority: args.priority,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(updateResult, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_frontier\": {\n            const frontierResult = await sdk.trigger({ function_id: \"mem::frontier\", payload: {\n              project: args.project,\n              agentId: args.agentId,\n              limit: args.limit,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(frontierResult, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_next\": {\n            const nextResult = await sdk.trigger({ function_id: \"mem::next\", payload: {\n              project: args.project,\n              agentId: args.agentId,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(nextResult, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_lease\": {\n            if (\n              typeof args.actionId !== \"string\" ||\n              typeof args.agentId !== \"string\" ||\n              typeof args.operation !== \"string\"\n            ) {\n              return {\n                status_code: 400,\n                body: { error: \"actionId, agentId, and operation are required\" },\n              };\n            }\n            const op = args.operation as string;\n            let leaseResult;\n            if (op === \"acquire\") {\n              leaseResult = await sdk.trigger({ function_id: \"mem::lease-acquire\", payload: {\n                actionId: args.actionId,\n                agentId: args.agentId,\n                ttlMs: args.ttlMs,\n              } });\n            } else if (op === \"release\") {\n              leaseResult = await sdk.trigger({ function_id: \"mem::lease-release\", payload: {\n                actionId: args.actionId,\n                agentId: args.agentId,\n                result: args.result,\n              } });\n            } else if (op === \"renew\") {\n              leaseResult = await sdk.trigger({ function_id: \"mem::lease-renew\", payload: {\n                actionId: args.actionId,\n                agentId: args.agentId,\n                ttlMs: args.ttlMs,\n              } });\n            } else {\n              return {\n                status_code: 400,\n                body: { error: \"operation must be acquire, release, or renew\" },\n              };\n            }\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(leaseResult, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_routine_run\": {\n            if (typeof args.routineId !== \"string\") {\n              return {\n                status_code: 400,\n                body: { error: \"routineId is required\" },\n              };\n            }\n            const runResult = await sdk.trigger({ function_id: \"mem::routine-run\", payload: {\n              routineId: args.routineId,\n              project: args.project,\n              initiatedBy: args.initiatedBy,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(runResult, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_signal_send\": {\n            if (\n              typeof args.from !== \"string\" ||\n              typeof args.content !== \"string\"\n            ) {\n              return {\n                status_code: 400,\n                body: { error: \"from and content are required\" },\n              };\n            }\n            const sigResult = await sdk.trigger({ function_id: \"mem::signal-send\", payload: {\n              from: args.from,\n              to: args.to,\n              content: args.content,\n              type: args.type,\n              replyTo: args.replyTo,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(sigResult, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_signal_read\": {\n            if (typeof args.agentId !== \"string\") {\n              return {\n                status_code: 400,\n                body: { error: \"agentId is required\" },\n              };\n            }\n            const readResult = await sdk.trigger({ function_id: \"mem::signal-read\", payload: {\n              agentId: args.agentId,\n              unreadOnly: args.unreadOnly === true || args.unreadOnly === \"true\",\n              threadId: args.threadId,\n              limit: args.limit,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(readResult, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_checkpoint\": {\n            const cpOp = args.operation as string;\n            if (!cpOp) {\n              return {\n                status_code: 400,\n                body: { error: \"operation is required\" },\n              };\n            }\n            let cpResult;\n            if (cpOp === \"create\") {\n              const linkedIds = typeof args.linkedActionIds === \"string\" && args.linkedActionIds.trim()\n                ? args.linkedActionIds.split(\",\").map((s: string) => s.trim())\n                : [];\n              cpResult = await sdk.trigger({ function_id: \"mem::checkpoint-create\", payload: {\n                name: args.name,\n                description: args.description,\n                type: args.type,\n                linkedActionIds: linkedIds,\n              } });\n            } else if (cpOp === \"resolve\") {\n              if (typeof args.checkpointId !== \"string\" || !args.checkpointId.trim()) {\n                return {\n                  status_code: 400,\n                  body: { error: \"checkpointId is required for resolve operation\" },\n                };\n              }\n              cpResult = await sdk.trigger({ function_id: \"mem::checkpoint-resolve\", payload: {\n                checkpointId: args.checkpointId,\n                status: args.status,\n              } });\n            } else if (cpOp === \"list\") {\n              cpResult = await sdk.trigger({ function_id: \"mem::checkpoint-list\", payload: {\n                status: args.status,\n                type: args.type,\n              } });\n            } else {\n              return {\n                status_code: 400,\n                body: { error: \"operation must be create, resolve, or list\" },\n              };\n            }\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(cpResult, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_mesh_sync\": {\n            const meshResult = await sdk.trigger({ function_id: \"mem::mesh-sync\", payload: {\n              peerId: args.peerId,\n              direction: args.direction,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                content: [\n                  { type: \"text\", text: JSON.stringify(meshResult, null, 2) },\n                ],\n              },\n            };\n          }\n\n          case \"memory_sentinel_create\": {\n            let snlConfig: Record<string, unknown> = {};\n            if (typeof args.config === \"object\" && args.config !== null) {\n              snlConfig = args.config as Record<string, unknown>;\n            } else if (typeof args.config === \"string\" && args.config.trim()) {\n              try { snlConfig = JSON.parse(args.config); } catch { return { status_code: 400, body: { error: \"invalid config JSON\" } }; }\n            }\n            const snlLinked = parseCsvList(args.linkedActionIds);\n            const expiresInMs = asNumber(args.expiresInMs);\n            const name = asNonEmptyString(args.name);\n            const type = asNonEmptyString(args.type);\n            const payload: {\n              name?: string;\n              type?: string;\n              config: Record<string, unknown>;\n              linkedActionIds?: string[];\n              expiresInMs?: number;\n            } = { config: snlConfig };\n            if (name) payload.name = name;\n            if (type) payload.type = type;\n            if (snlLinked.length) payload.linkedActionIds = snlLinked;\n            if (expiresInMs !== undefined) payload.expiresInMs = Math.max(0, expiresInMs);\n            const snlResult = await sdk.trigger({\n              function_id: \"mem::sentinel-create\",\n              payload,\n            });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(snlResult, null, 2) }] } };\n          }\n\n          case \"memory_sentinel_trigger\": {\n            let snlTrigPayload: unknown;\n            if (args.result !== undefined && args.result !== null) {\n              if (typeof args.result === \"string\") {\n                try { snlTrigPayload = JSON.parse(args.result); } catch { return { status_code: 400, body: { error: \"invalid result JSON\" } }; }\n              } else {\n                snlTrigPayload = args.result;\n              }\n            }\n            const sentinelId = asNonEmptyString(args.sentinelId);\n            if (!sentinelId) {\n              return {\n                status_code: 400,\n                body: { error: \"sentinelId is required for memory_sentinel_trigger\" },\n              };\n            }\n            const snlTrigResult = await sdk.trigger({ function_id: \"mem::sentinel-trigger\", payload: {\n              sentinelId,\n              result: snlTrigPayload,\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(snlTrigResult, null, 2) }] } };\n          }\n\n          case \"memory_sketch_create\": {\n            const title = asNonEmptyString(args.title);\n            if (!title) {\n              return {\n                status_code: 400,\n                body: { error: \"title is required for memory_sketch_create\" },\n              };\n            }\n            const sketchPayload = {\n              title,\n              description: asNonEmptyString(args.description),\n              expiresInMs: asNumber(args.expiresInMs),\n              project: asNonEmptyString(args.project),\n            };\n            const skResult = await sdk.trigger({\n              function_id: \"mem::sketch-create\",\n              payload: sketchPayload,\n            });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(skResult, null, 2) }] } };\n          }\n\n          case \"memory_sketch_promote\": {\n            const sketchId = asNonEmptyString(args.sketchId);\n            if (!sketchId) {\n              return {\n                status_code: 400,\n                body: { error: \"sketchId is required for memory_sketch_promote\" },\n              };\n            }\n            const skpResult = await sdk.trigger({ function_id: \"mem::sketch-promote\", payload: {\n              sketchId,\n              project: args.project,\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(skpResult, null, 2) }] } };\n          }\n\n          case \"memory_crystallize\": {\n            if (typeof args.actionIds !== \"string\" || !args.actionIds.trim()) {\n              return { status_code: 400, body: { error: \"actionIds is required\" } };\n            }\n            const crysIds = args.actionIds.split(\",\").map((s: string) => s.trim()).filter(Boolean);\n            const crysResult = await sdk.trigger({ function_id: \"mem::crystallize\", payload: {\n              actionIds: crysIds,\n              project: args.project,\n              sessionId: args.sessionId,\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(crysResult, null, 2) }] } };\n          }\n\n          case \"memory_diagnose\": {\n            const diagCats = typeof args.categories === \"string\" && args.categories.trim()\n              ? args.categories.split(\",\").map((s: string) => s.trim()).filter(Boolean)\n              : undefined;\n            const diagResult = await sdk.trigger({ function_id: \"mem::diagnose\", payload: { categories: diagCats } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(diagResult, null, 2) }] } };\n          }\n\n          case \"memory_heal\": {\n            const healCats = typeof args.categories === \"string\" && args.categories.trim()\n              ? args.categories.split(\",\").map((s: string) => s.trim()).filter(Boolean)\n              : undefined;\n            const healResult = await sdk.trigger({ function_id: \"mem::heal\", payload: {\n              categories: healCats,\n              dryRun: args.dryRun === true || args.dryRun === \"true\",\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(healResult, null, 2) }] } };\n          }\n\n          case \"memory_facet_tag\": {\n            const fctResult = await sdk.trigger({ function_id: \"mem::facet-tag\", payload: {\n              targetId: args.targetId,\n              targetType: args.targetType,\n              dimension: args.dimension,\n              value: args.value,\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(fctResult, null, 2) }] } };\n          }\n\n          case \"memory_facet_query\": {\n            if (args.matchAll !== undefined && typeof args.matchAll !== \"string\") {\n              return { status_code: 400, body: { error: \"matchAll must be a string\" } };\n            }\n            if (args.matchAny !== undefined && typeof args.matchAny !== \"string\") {\n              return { status_code: 400, body: { error: \"matchAny must be a string\" } };\n            }\n            const fqAll = typeof args.matchAll === \"string\" && args.matchAll.trim()\n              ? args.matchAll.split(\",\").map((s: string) => s.trim()).filter(Boolean)\n              : undefined;\n            const fqAny = typeof args.matchAny === \"string\" && args.matchAny.trim()\n              ? args.matchAny.split(\",\").map((s: string) => s.trim()).filter(Boolean)\n              : undefined;\n            const fqResult = await sdk.trigger({ function_id: \"mem::facet-query\", payload: {\n              matchAll: fqAll,\n              matchAny: fqAny,\n              targetType: args.targetType,\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(fqResult, null, 2) }] } };\n          }\n\n          case \"memory_verify\": {\n            if (!args.id || typeof args.id !== \"string\") {\n              return { status_code: 400, body: { error: \"id is required\" } };\n            }\n            const verifyResult = await sdk.trigger({ function_id: \"mem::verify\", payload: { id: args.id } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(verifyResult, null, 2) }] } };\n          }\n\n          case \"memory_lesson_save\": {\n            if (typeof args.content !== \"string\" || !args.content.trim()) {\n              return { status_code: 400, body: { error: \"content is required\" } };\n            }\n            const lessonTags = typeof args.tags === \"string\" && args.tags.trim()\n              ? args.tags.split(\",\").map((t: string) => t.trim()).filter(Boolean)\n              : [];\n            const lessonSaveResult = await sdk.trigger({ function_id: \"mem::lesson-save\", payload: {\n              content: args.content,\n              context: args.context || \"\",\n              confidence: args.confidence,\n              project: args.project,\n              tags: lessonTags,\n              source: \"manual\",\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(lessonSaveResult, null, 2) }] } };\n          }\n\n          case \"memory_lesson_recall\": {\n            if (typeof args.query !== \"string\" || !args.query.trim()) {\n              return { status_code: 400, body: { error: \"query is required\" } };\n            }\n            const lessonRecallResult = await sdk.trigger({ function_id: \"mem::lesson-recall\", payload: {\n              query: args.query,\n              project: args.project,\n              minConfidence: args.minConfidence,\n              limit: args.limit,\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(lessonRecallResult, null, 2) }] } };\n          }\n\n          case \"memory_reflect\": {\n            const reflectResult = await sdk.trigger({ function_id: \"mem::reflect\", payload: {\n              project: args.project,\n              maxClusters: args.maxClusters,\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(reflectResult, null, 2) }] } };\n          }\n\n          case \"memory_insight_list\": {\n            const insightListResult = await sdk.trigger({ function_id: \"mem::insight-list\", payload: {\n              project: args.project,\n              minConfidence: args.minConfidence,\n              limit: args.limit,\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(insightListResult, null, 2) }] } };\n          }\n\n          case \"memory_obsidian_export\": {\n            const exportTypes = typeof args.types === \"string\" && args.types.trim()\n              ? args.types.split(\",\").map((t: string) => t.trim()).filter(Boolean)\n              : undefined;\n            const obsidianResult = await sdk.trigger({ function_id: \"mem::obsidian-export\", payload: {\n              vaultDir: args.vaultDir,\n              types: exportTypes,\n            } });\n            return { status_code: 200, body: { content: [{ type: \"text\", text: JSON.stringify(obsidianResult, null, 2) }] } };\n          }\n\n          case \"memory_slot_list\": {\n            const result = await sdk.trigger({ function_id: \"mem::slot-list\", payload: {} });\n            return {\n              status_code: 200,\n              body: { content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }] },\n            };\n          }\n\n          case \"memory_slot_get\": {\n            const label = asNonEmptyString(args.label);\n            if (!label) return { status_code: 400, body: { error: \"label required\" } };\n            const result = await sdk.trigger({ function_id: \"mem::slot-get\", payload: { label } });\n            return {\n              status_code: 200,\n              body: { content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }] },\n            };\n          }\n\n          case \"memory_slot_create\": {\n            const label = asNonEmptyString(args.label);\n            if (!label) return { status_code: 400, body: { error: \"label required\" } };\n            const payload: Record<string, unknown> = { label };\n            if (typeof args.content === \"string\") payload.content = args.content;\n            if (typeof args.description === \"string\") payload.description = args.description;\n            if (typeof args.sizeLimit === \"number\") payload.sizeLimit = args.sizeLimit;\n            // Accept boolean and string-boolean forms; MCP clients bind either\n            // depending on their JSON schema wrapper.\n            if (args.pinned === false || args.pinned === \"false\") payload.pinned = false;\n            else if (args.pinned === true || args.pinned === \"true\") payload.pinned = true;\n            if (args.scope === \"global\" || args.scope === \"project\") payload.scope = args.scope;\n            const result = await sdk.trigger({ function_id: \"mem::slot-create\", payload });\n            return {\n              status_code: 200,\n              body: { content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }] },\n            };\n          }\n\n          case \"memory_slot_append\": {\n            const label = asNonEmptyString(args.label);\n            const text = typeof args.text === \"string\" ? args.text : null;\n            if (!label || !text) return { status_code: 400, body: { error: \"label and text required\" } };\n            const result = await sdk.trigger({ function_id: \"mem::slot-append\", payload: { label, text } });\n            return {\n              status_code: 200,\n              body: { content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }] },\n            };\n          }\n\n          case \"memory_slot_replace\": {\n            const label = asNonEmptyString(args.label);\n            if (!label || typeof args.content !== \"string\") {\n              return { status_code: 400, body: { error: \"label and content (string) required\" } };\n            }\n            const result = await sdk.trigger({ function_id: \"mem::slot-replace\", payload: { label, content: args.content } });\n            return {\n              status_code: 200,\n              body: { content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }] },\n            };\n          }\n\n          case \"memory_slot_delete\": {\n            const label = asNonEmptyString(args.label);\n            if (!label) return { status_code: 400, body: { error: \"label required\" } };\n            const result = await sdk.trigger({ function_id: \"mem::slot-delete\", payload: { label } });\n            return {\n              status_code: 200,\n              body: { content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }] },\n            };\n          }\n\n          case \"memory_commit_lookup\": {\n            const sha = asNonEmptyString(args.sha);\n            if (!sha) return { status_code: 400, body: { error: \"sha required\" } };\n            const link = await kv.get(KV.commits, sha);\n            if (!link) {\n              return {\n                status_code: 200,\n                body: { content: [{ type: \"text\", text: JSON.stringify({ commit: null, sessions: [] }, null, 2) }] },\n              };\n            }\n            const linkRecord = link as { sessionIds?: string[] };\n            const fetched = await Promise.all(\n              (linkRecord.sessionIds ?? []).map((sid) => kv.get(KV.sessions, sid)),\n            );\n            const sessions = fetched.filter((s) => s !== null);\n            return {\n              status_code: 200,\n              body: { content: [{ type: \"text\", text: JSON.stringify({ commit: link, sessions }, null, 2) }] },\n            };\n          }\n\n          case \"memory_commits\": {\n            const branch = typeof args.branch === \"string\" ? args.branch : undefined;\n            const repo = typeof args.repo === \"string\" ? args.repo : undefined;\n            const limit = Math.max(1, Math.min(500, asNumber(args.limit, 100) ?? 100));\n            const all = await kv.list(KV.commits);\n            const filtered = (all as Array<{ branch?: string; repo?: string; linkedAt?: string }>)\n              .filter((c) => !branch || c.branch === branch)\n              .filter((c) => !repo || c.repo === repo)\n              .sort((a, b) => ((a.linkedAt ?? \"\") < (b.linkedAt ?? \"\") ? 1 : -1))\n              .slice(0, limit);\n            return {\n              status_code: 200,\n              body: { content: [{ type: \"text\", text: JSON.stringify({ commits: filtered }, null, 2) }] },\n            };\n          }\n\n          default:\n            return {\n              status_code: 400,\n              body: { error: `Unknown tool: ${name}` },\n            };\n        }\n      } catch (err) {\n        return {\n          status_code: 500,\n          body: {\n            error: \"Internal error\",\n          },\n        };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"mcp::tools::call\",\n    config: { api_path: \"/agentmemory/mcp/call\", http_method: \"POST\" },\n  });\n\n  const MCP_RESOURCES = [\n    {\n      uri: \"agentmemory://status\",\n      name: \"Agent Memory Status\",\n      description: \"Current session count, memory count, and health status\",\n      mimeType: \"application/json\",\n    },\n    {\n      uri: \"agentmemory://project/{name}/profile\",\n      name: \"Project Profile\",\n      description:\n        \"Top concepts, frequently modified files, and conventions for a project\",\n      mimeType: \"application/json\",\n    },\n    {\n      uri: \"agentmemory://project/{name}/recent\",\n      name: \"Recent Sessions\",\n      description: \"Last 5 session summaries for a project\",\n      mimeType: \"application/json\",\n    },\n    {\n      uri: \"agentmemory://memories/latest\",\n      name: \"Latest Memories\",\n      description: \"Top 10 latest memories with their type and strength\",\n      mimeType: \"application/json\",\n    },\n    {\n      uri: \"agentmemory://graph/stats\",\n      name: \"Knowledge Graph Stats\",\n      description: \"Node and edge counts by type in the knowledge graph\",\n      mimeType: \"application/json\",\n    },\n    {\n      uri: \"agentmemory://team/{id}/profile\",\n      name: \"Team Profile\",\n      description: \"Team memory profile with shared concepts and patterns\",\n      mimeType: \"application/json\",\n    },\n  ];\n\n  sdk.registerFunction(\"mcp::resources::list\", \n    async (req: ApiRequest): Promise<McpResponse> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      return { status_code: 200, body: { resources: MCP_RESOURCES } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"mcp::resources::list\",\n    config: { api_path: \"/agentmemory/mcp/resources\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"mcp::resources::read\", \n    async (req: ApiRequest<{ uri: string }>): Promise<McpResponse> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n\n      const uri = req.body?.uri;\n      if (!uri || typeof uri !== \"string\") {\n        return { status_code: 400, body: { error: \"uri is required\" } };\n      }\n\n      try {\n        if (uri === \"agentmemory://status\") {\n          const sessions = await kv.list<Session>(KV.sessions);\n          const memories = await kv.list<Memory>(KV.memories);\n          const healthData = await kv.list(KV.health).catch(() => []);\n          return {\n            status_code: 200,\n            body: {\n              contents: [\n                {\n                  uri,\n                  mimeType: \"application/json\",\n                  text: JSON.stringify({\n                    sessionCount: sessions.length,\n                    memoryCount: memories.length,\n                    healthStatus:\n                      healthData.length > 0 ? \"available\" : \"no-data\",\n                  }),\n                },\n              ],\n            },\n          };\n        }\n\n        const projectProfileMatch = uri.match(\n          /^agentmemory:\\/\\/project\\/(.+)\\/profile$/,\n        );\n        if (projectProfileMatch) {\n          let projectName: string;\n          try {\n            projectName = decodeURIComponent(projectProfileMatch[1]);\n          } catch {\n            return {\n              status_code: 400,\n              body: { error: \"Invalid percent-encoding in URI\" },\n            };\n          }\n          const profile = await sdk.trigger({ function_id: \"mem::profile\", payload: {\n            project: projectName,\n          } });\n          return {\n            status_code: 200,\n            body: {\n              contents: [\n                {\n                  uri,\n                  mimeType: \"application/json\",\n                  text: JSON.stringify(profile),\n                },\n              ],\n            },\n          };\n        }\n\n        const projectRecentMatch = uri.match(\n          /^agentmemory:\\/\\/project\\/(.+)\\/recent$/,\n        );\n        if (projectRecentMatch) {\n          let projectName: string;\n          try {\n            projectName = decodeURIComponent(projectRecentMatch[1]);\n          } catch {\n            return {\n              status_code: 400,\n              body: { error: \"Invalid percent-encoding in URI\" },\n            };\n          }\n          const summaries = await kv.list<SessionSummary>(KV.summaries);\n          const filtered = summaries\n            .filter((s) => s.project === projectName)\n            .sort(\n              (a, b) =>\n                new Date(b.createdAt).getTime() -\n                new Date(a.createdAt).getTime(),\n            )\n            .slice(0, 5);\n          return {\n            status_code: 200,\n            body: {\n              contents: [\n                {\n                  uri,\n                  mimeType: \"application/json\",\n                  text: JSON.stringify(filtered),\n                },\n              ],\n            },\n          };\n        }\n\n        if (uri === \"agentmemory://memories/latest\") {\n          const memories = await kv.list<Memory>(KV.memories);\n          const latest = memories\n            .filter((m) => m.isLatest)\n            .sort(\n              (a, b) =>\n                new Date(b.updatedAt).getTime() -\n                new Date(a.updatedAt).getTime(),\n            )\n            .slice(0, 10)\n            .map((m) => ({\n              id: m.id,\n              title: m.title,\n              type: m.type,\n              strength: m.strength,\n            }));\n          return {\n            status_code: 200,\n            body: {\n              contents: [\n                {\n                  uri,\n                  mimeType: \"application/json\",\n                  text: JSON.stringify(latest),\n                },\n              ],\n            },\n          };\n        }\n\n        if (uri === \"agentmemory://graph/stats\") {\n          try {\n            const nodes = await kv.list<GraphNode>(KV.graphNodes);\n            const edges = await kv.list<GraphEdge>(KV.graphEdges);\n            const nodesByType: Record<string, number> = {};\n            for (const n of nodes)\n              nodesByType[n.type] = (nodesByType[n.type] || 0) + 1;\n            const edgesByType: Record<string, number> = {};\n            for (const e of edges)\n              edgesByType[e.type] = (edgesByType[e.type] || 0) + 1;\n            return {\n              status_code: 200,\n              body: {\n                contents: [\n                  {\n                    uri,\n                    mimeType: \"application/json\",\n                    text: JSON.stringify({\n                      totalNodes: nodes.length,\n                      totalEdges: edges.length,\n                      nodesByType,\n                      edgesByType,\n                    }),\n                  },\n                ],\n              },\n            };\n          } catch {\n            return {\n              status_code: 200,\n              body: {\n                contents: [\n                  {\n                    uri,\n                    mimeType: \"application/json\",\n                    text: JSON.stringify({\n                      totalNodes: 0,\n                      totalEdges: 0,\n                    }),\n                  },\n                ],\n              },\n            };\n          }\n        }\n\n        const teamProfileMatch = uri.match(\n          /^agentmemory:\\/\\/team\\/(.+)\\/profile$/,\n        );\n        if (teamProfileMatch) {\n          try {\n            const teamId = decodeURIComponent(teamProfileMatch[1]);\n            const items = await kv.list(KV.teamShared(teamId));\n            return {\n              status_code: 200,\n              body: {\n                contents: [\n                  {\n                    uri,\n                    mimeType: \"application/json\",\n                    text: JSON.stringify({\n                      teamId,\n                      sharedItems: items.length,\n                    }),\n                  },\n                ],\n              },\n            };\n          } catch {\n            return {\n              status_code: 200,\n              body: {\n                contents: [\n                  {\n                    uri,\n                    mimeType: \"application/json\",\n                    text: JSON.stringify({\n                      teamId: teamProfileMatch[1],\n                      sharedItems: 0,\n                    }),\n                  },\n                ],\n              },\n            };\n          }\n        }\n\n        return {\n          status_code: 404,\n          body: { error: `Unknown resource: ${uri}` },\n        };\n      } catch {\n        return { status_code: 500, body: { error: \"Internal error\" } };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"mcp::resources::read\",\n    config: {\n      api_path: \"/agentmemory/mcp/resources/read\",\n      http_method: \"POST\",\n    },\n  });\n\n  const MCP_PROMPTS = [\n    {\n      name: \"recall_context\",\n      description:\n        \"Search observations and memories to build context for a task\",\n      arguments: [\n        {\n          name: \"task_description\",\n          description: \"What you are working on\",\n          required: true,\n        },\n      ],\n    },\n    {\n      name: \"session_handoff\",\n      description:\n        \"Generate a handoff summary for continuing work in a new session\",\n      arguments: [\n        {\n          name: \"session_id\",\n          description: \"Session ID to hand off from\",\n          required: true,\n        },\n      ],\n    },\n    {\n      name: \"detect_patterns\",\n      description: \"Detect recurring patterns across sessions for a project\",\n      arguments: [\n        {\n          name: \"project\",\n          description: \"Project path to analyze (optional)\",\n          required: false,\n        },\n      ],\n    },\n  ];\n\n  sdk.registerFunction(\"mcp::prompts::list\", \n    async (req: ApiRequest): Promise<McpResponse> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n      return { status_code: 200, body: { prompts: MCP_PROMPTS } };\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"mcp::prompts::list\",\n    config: { api_path: \"/agentmemory/mcp/prompts\", http_method: \"GET\" },\n  });\n\n  sdk.registerFunction(\"mcp::prompts::get\", \n    async (\n      req: ApiRequest<{ name: string; arguments?: Record<string, string> }>,\n    ): Promise<McpResponse> => {\n      const authErr = checkAuth(req, secret);\n      if (authErr) return authErr;\n\n      const promptName = req.body?.name;\n      if (!promptName || typeof promptName !== \"string\") {\n        return { status_code: 400, body: { error: \"name is required\" } };\n      }\n\n      const promptArgs = req.body?.arguments || {};\n\n      try {\n        switch (promptName) {\n          case \"recall_context\": {\n            const taskDesc = promptArgs.task_description;\n            if (typeof taskDesc !== \"string\" || !taskDesc.trim()) {\n              return {\n                status_code: 400,\n                body: {\n                  error:\n                    \"task_description argument is required and must be a string\",\n                },\n              };\n            }\n            // #817: mem::search now enforces agent-scope upstream when\n            // AGENTMEMORY_AGENT_SCOPE=isolated, so the search half of\n            // this prompt is safe by default.\n            const searchResult = await sdk\n              .trigger({\n                function_id: \"mem::search\",\n                payload: { query: taskDesc, limit: 10 },\n              })\n              .catch(() => ({ results: [] }));\n            const memories = await kv.list<Memory>(KV.memories);\n            // #817: also filter the memory list. recall_context's\n            // second source is the latest-memory feed, which leaks\n            // cross-agent rows when isolated mode is on. Mirror the\n            // search-side filter explicitly here; the upstream filter\n            // doesn't apply to a raw kv.list.\n            //\n            // Fail-closed: if isolated mode is on but no AGENT_ID is\n            // available, return an empty `relevant` array rather than\n            // letting every memory through. The mem::search call\n            // above already throws in this case, but the kv.list feed\n            // is a separate path that has to enforce isolation on its\n            // own.\n            const isolated = isAgentScopeIsolated();\n            const activeAgentId = isolated ? getAgentId() : undefined;\n            const relevant =\n              isolated && activeAgentId === undefined\n                ? []\n                : memories\n                    .filter((m) => m.isLatest)\n                    .filter(\n                      (m) =>\n                        activeAgentId === undefined ||\n                        m.agentId === activeAgentId,\n                    )\n                    .slice(0, 5);\n            return {\n              status_code: 200,\n              body: {\n                messages: [\n                  {\n                    role: \"user\",\n                    content: {\n                      type: \"text\",\n                      text: `Here is relevant context from past sessions for the task: \"${taskDesc}\"\\n\\n## Past Observations\\n${JSON.stringify(searchResult, null, 2)}\\n\\n## Relevant Memories\\n${JSON.stringify(relevant, null, 2)}`,\n                    },\n                  },\n                ],\n              },\n            };\n          }\n\n          case \"session_handoff\": {\n            const sessionId = promptArgs.session_id;\n            if (typeof sessionId !== \"string\" || !sessionId.trim()) {\n              return {\n                status_code: 400,\n                body: {\n                  error: \"session_id argument is required and must be a string\",\n                },\n              };\n            }\n            const session = await kv.get<Session>(KV.sessions, sessionId);\n            const summaries = await kv.list<SessionSummary>(KV.summaries);\n            const summary = summaries.find((s) => s.sessionId === sessionId);\n            return {\n              status_code: 200,\n              body: {\n                messages: [\n                  {\n                    role: \"user\",\n                    content: {\n                      type: \"text\",\n                      text: `## Session Handoff\\n\\n### Session\\n${JSON.stringify(session, null, 2)}\\n\\n### Summary\\n${JSON.stringify(summary || \"No summary available\", null, 2)}`,\n                    },\n                  },\n                ],\n              },\n            };\n          }\n\n          case \"detect_patterns\": {\n            if (\n              promptArgs.project !== undefined &&\n              typeof promptArgs.project !== \"string\"\n            ) {\n              return {\n                status_code: 400,\n                body: { error: \"project argument must be a string\" },\n              };\n            }\n            const result = await sdk.trigger({ function_id: \"mem::patterns\", payload: {\n              project: promptArgs.project || undefined,\n            } });\n            return {\n              status_code: 200,\n              body: {\n                messages: [\n                  {\n                    role: \"user\",\n                    content: {\n                      type: \"text\",\n                      text: `## Pattern Analysis\\n\\n${JSON.stringify(result, null, 2)}`,\n                    },\n                  },\n                ],\n              },\n            };\n          }\n\n          default:\n            return {\n              status_code: 400,\n              body: { error: `Unknown prompt: ${promptName}` },\n            };\n        }\n      } catch {\n        return { status_code: 500, body: { error: \"Internal error\" } };\n      }\n    },\n  );\n  sdk.registerTrigger({\n    type: \"http\",\n    function_id: \"mcp::prompts::get\",\n    config: { api_path: \"/agentmemory/mcp/prompts/get\", http_method: \"POST\" },\n  });\n}\n","import type { FunctionMetrics } from \"../types.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\n\nexport class MetricsStore {\n  private cache = new Map<string, FunctionMetrics>();\n  private qualityCallCounts = new Map<string, number>();\n\n  constructor(private kv: StateKV) {}\n\n  async record(\n    functionId: string,\n    latencyMs: number,\n    success: boolean,\n    qualityScore?: number,\n  ): Promise<void> {\n    let m = this.cache.get(functionId);\n    if (!m) {\n      m = (await this.kv.get<FunctionMetrics>(KV.metrics, functionId)) ?? {\n        functionId,\n        totalCalls: 0,\n        successCount: 0,\n        failureCount: 0,\n        avgLatencyMs: 0,\n        avgQualityScore: 0,\n      };\n    }\n\n    const prev = m.totalCalls;\n    m.totalCalls += 1;\n    m.avgLatencyMs = (m.avgLatencyMs * prev + latencyMs) / m.totalCalls;\n    if (success) {\n      m.successCount += 1;\n    } else {\n      m.failureCount += 1;\n    }\n    if (qualityScore !== undefined) {\n      const prevQualityCalls = this.qualityCallCounts.get(functionId) || 0;\n      m.avgQualityScore =\n        (m.avgQualityScore * prevQualityCalls + qualityScore) /\n        (prevQualityCalls + 1);\n      this.qualityCallCounts.set(functionId, prevQualityCalls + 1);\n    }\n\n    this.cache.set(functionId, m);\n    await this.kv.set(KV.metrics, functionId, m).catch(() => {});\n  }\n\n  async get(functionId: string): Promise<FunctionMetrics | null> {\n    return (\n      this.cache.get(functionId) ??\n      (await this.kv.get<FunctionMetrics>(KV.metrics, functionId))\n    );\n  }\n\n  async getAll(): Promise<FunctionMetrics[]> {\n    const kvMetrics = await this.kv\n      .list<FunctionMetrics>(KV.metrics)\n      .catch(() => []);\n    const merged = new Map<string, FunctionMetrics>();\n    for (const m of kvMetrics) merged.set(m.functionId, m);\n    for (const [id, m] of this.cache) merged.set(id, m);\n    return Array.from(merged.values());\n  }\n}\n","import { createHash } from \"node:crypto\";\n\nconst TTL_MS = 5 * 60 * 1000;\nconst CLEANUP_INTERVAL_MS = 60_000;\n\ninterface DedupEntry {\n  hash: string;\n  expiresAt: number;\n}\n\nexport class DedupMap {\n  private entries = new Map<string, DedupEntry>();\n  private cleanupTimer: ReturnType<typeof setInterval>;\n\n  constructor() {\n    this.cleanupTimer = setInterval(() => this.cleanup(), CLEANUP_INTERVAL_MS);\n    this.cleanupTimer.unref();\n  }\n\n  computeHash(sessionId: string, toolName: string, toolInput: unknown): string {\n    const input =\n      typeof toolInput === \"string\"\n        ? toolInput.slice(0, 500)\n        : JSON.stringify(toolInput ?? \"\").slice(0, 500);\n    const raw = `${sessionId}:${toolName}:${input}`;\n    return createHash(\"sha256\").update(raw).digest(\"hex\");\n  }\n\n  isDuplicate(hash: string): boolean {\n    const entry = this.entries.get(hash);\n    if (!entry) return false;\n    if (Date.now() > entry.expiresAt) {\n      this.entries.delete(hash);\n      return false;\n    }\n    return true;\n  }\n\n  record(hash: string): void {\n    this.entries.set(hash, { hash, expiresAt: Date.now() + TTL_MS });\n  }\n\n  private cleanup(): void {\n    const now = Date.now();\n    for (const [key, entry] of this.entries) {\n      if (now > entry.expiresAt) this.entries.delete(key);\n    }\n  }\n\n  stop(): void {\n    clearInterval(this.cleanupTimer);\n  }\n\n  get size(): number {\n    return this.entries.size;\n  }\n}\n","import { registerWorker } from \"iii-sdk\";\nimport {\n  loadConfig,\n  getEnvVar,\n  loadEmbeddingConfig,\n  loadFallbackConfig,\n  loadClaudeBridgeConfig,\n  loadTeamConfig,\n  loadSnapshotConfig,\n  isGraphExtractionEnabled,\n  isAutoCompressEnabled,\n  isConsolidationEnabled,\n  isContextInjectionEnabled,\n  isDropStaleIndexEnabled,\n} from \"./config.js\";\nimport {\n  createProvider,\n  createFallbackProvider,\n  createEmbeddingProvider,\n  createImageEmbeddingProvider,\n} from \"./providers/index.js\";\nimport { StateKV } from \"./state/kv.js\";\nimport { KV } from \"./state/schema.js\";\nimport { VectorIndex } from \"./state/vector-index.js\";\nimport { HybridSearch } from \"./state/hybrid-search.js\";\nimport { IndexPersistence } from \"./state/index-persistence.js\";\nimport { registerPrivacyFunction } from \"./functions/privacy.js\";\nimport { registerObserveFunction } from \"./functions/observe.js\";\nimport { registerImageQuotaCleanup } from \"./functions/image-quota-cleanup.js\";\nimport { registerVisionSearchFunctions } from \"./functions/vision-search.js\";\nimport { registerSlotsFunctions, isSlotsEnabled, isReflectEnabled } from \"./functions/slots.js\";\nimport { registerDiskSizeManager } from \"./functions/disk-size-manager.js\";\nimport { registerCompressFunction } from \"./functions/compress.js\";\nimport {\n  registerSearchFunction,\n  rebuildIndex,\n  getSearchIndex,\n  setVectorIndex,\n  setEmbeddingProvider,\n  setIndexPersistence,\n} from \"./functions/search.js\";\nimport { registerContextFunction } from \"./functions/context.js\";\nimport { registerSummarizeFunction } from \"./functions/summarize.js\";\nimport { registerMigrateFunction } from \"./functions/migrate.js\";\nimport { registerFileIndexFunction } from \"./functions/file-index.js\";\nimport { registerConsolidateFunction } from \"./functions/consolidate.js\";\nimport { registerPatternsFunction } from \"./functions/patterns.js\";\nimport { registerRememberFunction } from \"./functions/remember.js\";\nimport { registerEvictFunction } from \"./functions/evict.js\";\nimport { registerRelationsFunction } from \"./functions/relations.js\";\nimport { registerTimelineFunction } from \"./functions/timeline.js\";\nimport { registerSmartSearchFunction } from \"./functions/smart-search.js\";\nimport { registerRecentSearchesSweepFunction } from \"./functions/recent-searches-sweep.js\";\nimport { registerProfileFunction } from \"./functions/profile.js\";\nimport { registerAutoForgetFunction } from \"./functions/auto-forget.js\";\nimport { registerExportImportFunction } from \"./functions/export-import.js\";\nimport { registerEnrichFunction } from \"./functions/enrich.js\";\nimport { registerClaudeBridgeFunction } from \"./functions/claude-bridge.js\";\nimport { registerGraphFunction } from \"./functions/graph.js\";\nimport { registerConsolidationPipelineFunction } from \"./functions/consolidation-pipeline.js\";\nimport { registerTeamFunction } from \"./functions/team.js\";\nimport { registerGovernanceFunction } from \"./functions/governance.js\";\nimport { registerSnapshotFunction } from \"./functions/snapshot.js\";\nimport { registerActionsFunction } from \"./functions/actions.js\";\nimport { registerFrontierFunction } from \"./functions/frontier.js\";\nimport { registerLeasesFunction } from \"./functions/leases.js\";\nimport { registerRoutinesFunction } from \"./functions/routines.js\";\nimport { registerSignalsFunction } from \"./functions/signals.js\";\nimport { registerCheckpointsFunction } from \"./functions/checkpoints.js\";\nimport { registerFlowCompressFunction } from \"./functions/flow-compress.js\";\nimport { registerMeshFunction } from \"./functions/mesh.js\";\nimport { registerBranchAwareFunction } from \"./functions/branch-aware.js\";\nimport { registerSentinelsFunction } from \"./functions/sentinels.js\";\nimport { registerSketchesFunction } from \"./functions/sketches.js\";\nimport { registerCrystallizeFunction } from \"./functions/crystallize.js\";\nimport { registerDiagnosticsFunction } from \"./functions/diagnostics.js\";\nimport { registerFacetsFunction } from \"./functions/facets.js\";\nimport { registerVerifyFunction } from \"./functions/verify.js\";\nimport { registerCascadeFunction } from \"./functions/cascade.js\";\nimport { registerLessonsFunctions } from \"./functions/lessons.js\";\nimport { registerObsidianExportFunction } from \"./functions/obsidian-export.js\";\nimport { registerReflectFunctions } from \"./functions/reflect.js\";\nimport { registerWorkingMemoryFunctions } from \"./functions/working-memory.js\";\nimport { registerSkillExtractFunctions } from \"./functions/skill-extract.js\";\nimport { registerSlidingWindowFunction } from \"./functions/sliding-window.js\";\nimport { registerQueryExpansionFunction } from \"./functions/query-expansion.js\";\nimport { registerTemporalGraphFunctions } from \"./functions/temporal-graph.js\";\nimport { registerRetentionFunctions } from \"./functions/retention.js\";\nimport { registerCompressFileFunction } from \"./functions/compress-file.js\";\nimport { registerReplayFunctions } from \"./functions/replay.js\";\nimport { registerApiTriggers } from \"./triggers/api.js\";\nimport { registerEventTriggers } from \"./triggers/events.js\";\nimport { registerMcpEndpoints } from \"./mcp/server.js\";\nimport { getAllTools } from \"./mcp/tools-registry.js\";\nimport { startViewerServer } from \"./viewer/server.js\";\nimport { MetricsStore } from \"./eval/metrics-store.js\";\nimport { DedupMap } from \"./functions/dedup.js\";\nimport { registerHealthMonitor } from \"./health/monitor.js\";\nimport { initMetrics, OTEL_CONFIG } from \"./telemetry/setup.js\";\nimport { VERSION } from \"./version.js\";\nimport { bootLog } from \"./logger.js\";\nimport { mkdirSync, writeFileSync, unlinkSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\n// #640 + #474: the worker process (this file) is spawned by iii-exec\n// inside the engine. When `agentmemory stop` kills only the engine pid,\n// this worker can survive (detached spawn, signal not propagated, or a\n// wrapper script keeps it running) and reconnects to the next engine as\n// a duplicate worker. Write the worker pid alongside iii.pid so\n// `agentmemory stop` can reap us too.\nfunction workerPidfilePath(): string {\n  return join(homedir(), \".agentmemory\", \"worker.pid\");\n}\nfunction writeWorkerPidfile(): void {\n  try {\n    const p = workerPidfilePath();\n    mkdirSync(dirname(p), { recursive: true });\n    writeFileSync(p, `${process.pid}\\n`, { encoding: \"utf-8\" });\n  } catch {\n    // best-effort; stop still has the engine pidfile + port scan fallback\n  }\n}\nfunction clearWorkerPidfile(): void {\n  try {\n    unlinkSync(workerPidfilePath());\n  } catch {}\n}\n\nfunction hasGetMeter(\n  sdk: unknown,\n): sdk is { getMeter: (name: string) => unknown } {\n  return (\n    typeof sdk === \"object\" &&\n    sdk !== null &&\n    \"getMeter\" in sdk &&\n    typeof (sdk as { getMeter?: unknown }).getMeter === \"function\"\n  );\n}\n\n// Top-level safety net for iii-engine invocation timeouts (issue #204).\n// Under sustained write load (e.g. Claude Code hooks across many\n// projects) `state::set` can occasionally exceed the SDK's 30s timeout.\n// We don't want one such timeout to terminate the long-lived memory\n// service — the rejection is surfaced to the relevant call site via\n// .catch() where it matters; everything else is logged-and-continued.\n// Throttle logs to avoid spamming on bursts.\nlet lastUnhandledLogAt = 0;\nprocess.on(\"unhandledRejection\", (reason) => {\n  const now = Date.now();\n  if (now - lastUnhandledLogAt < 60_000) return;\n  lastUnhandledLogAt = now;\n  const r = reason as { code?: string; function_id?: string; message?: string };\n  console.warn(\n    `[agentmemory] unhandledRejection (suppressed):`,\n    r?.code ? `${r.code} ${r.function_id ?? \"\"} ${r.message ?? \"\"}`.trim() : reason,\n  );\n});\n\nasync function main() {\n  const config = loadConfig();\n  const embeddingConfig = loadEmbeddingConfig();\n  const fallbackConfig = loadFallbackConfig();\n\n  const provider =\n    fallbackConfig.providers.length > 0\n      ? createFallbackProvider(config.provider, fallbackConfig)\n      : createProvider(config.provider);\n\n  const embeddingProvider = createEmbeddingProvider();\n  const imageEmbeddingProvider = createImageEmbeddingProvider();\n\n  bootLog(`Starting worker v${VERSION}...`);\n  bootLog(`Engine: ${config.engineUrl}`);\n  bootLog(\n    `Provider: ${config.provider.provider} (${config.provider.model})`,\n  );\n  if (embeddingProvider) {\n    bootLog(\n      `Embedding provider: ${embeddingProvider.name} (${embeddingProvider.dimensions} dims)`,\n    );\n  } else {\n    bootLog(`Embedding provider: none (BM25-only mode)`);\n  }\n  if (imageEmbeddingProvider) {\n    bootLog(\n      `Image embedding provider: ${imageEmbeddingProvider.name} (${imageEmbeddingProvider.dimensions} dims) — vision-search active`,\n    );\n  }\n  bootLog(\n    `REST API: http://localhost:${config.restPort}/agentmemory/*`,\n  );\n  bootLog(`Streams: ws://localhost:${config.streamsPort}`);\n\n  const sdk = registerWorker(config.engineUrl, {\n    workerName: \"agentmemory\",\n    invocationTimeoutMs: 180000,\n    otel: {\n      serviceName: OTEL_CONFIG.serviceName,\n      serviceVersion: OTEL_CONFIG.serviceVersion,\n      metricsExportIntervalMs: OTEL_CONFIG.metricsExportIntervalMs,\n    },\n    // Explicit worker telemetry metadata. iii-sdk falls back to\n    // auto-detection (cwd / package.json name / hostname) when this\n    // is omitted, which produces inconsistent values per host —\n    // `agentmemory`, `node`, `npm`, occasionally the user's home\n    // directory basename. Pinning the value here gives every install\n    // the same stable project identifier for downstream attribution\n    // and grouping in the engine's metrics + traces output.\n    telemetry: {\n      project_name: \"agentmemory\",\n      language: \"node\",\n      framework: \"iii-sdk\",\n    },\n  });\n\n  writeWorkerPidfile();\n\n  const kv = new StateKV(sdk);\n  const secret = getEnvVar(\"AGENTMEMORY_SECRET\");\n  const metricsStore = new MetricsStore(kv);\n  const dedupMap = new DedupMap();\n\n  const vectorIndex = embeddingProvider ? new VectorIndex() : null;\n\n  setVectorIndex(vectorIndex);\n  setEmbeddingProvider(embeddingProvider);\n\n  const meterAccessor = hasGetMeter(sdk)\n    ? (sdk.getMeter.bind(sdk) as (name: string) => unknown)\n    : undefined;\n\n  initMetrics(meterAccessor as ((name: string) => import(\"@opentelemetry/api\").Meter) | undefined);\n\n  registerPrivacyFunction(sdk);\n  registerObserveFunction(sdk, kv, dedupMap, config.maxObservationsPerSession);\n  registerImageQuotaCleanup(sdk, kv);\n  registerVisionSearchFunctions(sdk, kv, imageEmbeddingProvider);\n  if (isSlotsEnabled()) {\n    registerSlotsFunctions(sdk, kv);\n  }\n  registerDiskSizeManager(sdk, kv);\n  registerCompressFunction(sdk, kv, provider, metricsStore);\n  registerSearchFunction(sdk, kv);\n  registerContextFunction(sdk, kv, config.tokenBudget);\n  registerSummarizeFunction(sdk, kv, provider, metricsStore);\n  registerMigrateFunction(sdk, kv);\n  registerFileIndexFunction(sdk, kv);\n  registerConsolidateFunction(sdk, kv, provider);\n  registerPatternsFunction(sdk, kv);\n  registerRememberFunction(sdk, kv);\n  registerEvictFunction(sdk, kv);\n\n  registerRelationsFunction(sdk, kv);\n  registerTimelineFunction(sdk, kv);\n  registerProfileFunction(sdk, kv);\n  registerAutoForgetFunction(sdk, kv);\n  registerExportImportFunction(sdk, kv);\n  registerEnrichFunction(sdk, kv);\n\n  const claudeBridgeConfig = loadClaudeBridgeConfig();\n  if (claudeBridgeConfig.enabled) {\n    registerClaudeBridgeFunction(sdk, kv, claudeBridgeConfig);\n    bootLog(\n      `Claude bridge: syncing to ${claudeBridgeConfig.memoryFilePath}`,\n    );\n  }\n\n  if (isGraphExtractionEnabled()) {\n    registerGraphFunction(sdk, kv, provider);\n    bootLog(`Knowledge graph: extraction enabled`);\n  }\n\n  registerConsolidationPipelineFunction(sdk, kv, provider);\n  bootLog(`Consolidation pipeline: registered (CONSOLIDATION_ENABLED=${isConsolidationEnabled() ? \"true\" : \"false\"})`);\n\n  if (isAutoCompressEnabled()) {\n    bootLog(\n      `WARNING: AGENTMEMORY_AUTO_COMPRESS=true — every PostToolUse observation will be sent to your LLM provider for compression. This spends API tokens proportional to your session tool-use frequency. Set AGENTMEMORY_AUTO_COMPRESS=false to disable.`,\n    );\n  } else {\n    bootLog(\n      `Auto-compress: OFF (default) — observations indexed via zero-LLM synthetic compression. Set AGENTMEMORY_AUTO_COMPRESS=true to opt-in to LLM-powered summaries (uses your API key).`,\n    );\n  }\n\n  if (isContextInjectionEnabled()) {\n    bootLog(\n      `WARNING: AGENTMEMORY_INJECT_CONTEXT=true — the PreToolUse and SessionStart hooks will inject up to ~4000 chars of memory context into every tool turn. On Claude Pro this burns session tokens proportional to your tool-call frequency. Set AGENTMEMORY_INJECT_CONTEXT=false to disable.`,\n    );\n  } else {\n    bootLog(\n      `Context injection: OFF (default) — hooks capture observations but do not inject context into Claude Code's conversation. Set AGENTMEMORY_INJECT_CONTEXT=true to opt-in (warning: expect your Claude Pro allocation to drain faster).`,\n    );\n  }\n\n  const teamConfig = loadTeamConfig();\n  if (teamConfig) {\n    registerTeamFunction(sdk, kv, teamConfig);\n    bootLog(\n      `Team memory: ${teamConfig.teamId} (${teamConfig.mode})`,\n    );\n  }\n\n  registerGovernanceFunction(sdk, kv);\n\n  registerActionsFunction(sdk, kv);\n  registerFrontierFunction(sdk, kv);\n  registerLeasesFunction(sdk, kv);\n  registerRoutinesFunction(sdk, kv);\n  registerSignalsFunction(sdk, kv);\n  registerCheckpointsFunction(sdk, kv);\n  registerMeshFunction(sdk, kv, secret);\n  registerBranchAwareFunction(sdk, kv);\n  registerFlowCompressFunction(sdk, kv, provider);\n  registerSentinelsFunction(sdk, kv);\n  registerSketchesFunction(sdk, kv);\n  registerCrystallizeFunction(sdk, kv, provider);\n  registerDiagnosticsFunction(sdk, kv);\n  registerFacetsFunction(sdk, kv);\n  registerVerifyFunction(sdk, kv);\n  registerLessonsFunctions(sdk, kv);\n  registerObsidianExportFunction(sdk, kv);\n  registerReflectFunctions(sdk, kv, provider);\n  registerWorkingMemoryFunctions(sdk, kv, config.tokenBudget);\n  registerSkillExtractFunctions(sdk, kv, provider);\n  registerCascadeFunction(sdk, kv);\n\n  registerSlidingWindowFunction(sdk, kv, provider);\n  registerQueryExpansionFunction(sdk, provider);\n  registerTemporalGraphFunctions(sdk, kv, provider);\n  registerRetentionFunctions(sdk, kv);\n  registerCompressFileFunction(sdk, kv, provider);\n  registerReplayFunctions(sdk, kv);\n  bootLog(\n    `v0.6 advanced retrieval: sliding-window, query-expansion, temporal-graph, retention-scoring`,\n  );\n  bootLog(\n    `Orchestration layer: actions, frontier, leases, routines, signals, checkpoints, flow-compress, mesh, branch-aware, sentinels, sketches, crystallize, diagnostics, facets`,\n  );\n  if (isSlotsEnabled()) {\n    bootLog(\n      `Slots: enabled (pinned editable memory). Reflect on Stop hook: ${isReflectEnabled() ? \"on\" : \"off\"}`,\n    );\n  }\n\n  const snapshotConfig = loadSnapshotConfig();\n  if (snapshotConfig.enabled) {\n    registerSnapshotFunction(sdk, kv, snapshotConfig.dir);\n    bootLog(\n      `Git snapshots: ${snapshotConfig.dir} (every ${snapshotConfig.interval}s)`,\n    );\n  }\n\n  const bm25Index = getSearchIndex();\n  const graphWeight = parseFloat(getEnvVar(\"AGENTMEMORY_GRAPH_WEIGHT\") || \"0.3\");\n  const hybridSearch = new HybridSearch(\n    bm25Index,\n    vectorIndex,\n    embeddingProvider,\n    kv,\n    embeddingConfig.bm25Weight,\n    embeddingConfig.vectorWeight,\n    graphWeight,\n  );\n\n  registerSmartSearchFunction(sdk, kv, (query, limit) =>\n    hybridSearch.search(query, limit),\n  );\n  registerRecentSearchesSweepFunction(sdk, kv);\n\n  registerApiTriggers(sdk, kv, secret, metricsStore, provider);\n  registerEventTriggers(sdk, kv);\n  registerMcpEndpoints(sdk, kv, secret);\n\n  const healthMonitor = registerHealthMonitor(sdk, kv);\n\n  const indexPersistence = new IndexPersistence(kv, bm25Index, vectorIndex);\n  // Wire the persistence hook so delete paths can flush BM25/vector\n  // index mutations to disk. Without this, an in-memory remove can be\n  // lost across a hard process exit and the persisted snapshot\n  // restores the deleted entry at next boot.\n  setIndexPersistence(indexPersistence);\n\n  const loaded = await indexPersistence.load().catch((err) => {\n    console.warn(`[agentmemory] Failed to load persisted index:`, err);\n    return null;\n  });\n  if (loaded?.bm25 && loaded.bm25.size > 0) {\n    bm25Index.restoreFrom(loaded.bm25);\n    bootLog(\n      `Loaded persisted BM25 index (${bm25Index.size} docs)`,\n    );\n  }\n  if (loaded?.vector && vectorIndex && loaded.vector.size > 0) {\n    // Persisted vectors carry whatever dimension the provider had when\n    // they were written. If the active provider declares a different\n    // dimension — or if the on-disk index contains a mix of dimensions\n    // (legacy indexes written before the live-API guard in this PR) —\n    // restoring would silently corrupt search: cosineSimilarity returns\n    // 0 on cross-dim pairs, so affected observations stop matching\n    // anything and recall degrades without an error. Walk every stored\n    // vector instead of trusting the first; refuse to load if anything\n    // is off.\n    const activeDim = embeddingProvider?.dimensions ?? 0;\n    const { mismatches, seenDimensions } =\n      activeDim > 0\n        ? loaded.vector.validateDimensions(activeDim)\n        : { mismatches: [], seenDimensions: new Set<number>() };\n\n    if (mismatches.length > 0) {\n      const sample = mismatches\n        .slice(0, 5)\n        .map((m) => `${m.obsId} (dim=${m.dim})`)\n        .join(\", \");\n      const distinct = Array.from(seenDimensions).sort((a, b) => a - b).join(\", \");\n      const dropStale = isDropStaleIndexEnabled();\n      if (dropStale) {\n        console.warn(\n          `[agentmemory] Persisted vector index has ${mismatches.length} of ` +\n            `${loaded.vector.size} vectors with the wrong dimension. Active ` +\n            `provider (${embeddingProvider?.name}) declares ${activeDim}; ` +\n            `dimensions seen on disk: ${distinct}. ` +\n            `AGENTMEMORY_DROP_STALE_INDEX=true is set — discarding the persisted ` +\n            `vectors. Live observations will rebuild the index over time.`,\n        );\n      } else {\n        throw new Error(\n          `[agentmemory] Refusing to start: persisted vector index has ` +\n            `${mismatches.length} of ${loaded.vector.size} vectors with the ` +\n            `wrong dimension. Active provider (${embeddingProvider?.name}) ` +\n            `declares ${activeDim}; dimensions seen on disk: ${distinct}. ` +\n            `First mismatched obsIds: ${sample}. Loading would silently corrupt ` +\n            `search (cross-dimension cosine returns 0). Choose one:\\n` +\n            `  - Re-embed the existing index against the new provider, then start.\\n` +\n            `  - Set AGENTMEMORY_DROP_STALE_INDEX=true to discard the persisted ` +\n            `vectors and rebuild from live observations.\\n` +\n            `  - Switch the embedding provider back to the one that wrote the index.`,\n        );\n      }\n    } else {\n      vectorIndex.restoreFrom(loaded.vector);\n      bootLog(\n        `Loaded persisted vector index (${vectorIndex.size} vectors)`,\n      );\n    }\n  }\n\n  const needsRebuild = bm25Index.size === 0;\n\n  if (needsRebuild) {\n    // Fire-and-forget. rebuildIndex iterates every observation across\n    // every session and AWAITS an embedding-provider call per record.\n    // On a large corpus + rate-limited embedding endpoint that can\n    // take HOURS; awaiting it here blocks every subsequent boot step\n    // (including startViewerServer below, leaving the viewer port\n    // unbound for the duration). The index lazily fills in over time\n    // and search degrades gracefully — partial coverage > no viewer\n    // for hours. Errors still surface via the inner .catch.\n    void rebuildIndex(kv)\n      .then((indexCount) => {\n        if (indexCount > 0) {\n          bootLog(`Search index rebuilt: ${indexCount} entries`);\n          indexPersistence.scheduleSave();\n        }\n      })\n      .catch((err) => {\n        console.warn(`[agentmemory] Failed to rebuild search index:`, err);\n      });\n  } else {\n    // Backfill memories into BM25 for users upgrading from <0.9.5: prior\n    // versions of mem::remember never indexed memories, so the persisted\n    // BM25 covers observations only and `memory_smart_search` returns\n    // empty for everything saved via memory_save (#257). Walk KV.memories\n    // and add the ones missing from the restored index. Idempotent on\n    // re-runs because SearchIndex.has() short-circuits already-indexed\n    // ids.\n    try {\n      const memories = await kv.list<import(\"./types.js\").Memory>(KV.memories);\n      let backfilled = 0;\n      for (const memory of memories) {\n        if (memory.isLatest === false) continue;\n        if (!memory.title || !memory.content) continue;\n        if (bm25Index.has(memory.id)) continue;\n        bm25Index.add({\n          id: memory.id,\n          sessionId: memory.sessionIds?.[0] ?? \"memory\",\n          timestamp: memory.createdAt,\n          type: \"decision\",\n          title: memory.title,\n          facts: [memory.content],\n          narrative: memory.content,\n          concepts: memory.concepts,\n          files: memory.files,\n          importance: memory.strength,\n        });\n        backfilled++;\n      }\n      if (backfilled > 0) {\n        bootLog(\n          `Backfilled ${backfilled} memories into BM25 (legacy index gap)`,\n        );\n        indexPersistence.scheduleSave();\n      }\n    } catch (err) {\n      console.warn(\n        `[agentmemory] Failed to backfill memories into BM25:`,\n        err,\n      );\n    }\n  }\n\n  // Ready / Endpoints lines are emitted via `bootLog` so they're\n  // buffered in quiet mode and printed verbatim under --verbose. The\n  // CLI surfaces a compact summary when it sees the worker reach\n  // ready state.\n  bootLog(\n    `Ready. ${embeddingProvider ? \"Triple-stream (BM25+Vector+Graph)\" : \"BM25+Graph\"} search active.`,\n  );\n  bootLog(\n    `REST API: 128 endpoints at http://localhost:${config.restPort}/agentmemory/*`,\n  );\n  bootLog(\n    `MCP surface (opt-in via \\`npx @ruby_sakura/mcp\\`): ${getAllTools().length} tools · 6 resources · 3 prompts`,\n  );\n\n  const viewerPort = config.restPort + 2;\n  const viewerServer = startViewerServer(\n    viewerPort,\n    kv,\n    sdk,\n    secret,\n    config.restPort,\n  );\n\n  const autoForgetIntervalMs = parseInt(process.env.AUTO_FORGET_INTERVAL_MS || \"3600000\", 10);\n  const consolidationIntervalMs = parseInt(process.env.CONSOLIDATION_INTERVAL_MS || \"7200000\", 10);\n\n  if (process.env.AUTO_FORGET_ENABLED !== \"false\") {\n    const autoForgetTimer = setInterval(async () => {\n      try {\n        await sdk.trigger({ function_id: \"mem::auto-forget\", payload: { dryRun: false } });\n      } catch {}\n    }, autoForgetIntervalMs);\n    autoForgetTimer.unref();\n    bootLog(`Auto-forget: enabled (every ${autoForgetIntervalMs / 60000}m)`);\n  }\n\n  if (process.env.LESSON_DECAY_ENABLED !== \"false\") {\n    const lessonDecayTimer = setInterval(async () => {\n      try {\n        await sdk.trigger({ function_id: \"mem::lesson-decay-sweep\", payload: {} });\n      } catch {}\n    }, 86400000);\n    lessonDecayTimer.unref();\n    bootLog(`Lesson decay sweep: enabled (every 24h)`);\n  }\n\n  if (process.env.INSIGHT_DECAY_ENABLED !== \"false\") {\n    const insightDecayTimer = setInterval(async () => {\n      try {\n        await sdk.trigger({ function_id: \"mem::insight-decay-sweep\", payload: {} });\n      } catch {}\n    }, 86400000);\n    insightDecayTimer.unref();\n  }\n\n  // #771: hourly TTL sweep for the followup-rate diagnostic. The\n  // recent-searches scope only needs the last entry per session;\n  // sweeping anything older than the retention window keeps the scope\n  // from growing unbounded across long-lived deployments.\n  const recentSearchesSweepTimer = setInterval(async () => {\n    try {\n      await sdk.trigger({\n        function_id: \"mem::diagnostic::recent-searches-sweep\",\n        payload: {},\n      });\n    } catch {}\n  }, 60 * 60 * 1000);\n  recentSearchesSweepTimer.unref();\n\n  if (isConsolidationEnabled()) {\n    const consolidationTimer = setInterval(async () => {\n      try {\n        await sdk.trigger({ function_id: \"mem::consolidate-pipeline\", payload: {} });\n      } catch {}\n    }, consolidationIntervalMs);\n    consolidationTimer.unref();\n    bootLog(`Auto-consolidation: enabled (every ${consolidationIntervalMs / 60000}m)`);\n  }\n\n  const shutdown = async () => {\n    console.log(`\\n[agentmemory] Shutting down...`);\n    healthMonitor.stop();\n    dedupMap.stop();\n    indexPersistence.stop();\n    await new Promise<void>((resolve) => viewerServer.close(() => resolve()));\n    await indexPersistence.save().catch((err) => {\n      console.warn(`[agentmemory] Failed to save index on shutdown:`, err);\n    });\n    await sdk.shutdown();\n    clearWorkerPidfile();\n    process.exit(0);\n  };\n  process.on(\"SIGINT\", shutdown);\n  process.on(\"SIGTERM\", shutdown);\n}\n\nmain().catch((err) => {\n  console.error(`[agentmemory] Fatal:`, err);\n  process.exit(1);\n});\n"],"mappings":"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"}