{"version":3,"sources":["../src/agentproto-dir.ts","../src/command-tools.ts","../src/conversations.ts","../src/events.ts","../src/fs-tools.ts","../src/tool-presenter.ts","../src/transcript-writer.ts","../src/transcript-export.ts","../src/json-tolerant.ts","../src/workspaces-config.ts","../src/session-spawn.ts","../src/agent-tools.ts","../src/mcp-discovery.ts","../src/resume-strategies.ts","../src/mcp-imports.ts","../src/tool-subset.ts","../src/session-tools.ts","../src/browser-tools.ts","../src/mcp-apps-adapter.ts","../src/sessions-panel.ts","../src/sessions-panel-app.ts","../src/agents-overview-app.ts","../src/bureau-sessions-app.ts","../src/heartbeat.ts","../src/sessions.ts","../src/orchestration-tools.ts","../src/http-server.ts","../src/mcp-proxy.ts","../src/session-event-bus.ts","../src/event-ring.ts","../src/webhook-notifier.ts","../src/routine-runner.ts","../src/sessions-registry-agent-host.ts","../src/workflow-step-cache.ts","../src/workflow-runner.ts","../src/deferred-tools.ts","../src/supervisor.ts","../src/inbound-watcher.ts","../src/cron-scheduler.ts","../src/orchestrator-gateway.ts","../src/browser-adapters.ts","../src/remote-providers/quick.ts","../src/remote-controller.ts","../src/remote-tools.ts","../src/remote-providers/named.ts","../src/remote-providers/ngrok.ts","../src/remote-providers/registry.ts","../src/tunnel-registry.ts","../src/tunnel-tools.ts","../src/tunnel-adapters.ts","../src/workspace-fs.ts","../src/providers-store.ts","../src/index.ts"],"names":["resolve","stat","readFile","join","text","mkdir","existsSync","writeFile","readdir","isAbsolute","normalize","relative","z","homedir","spawn","fs","resolvePath","dirname","desc","adapters","EventEmitter","rt","mkdirSync","state","server","id","createReadStream","createInterface","policyId","jobId","readFileSync","writeFileSync","randomUUID","isRecord","renameSync","DEFAULT_PERSIST_PATH","loadRuns","saveRuns","ANSI_RE","stripAnsi","PERSIST_DEBOUNCE_MS","fsp","basename","entry","toDescriptor","randomBytes","rm","execFileAsync","promisify","execFile","STARTUP_TIMEOUT_MS","cloudflaredOnPath","assertCloudflaredOnPath","opts","HISTORY_CAP","makeAdapterLister","fields","fsReadFile","fsWriteFile","createMcpServer"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * `.agentproto/` config dir — runtime-managed state at the root of\n * every workspace. Mirrors the `.git/` model: user-content stays at\n * the workspace root (HEARTBEAT.md, conversations/, .agents/) while\n * everything the runtime owns lives in `<workspace>/.agentproto/`.\n *\n * What goes here today:\n *   - `runtime.json` — boot-time snapshot of the live config (PID,\n *     port, resolved workspace, MCP server name, startedAt). Useful\n *     for `cat .agentproto/runtime.json` diagnostics + future tooling\n *     that wants to discover a running gateway from disk.\n *\n * The same snapshot is ALSO mirrored to the central, workspace-\n * independent daemon registry at `~/.agentproto/daemons/<port>.json`\n * (see daemonRegistryDir / writeDaemonRegistryEntry below). The\n * per-workspace file only helps `cat`-style local diagnostics and\n * discovery for REGISTERED workspaces; a daemon launched from an\n * arbitrary cwd (tunnel mode, a repo checkout) writes its workspace\n * file somewhere discovery never walks. The central entry is what\n * makes `agentproto chat` / `sessions` find such a daemon.\n *\n * What does NOT go here:\n *   - HEARTBEAT.md — user-edited content\n *   - conversations/ — user-readable chat history\n *   - .agents/ — user-authored manifests\n *\n * The `.agentproto/` dir is safe to gitignore. The `runtime.json`\n * file contains a per-boot bearer token used to gate mutating HTTP\n * routes (POST /sessions/*, WS /sessions/:id/pty). The token lives\n * in RAM + on disk only — never logged. File mode 0600 below; only\n * processes running as the workspace user (and the daemon itself)\n * can read it. A browser-loaded localhost page CAN'T read this file,\n * which is what defends against the localhost-DNS-rebinding drive-by\n * spawn vector.\n */\n\nimport { mkdir, readdir, readFile, stat, unlink, writeFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\n\nexport interface RuntimeMeta {\n  /** Absolute path to the workspace root the gateway is bound to. */\n  workspace: string\n  /** HTTP listener port. */\n  port: number\n  /** HTTP bind address (loopback or `0.0.0.0`). */\n  bind: string\n  /** Process id of the running gateway. */\n  pid: number\n  /** Wall-clock ISO timestamp at boot. */\n  startedAt: string\n  /** MCP server name advertised in the initialize handshake. */\n  name: string\n  /** AIP doctype names + extensions registered as MCP CRUD tools. */\n  registered: readonly string[]\n  /**\n   * Per-boot bearer token. Required on mutating routes (POST\n   * /sessions/*, POST /sessions/:id/kill, DELETE /sessions/:id, and\n   * WS upgrade to /sessions/:id/pty). Random uuid generated at boot\n   * by createGateway; regenerated each restart.\n   */\n  token: string\n}\n\n/**\n * Create `<workspace>/.agentproto/` (idempotent) and write the\n * `runtime.json` snapshot. Errors are logged but non-fatal — losing\n * the meta file shouldn't crash the gateway, the runtime is still\n * fully functional without it.\n */\nexport async function writeRuntimeMeta(\n  workspace: string,\n  meta: RuntimeMeta,\n): Promise<void> {\n  const dir = join(workspace, \".agentproto\")\n  try {\n    await mkdir(dir, { recursive: true })\n    // mode 0600 so other local users can't read the bearer token.\n    await writeFile(\n      join(dir, \"runtime.json\"),\n      JSON.stringify(meta, null, 2) + \"\\n\",\n      { encoding: \"utf8\", mode: 0o600 },\n    )\n  } catch (err) {\n    console.error(\"[runtime] failed to write .agentproto/runtime.json:\", err)\n  }\n  // Also publish to the central daemon registry so the CLI can discover\n  // this daemon WITHOUT its workspace being registered in\n  // workspaces.json. A daemon launched from an arbitrary cwd (the common\n  // case: `agentproto serve` from a repo checkout, or tunnel mode) lands\n  // its workspace runtime.json somewhere discovery never walks; the\n  // central entry closes that gap. Keyed by port so multiple daemons\n  // coexist. Best-effort — the workspace file above is the source of\n  // truth; this is purely an additional discovery hint.\n  await writeDaemonRegistryEntry(meta)\n}\n\n/** `~/.agentproto/daemons/` — the central, workspace-independent daemon\n *  registry. Each live daemon owns one `<port>.json` here. */\nexport function daemonRegistryDir(): string {\n  return resolve(homedir(), \".agentproto\", \"daemons\")\n}\n\nfunction daemonRegistryPath(port: number): string {\n  return join(daemonRegistryDir(), `${port}.json`)\n}\n\n/**\n * Write `<registry>/<port>.json` (mode 0600 — holds the bearer token).\n * Best-effort; failure here never gates the gateway. Mirrors the\n * per-workspace runtime.json so the same `RuntimeMeta` shape is readable\n * from either location.\n */\nexport async function writeDaemonRegistryEntry(meta: RuntimeMeta): Promise<void> {\n  try {\n    await mkdir(daemonRegistryDir(), { recursive: true })\n    await writeFile(\n      daemonRegistryPath(meta.port),\n      JSON.stringify(meta, null, 2) + \"\\n\",\n      { encoding: \"utf8\", mode: 0o600 },\n    )\n  } catch (err) {\n    console.error(\"[runtime] failed to write daemons/<port>.json:\", err)\n  }\n}\n\n/** Remove a daemon's central registry entry. Best-effort; missing is a\n *  no-op. Called from graceful shutdown alongside unlinkRuntimeMeta. */\nexport async function unlinkDaemonRegistryEntry(port: number): Promise<void> {\n  try {\n    await unlink(daemonRegistryPath(port))\n  } catch {\n    // ENOENT / permission — not worth surfacing on shutdown.\n  }\n}\n\n/**\n * Read every entry in the central daemon registry, newest-first by\n * `startedAt`. No liveness filtering here — callers decide (discovery\n * skips dead PIDs; the sweep deletes them). Malformed / unreadable\n * entries are skipped silently.\n */\nexport async function readDaemonRegistry(): Promise<\n  Array<{ meta: Partial<RuntimeMeta> & Record<string, unknown>; path: string; mtime: Date }>\n> {\n  let names: string[]\n  try {\n    names = await readdir(daemonRegistryDir())\n  } catch {\n    return [] // registry dir doesn't exist yet — no daemons published.\n  }\n  const out: Array<{\n    meta: Partial<RuntimeMeta> & Record<string, unknown>\n    path: string\n    mtime: Date\n  }> = []\n  for (const name of names) {\n    if (!name.endsWith(\".json\")) continue\n    const path = join(daemonRegistryDir(), name)\n    try {\n      const [raw, st] = await Promise.all([readFile(path, \"utf8\"), stat(path)])\n      out.push({ meta: JSON.parse(raw) as Record<string, unknown>, path, mtime: st.mtime })\n    } catch {\n      // skip malformed / unreadable\n    }\n  }\n  // Newest daemon first — discovery prefers the most recently booted.\n  return out.sort((a, b) => b.mtime.getTime() - a.mtime.getTime())\n}\n\n/**\n * Delete central registry entries whose PID is dead (kill -9, crash,\n * reboot). Returns the paths cleaned. Called at `serve` boot — the same\n * footgun the per-workspace sweep guards against, applied to the central\n * registry. Skips `currentPort` (the booting daemon's own entry).\n */\nexport async function sweepStaleDaemonRegistry(currentPort: number): Promise<string[]> {\n  const cleaned: string[] = []\n  for (const entry of await readDaemonRegistry()) {\n    if (entry.meta.port === currentPort) continue\n    const pid = entry.meta.pid\n    if (typeof pid === \"number\" && !isPidAlive(pid)) {\n      try {\n        await unlink(entry.path)\n        cleaned.push(entry.path)\n      } catch {\n        // ignore — best-effort\n      }\n    }\n  }\n  return cleaned\n}\n\n/**\n * Delete `<workspace>/.agentproto/runtime.json`. Best-effort — called\n * from the daemon's graceful shutdown path so a CLI looking for the\n * live daemon doesn't pick up a stale token after this process exits.\n * Missing file is a no-op (the daemon may never have written one).\n */\nexport async function unlinkRuntimeMeta(\n  workspace: string,\n  port?: number,\n): Promise<void> {\n  try {\n    await unlink(join(workspace, \".agentproto\", \"runtime.json\"))\n  } catch {\n    // ENOENT / permission — not worth surfacing on shutdown.\n  }\n  // Tear down the matching central registry entry too (when the caller\n  // knows the port) so discovery doesn't pick up a dead daemon.\n  if (typeof port === \"number\") await unlinkDaemonRegistryEntry(port)\n}\n\n/**\n * Read a runtime.json from `<workspace>/.agentproto/`. Returns the\n * parsed object (no validation) plus the on-disk mtime, or null when\n * the file is missing / unreadable / malformed.\n */\nexport async function readRuntimeMeta(workspace: string): Promise<{\n  meta: Partial<RuntimeMeta> & Record<string, unknown>\n  mtime: Date\n} | null> {\n  const path = join(workspace, \".agentproto\", \"runtime.json\")\n  try {\n    const [raw, st] = await Promise.all([readFile(path, \"utf8\"), stat(path)])\n    const meta = JSON.parse(raw) as Record<string, unknown>\n    return { meta, mtime: st.mtime }\n  } catch {\n    return null\n  }\n}\n\n/**\n * For each `workspace` path, check whether its runtime.json points\n * at a now-dead PID; if so, delete it. Returns the list of paths\n * that were cleaned. Called by `agentproto serve` at boot to keep\n * the discovery layer's view of \"live daemons\" honest — a stale\n * file with the same port as the new daemon is the classic source\n * of `sessions_unauthorized` 401s.\n *\n * Skips the running daemon's own workspace (passed in as\n * `currentWorkspace`) since that file is OURS to write.\n */\nexport async function sweepStaleRuntimeMetas(\n  workspaces: readonly string[],\n  currentWorkspace: string,\n): Promise<string[]> {\n  const cleaned: string[] = []\n  for (const ws of workspaces) {\n    if (ws === currentWorkspace) continue\n    const meta = await readRuntimeMeta(ws)\n    if (!meta) continue\n    const pid = meta.meta.pid\n    if (typeof pid === \"number\" && !isPidAlive(pid)) {\n      try {\n        await unlink(join(ws, \".agentproto\", \"runtime.json\"))\n        cleaned.push(join(ws, \".agentproto\", \"runtime.json\"))\n      } catch {\n        // ignore — best-effort\n      }\n    }\n  }\n  return cleaned\n}\n\nfunction isPidAlive(pid: number): boolean {\n  try {\n    process.kill(pid, 0)\n    return true\n  } catch (err) {\n    const code = (err as NodeJS.ErrnoException).code\n    if (code === \"EPERM\") return true // exists, foreign user\n    return false\n  }\n}\n","/**\n * Shell-execution MCP tools for the runtime.\n *\n * The runtime is a remote shell as far as cloud agents are concerned —\n * the workspace lives on the user's machine, so the only place a\n * `claude -p`, `gh pr view`, `pnpm test` etc. can actually run *is*\n * the user's machine. This module exposes one MCP tool,\n * `command_execute`, that any MCP client (cloud Guilde Blake,\n * Claude Code as a sub-agent, …) can call to spawn a subprocess.\n *\n * ## Allowlist\n *\n * Default-deny. The runtime reads\n * `<workspace>/.agentproto/allowed-commands.json` on every call (cheap\n * stat; cached for 1s) for the list of allowed command basenames.\n * Missing / empty file ⇒ no commands run. The error message points the\n * user at the file path so they know exactly where to opt in.\n *\n * Allowlist file shape:\n *   { \"version\": 1, \"commands\": [\"claude\", \"gh\", \"pnpm\", \"node\"] }\n *\n * Match is by command BASENAME (`/usr/local/bin/claude` → `claude`)\n * to keep the allowlist short and not break when users have multiple\n * binaries on their PATH.\n *\n * ## Safety notes\n *\n * - We use `spawn()` with `shell: false` so arguments are passed\n *   verbatim — no shell interpolation surprises.\n * - `cwd` is anchored to the workspace root via the same path-escape\n *   guard used by `fs-tools.ts`. Callers can't run a subprocess in\n *   `/etc` unless they also bind-mounted it inside the workspace.\n * - Every spawn has a `timeoutMs` cap (default 60s, max 600s). Hung\n *   subprocesses can't pin the runtime forever.\n */\n\nimport { spawn } from \"node:child_process\"\nimport { existsSync } from \"node:fs\"\nimport { readFile, stat } from \"node:fs/promises\"\nimport {\n  basename,\n  isAbsolute,\n  join,\n  normalize,\n  relative,\n  resolve,\n} from \"node:path\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\n\nconst DEFAULT_TIMEOUT_MS = 60_000\nconst MAX_TIMEOUT_MS = 600_000\nconst ALLOWLIST_REL = \".agentproto/allowed-commands.json\"\n\nexport interface RegisterCommandToolsOptions {\n  workspace: string\n}\n\ninterface AllowlistFile {\n  version?: number\n  commands?: string[]\n}\n\ninterface AllowlistCacheEntry {\n  mtimeMs: number\n  commands: Set<string>\n}\n\nlet allowlistCache: { path: string; entry: AllowlistCacheEntry } | null = null\n\nexport async function loadAllowlist(workspace: string): Promise<Set<string>> {\n  const path = resolve(workspace, ALLOWLIST_REL)\n  if (!existsSync(path)) {\n    allowlistCache = null\n    return new Set()\n  }\n  try {\n    const s = await stat(path)\n    if (\n      allowlistCache &&\n      allowlistCache.path === path &&\n      allowlistCache.entry.mtimeMs === s.mtimeMs\n    ) {\n      return allowlistCache.entry.commands\n    }\n    const raw = await readFile(path, \"utf8\")\n    const parsed = JSON.parse(raw) as AllowlistFile\n    const list = Array.isArray(parsed.commands) ? parsed.commands : []\n    const commands = new Set(\n      list\n        .filter((x): x is string => typeof x === \"string\" && x.length > 0)\n        .map(x => x.trim()),\n    )\n    allowlistCache = { path, entry: { mtimeMs: s.mtimeMs, commands } }\n    return commands\n  } catch (err) {\n    // Bad JSON / unreadable file ⇒ deny all and surface in the error\n    // the next caller gets. Don't poison the cache.\n    console.error(\n      `[runtime] failed to load ${ALLOWLIST_REL} (will deny all):`,\n      err,\n    )\n    allowlistCache = null\n    return new Set()\n  }\n}\n\nexport function makeCwdAnchor(workspace: string): (input: string | undefined) => string {\n  const root = resolve(workspace)\n  return (input?: string) => {\n    if (!input || input.length === 0) return root\n    const candidate = isAbsolute(input)\n      ? normalize(input)\n      : normalize(join(root, input))\n    const rel = relative(root, candidate)\n    if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n      throw new Error(\n        `cwd escapes the workspace: '${input}' (workspace=${root})`,\n      )\n    }\n    return candidate\n  }\n}\n\nexport interface ExecuteResult {\n  exitCode: number\n  signal: string | null\n  stdout: string\n  stderr: string\n  truncated?: boolean\n  durationMs: number\n}\n\n/**\n * Register `command_execute` on the given MCP server. The tool returns\n * a JSON-encoded `ExecuteResult` as a single text content item — that\n * matches the response shape `@modelcontextprotocol/server-filesystem`\n * uses for `file_read` and friends, so the existing\n * `parseReadFileResponse`-style parsers in workspace-providers can\n * decode it without bespoke logic.\n */\nexport function registerCommandTools(\n  server: McpServer,\n  opts: RegisterCommandToolsOptions,\n): void {\n  const anchorCwd = makeCwdAnchor(opts.workspace)\n\n  server.tool(\n    \"command_execute\",\n    \"Run a shell command on the host running the runtime. The command basename must be in `<workspace>/.agentproto/allowed-commands.json`; default-deny otherwise. Captures stdout / stderr / exit code and returns them as JSON. Use this to drive local CLIs (Claude Code, gh, pnpm, …) from a remote agent.\",\n    {\n      command: z\n        .string()\n        .min(1)\n        .describe(\n          \"Executable name or absolute path. Must be allowlisted by basename in the workspace's allowed-commands.json.\",\n        ),\n      args: z\n        .array(z.string())\n        .optional()\n        .describe(\n          \"Argv array. Passed verbatim — no shell expansion (we spawn with shell:false so quoting doesn't bite).\",\n        ),\n      cwd: z\n        .string()\n        .optional()\n        .describe(\n          \"Working directory, workspace-relative or an absolute path inside the workspace. Defaults to the workspace root.\",\n        ),\n      stdin: z\n        .string()\n        .optional()\n        .describe(\"Optional input piped to the process's stdin.\"),\n      timeoutMs: z\n        .number()\n        .int()\n        .positive()\n        .max(MAX_TIMEOUT_MS)\n        .optional()\n        .describe(\n          `Hard kill after this many ms. Defaults to ${DEFAULT_TIMEOUT_MS}; capped at ${MAX_TIMEOUT_MS}.`,\n        ),\n    },\n    async ({ command, args, cwd, stdin, timeoutMs }) => {\n      const allowlist = await loadAllowlist(opts.workspace)\n      const baseName = basename(command)\n      if (!allowlist.has(baseName)) {\n        const allowed = [...allowlist].sort().join(\", \") || \"(empty)\"\n        throw new Error(\n          `command '${baseName}' is not in the allowlist. ` +\n            `Add it to ${join(opts.workspace, ALLOWLIST_REL)} ` +\n            `under \"commands\": [...]. Currently allowed: ${allowed}.`,\n        )\n      }\n      const resolvedCwd = anchorCwd(cwd)\n      const limit = Math.min(timeoutMs ?? DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS)\n      const result = await runCommand({\n        command,\n        args: args ?? [],\n        cwd: resolvedCwd,\n        stdin,\n        timeoutMs: limit,\n      })\n      return {\n        content: [{ type: \"text\" as const, text: JSON.stringify(result) }],\n      }\n    },\n  )\n}\n\nexport interface RunCommandInput {\n  command: string\n  args: string[]\n  cwd: string\n  stdin?: string\n  timeoutMs: number\n}\n\nconst STREAM_BUFFER_CAP = 1_048_576 // 1 MiB per stream\n\nexport async function runCommand(input: RunCommandInput): Promise<ExecuteResult> {\n  return new Promise<ExecuteResult>(resolvePromise => {\n    const startedAt = Date.now()\n    const child = spawn(input.command, input.args, {\n      cwd: input.cwd,\n      shell: false,\n      // Inherit user env so PATH lookups for `claude`, `gh`, etc. work.\n      env: process.env,\n      stdio: [\"pipe\", \"pipe\", \"pipe\"],\n    })\n\n    let stdout = \"\"\n    let stderr = \"\"\n    let truncated = false\n    let timedOut = false\n\n    function appendCapped(buf: string, chunk: Buffer): string {\n      if (buf.length >= STREAM_BUFFER_CAP) {\n        truncated = true\n        return buf\n      }\n      const room = STREAM_BUFFER_CAP - buf.length\n      const text = chunk.toString(\"utf8\")\n      if (text.length > room) {\n        truncated = true\n        return buf + text.slice(0, room)\n      }\n      return buf + text\n    }\n    child.stdout?.on(\"data\", d => {\n      stdout = appendCapped(stdout, d)\n    })\n    child.stderr?.on(\"data\", d => {\n      stderr = appendCapped(stderr, d)\n    })\n\n    if (input.stdin) {\n      child.stdin?.write(input.stdin)\n    }\n    child.stdin?.end()\n\n    const timer = setTimeout(() => {\n      timedOut = true\n      // SIGTERM first; the close handler resolves either way. Ignore\n      // EPERM if the child is already gone.\n      try {\n        child.kill(\"SIGTERM\")\n      } catch {\n        /* noop */\n      }\n      // Hard kill 2s later if it hasn't exited.\n      setTimeout(() => {\n        try {\n          child.kill(\"SIGKILL\")\n        } catch {\n          /* noop */\n        }\n      }, 2_000).unref()\n    }, input.timeoutMs)\n    timer.unref()\n\n    child.on(\"error\", err => {\n      clearTimeout(timer)\n      // spawn errors (ENOENT, EACCES) become exitCode -1 with the\n      // message in stderr — the JSON shape stays consistent.\n      resolvePromise({\n        exitCode: -1,\n        signal: null,\n        stdout,\n        stderr: stderr + (stderr ? \"\\n\" : \"\") + (err as Error).message,\n        truncated,\n        durationMs: Date.now() - startedAt,\n      })\n    })\n    child.on(\"close\", (code, signal) => {\n      clearTimeout(timer)\n      resolvePromise({\n        exitCode: typeof code === \"number\" ? code : -1,\n        signal: signal ?? (timedOut ? \"SIGTERM-timeout\" : null),\n        stdout,\n        stderr,\n        truncated,\n        durationMs: Date.now() - startedAt,\n      })\n    })\n  })\n}\n","/**\n * Append-only conversation persistence as plain markdown.\n *\n * Each conversation is a file at `<workspace>/conversations/<id>.md`\n * with a frontmatter header (`schema: conversation/v1`, `id`, `agent`,\n * `started`, `status`) and a body composed of `## <role> — <iso>`\n * blocks. Append-only: turns are concatenated to the body, never\n * rewritten in place. Readers tolerant to clock skew use the timestamp\n * in each block, not file mtime.\n *\n * The format is intentionally trivial — git-diffable, human-editable,\n * survives `cat`. Designed to converge with the AIP runtime/v1 spec\n * (TBD) once it lands.\n */\n\nimport { existsSync } from \"node:fs\"\nimport { mkdir, readFile, readdir, writeFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\n\nconst FRONTMATTER_RE = /^---\\n([\\s\\S]*?)\\n---\\n/\n\nexport type ConvRole = \"user\" | \"assistant\" | \"system\"\n\nexport interface ConversationMeta {\n  id: string\n  agent: string\n  started: string\n  status: \"open\" | \"closed\"\n}\n\nexport interface ConversationTurn {\n  role: ConvRole\n  at: string\n  /** Optional sub-attribution after the role (e.g. agent id). */\n  attribution?: string\n  content: string\n}\n\nexport interface ConversationStore {\n  /**\n   * Open a conversation. If the file doesn't exist, it's created with\n   * a frontmatter header. If it exists, no-op (idempotent).\n   */\n  open(id: string, meta: { agent: string }): Promise<void>\n  appendTurn(\n    id: string,\n    role: ConvRole,\n    content: string,\n    opts?: { attribution?: string; at?: string },\n  ): Promise<void>\n  read(\n    id: string,\n  ): Promise<{ meta: ConversationMeta; turns: ConversationTurn[] }>\n  list(): Promise<Array<{ id: string; meta: ConversationMeta }>>\n  /** Workspace-relative path to the conv file, for tooling. */\n  pathFor(id: string): string\n}\n\nexport interface FileConversationStoreOptions {\n  /** Absolute workspace root. */\n  workspace: string\n  /** Override `<workspace>/conversations`. */\n  dir?: string\n}\n\nexport function fileConversationStore(\n  opts: FileConversationStoreOptions,\n): ConversationStore {\n  const dir = opts.dir ?? join(opts.workspace, \"conversations\")\n\n  const filePath = (id: string) => join(dir, `${id}.md`)\n\n  return {\n    pathFor: filePath,\n\n    async open(id, meta) {\n      await mkdir(dir, { recursive: true })\n      const path = filePath(id)\n      if (existsSync(path)) return\n      const header = renderHeader({\n        id,\n        agent: meta.agent,\n        started: new Date().toISOString(),\n        status: \"open\",\n      })\n      await writeFile(path, header, \"utf8\")\n    },\n\n    async appendTurn(id, role, content, options) {\n      const path = filePath(id)\n      // Lazy-open: if a caller appends without opening, create the\n      // file so the operation never silently drops a turn.\n      if (!existsSync(path)) {\n        await this.open(id, { agent: options?.attribution ?? \"unknown\" })\n      }\n      const block = renderTurn({\n        role,\n        at: options?.at ?? new Date().toISOString(),\n        attribution: options?.attribution,\n        content,\n      })\n      // Append a leading blank line so the new block is always\n      // separated from whatever's above (header or prev turn).\n      await writeFile(path, block, { encoding: \"utf8\", flag: \"a\" })\n    },\n\n    async read(id) {\n      const path = filePath(id)\n      const source = await readFile(path, \"utf8\")\n      return parseConversation(source, id)\n    },\n\n    async list() {\n      if (!existsSync(dir)) return []\n      const entries = await readdir(dir, { withFileTypes: true })\n      const out: Array<{ id: string; meta: ConversationMeta }> = []\n      for (const entry of entries) {\n        if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue\n        const id = entry.name.slice(0, -3)\n        try {\n          const source = await readFile(join(dir, entry.name), \"utf8\")\n          const { meta } = parseConversation(source, id)\n          out.push({ id, meta })\n        } catch {\n          // Skip malformed conv files rather than crash list().\n        }\n      }\n      return out\n    },\n  }\n}\n\n// ── render ───────────────────────────────────────────────────────────\n\nfunction renderHeader(meta: ConversationMeta): string {\n  return [\n    \"---\",\n    `schema: conversation/v1`,\n    `id: ${meta.id}`,\n    `agent: ${meta.agent}`,\n    `started: ${meta.started}`,\n    `status: ${meta.status}`,\n    \"---\",\n    \"\",\n    \"\",\n  ].join(\"\\n\")\n}\n\nfunction renderTurn(turn: ConversationTurn): string {\n  const heading = turn.attribution\n    ? `## ${turn.role} — ${turn.at} (${turn.attribution})`\n    : `## ${turn.role} — ${turn.at}`\n  return `${heading}\\n\\n${turn.content.trimEnd()}\\n\\n`\n}\n\n// ── parse ────────────────────────────────────────────────────────────\n\ninterface ParsedConversation {\n  meta: ConversationMeta\n  turns: ConversationTurn[]\n}\n\nfunction parseConversation(source: string, fallbackId: string): ParsedConversation {\n  const match = source.match(FRONTMATTER_RE)\n  let meta: ConversationMeta = {\n    id: fallbackId,\n    agent: \"unknown\",\n    started: \"\",\n    status: \"open\",\n  }\n  let body = source\n  if (match) {\n    meta = parseFrontmatter(match[1] ?? \"\", fallbackId)\n    body = source.slice(match[0].length)\n  }\n\n  const turns: ConversationTurn[] = []\n  // Split on `## <role> — <iso>` headings. Conservative — anything\n  // that doesn't match is treated as continuation of the prior turn.\n  const lines = body.split(\"\\n\")\n  let current: ConversationTurn | null = null\n  let buffer: string[] = []\n\n  const flush = () => {\n    if (!current) return\n    current.content = buffer.join(\"\\n\").trim()\n    turns.push(current)\n    current = null\n    buffer = []\n  }\n\n  const headingRe =\n    /^##\\s+(user|assistant|system)\\s+—\\s+(\\S+)(?:\\s+\\(([^)]+)\\))?\\s*$/\n\n  for (const line of lines) {\n    const m = line.match(headingRe)\n    if (m) {\n      flush()\n      current = {\n        role: m[1] as ConvRole,\n        at: m[2] ?? \"\",\n        attribution: m[3],\n        content: \"\",\n      }\n      continue\n    }\n    if (current) buffer.push(line)\n  }\n  flush()\n\n  return { meta, turns }\n}\n\nfunction parseFrontmatter(\n  raw: string,\n  fallbackId: string,\n): ConversationMeta {\n  const out: Record<string, string> = {}\n  for (const line of raw.split(\"\\n\")) {\n    const colon = line.indexOf(\":\")\n    if (colon < 1) continue\n    const key = line.slice(0, colon).trim()\n    const value = line.slice(colon + 1).trim()\n    out[key] = value\n  }\n  return {\n    id: out.id ?? fallbackId,\n    agent: out.agent ?? \"unknown\",\n    started: out.started ?? \"\",\n    status: (out.status === \"closed\" ? \"closed\" : \"open\"),\n  }\n}\n","/**\n * In-process event bus for the runtime gateway. Anything the daemon\n * does that an external observer might want to watch (heartbeat fired,\n * conversation turn appended, boot completed, …) flows through here.\n *\n * The HTTP server's `/events` SSE stream subscribes to it and forwards\n * each event as a `data: <json>\\n\\n` frame. Tests and embedded usage\n * subscribe directly via `events.on()`.\n */\n\nimport { EventEmitter } from \"node:events\"\n\nexport interface BootEvent {\n  type: \"boot\"\n  at: string\n  workspace: string\n  registered: readonly string[]\n}\n\nexport interface HeartbeatFiredEvent {\n  type: \"heartbeat-fired\"\n  at: string\n  agent: string\n  conversationId: string\n  prompt: string\n  reply: string\n  durationMs: number\n}\n\nexport interface HeartbeatErrorEvent {\n  type: \"heartbeat-error\"\n  at: string\n  agent?: string\n  error: string\n}\n\nexport interface ConvTurnEvent {\n  type: \"conv-turn-appended\"\n  at: string\n  conversationId: string\n  role: \"user\" | \"assistant\"\n  contentPreview: string\n}\n\n/**\n * One log line from a supervised tunnel provider (cloudflared today).\n * Surfaced verbatim so users can debug \"why didn't my remote URL come\n * up\" by tailing /events.\n */\nexport interface RemoteLogEvent {\n  type: \"remote-log\"\n  at: string\n  line: string\n}\n\nexport type RuntimeEvent =\n  | BootEvent\n  | HeartbeatFiredEvent\n  | HeartbeatErrorEvent\n  | ConvTurnEvent\n  | RemoteLogEvent\n\nexport interface RuntimeEvents {\n  on<E extends RuntimeEvent[\"type\"]>(\n    type: E,\n    handler: (ev: Extract<RuntimeEvent, { type: E }>) => void,\n  ): () => void\n  onAny(handler: (ev: RuntimeEvent) => void): () => void\n  emit(ev: RuntimeEvent): void\n}\n\nexport function createRuntimeEvents(): RuntimeEvents {\n  const ee = new EventEmitter()\n  ee.setMaxListeners(50)\n\n  return {\n    on(type, handler) {\n      const wrapped = (ev: RuntimeEvent) => {\n        if (ev.type === type) handler(ev as Extract<RuntimeEvent, { type: typeof type }>)\n      }\n      ee.on(\"event\", wrapped)\n      return () => ee.off(\"event\", wrapped)\n    },\n    onAny(handler) {\n      ee.on(\"event\", handler)\n      return () => ee.off(\"event\", handler)\n    },\n    emit(ev) {\n      ee.emit(\"event\", ev)\n    },\n  }\n}\n","/**\n * Filesystem MCP tools registered on the runtime's MCP server.\n *\n * The runtime already exposes AIP CRUD verbs (create_tool, load_agent, …)\n * via @agentproto/mcp-server. To make the workspace genuinely reachable\n * to remote MCP clients (Guilde cloud agents through a tunnel, IDEs,\n * etc.), we also register canonical filesystem tools that match the\n * shape used by `@modelcontextprotocol/server-filesystem` so existing\n * MCP-fs proxy clients can target the runtime without bespoke logic:\n *\n *   file_read        ({ path })          → string\n *   file_write       ({ path, content }) → \"ok\"\n *   directory_list   ({ path? })         → \"[FILE] x\\n[DIR]  y\" lines\n *   file_info        ({ path })          → { name, type, size, modified }\n *   directory_create ({ path })          → \"ok\"\n *   file_delete      ({ path })          → \"ok\"\n *\n * All paths are resolved relative to the workspace root via the same\n * escape guard used by `WorkspaceFs`. Absolute paths inside the root\n * are accepted (so callers that prefix `basePath` with the absolute\n * workspace path keep working).\n */\n\nimport {\n  mkdir,\n  readFile,\n  readdir,\n  rm,\n  stat,\n  writeFile,\n} from \"node:fs/promises\"\nimport { dirname, isAbsolute, join, normalize, relative, resolve } from \"node:path\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\n\nexport interface RegisterFsToolsOptions {\n  workspace: string\n}\n\nclass FsPathError extends Error {\n  constructor(message: string) {\n    super(message)\n    this.name = \"FsPathError\"\n  }\n}\n\nfunction makeAnchor(workspace: string): (input: string) => string {\n  const root = resolve(workspace)\n  return (input: string) => {\n    if (typeof input !== \"string\" || input.length === 0) {\n      throw new FsPathError(\"path must be a non-empty string\")\n    }\n    const candidate = isAbsolute(input)\n      ? normalize(input)\n      : normalize(join(root, input))\n    const rel = relative(root, candidate)\n    if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n      throw new FsPathError(`path escapes the workspace: '${input}'`)\n    }\n    return candidate\n  }\n}\n\nfunction text(value: string | object): {\n  content: Array<{ type: \"text\"; text: string }>\n} {\n  return {\n    content: [\n      {\n        type: \"text\",\n        text: typeof value === \"string\" ? value : JSON.stringify(value),\n      },\n    ],\n  }\n}\n\nexport function registerFsTools(\n  server: McpServer,\n  opts: RegisterFsToolsOptions,\n): void {\n  const anchor = makeAnchor(opts.workspace)\n\n  server.tool(\n    \"file_read\",\n    \"Read a UTF-8 file from the workspace.\",\n    { path: z.string().describe(\"Workspace-relative path to the file.\") },\n    async ({ path }) => {\n      const abs = anchor(path)\n      const buf = await readFile(abs)\n      return text(buf.toString(\"utf8\"))\n    },\n  )\n\n  server.tool(\n    \"file_write\",\n    \"Write a file to the workspace. Parent directories are created on demand.\",\n    {\n      path: z.string().describe(\"Workspace-relative path to the file.\"),\n      content: z.string().describe(\"File body (UTF-8).\"),\n    },\n    async ({ path, content }) => {\n      const abs = anchor(path)\n      await mkdir(dirname(abs), { recursive: true })\n      await writeFile(abs, content, \"utf8\")\n      return text(\"ok\")\n    },\n  )\n\n  server.tool(\n    \"directory_list\",\n    \"List entries of a directory in the workspace. Returns one '[FILE]' or '[DIR]' line per entry, mirroring `@modelcontextprotocol/server-filesystem`.\",\n    {\n      path: z\n        .string()\n        .optional()\n        .describe(\"Workspace-relative directory (defaults to workspace root).\"),\n    },\n    async ({ path }) => {\n      const abs = anchor(path && path.length > 0 ? path : \".\")\n      const entries = await readdir(abs, { withFileTypes: true })\n      const lines = entries.map(e =>\n        e.isDirectory() ? `[DIR]  ${e.name}` : `[FILE] ${e.name}`,\n      )\n      return text(lines.join(\"\\n\"))\n    },\n  )\n\n  server.tool(\n    \"file_info\",\n    \"Stat a file or directory in the workspace.\",\n    { path: z.string().describe(\"Workspace-relative path.\") },\n    async ({ path }) => {\n      const abs = anchor(path)\n      const info = await stat(abs)\n      return text({\n        name: abs.split(\"/\").pop() ?? path,\n        path,\n        type: info.isDirectory() ? \"directory\" : \"file\",\n        size: info.size,\n        modified: info.mtime.toISOString(),\n        created: info.birthtime.toISOString(),\n      })\n    },\n  )\n\n  server.tool(\n    \"directory_create\",\n    \"Create a directory (recursive) in the workspace.\",\n    { path: z.string().describe(\"Workspace-relative directory path.\") },\n    async ({ path }) => {\n      const abs = anchor(path)\n      await mkdir(abs, { recursive: true })\n      return text(\"ok\")\n    },\n  )\n\n  server.tool(\n    \"file_delete\",\n    \"Delete a file or empty directory in the workspace.\",\n    { path: z.string().describe(\"Workspace-relative path.\") },\n    async ({ path }) => {\n      const abs = anchor(path)\n      await rm(abs, { recursive: true, force: true })\n      return text(\"ok\")\n    },\n  )\n}\n","/**\n * Turns a raw tool-call name + args (and its eventual result) into a short,\n * human-readable line for ring-buffer / CLI / transcript rendering. Without\n * this, every tool call renders as a bare `[tool] view` with no args and no\n * outcome — this module is the one place that knows how to summarize both.\n */\n\nconst SALIENT_ARG_KEYS = [\n  \"file_path\",\n  \"path\",\n  \"filePath\",\n  \"file\",\n  \"command\",\n  \"pattern\",\n  \"query\",\n  \"q\",\n  \"url\",\n  \"todos\",\n  \"description\",\n  \"prompt\",\n] as const\n\nconst MAX_CALL_LENGTH = 120\nconst MAX_RESULT_LENGTH = 160\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction truncate(value: string, max: number): string {\n  const oneLine = value.replace(/\\s+/g, \" \").trim()\n  return oneLine.length > max ? `${oneLine.slice(0, max - 1)}…` : oneLine\n}\n\nfunction formatArgValue(value: unknown): string {\n  if (typeof value === \"string\") return value\n  if (Array.isArray(value)) return `${value.length} item${value.length === 1 ? \"\" : \"s\"}`\n  if (isRecord(value)) return JSON.stringify(value)\n  return String(value)\n}\n\nfunction pickSalientArg(args: Record<string, unknown>): string | null {\n  for (const key of SALIENT_ARG_KEYS) {\n    const value = args[key]\n    if (value !== undefined && value !== null && value !== \"\") {\n      return formatArgValue(value)\n    }\n  }\n  return null\n}\n\ntype BespokeFormatter = (args: Record<string, unknown>) => string\n\nfunction subagentSummary(args: Record<string, unknown>): string {\n  const description =\n    typeof args.description === \"string\"\n      ? args.description\n      : typeof args.prompt === \"string\"\n        ? args.prompt\n        : \"subagent\"\n  return `↳ subagent: ${truncate(description, MAX_CALL_LENGTH)}`\n}\n\n// Bespoke one-liners for control tools where the generic arg-sniffing\n// below would either miss the point (ScheduleWakeup's payload isn't a\n// file/command/pattern) or just repeat the tool name pointlessly\n// (TodoWrite, ExitPlanMode carry no salient single-value arg).\nconst BESPOKE_TOOLS: Record<string, BespokeFormatter> = {\n  schedulewakeup: (args) => {\n    const delay = args.delaySeconds ?? args.delay ?? \"?\"\n    const reason = typeof args.reason === \"string\" ? args.reason : \"\"\n    return reason ? `⏰ wake in ${delay}s — ${reason}` : `⏰ wake in ${delay}s`\n  },\n  task: subagentSummary,\n  agent: subagentSummary,\n  todowrite: (args) => {\n    const todos = Array.isArray(args.todos) ? args.todos : []\n    return `☑ todos (${todos.length})`\n  },\n  exitplanmode: () => \"📋 plan ready\",\n}\n\n/** A one-line human summary of a tool call, e.g. `read src/foo.ts` or `⏰ wake in 30s — checking CI`. */\nexport function formatToolCall(toolName: string, args: unknown): string {\n  const name = toolName || \"tool\"\n  const argsRecord = isRecord(args) ? args : {}\n\n  const bespoke = BESPOKE_TOOLS[name.toLowerCase()]\n  if (bespoke) return bespoke(argsRecord)\n\n  const salient = pickSalientArg(argsRecord)\n  if (salient !== null) {\n    // Some ACP agents (e.g. claude-agent-acp) already bake the salient\n    // value into a curated title — \"Read src/foo.ts\" alongside\n    // arguments.path === \"src/foo.ts\". Appending it again would render\n    // \"Read src/foo.ts src/foo.ts\". Only append when it adds new info.\n    if (name.toLowerCase().includes(salient.toLowerCase())) {\n      return truncate(name, MAX_CALL_LENGTH)\n    }\n    return truncate(`${name} ${salient}`, MAX_CALL_LENGTH)\n  }\n\n  if (Object.keys(argsRecord).length === 0) return name\n\n  return truncate(`${name} ${JSON.stringify(args)}`, MAX_CALL_LENGTH)\n}\n\nfunction extractText(value: unknown): string | null {\n  if (value == null) return null\n  if (typeof value === \"string\") return value\n  if (Array.isArray(value)) {\n    const parts = value.map(extractText).filter((v): v is string => v != null)\n    return parts.length ? parts.join(\"\\n\") : null\n  }\n  if (isRecord(value)) {\n    if (typeof value.text === \"string\") return value.text\n    if (typeof value.message === \"string\") return value.message\n    if (Array.isArray(value.content)) return extractText(value.content)\n    if (typeof value.error === \"string\") return value.error\n    if (isRecord(value.error) && typeof value.error.message === \"string\") {\n      return value.error.message\n    }\n    return null\n  }\n  return null\n}\n\n/**\n * A short outcome line for a completed tool call, or `null` when there's\n * nothing useful to show (e.g. an empty/void result). `toolName` is\n * accepted for parity with `formatToolCall` and future bespoke result\n * formatting, but generic text extraction covers today's cases.\n */\nexport function formatToolResult(\n  toolName: string | undefined,\n  result: unknown,\n  isError: boolean,\n): string | null {\n  void toolName\n  const text = extractText(result)\n\n  if (isError) {\n    const message = text ?? (result != null ? JSON.stringify(result) : \"failed\")\n    const firstLine = message.split(/\\r?\\n/)[0] ?? message\n    return truncate(firstLine, MAX_RESULT_LENGTH)\n  }\n\n  if (text == null) return null\n  const trimmed = text.trim()\n  if (!trimmed) return null\n\n  const lines = trimmed.split(/\\r?\\n/)\n  if (lines.length > 1) {\n    const bytes = Buffer.byteLength(trimmed, \"utf8\")\n    return `${lines.length} lines, ${bytes}B`\n  }\n  return truncate(lines[0]!, MAX_RESULT_LENGTH)\n}\n","/**\n * Per-session structured event capture — one append-only JSONL file per\n * agent-cli session, written at the same tap point where `projectEvent`\n * (sessions.ts) flattens `StreamEvent`s into the ANSI ring buffer, but\n * BEFORE that flattening happens. Gives agentproto the Claude-Code\n * property: a daemon-owned structured transcript that survives a daemon\n * restart (the ring buffer doesn't) and that any frontend can render,\n * not just the two adapters `transcript-export.ts` knows how to re-read\n * from their own native stores.\n *\n * File layout: `~/.agentproto/sessions/<sessionId>/events.jsonl`, one\n * JSON object per line: `{seq, ts, kind, ...fields}`.\n *\n * PTY (`terminal`) and `command` sessions never call into this writer —\n * they have no structured event source (see report-transcript-\n * architecture.md finding C.17), so this module is only ever driven from\n * `agent-cli` sessions' `runAgentTurn`.\n */\n\nimport { createWriteStream, mkdirSync, type WriteStream } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport type { AgentStreamEvent } from \"./sessions.js\"\n\n/** Debounce window for flushing a buffered text-delta/thought fragment\n *  that hasn't hit a newline yet. Keeps a long no-newline stream from\n *  sitting in memory indefinitely without also spamming one record per\n *  token — mirrors the \"coalesce, don't spam\" rule `projectEvent`\n *  already applies to the ring buffer, just with a disk-durability\n *  angle added. */\nconst DEBOUNCE_MS = 250\n\n/** `baseDir` defaults to `~/.agentproto/sessions` — overridable so tests\n *  (and a future `--home` style daemon flag) can redirect writes away from\n *  the real home directory instead of mocking `node:os`. */\nexport function sessionTranscriptDir(sessionId: string, baseDir?: string): string {\n  return join(baseDir ?? join(homedir(), \".agentproto\", \"sessions\"), sessionId)\n}\n\nexport function sessionEventsPath(sessionId: string, baseDir?: string): string {\n  return join(sessionTranscriptDir(sessionId, baseDir), \"events.jsonl\")\n}\n\nexport interface TranscriptWriter {\n  /** Record the outgoing message for a new turn. Not an ACP `StreamEvent`\n   *  kind (ACP's own \"agent-prompt\" means the agent asking the human a\n   *  question, the opposite direction) — recorded under its own\n   *  \"user-prompt\" kind so turns stay reconstructable without overloading\n   *  that name. */\n  recordPrompt(sessionId: string, message: unknown): void\n  /** Record one structured stream event, ahead of `projectEvent`'s\n   *  flattening. Coalesces consecutive text-delta/thought chunks the same\n   *  way the ring buffer does. */\n  recordEvent(sessionId: string, evt: AgentStreamEvent): void\n  /** Flush buffers and close the session's append stream. Safe to call\n   *  more than once (subsequent calls are no-ops) and safe to call for a\n   *  session that never wrote anything (also a no-op). Production call\n   *  sites treat this as fire-and-forget (same as `agentSession.close()`);\n   *  the returned promise exists so tests can await the on-disk flush. */\n  close(sessionId: string): Promise<void>\n  /** Close every open session stream — called from the registry's\n   *  synchronous shutdown path (fire-and-forget there too). */\n  closeAll(): Promise<void>\n}\n\ninterface WriterState {\n  stream: WriteStream\n  seq: number\n  textBuf: string\n  thoughtBuf: string\n  textDebounce: ReturnType<typeof setTimeout> | null\n  thoughtDebounce: ReturnType<typeof setTimeout> | null\n}\n\nexport function createTranscriptWriter(opts?: { baseDir?: string }): TranscriptWriter {\n  const baseDir = opts?.baseDir\n  const states = new Map<string, WriterState>()\n\n  const getState = (sessionId: string): WriterState => {\n    const existing = states.get(sessionId)\n    if (existing) return existing\n    mkdirSync(sessionTranscriptDir(sessionId, baseDir), { recursive: true })\n    const stream = createWriteStream(sessionEventsPath(sessionId, baseDir), { flags: \"a\" })\n    stream.on(\"error\", err => {\n      console.warn(`[transcript-writer] session ${sessionId}: ${err.message}`)\n    })\n    const state: WriterState = {\n      stream,\n      seq: 0,\n      textBuf: \"\",\n      thoughtBuf: \"\",\n      textDebounce: null,\n      thoughtDebounce: null,\n    }\n    states.set(sessionId, state)\n    return state\n  }\n\n  const writeRecord = (\n    sessionId: string,\n    state: WriterState,\n    record: Record<string, unknown>\n  ): void => {\n    state.seq += 1\n    state.stream.write(\n      JSON.stringify({ seq: state.seq, ts: new Date().toISOString(), ...record }) + \"\\n\"\n    )\n  }\n\n  const flushTextBuf = (sessionId: string, state: WriterState): void => {\n    if (state.textDebounce) {\n      clearTimeout(state.textDebounce)\n      state.textDebounce = null\n    }\n    if (!state.textBuf) return\n    const text = state.textBuf\n    state.textBuf = \"\"\n    writeRecord(sessionId, state, { kind: \"text-delta\", sessionId, text })\n  }\n\n  const flushThoughtBuf = (sessionId: string, state: WriterState): void => {\n    if (state.thoughtDebounce) {\n      clearTimeout(state.thoughtDebounce)\n      state.thoughtDebounce = null\n    }\n    if (!state.thoughtBuf) return\n    const text = state.thoughtBuf\n    state.thoughtBuf = \"\"\n    writeRecord(sessionId, state, { kind: \"thought\", sessionId, text })\n  }\n\n  /** Flush both coalescing buffers as FINAL (non-partial) records — called\n   *  before any non text/thought event so on-disk order matches wall-clock\n   *  order even when a partial line was still sitting in the buffer. */\n  const flushBuffers = (sessionId: string, state: WriterState): void => {\n    flushThoughtBuf(sessionId, state)\n    flushTextBuf(sessionId, state)\n  }\n\n  const scheduleTextDebounce = (sessionId: string, state: WriterState): void => {\n    if (state.textDebounce) clearTimeout(state.textDebounce)\n    state.textDebounce = setTimeout(() => {\n      state.textDebounce = null\n      if (!state.textBuf) return\n      const text = state.textBuf\n      state.textBuf = \"\"\n      writeRecord(sessionId, state, { kind: \"text-delta\", sessionId, text, partial: true })\n    }, DEBOUNCE_MS)\n  }\n\n  const scheduleThoughtDebounce = (sessionId: string, state: WriterState): void => {\n    if (state.thoughtDebounce) clearTimeout(state.thoughtDebounce)\n    state.thoughtDebounce = setTimeout(() => {\n      state.thoughtDebounce = null\n      if (!state.thoughtBuf) return\n      const text = state.thoughtBuf\n      state.thoughtBuf = \"\"\n      writeRecord(sessionId, state, { kind: \"thought\", sessionId, text, partial: true })\n    }, DEBOUNCE_MS)\n  }\n\n  return {\n    recordPrompt(sessionId, message) {\n      const state = getState(sessionId)\n      flushBuffers(sessionId, state)\n      const text = typeof message === \"string\" ? message : JSON.stringify(message)\n      writeRecord(sessionId, state, { kind: \"user-prompt\", sessionId, text })\n    },\n    recordEvent(sessionId, evt) {\n      const state = getState(sessionId)\n      switch (evt.kind) {\n        case \"text-delta\": {\n          if (!evt.text) break\n          const combined = state.textBuf + evt.text\n          const lines = combined.split(/\\r?\\n/)\n          state.textBuf = lines.pop() ?? \"\"\n          // `split` consumes each line's terminator — reappend it so the\n          // on-disk record stays byte-for-byte reconstructable (a blank\n          // line becomes \"\\n\" rather than a lossy \"\").\n          for (const line of lines) {\n            writeRecord(sessionId, state, { kind: \"text-delta\", sessionId, text: `${line}\\n` })\n          }\n          if (state.textBuf) scheduleTextDebounce(sessionId, state)\n          break\n        }\n        case \"thought\": {\n          if (!evt.text) break\n          const combined = state.thoughtBuf + evt.text\n          const lines = combined.split(/\\r?\\n/)\n          state.thoughtBuf = lines.pop() ?? \"\"\n          for (const line of lines) {\n            writeRecord(sessionId, state, { kind: \"thought\", sessionId, text: `${line}\\n` })\n          }\n          if (state.thoughtBuf) scheduleThoughtDebounce(sessionId, state)\n          break\n        }\n        case \"tool-call\":\n          flushBuffers(sessionId, state)\n          writeRecord(sessionId, state, {\n            kind: \"tool-call\",\n            sessionId,\n            toolCallId: evt.toolCallId,\n            toolName: evt.toolName,\n            arguments: evt.arguments,\n          })\n          break\n        case \"tool-result\":\n          flushBuffers(sessionId, state)\n          writeRecord(sessionId, state, {\n            kind: \"tool-result\",\n            sessionId,\n            toolCallId: evt.toolCallId,\n            result: evt.result,\n            isError: evt.isError ?? false,\n          })\n          break\n        case \"agent-prompt\":\n          flushBuffers(sessionId, state)\n          writeRecord(sessionId, state, {\n            kind: \"agent-prompt\",\n            sessionId,\n            toolCallId: evt.toolCallId,\n            options: evt.options,\n          })\n          break\n        case \"turn-end\":\n          flushBuffers(sessionId, state)\n          writeRecord(sessionId, state, { kind: \"turn-end\", sessionId, reason: evt.reason })\n          break\n        case \"error\":\n          flushBuffers(sessionId, state)\n          writeRecord(sessionId, state, { kind: \"error\", sessionId, error: evt.error })\n          break\n        case \"plan\":\n          flushBuffers(sessionId, state)\n          writeRecord(sessionId, state, { kind: \"plan\", sessionId, entries: evt.entries ?? [] })\n          break\n        case \"usage_update\":\n          flushBuffers(sessionId, state)\n          writeRecord(sessionId, state, {\n            kind: \"usage_update\",\n            sessionId,\n            size: evt.size,\n            used: evt.used,\n            ...(evt.cost ? { cost: evt.cost } : {}),\n          })\n          break\n        default:\n          // Unknown kind — drop, same as `projectEvent`'s implicit\n          // no-op for anything it doesn't switch on.\n          break\n      }\n    },\n    close(sessionId) {\n      const state = states.get(sessionId)\n      if (!state) return Promise.resolve()\n      flushBuffers(sessionId, state)\n      states.delete(sessionId)\n      return new Promise<void>(resolve => {\n        state.stream.end(() => resolve())\n      })\n    },\n    closeAll() {\n      const closings: Promise<void>[] = []\n      for (const sessionId of Array.from(states.keys())) {\n        const state = states.get(sessionId)\n        if (!state) continue\n        flushBuffers(sessionId, state)\n        closings.push(new Promise<void>(resolve => state.stream.end(() => resolve())))\n      }\n      states.clear()\n      return Promise.all(closings).then(() => undefined)\n    },\n  }\n}\n","/**\n * Export a clean, readable transcript, dispatched between two kinds of\n * source:\n *\n *   native — the adapter's OWN persistence, re-read after the fact:\n *     claude-code — ~/.claude/projects/<cwd-encoded>/<sessionId>.jsonl\n *     hermes      — ~/.hermes/state.db via node:sqlite (read-only)\n *   daemon — agentproto's own capture, `~/.agentproto/sessions/<id>/events.jsonl`\n *     (written by transcript-writer.ts at the same point `projectEvent`\n *     flattens events into the ANSI ring buffer, ahead of that flattening).\n *     Available for ANY agent-cli session (acp or print protocol), not just\n *     the two adapters with a native store.\n *\n * `source: \"auto\"` (the default) tries native first and falls back to\n * daemon events when there's no native strategy or its store can't be\n * read; `\"native\"` / `\"daemon\"` force one and surface its own error.\n *\n * Output: Markdown (default) or JSON, built from a shared ExportedSession\n * model so every source produces identical rendering logic.\n */\n\nimport { createReadStream } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport { createInterface } from \"node:readline\"\nimport type { SessionDescriptor, SessionsRegistry } from \"./sessions.js\"\nimport { formatToolCall } from \"./tool-presenter.js\"\nimport { sessionEventsPath } from \"./transcript-writer.js\"\n\n// ── Common model ──────────────────────────────────────────────────────\n\nexport interface ExportedMessage {\n  role: \"user\" | \"assistant\" | \"tool\" | \"system\"\n  text?: string\n  reasoning?: string\n  toolName?: string\n  toolCalls?: { name: string; args: string }[]\n  ts?: number\n}\n\nexport interface ExportedSessionMeta {\n  title?: string\n  model?: string\n  startedAt?: string\n  endedAt?: string\n  messageCount?: number\n  toolCallCount?: number\n  tokens?: {\n    input?: number\n    output?: number\n    cacheRead?: number\n    cacheWrite?: number\n    reasoning?: number\n  }\n  costUsd?: number\n  source?: string\n}\n\nexport interface ExportedSession {\n  meta: ExportedSessionMeta\n  messages: ExportedMessage[]\n}\n\n// ── Render ────────────────────────────────────────────────────────────\n\nconst ROLE_ICON: Record<string, string> = {\n  user: \"🧑 User\",\n  assistant: \"🤖 Assistant\",\n  tool: \"🔧 Tool\",\n  system: \"⚙️ System\",\n}\n\nfunction trunc(text: string, n: number): string {\n  if (text.length <= n) return text\n  return text.slice(0, n) + `\\n… [${text.length - n} chars truncated]`\n}\n\nexport function renderMarkdown(\n  session: ExportedSession,\n  opts: { maxToolChars?: number } = {},\n): string {\n  const { meta, messages } = session\n  const maxToolChars = opts.maxToolChars ?? 1200\n  const out: string[] = []\n\n  out.push(`# ${meta.title ?? \"(untitled)\"}`)\n  out.push(\"\")\n\n  const sourceNote = meta.source ? ` · source \\`${meta.source}\\`` : \"\"\n  out.push(`> Session${sourceNote}`)\n  out.push(\"\")\n  out.push(\"| | |\")\n  out.push(\"|---|---|\")\n  if (meta.model) out.push(`| Model | \\`${meta.model}\\` |`)\n  if (meta.startedAt || meta.endedAt) {\n    out.push(`| Start → end | ${meta.startedAt ?? \"?\"} → ${meta.endedAt ?? \"?\"} |`)\n  }\n  if (meta.messageCount !== undefined || meta.toolCallCount !== undefined) {\n    const parts: string[] = []\n    if (meta.messageCount !== undefined) parts.push(`${meta.messageCount} messages`)\n    if (meta.toolCallCount !== undefined) parts.push(`${meta.toolCallCount} tool calls`)\n    out.push(`| Count | ${parts.join(\" · \")} |`)\n  }\n  if (meta.tokens && Object.keys(meta.tokens).length) {\n    const t = meta.tokens\n    const parts: string[] = []\n    if (t.input !== undefined) parts.push(`in ${t.input.toLocaleString(\"en-US\")}`)\n    if (t.output !== undefined) parts.push(`out ${t.output.toLocaleString(\"en-US\")}`)\n    if (t.cacheRead !== undefined || t.cacheWrite !== undefined) {\n      parts.push(\n        `cache r/w ${(t.cacheRead ?? 0).toLocaleString(\"en-US\")}/${(t.cacheWrite ?? 0).toLocaleString(\"en-US\")}`,\n      )\n    }\n    if (t.reasoning !== undefined) parts.push(`reason. ${t.reasoning.toLocaleString(\"en-US\")}`)\n    if (parts.length) out.push(`| Tokens | ${parts.join(\" · \")} |`)\n  }\n  if (meta.costUsd !== undefined) {\n    out.push(`| Cost | $${meta.costUsd.toFixed(4)} |`)\n  }\n  out.push(\"\")\n  out.push(\"---\")\n  out.push(\"\")\n\n  for (const m of messages) {\n    const icon = ROLE_ICON[m.role] ?? m.role\n    const nameSuffix = m.toolName ? ` · \\`${m.toolName}\\`` : \"\"\n    out.push(`### ${icon}${nameSuffix}`)\n\n    if (m.reasoning?.trim()) {\n      out.push(\"\")\n      out.push(\"<details><summary>💭 reasoning</summary>\")\n      out.push(\"\")\n      out.push(trunc(m.reasoning, 4000))\n      out.push(\"\")\n      out.push(\"</details>\")\n    }\n\n    if (m.text?.trim()) {\n      out.push(\"\")\n      if (m.role === \"tool\") {\n        out.push(\"```\")\n        out.push(trunc(m.text, maxToolChars))\n        out.push(\"```\")\n      } else {\n        out.push(m.text.trim())\n      }\n    }\n\n    if (m.toolCalls?.length) {\n      out.push(\"\")\n      for (const tc of m.toolCalls) {\n        let parsedArgs: unknown\n        try {\n          parsedArgs = JSON.parse(tc.args)\n        } catch {\n          parsedArgs = tc.args\n        }\n        out.push(`> 📞 ${formatToolCall(tc.name, parsedArgs)}`)\n      }\n    }\n\n    out.push(\"\")\n  }\n\n  return out.join(\"\\n\")\n}\n\nexport function renderJson(session: ExportedSession): string {\n  return JSON.stringify(session, null, 2)\n}\n\n// ── Exporter interface ────────────────────────────────────────────────\n\ninterface ExportStrategy {\n  exportSession(adapterSessionId: string, cwd?: string): Promise<ExportedSession>\n}\n\n// ── claude-code exporter (JSONL) ──────────────────────────────────────\n\ninterface ClaudeTextBlock {\n  type: \"text\"\n  text: string\n}\ninterface ClaudeThinkingBlock {\n  type: \"thinking\"\n  thinking: string\n}\ninterface ClaudeToolUseBlock {\n  type: \"tool_use\"\n  name: string\n  input?: unknown\n}\ninterface ClaudeToolResultBlock {\n  type: \"tool_result\"\n  tool_use_id?: string\n  content?: unknown\n}\ntype ClaudeContentBlock =\n  | ClaudeTextBlock\n  | ClaudeThinkingBlock\n  | ClaudeToolUseBlock\n  | ClaudeToolResultBlock\n  | { type: string }\n\ninterface ClaudeCodeJsonlLine {\n  type: string\n  message?: {\n    role?: string\n    content?: string | ClaudeContentBlock[]\n  }\n}\n\nconst IGNORED_CLAUDE_TYPES = new Set([\n  \"queue-operation\",\n  \"attachment\",\n  \"file-history-snapshot\",\n  \"ai-title\",\n  \"last-prompt\",\n])\n\nasync function exportClaudeCodeSession(\n  adapterSessionId: string,\n  cwd?: string,\n): Promise<ExportedSession> {\n  if (!cwd) {\n    throw new Error(\n      \"claude-code exporter: cwd is required to locate the JSONL file.\\n\" +\n        \"Pass cwd explicitly or use a session id that is in the registry.\",\n    )\n  }\n  const encoded = cwd.replace(/\\//g, \"-\")\n  const filePath = join(homedir(), \".claude\", \"projects\", encoded, `${adapterSessionId}.jsonl`)\n\n  let stream: ReturnType<typeof createReadStream>\n  try {\n    stream = createReadStream(filePath, { encoding: \"utf8\" })\n    // Trigger ENOENT eagerly before readline wraps it.\n    await new Promise<void>((resolve, reject) => {\n      stream.once(\"error\", reject)\n      stream.once(\"open\", resolve)\n    })\n  } catch (err) {\n    const code = (err as NodeJS.ErrnoException).code\n    if (code === \"ENOENT\") {\n      throw new Error(\n        `claude-code: JSONL file not found: ${filePath}\\n` +\n          `Verify cwd=\"${cwd}\" and adapterSessionId=\"${adapterSessionId}\".`,\n      )\n    }\n    throw err\n  }\n\n  const messages: ExportedMessage[] = []\n  const rl = createInterface({ input: stream, crlfDelay: Infinity })\n\n  for await (const line of rl) {\n    const trimmed = line.trim()\n    if (!trimmed) continue\n    let entry: ClaudeCodeJsonlLine\n    try {\n      entry = JSON.parse(trimmed) as ClaudeCodeJsonlLine\n    } catch {\n      continue\n    }\n    if (IGNORED_CLAUDE_TYPES.has(entry.type)) continue\n    if (entry.type !== \"user\" && entry.type !== \"assistant\") continue\n    const msg = entry.message\n    if (!msg) continue\n\n    const role: ExportedMessage[\"role\"] =\n      msg.role === \"assistant\" ? \"assistant\" : \"user\"\n    const content = msg.content\n\n    if (typeof content === \"string\") {\n      if (content.trim()) messages.push({ role, text: content.trim() })\n      continue\n    }\n    if (!Array.isArray(content)) continue\n\n    // Collect all block types from this message event\n    let textAcc = \"\"\n    let reasoningAcc = \"\"\n    const toolCalls: { name: string; args: string }[] = []\n    const toolResults: { text: string }[] = []\n\n    for (const block of content) {\n      switch (block.type) {\n        case \"text\": {\n          textAcc += (block as ClaudeTextBlock).text\n          break\n        }\n        case \"thinking\": {\n          reasoningAcc += (block as ClaudeThinkingBlock).thinking\n          break\n        }\n        case \"tool_use\": {\n          const tb = block as ClaudeToolUseBlock\n          const args =\n            typeof tb.input === \"string\"\n              ? tb.input\n              : JSON.stringify(tb.input ?? {})\n          toolCalls.push({ name: tb.name, args })\n          break\n        }\n        case \"tool_result\": {\n          const tb = block as ClaudeToolResultBlock\n          let resultText = \"\"\n          if (typeof tb.content === \"string\") {\n            resultText = tb.content\n          } else if (Array.isArray(tb.content)) {\n            for (const c of tb.content as ClaudeContentBlock[]) {\n              if (c.type === \"text\") resultText += (c as ClaudeTextBlock).text\n            }\n          }\n          toolResults.push({ text: resultText })\n          break\n        }\n      }\n    }\n\n    // Emit the main message (user text or assistant with optional tool calls)\n    if (textAcc.trim() || toolCalls.length || reasoningAcc) {\n      const m: ExportedMessage = { role }\n      if (textAcc.trim()) m.text = textAcc.trim()\n      if (reasoningAcc) m.reasoning = reasoningAcc\n      if (toolCalls.length) m.toolCalls = toolCalls\n      messages.push(m)\n    }\n\n    // Emit each tool result as its own role=tool message\n    for (const tr of toolResults) {\n      messages.push({ role: \"tool\", text: tr.text })\n    }\n  }\n\n  return { meta: { source: \"claude-code\" }, messages }\n}\n\n// ── hermes exporter (SQLite) ──────────────────────────────────────────\n// node:sqlite is experimental in Node 22.x but functional.\n// Isolated here so a future stable import replaces only this function.\n\ninterface HermesSessionRow {\n  id: string\n  title?: string\n  model?: string\n  started_at?: number\n  ended_at?: number\n  message_count?: number\n  tool_call_count?: number\n  api_call_count?: number\n  input_tokens?: number\n  output_tokens?: number\n  cache_read_tokens?: number\n  cache_write_tokens?: number\n  reasoning_tokens?: number\n  actual_cost_usd?: number\n  estimated_cost_usd?: number\n  source?: string\n  end_reason?: string\n}\n\ninterface HermesMessageRow {\n  id: number\n  session_id: string\n  role: string\n  content?: string\n  tool_calls?: string\n  tool_name?: string\n  reasoning?: string\n  reasoning_content?: string\n  timestamp?: number\n}\n\nasync function exportHermesSession(adapterSessionId: string): Promise<ExportedSession> {\n  const dbPath = join(homedir(), \".hermes\", \"state.db\")\n\n  // Dynamic import isolates the experimental module warning and lets\n  // callers on older Node get a clear error instead of a crash at load time.\n  let DatabaseSync: (typeof import(\"node:sqlite\"))[\"DatabaseSync\"]\n  try {\n    const sqlite = await import(\"node:sqlite\")\n    DatabaseSync = sqlite.DatabaseSync\n  } catch {\n    throw new Error(\n      \"hermes exporter: node:sqlite unavailable. Requires Node.js ≥22.5.0.\",\n    )\n  }\n\n  let db: InstanceType<typeof DatabaseSync>\n  try {\n    db = new DatabaseSync(dbPath, { readOnly: true })\n  } catch (err) {\n    const msg = String(err)\n    if (\n      (err as NodeJS.ErrnoException).code === \"ENOENT\" ||\n      msg.includes(\"unable to open database file\")\n    ) {\n      throw new Error(\n        `hermes: state.db not found at ${dbPath}. ` +\n          `Has hermes been run at least once?`,\n      )\n    }\n    if (msg.includes(\"SQLITE_BUSY\") || msg.includes(\"database is locked\")) {\n      throw new Error(\n        `hermes: database is locked (SQLITE_BUSY). ` +\n          `Hermes may be writing. Try again in a moment.`,\n      )\n    }\n    throw err\n  }\n\n  const withRetryOnBusy = <T>(fn: () => T): T => {\n    try {\n      return fn()\n    } catch (err) {\n      const msg = String(err)\n      if (msg.includes(\"SQLITE_BUSY\") || msg.includes(\"database is locked\")) {\n        // One brief retry — the lock is usually transient\n        try {\n          return fn()\n        } catch {\n          throw new Error(\n            `hermes: database is locked. Hermes may be actively writing. Try again.`,\n          )\n        }\n      }\n      throw err\n    }\n  }\n\n  const session = withRetryOnBusy(\n    () =>\n      db\n        .prepare(\"SELECT * FROM sessions WHERE id = ?\")\n        .get(adapterSessionId) as unknown as HermesSessionRow | undefined,\n  )\n\n  if (!session) {\n    db.close()\n    throw new Error(\n      `hermes: session \"${adapterSessionId}\" not found in ${dbPath}. ` +\n        `ACP sessions are indexed by the agentproto UUID passed as resumeSessionId.`,\n    )\n  }\n\n  const rows = withRetryOnBusy(\n    () =>\n      db\n        .prepare(\n          \"SELECT * FROM messages WHERE session_id = ? ORDER BY id ASC\",\n        )\n        .all(adapterSessionId) as unknown as HermesMessageRow[],\n  )\n\n  db.close()\n\n  const cost =\n    session.actual_cost_usd != null\n      ? session.actual_cost_usd\n      : session.estimated_cost_usd\n\n  const startedAt = session.started_at\n    ? new Date(session.started_at * 1000).toISOString().replace(\"T\", \" \").slice(0, 19)\n    : undefined\n  const endedAt = session.ended_at\n    ? new Date(session.ended_at * 1000).toISOString().replace(\"T\", \" \").slice(0, 19)\n    : undefined\n\n  const meta: ExportedSessionMeta = {\n    ...(session.title ? { title: session.title } : {}),\n    ...(session.model ? { model: session.model } : {}),\n    ...(startedAt ? { startedAt } : {}),\n    ...(endedAt ? { endedAt } : {}),\n    ...(session.message_count !== undefined ? { messageCount: session.message_count } : {}),\n    ...(session.tool_call_count !== undefined\n      ? { toolCallCount: session.tool_call_count }\n      : {}),\n    ...(cost != null ? { costUsd: Number(cost) } : {}),\n    ...(session.source ? { source: session.source } : {}),\n  }\n\n  // Only include tokens sub-object when at least one field is present\n  const tokensInput = session.input_tokens\n  const tokensOutput = session.output_tokens\n  const tokensCacheRead = session.cache_read_tokens\n  const tokensCacheWrite = session.cache_write_tokens\n  const tokensReasoning = session.reasoning_tokens\n  if (\n    tokensInput !== undefined ||\n    tokensOutput !== undefined ||\n    tokensCacheRead !== undefined ||\n    tokensCacheWrite !== undefined ||\n    tokensReasoning !== undefined\n  ) {\n    meta.tokens = {\n      ...(tokensInput !== undefined ? { input: tokensInput } : {}),\n      ...(tokensOutput !== undefined ? { output: tokensOutput } : {}),\n      ...(tokensCacheRead !== undefined ? { cacheRead: tokensCacheRead } : {}),\n      ...(tokensCacheWrite !== undefined ? { cacheWrite: tokensCacheWrite } : {}),\n      ...(tokensReasoning !== undefined ? { reasoning: tokensReasoning } : {}),\n    }\n  }\n\n  const messages: ExportedMessage[] = rows.map(row => {\n    const validRoles = new Set([\"user\", \"assistant\", \"tool\", \"system\"])\n    const role = (\n      validRoles.has(row.role) ? row.role : \"user\"\n    ) as ExportedMessage[\"role\"]\n\n    const reasoning = row.reasoning ?? row.reasoning_content\n\n    let toolCalls: { name: string; args: string }[] | undefined\n    if (row.tool_calls) {\n      try {\n        const tc = JSON.parse(row.tool_calls) as unknown[]\n        if (Array.isArray(tc) && tc.length) {\n          toolCalls = tc.map(c => {\n            const entry = c as Record<string, unknown>\n            const fn =\n              entry.function != null\n                ? (entry.function as Record<string, unknown>)\n                : entry\n            const name = String(fn.name ?? entry.name ?? \"tool\")\n            const args =\n              typeof fn.arguments === \"string\"\n                ? fn.arguments\n                : JSON.stringify(fn.arguments ?? {})\n            return { name, args }\n          })\n        }\n      } catch {\n        // malformed tool_calls — skip\n      }\n    }\n\n    const m: ExportedMessage = { role }\n    if (row.content?.trim()) m.text = row.content.trim()\n    if (reasoning && String(reasoning).trim()) m.reasoning = String(reasoning)\n    if (row.tool_name) m.toolName = row.tool_name\n    if (toolCalls) m.toolCalls = toolCalls\n    if (row.timestamp) m.ts = row.timestamp\n    return m\n  })\n\n  // Fire-and-forget: cross-check our row count against the binary's export.\n  // Non-blocking — a mismatch only logs a warning, it never fails the call.\n  void crossValidateHermesExport(adapterSessionId, messages.length).catch(() => {})\n\n  return { meta, messages }\n}\n\n// ── Hermes cross-validation via native CLI ────────────────────────────\n//\n// `hermes sessions export --session-id <id> -` emits a stable JSONL\n// transcript on stdout. We use it as a non-blocking sanity-check:\n// if the message count from state.db differs from the binary's output,\n// something in the SQLite schema likely changed and the reader needs\n// updating. The check is fire-and-forget — a mismatch logs a warning but\n// does NOT affect the returned ExportedSession (SQLite stays primary).\n//\n// The export JSONL has one JSON object per message line; lines with a\n// `role` key are treated as messages (other metadata lines are ignored).\n\nexport interface HermesCrossValidationResult {\n  sqliteCount: number\n  binaryCount: number\n  matched: boolean\n  /** True when the hermes binary was not found on PATH */\n  binaryUnavailable?: boolean\n}\n\n/** Default subprocess runner: spawns `hermes sessions export --session-id <id> -`\n *  and returns stdout. Throws with `.code=\"ENOENT\"` when the binary isn't on PATH. */\nasync function defaultHermesRunner(adapterSessionId: string): Promise<string> {\n  const { spawn } = await import(\"node:child_process\")\n  return new Promise<string>((resolve, reject) => {\n    const chunks: Buffer[] = []\n    const errChunks: Buffer[] = []\n    const proc = spawn(\n      \"hermes\",\n      [\"sessions\", \"export\", \"--session-id\", adapterSessionId, \"-\"],\n      { stdio: [\"ignore\", \"pipe\", \"pipe\"] },\n    )\n    proc.stdout.on(\"data\", (chunk: Buffer) => chunks.push(chunk))\n    proc.stderr.on(\"data\", (chunk: Buffer) => errChunks.push(chunk))\n    proc.on(\"error\", reject)\n    proc.on(\"close\", code => {\n      if (code !== 0) {\n        reject(\n          new Error(\n            `hermes exited with code ${code}: ${Buffer.concat(errChunks).toString()}`,\n          ),\n        )\n      } else {\n        resolve(Buffer.concat(chunks).toString(\"utf8\"))\n      }\n    })\n  })\n}\n\n/** Run `hermes sessions export` and compare its message count with\n *  what our SQLite reader produced. Returns null on any subprocess\n *  error (binary missing, timeout, parse failure).\n *\n *  The optional `_runner` parameter lets tests inject a mock that returns stdout\n *  directly, avoiding subprocess mocking complexity (promisify + child_process). */\nexport async function crossValidateHermesExport(\n  adapterSessionId: string,\n  sqliteCount: number,\n  _runner: (id: string) => Promise<string> = defaultHermesRunner,\n): Promise<HermesCrossValidationResult | null> {\n  let stdout: string\n  try {\n    stdout = await _runner(adapterSessionId)\n  } catch (err) {\n    const msg = String(err)\n    // ENOENT = binary not on PATH — expected when hermes isn't installed\n    if (\n      (err as NodeJS.ErrnoException).code === \"ENOENT\" ||\n      msg.includes(\"ENOENT\") ||\n      msg.includes(\"not found\")\n    ) {\n      return { sqliteCount, binaryCount: -1, matched: true, binaryUnavailable: true }\n    }\n    // Any other error (timeout, non-zero exit, etc.) — skip validation\n    return null\n  }\n\n  // Count lines that look like message objects (have a `role` field)\n  const binaryCount = stdout\n    .split(\"\\n\")\n    .filter(l => l.trim())\n    .filter(l => {\n      try {\n        const obj = JSON.parse(l) as Record<string, unknown>\n        return typeof obj.role === \"string\"\n      } catch {\n        return false\n      }\n    }).length\n\n  const matched = binaryCount === sqliteCount\n  if (!matched) {\n    console.warn(\n      `[hermes export] cross-validation mismatch for session ${adapterSessionId}: ` +\n        `SQLite=${sqliteCount} messages, binary=${binaryCount} messages. ` +\n        `The state.db schema may have changed — check the SQLite reader in transcript-export.ts.`,\n    )\n  }\n  return { sqliteCount, binaryCount, matched }\n}\n\n// ── daemon-events exporter (agentproto's own JSONL capture) ────────────\n\n/** Structural shape of one events.jsonl line — a superset of every\n *  `AgentStreamEvent` kind (see sessions.ts) plus the writer's own\n *  \"user-prompt\" record. Untyped fields default to undefined rather than\n *  erroring, so a future field this reader doesn't know about is just\n *  ignored instead of breaking the export. */\ninterface TranscriptRecord {\n  seq: number\n  ts: string\n  kind: string\n  text?: string\n  partial?: boolean\n  toolCallId?: string\n  toolName?: string\n  arguments?: unknown\n  result?: unknown\n  isError?: boolean\n  reason?: string\n  error?: { message: string; code?: number }\n  entries?: Array<{ content: string; priority: string; status: string }>\n  size?: number\n  used?: number\n  cost?: { amount: number; currency: string }\n}\n\nasync function exportDaemonEventsSession(\n  sessionId: string,\n  desc?: SessionDescriptor,\n): Promise<ExportedSession> {\n  const filePath = sessionEventsPath(sessionId)\n\n  let stream: ReturnType<typeof createReadStream>\n  try {\n    stream = createReadStream(filePath, { encoding: \"utf8\" })\n    await new Promise<void>((resolve, reject) => {\n      stream.once(\"error\", reject)\n      stream.once(\"open\", resolve)\n    })\n  } catch (err) {\n    const code = (err as NodeJS.ErrnoException).code\n    if (code === \"ENOENT\") {\n      throw new Error(\n        `daemon-events: no events.jsonl for session \"${sessionId}\" (${filePath}).\\n` +\n          `Either the session never drove an agent-cli turn, or it predates this feature.`,\n      )\n    }\n    throw err\n  }\n\n  const messages: ExportedMessage[] = []\n  const toolNameById = new Map<string, string>()\n  let toolCallCount = 0\n  let lastUsage: { size?: number; used?: number; cost?: { amount: number; currency: string } } | undefined\n\n  // One assistant \"turn batch\" accumulator — text/thought/tool-calls that\n  // arrive between two boundary events (a tool-result, a new prompt, a\n  // turn-end, ...) collapse into ONE assistant message, mirroring how the\n  // claude-code exporter batches a single API-level assistant entry.\n  let asmText = \"\"\n  let asmReasoning = \"\"\n  let asmToolCalls: { name: string; args: string }[] = []\n  let asmTs: number | undefined\n\n  const flushAssistant = (): void => {\n    if (!asmText.trim() && !asmReasoning.trim() && asmToolCalls.length === 0) return\n    const m: ExportedMessage = { role: \"assistant\" }\n    if (asmText.trim()) m.text = asmText.trim()\n    if (asmReasoning.trim()) m.reasoning = asmReasoning.trim()\n    if (asmToolCalls.length) m.toolCalls = asmToolCalls\n    if (asmTs !== undefined) m.ts = asmTs\n    messages.push(m)\n    asmText = \"\"\n    asmReasoning = \"\"\n    asmToolCalls = []\n    asmTs = undefined\n  }\n\n  const rl = createInterface({ input: stream, crlfDelay: Infinity })\n  for await (const line of rl) {\n    const trimmed = line.trim()\n    if (!trimmed) continue\n    let rec: TranscriptRecord\n    try {\n      rec = JSON.parse(trimmed) as TranscriptRecord\n    } catch {\n      continue\n    }\n    const ts = Date.parse(rec.ts)\n    const tsOrUndefined = Number.isNaN(ts) ? undefined : ts\n\n    switch (rec.kind) {\n      case \"user-prompt\":\n        flushAssistant()\n        messages.push({ role: \"user\", text: rec.text ?? \"\", ...(tsOrUndefined !== undefined ? { ts: tsOrUndefined } : {}) })\n        break\n      case \"text-delta\":\n        // Terminated lines already carry their own trailing \"\\n\" (see\n        // transcript-writer.ts) — only an unterminated tail fragment\n        // (still `partial`, or flushed bare at a turn boundary) lacks one,\n        // and that's exactly the byte-for-byte original content.\n        if (asmTs === undefined) asmTs = tsOrUndefined\n        asmText += rec.text ?? \"\"\n        break\n      case \"thought\":\n        if (asmTs === undefined) asmTs = tsOrUndefined\n        asmReasoning += rec.text ?? \"\"\n        break\n      case \"tool-call\": {\n        if (asmTs === undefined) asmTs = tsOrUndefined\n        const name = rec.toolName ?? \"tool\"\n        if (rec.toolCallId) toolNameById.set(rec.toolCallId, name)\n        const args =\n          typeof rec.arguments === \"string\" ? rec.arguments : JSON.stringify(rec.arguments ?? {})\n        asmToolCalls.push({ name, args })\n        toolCallCount += 1\n        break\n      }\n      case \"tool-result\": {\n        flushAssistant()\n        const name = rec.toolCallId ? toolNameById.get(rec.toolCallId) : undefined\n        const text = typeof rec.result === \"string\" ? rec.result : JSON.stringify(rec.result ?? \"\")\n        messages.push({\n          role: \"tool\",\n          text: rec.isError ? `[error] ${text}` : text,\n          ...(name ? { toolName: name } : {}),\n          ...(tsOrUndefined !== undefined ? { ts: tsOrUndefined } : {}),\n        })\n        break\n      }\n      case \"agent-prompt\":\n        flushAssistant()\n        messages.push({ role: \"system\", text: \"[awaiting input] agent requested a decision\" })\n        break\n      case \"plan\": {\n        flushAssistant()\n        const entries = rec.entries ?? []\n        const done = entries.filter(e => e.status === \"completed\").length\n        const list = entries.map(e => e.content).join(\"; \")\n        messages.push({ role: \"system\", text: `[plan] ${done}/${entries.length} ${list}`.trim() })\n        break\n      }\n      case \"usage_update\":\n        lastUsage = { size: rec.size, used: rec.used, cost: rec.cost }\n        break\n      case \"error\":\n        flushAssistant()\n        messages.push({ role: \"system\", text: `[error] ${rec.error?.message ?? \"unknown\"}` })\n        break\n      case \"turn-end\":\n        flushAssistant()\n        break\n      default:\n        break\n    }\n  }\n  flushAssistant()\n\n  const meta: ExportedSessionMeta = { source: \"daemon-events\" }\n  if (desc?.label) meta.title = desc.label\n  if (desc?.model) meta.model = desc.model\n  if (desc?.startedAt) meta.startedAt = desc.startedAt\n  if (desc?.endedAt) meta.endedAt = desc.endedAt\n  meta.messageCount = messages.length\n  meta.toolCallCount = toolCallCount\n  if (desc?.costUsd !== undefined) meta.costUsd = desc.costUsd\n  else if (lastUsage?.cost) meta.costUsd = lastUsage.cost.amount\n  if (desc?.tokensIn !== undefined || desc?.tokensOut !== undefined) {\n    meta.tokens = {\n      ...(desc?.tokensIn !== undefined ? { input: desc.tokensIn } : {}),\n      ...(desc?.tokensOut !== undefined ? { output: desc.tokensOut } : {}),\n    }\n  }\n\n  return { meta, messages }\n}\n\n// ── Strategy registry ─────────────────────────────────────────────────\n\nconst EXPORT_STRATEGIES: Record<string, ExportStrategy> = {\n  \"claude-code\": {\n    exportSession: exportClaudeCodeSession,\n  },\n  hermes: {\n    exportSession: (id: string) => exportHermesSession(id),\n  },\n}\n\n// ── Public API ────────────────────────────────────────────────────────\n\nexport type ExportSource = \"auto\" | \"native\" | \"daemon\"\n\nexport interface ExportAgentSessionInput {\n  /** agentproto session id (sess_xxx) or an adapter-native id */\n  sessionId: string\n  registry: SessionsRegistry\n  format?: \"markdown\" | \"json\"\n  maxToolChars?: number\n  /** Override adapter slug when sessionId is an adapter-native id */\n  adapter?: string\n  /** Override cwd when sessionId is an adapter-native id (claude-code only) */\n  cwd?: string\n  /** Which backend to read from. \"auto\" (default) prefers the adapter's\n   *  own native store and falls back to agentproto's own events.jsonl\n   *  capture when there isn't one (or it can't be read); \"native\" / \"daemon\"\n   *  force one and surface its own error instead of falling back. */\n  source?: ExportSource\n}\n\nexport interface ExportAgentSessionResult {\n  sessionId: string\n  adapter: string\n  format: string\n  meta: ExportedSessionMeta\n  content: string\n}\n\nexport async function exportAgentSession(\n  input: ExportAgentSessionInput,\n): Promise<ExportAgentSessionResult> {\n  const { sessionId, registry, format = \"markdown\", maxToolChars = 1200 } = input\n  const source = input.source ?? \"auto\"\n\n  // Resolve via registry first. `err` closes over `adapterSlug` so it\n  // returns the resolved slug (not the raw input) after registry lookup.\n  let adapterSlug = input.adapter\n  let cwd = input.cwd\n  let adapterSessionId = sessionId\n\n  const err = (msg: string): ExportAgentSessionResult => ({\n    sessionId,\n    adapter: adapterSlug ?? \"unknown\",\n    format,\n    meta: {},\n    content: `Error: ${msg}`,\n  })\n\n  const desc = registry.findByIdOrName(sessionId)\n  // events.jsonl is always keyed by the agentproto session id — never the\n  // adapter-native id substituted below for the native strategies.\n  const daemonSessionId = desc?.id ?? sessionId\n  if (desc) {\n    adapterSlug = adapterSlug ?? desc.adapterSlug\n    cwd = cwd ?? desc.cwd\n    // prefer the adapter-native id over the agentproto id\n    if (desc.adapterSessionId) adapterSessionId = desc.adapterSessionId\n  }\n\n  const tryNative = async (): Promise<ExportedSession> => {\n    if (!adapterSlug) {\n      throw new Error(\n        `session \"${sessionId}\" not found in registry and no adapter override supplied.\\n` +\n          `Pass adapter explicitly or use a known session id (sess_xxx or name).`,\n      )\n    }\n    const exporter = EXPORT_STRATEGIES[adapterSlug]\n    if (!exporter) {\n      const supported = Object.keys(EXPORT_STRATEGIES).join(\", \")\n      throw new Error(\n        `no exporter for adapter \"${adapterSlug}\". Supported: ${supported}.\\n` +\n          `Only sessions spawned via claude-code or hermes can be exported.`,\n      )\n    }\n    return exporter.exportSession(adapterSessionId, cwd)\n  }\n\n  const tryDaemon = (): Promise<ExportedSession> => exportDaemonEventsSession(daemonSessionId, desc)\n\n  let session: ExportedSession\n  try {\n    if (source === \"native\") {\n      session = await tryNative()\n    } else if (source === \"daemon\") {\n      session = await tryDaemon()\n    } else {\n      try {\n        session = await tryNative()\n      } catch (nativeErr) {\n        try {\n          session = await tryDaemon()\n        } catch (daemonErr) {\n          const nativeMsg = nativeErr instanceof Error ? nativeErr.message : String(nativeErr)\n          const daemonMsg = daemonErr instanceof Error ? daemonErr.message : String(daemonErr)\n          return err(`${nativeMsg}\\n(daemon-events fallback also failed: ${daemonMsg})`)\n        }\n      }\n    }\n  } catch (e) {\n    return err(e instanceof Error ? e.message : String(e))\n  }\n\n  const content =\n    format === \"json\"\n      ? renderJson(session)\n      : renderMarkdown(session, { maxToolChars })\n\n  return {\n    sessionId,\n    adapter: adapterSlug ?? (session.meta.source === \"daemon-events\" ? \"daemon\" : \"unknown\"),\n    format,\n    meta: session.meta,\n    content,\n  }\n}\n","/**\n * `jsonTolerant` — wrap a zod schema so it also accepts a JSON-stringified\n * form of its value.\n *\n * Why: some MCP clients (notably the cowork client) stringify parameters\n * whose declared type is a UNION or an OBJECT/ARRAY before sending them\n * over the wire. A field declared `z.union([z.boolean(), z.object({…})])`\n * then receives the literal string `\"true\"` or `\"{\\\"tools\\\":[…]}\"`, and the\n * daemon's strict zod rejects it (`invalid_union: … received string`).\n * Plain scalars (a bare `onlyAlive: true`) survive because the client\n * doesn't stringify them; only composite types break.\n *\n * What: `jsonTolerant(schema)` returns `z.preprocess(…, schema)` that, when\n * it sees a string, tries `JSON.parse` and feeds the parsed result to the\n * inner schema. If the string is NOT valid JSON, it is passed through\n * untouched so the inner schema produces its normal, readable validation\n * error (we never swallow the failure into a crash or a silent default).\n *\n * Semantics are unchanged for well-behaved clients: a value that already\n * has the right type is never a string, so `tryParse` is never invoked and\n * the inner schema sees it verbatim.\n */\n\nimport { z } from \"zod\"\n\n/**\n * Attempt to JSON-parse a string. Returns the parsed value on success, or\n * the original string on failure (so the inner schema reports the real\n * type error instead of us masking it). Only objects/arrays/primitives\n * that JSON can express are produced — exactly the shapes a client would\n * have stringified.\n */\nexport function tryParseJson(value: string): unknown {\n  try {\n    return JSON.parse(value)\n  } catch {\n    return value\n  }\n}\n\n/**\n * Wrap `schema` so a JSON-stringified value is coerced back to its parsed\n * form before validation. Non-string inputs flow straight through.\n */\nexport function jsonTolerant<T extends z.ZodTypeAny>(schema: T) {\n  return z.preprocess(\n    v => (typeof v === \"string\" ? tryParseJson(v) : v),\n    schema,\n  )\n}\n","/**\n * `~/.agentproto/workspaces.json` — single source of truth for the\n * local agentproto control plane. Tracks which directories the user\n * has opted into as agentproto workspaces, plus which one is \"active\"\n * (the daemon's default working set when no workspace is named in\n * a tool call).\n *\n * Why a config file instead of recreating an MCP entry per workspace:\n *   - One daemon = one MCP entry in the user's IDE (clean to read in\n *     `claude mcp list`, no `dapper_willow` / `noble_lantern` spam).\n *   - The daemon walks `workspaces[]` at boot and exposes them all;\n *     tools that need a target take an optional `workspace` arg and\n *     fall back to `active` when omitted.\n *   - The CLI (`agentproto workspace add/list/remove/use`), the daemon,\n *     and the guilde-web onboarding dialog all read+write the same\n *     file, so changes from one surface are immediately visible to\n *     the others.\n *\n * File layout is intentionally boring (small, hand-editable JSON) —\n * future fields go on top, never break v1 readers.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { dirname, isAbsolute, resolve } from \"node:path\"\n\nexport const WORKSPACES_CONFIG_VERSION = 1 as const\n\nexport interface WorkspaceEntry {\n  /** Stable handle — what tools accept as `workspace`. Lowercase\n   *  ASCII, hyphen-only. The CLI sanitises arbitrary names down to\n   *  this shape so paste-from-finder Just Works. */\n  slug: string\n  /** Absolute filesystem path. Required absolute so the daemon can\n   *  serve the workspace regardless of its own cwd. */\n  path: string\n  /** ISO-8601 — first time the entry was added. Pure metadata, no\n   *  behavioural impact. */\n  addedAt: string\n  /** Last time the entry was touched (renamed, path edited, used as\n   *  active). Lets the CLI sort by recency without an N+1 stat. */\n  updatedAt: string\n  /** Free-text label the user can attach so workspaces with similar\n   *  slugs stay distinguishable in `agentproto workspace list`. */\n  label?: string\n}\n\nexport interface WorkspacesConfig {\n  version: typeof WORKSPACES_CONFIG_VERSION\n  /** Active workspace slug — daemon defaults to this when no\n   *  `workspace` arg is passed. May be undefined when no workspaces\n   *  are registered yet. */\n  active?: string\n  workspaces: WorkspaceEntry[]\n}\n\nexport const DEFAULT_CONFIG_DIR = (): string =>\n  resolve(homedir(), \".agentproto\")\nexport const DEFAULT_CONFIG_PATH = (): string =>\n  resolve(DEFAULT_CONFIG_DIR(), \"workspaces.json\")\n\n/** Reduce arbitrary user input to a safe slug. Aligns with what most\n *  tooling validates against (`/^[a-z0-9][a-z0-9-]{0,63}$/`) so the\n *  daemon never has to encode it for URLs or filesystem paths. */\nexport function sanitizeSlug(input: string): string {\n  const trimmed = input.trim().toLowerCase()\n  const cleaned = trimmed\n    .replace(/[^a-z0-9_-]+/g, \"-\")\n    .replace(/^-+|-+$/g, \"\")\n    .slice(0, 64)\n  // Edge case: input was entirely non-conforming — fall back to a\n  // generic so we never return an empty string.\n  return cleaned || \"workspace\"\n}\n\n/** Read the config from disk. Returns an empty config (no workspaces,\n *  no active) when the file is missing — this is the legitimate\n *  first-boot state, not an error. */\nexport async function loadWorkspacesConfig(\n  path: string = DEFAULT_CONFIG_PATH()\n): Promise<WorkspacesConfig> {\n  let raw: string\n  try {\n    raw = await fs.readFile(path, \"utf8\")\n  } catch (err) {\n    if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n      return { version: WORKSPACES_CONFIG_VERSION, workspaces: [] }\n    }\n    throw err\n  }\n  let parsed: unknown\n  try {\n    parsed = JSON.parse(raw)\n  } catch (err) {\n    throw new Error(\n      `agentproto: ${path} is not valid JSON (${\n        err instanceof Error ? err.message : String(err)\n      }). Delete the file or fix it manually.`\n    )\n  }\n  return normalizeConfig(parsed)\n}\n\n/** Write the config back. Creates the parent directory if missing.\n *  Atomic-ish: writes to a temp file first, then renames over the\n *  target — avoids the partial-write window where a concurrent reader\n *  sees half a JSON object. */\nexport async function saveWorkspacesConfig(\n  config: WorkspacesConfig,\n  path: string = DEFAULT_CONFIG_PATH()\n): Promise<void> {\n  const normalized = normalizeConfig(config)\n  await fs.mkdir(dirname(path), { recursive: true })\n  const tmp = `${path}.tmp.${process.pid}`\n  await fs.writeFile(tmp, JSON.stringify(normalized, null, 2) + \"\\n\", \"utf8\")\n  await fs.rename(tmp, path)\n}\n\n/**\n * Pure helpers — caller manages persistence. Returns a NEW config\n * (never mutates) so callers can compose multiple updates before\n * a single save.\n */\nexport function addWorkspace(\n  config: WorkspacesConfig,\n  input: { slug: string; path: string; label?: string }\n): WorkspacesConfig {\n  if (!isAbsolute(input.path)) {\n    throw new Error(\n      `addWorkspace: path must be absolute, got \"${input.path}\".`\n    )\n  }\n  const slug = sanitizeSlug(input.slug)\n  const now = new Date().toISOString()\n  const existingIdx = config.workspaces.findIndex(w => w.slug === slug)\n  const next: WorkspaceEntry = existingIdx >= 0\n    ? {\n        ...config.workspaces[existingIdx]!,\n        path: input.path,\n        ...(input.label !== undefined ? { label: input.label } : {}),\n        updatedAt: now,\n      }\n    : {\n        slug,\n        path: input.path,\n        ...(input.label ? { label: input.label } : {}),\n        addedAt: now,\n        updatedAt: now,\n      }\n  const workspaces = [...config.workspaces]\n  if (existingIdx >= 0) workspaces[existingIdx] = next\n  else workspaces.push(next)\n  // First-add becomes active automatically — saves the user a\n  // separate `workspace use` call right after a fresh `add`.\n  const active = config.active ?? slug\n  return { ...config, workspaces, active }\n}\n\nexport function removeWorkspace(\n  config: WorkspacesConfig,\n  slug: string\n): WorkspacesConfig {\n  const sanitised = sanitizeSlug(slug)\n  const workspaces = config.workspaces.filter(w => w.slug !== sanitised)\n  // If the removed workspace was active, hand off to whatever's\n  // first — predictable and avoids leaving the daemon in an\n  // unreachable state when the user removes the only one.\n  let active = config.active\n  if (active === sanitised) {\n    active = workspaces[0]?.slug\n  }\n  const next: WorkspacesConfig = { ...config, workspaces }\n  if (active !== undefined) next.active = active\n  else delete next.active\n  return next\n}\n\nexport function setActiveWorkspace(\n  config: WorkspacesConfig,\n  slug: string\n): WorkspacesConfig {\n  const sanitised = sanitizeSlug(slug)\n  if (!config.workspaces.some(w => w.slug === sanitised)) {\n    throw new Error(\n      `setActiveWorkspace: no workspace registered with slug \"${sanitised}\". ` +\n        `Run \\`agentproto workspace add <path> --slug ${sanitised}\\` first.`\n    )\n  }\n  return { ...config, active: sanitised }\n}\n\nexport function findWorkspace(\n  config: WorkspacesConfig,\n  slug: string\n): WorkspaceEntry | undefined {\n  return config.workspaces.find(w => w.slug === sanitizeSlug(slug))\n}\n\n/** The active workspace, or undefined when none is registered. Pure\n *  convenience to avoid re-implementing the lookup at every caller. */\nexport function getActiveWorkspace(\n  config: WorkspacesConfig\n): WorkspaceEntry | undefined {\n  if (!config.active) return config.workspaces[0]\n  return findWorkspace(config, config.active) ?? config.workspaces[0]\n}\n\n/**\n * Coerce arbitrary parsed JSON into a valid config. Skips entries\n * with missing required fields rather than throwing — partial recovery\n * is friendlier than \"your config file is corrupted, here's a stack\n * trace\". Logs nothing here; the CLI shells that consume this should\n * decide whether to surface a warning.\n */\nfunction normalizeConfig(parsed: unknown): WorkspacesConfig {\n  if (!parsed || typeof parsed !== \"object\") {\n    return { version: WORKSPACES_CONFIG_VERSION, workspaces: [] }\n  }\n  const obj = parsed as Record<string, unknown>\n  const workspaces: WorkspaceEntry[] = []\n  if (Array.isArray(obj.workspaces)) {\n    for (const entry of obj.workspaces) {\n      if (!entry || typeof entry !== \"object\") continue\n      const e = entry as Record<string, unknown>\n      const slug = typeof e.slug === \"string\" ? sanitizeSlug(e.slug) : \"\"\n      const path = typeof e.path === \"string\" ? e.path : \"\"\n      if (!slug || !path) continue\n      const addedAt =\n        typeof e.addedAt === \"string\" ? e.addedAt : new Date().toISOString()\n      const updatedAt = typeof e.updatedAt === \"string\" ? e.updatedAt : addedAt\n      const we: WorkspaceEntry = { slug, path, addedAt, updatedAt }\n      if (typeof e.label === \"string\" && e.label.trim()) {\n        we.label = e.label.trim()\n      }\n      workspaces.push(we)\n    }\n  }\n  // De-dupe by slug (last wins) — the file is hand-editable so a\n  // typo could have produced two entries with the same slug.\n  const dedup = new Map<string, WorkspaceEntry>()\n  for (const w of workspaces) dedup.set(w.slug, w)\n  const finalList = Array.from(dedup.values())\n  const active =\n    typeof obj.active === \"string\" && finalList.some(w => w.slug === obj.active)\n      ? (obj.active as string)\n      : finalList[0]?.slug\n  const out: WorkspacesConfig = {\n    version: WORKSPACES_CONFIG_VERSION,\n    workspaces: finalList,\n  }\n  if (active !== undefined) out.active = active\n  return out\n}\n","/**\n * Shared `agent_start` spawn logic — orchestrator scoped sub-gateway\n * minting, `mcpServers` merge, hermes default-mcpServers safety net,\n * depth/quota checks. Extracted from `agent-tools.ts` (the MCP tool)\n * so the HTTP route can reuse it without re-implementing (and\n * re-drifting from) the same behaviour.\n */\n\nimport type { AcpMcpServer } from \"@agentproto/acp\"\nimport type { SessionsRegistry, SessionDescriptor } from \"./sessions.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\nimport {\n  loadWorkspacesConfig,\n  findWorkspace,\n  getActiveWorkspace,\n} from \"./workspaces-config.js\"\nimport type { OrchestratorScope } from \"./orchestrator-gateway.js\"\nimport type { WebhookNotifier } from \"./webhook-notifier.js\"\n\n/** Matches `RegisterAgentToolsOptions.buildOrchestratorMcp` in\n *  agent-tools.ts — kept as its own alias here since that's the shape\n *  actually passed in (opts required), not the more permissive\n *  `OrchestratorInjector` (opts optional) from orchestrator-gateway.ts. */\nexport type BuildOrchestratorMcp = (opts: {\n  tools?: readonly string[]\n  caller?: OrchestratorScope\n  maxDepth?: number\n  maxChildren?: number\n}) => {\n  entry: AcpMcpServer\n  bindLifecycle: (sessionId: string) => () => void\n}\n\n/** Strip ANSI escapes and drop the ACP framing/marker noise (`── … ──`\n *  turn frames + `[thought]` / `[tool]` lines) so the lines read as plain,\n *  human-friendly text. Used by `agent_output({clean})` and the\n *  `spawnAgentSession({wait})` one-shot output. */\nexport function cleanAgentLines(lines: string[]): string[] {\n  return lines\n    .map(l => l.replace(/\\x1b\\[[0-9;]*m/g, \"\"))\n    .filter(l => {\n      const t = l.trim()\n      return !t.startsWith(\"──\") && !/^\\[(thought|tool)\\b/.test(t)\n    })\n}\n\nexport interface SpawnAgentSessionDeps {\n  registry: SessionsRegistry\n  /** Required — callers must check for its absence themselves (the MCP\n   *  tool and HTTP route each have their own \"not enabled\" response\n   *  shape for the missing-resolver case). */\n  resolveAgentAdapter: AgentAdapterResolver\n  /** Optional orchestrator-injection builder (WP3). See\n   *  `RegisterAgentToolsOptions.buildOrchestratorMcp` for the full\n   *  contract. Omitted → `orchestrator` is rejected with\n   *  `orchestrator_not_enabled`. */\n  buildOrchestratorMcp?: BuildOrchestratorMcp\n  /** The daemon's own plain `/mcp` gateway URL. See\n   *  `RegisterAgentToolsOptions.daemonMcpUrl`. */\n  daemonMcpUrl?: string\n  /** Calling orchestrator's scope (orchestrator WP4). See\n   *  `RegisterAgentToolsOptions.callerScope`. */\n  callerScope?: OrchestratorScope\n  /** Optional webhook notifier — see `RegisterAgentToolsOptions.webhookNotifier`. */\n  webhookNotifier?: WebhookNotifier\n}\n\nexport interface SpawnAgentSessionInput {\n  adapter: string\n  cwd?: string\n  workspaceSlug?: string\n  /** Reattach to a pre-existing adapter-native session (claude-code's\n   *  conversation id, hermes' chat handle, …) instead of starting\n   *  blank. Not exposed on the MCP `agent_start` tool today — only the\n   *  HTTP route (`sessions restart`) passes this. */\n  resumeSessionId?: string\n  prompt?: string\n  label?: string\n  mode?: string\n  model?: string\n  effort?: string\n  mcpServers?: AcpMcpServer[]\n  orchestrator?: boolean | { tools?: string[]; maxDepth?: number; maxChildren?: number }\n  notifyUrl?: string\n  wait?: boolean\n  maxCostUsd?: number\n}\n\nexport type SpawnAgentSessionResult =\n  | { ok: true; descriptor: SessionDescriptor; output?: string[] }\n  | {\n      ok: false\n      code:\n        | \"adapter_not_found\"\n        | \"no_cwd\"\n        | \"orchestrator_not_enabled\"\n        | \"orchestrator_max_depth_exceeded\"\n        | \"orchestrator_child_quota_exceeded\"\n        | \"agent_spawn_failed\"\n      message: string\n      details?: Record<string, unknown>\n    }\n\nexport async function spawnAgentSession(\n  deps: SpawnAgentSessionDeps,\n  input: SpawnAgentSessionInput,\n): Promise<SpawnAgentSessionResult> {\n  const {\n    registry,\n    resolveAgentAdapter,\n    buildOrchestratorMcp,\n    daemonMcpUrl,\n    callerScope,\n    webhookNotifier,\n  } = deps\n\n  // cwd resolution mirrors the HTTP route: explicit cwd wins,\n  // then workspaceSlug lookup, then active workspace, then a\n  // hard error (the operator probably forgot a step).\n  let cwd = input.cwd\n  let resolvedSlug = input.workspaceSlug ?? \"default\"\n  if (!cwd) {\n    try {\n      const config = await loadWorkspacesConfig()\n      const ws = input.workspaceSlug\n        ? findWorkspace(config, input.workspaceSlug)\n        : getActiveWorkspace(config)\n      if (ws) {\n        cwd = ws.path\n        resolvedSlug = ws.slug\n      }\n    } catch {\n      // fall through to error below\n    }\n  }\n  if (!cwd) {\n    return {\n      ok: false,\n      code: \"no_cwd\",\n      message:\n        \"agent_start: no cwd resolvable. Pass `cwd` explicitly, \" +\n        \"or pass `workspaceSlug` matching `agentproto workspace list`, \" +\n        \"or set an active workspace via `agentproto workspace use <slug>`.\",\n    }\n  }\n  const resolved = await resolveAgentAdapter(input.adapter)\n  if (!resolved) {\n    return {\n      ok: false,\n      code: \"adapter_not_found\",\n      message: `agent_start: adapter \"${input.adapter}\" not found. Try \\`agentproto install <slug>\\` first.`,\n    }\n  }\n  // ── Recursion guardrails (WP4) ──────────────────────────────\n  // When this call arrives through the scoped sub-gateway,\n  // `callerScope` is the spawning orchestrator's identity. Enforce\n  // the depth cap and per-parent child quota BEFORE spawning, and\n  // compute the new session's parent attribution. A direct `/mcp`\n  // spawn (no callerScope) is a root: depth 0, no parent, no caps.\n  const childDepth = callerScope ? callerScope.depth + 1 : 0\n  const parentSessionId = callerScope?.ownerSessionId\n  if (callerScope) {\n    if (childDepth > callerScope.maxDepth) {\n      return {\n        ok: false,\n        code: \"orchestrator_max_depth_exceeded\",\n        message:\n          `Spawn rejected: this orchestrator is at depth ${callerScope.depth}; ` +\n          `a child would be depth ${childDepth}, exceeding the max depth ` +\n          `${callerScope.maxDepth}. No session was created.`,\n        details: {\n          depth: callerScope.depth,\n          childDepth,\n          maxDepth: callerScope.maxDepth,\n        },\n      }\n    }\n    // Count this orchestrator's currently-alive children. Killed/\n    // exited children free a slot (the cap bounds concurrent load,\n    // not lifetime spawns).\n    const aliveChildren = parentSessionId\n      ? registry.list().filter(\n          s =>\n            s.parentSessionId === parentSessionId &&\n            (s.status === \"running\" || s.status === \"starting\"),\n        ).length\n      : 0\n    if (aliveChildren >= callerScope.maxChildren) {\n      return {\n        ok: false,\n        code: \"orchestrator_child_quota_exceeded\",\n        message:\n          `Spawn rejected: this orchestrator already has ${aliveChildren} ` +\n          `alive children, at the max of ${callerScope.maxChildren}. ` +\n          `Kill one before spawning another. No session was created.`,\n        details: {\n          aliveChildren,\n          maxChildren: callerScope.maxChildren,\n        },\n      }\n    }\n  }\n  // Orchestrator role (WP3): when requested, mint a scoped\n  // sub-gateway token and MERGE its `mcpServers` entry with any\n  // caller-provided ones (WP1) — both coexist on the child's\n  // session. The child thus receives the curated orchestration\n  // toolset and can spawn + supervise its own sub-agents. The\n  // token is revoked when the session exits (bindLifecycle below).\n  // When the spawn is itself recursive (callerScope present), the\n  // child's token inherits depth+1 and is bounded by the caller's\n  // tools (non-re-grant — a child can't widen past its parent).\n  let mcpServers = input.mcpServers\n  // hermes (unlike claude-code) has zero built-in tools — without an\n  // explicit `mcpServers`, it silently spawns as a chat-only session\n  // with no error. Default it to the daemon's own gateway so it's no\n  // longer possible to get this wrong by omission. An explicit `[]`\n  // is a deliberate opt-out and must be respected as such, so this\n  // only fires when the caller passed no `mcpServers` at all.\n  if (!mcpServers && input.adapter === \"hermes\" && daemonMcpUrl) {\n    mcpServers = [{ name: \"agentproto\", transport: \"http\", ref: daemonMcpUrl }]\n  }\n  let bindOrchestratorLifecycle:\n    | ((sessionId: string) => () => void)\n    | undefined\n  if (input.orchestrator !== undefined && input.orchestrator !== false) {\n    if (!buildOrchestratorMcp) {\n      return {\n        ok: false,\n        code: \"orchestrator_not_enabled\",\n        message:\n          \"agent_start: `orchestrator` is not enabled — the daemon \" +\n          \"was started without the scoped orchestrator sub-gateway. Wire \" +\n          \"`buildOrchestratorMcp` in createGateway (it needs the scope-token \" +\n          \"registry + HTTP port + session-event bus).\",\n      }\n    }\n    const orchestratorOpts =\n      typeof input.orchestrator === \"object\" ? input.orchestrator : undefined\n    const requestedTools = orchestratorOpts?.tools\n    const injection = buildOrchestratorMcp({\n      ...(requestedTools ? { tools: requestedTools } : {}),\n      ...(callerScope ? { caller: callerScope } : {}),\n      ...(orchestratorOpts?.maxDepth !== undefined\n        ? { maxDepth: orchestratorOpts.maxDepth }\n        : {}),\n      ...(orchestratorOpts?.maxChildren !== undefined\n        ? { maxChildren: orchestratorOpts.maxChildren }\n        : {}),\n    })\n    mcpServers = [...(mcpServers ?? []), injection.entry]\n    bindOrchestratorLifecycle = injection.bindLifecycle\n  }\n  try {\n    // The registry doesn't assign a session id until `spawnAgent`\n    // returns below, but `onActivity` can start firing as soon as\n    // `startSession` connects — this box lets the closure defer\n    // pulsing until the id is known, dropping any pre-spawn activity.\n    let liveSessionId: string | undefined\n    const agentSession = await resolved.startSession({\n      cwd,\n      ...(input.resumeSessionId ? { resumeSessionId: input.resumeSessionId } : {}),\n      ...(input.mode ? { mode: input.mode } : {}),\n      ...(input.model ? { model: input.model } : {}),\n      ...(input.effort ? { effort: input.effort } : {}),\n      ...(mcpServers ? { mcpServers } : {}),\n      onActivity: () => {\n        if (liveSessionId) registry.pulseActivity(liveSessionId)\n      },\n    })\n    const desc = registry.spawnAgent({\n      workspaceSlug: resolvedSlug,\n      cwd,\n      agentSession,\n      adapterSlug: input.adapter,\n      ...(input.model ? { model: input.model } : {}),\n      ...(input.wait && input.prompt ? {} : input.prompt ? { initialPrompt: input.prompt } : {}),\n      ...(input.label ? { label: input.label } : {}),\n      ...(mcpServers ? { mcpServers } : {}),\n      // Parent attribution + depth (WP4) — only set for spawns that\n      // arrived via the scoped sub-gateway; root spawns stay\n      // parentless at depth 0.\n      ...(parentSessionId ? { parentSessionId } : {}),\n      depth: childDepth,\n      ...(resolved.commandPreview\n        ? { commandPreview: resolved.commandPreview }\n        : {}),\n      ...(input.maxCostUsd !== undefined ? { maxCostUsd: input.maxCostUsd } : {}),\n      ...(resolved.readUsage ? { readUsage: () => resolved.readUsage!(agentSession.sessionId) } : {}),\n    })\n    liveSessionId = desc.id\n    // Bind the scope-token's lifetime to the child session — once\n    // it exits, the token is revoked so it can't outlive its child.\n    bindOrchestratorLifecycle?.(desc.id)\n    // Per-session webhook: register if notifyUrl was supplied and\n    // the notifier is wired. Unregistered on session:exited by the\n    // gateway's session-event bus handler.\n    if (input.notifyUrl && webhookNotifier) {\n      webhookNotifier.register(desc.id, input.notifyUrl)\n    }\n    // wait mode: block until the first turn completes, then return\n    // the descriptor with cleaned output appended.\n    if (input.wait && input.prompt) {\n      await registry.sendPrompt(desc.id, input.prompt)\n      const waitLines: string[] = []\n      const waitUnsub = registry.attach(desc.id, (line: string) => {\n        waitLines.push(line)\n      })\n      if (waitUnsub) waitUnsub()\n      const waitTail = waitLines.slice(-80)\n      const output = cleanAgentLines(waitTail)\n      return { ok: true, descriptor: desc, output }\n    }\n    return { ok: true, descriptor: desc }\n  } catch (err) {\n    return {\n      ok: false,\n      code: \"agent_spawn_failed\",\n      message: `agent_start: spawn failed — ${\n        err instanceof Error ? err.message : String(err)\n      }`,\n    }\n  }\n}\n","/**\n * MCP tools that expose agent-CLI lifecycle operations to clients.\n * Extracted from session-tools.ts as the \"agent family\" module.\n *\n * Lets a remote operator spawn and drive agent CLIs on the user's\n * machine through the same MCP connection they already use for fs/exec.\n *\n * Tools:\n *   agent_start   spawn a long-running agent (claude / hermes / …)\n *   agent_prompt  send a follow-up turn to a live session\n *   agent_output  tail the ring buffer\n *   agent_kill    SIGTERM the session\n *   agent_export  export a clean transcript\n *   agent_sessions_list   browse alive + recent agent sessions\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { AcpMcpServer } from \"@agentproto/acp\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport {\n  exportAgentSession,\n  type ExportAgentSessionInput,\n  type ExportAgentSessionResult,\n} from \"./transcript-export.js\"\nimport type {\n  AgentAdapterResolver,\n  AgentAdapterLister,\n} from \"./http-server.js\"\nimport { jsonTolerant } from \"./json-tolerant.js\"\nimport type { OrchestratorScope } from \"./orchestrator-gateway.js\"\nimport type { WebhookNotifier } from \"./webhook-notifier.js\"\nimport { spawnAgentSession, cleanAgentLines } from \"./session-spawn.js\"\n\n/** Strip CSI/SGR ANSI escape sequences. Exported for test access. */\nexport function stripAnsi(s: string): string {\n  return s.replace(/\\x1b\\[[0-9;?]*[A-Za-z]/g, \"\")\n}\n\n/** MCP clients commonly stringify scalar arguments (\"true\"/\"false\"/\"42\").\n *  These coercers let a flag work whether the client sends a real JSON\n *  boolean/number or its string form — avoids opaque \"expected boolean,\n *  received string\" validation errors over the wire. */\nconst mcpBool = z.preprocess(\n  v => (v === \"true\" ? true : v === \"false\" ? false : v),\n  z.boolean(),\n)\nconst mcpPositiveNumber = z.preprocess(\n  v => (typeof v === \"string\" && v.trim() !== \"\" ? Number(v) : v),\n  z.number().positive(),\n)\n\nexport interface RegisterAgentToolsOptions {\n  registry: SessionsRegistry\n  /** Optional adapter resolver — required for `agent_start`\n   *  (the others work with raw spawn sessions too). When unset the\n   *  start tool returns a clear error pointing at the host wiring. */\n  resolveAgentAdapter?: AgentAdapterResolver\n  /** Optional adapter lister — when wired, exposes `adapter_list`\n   *  MCP tool. Without it the tool returns a clear \"not configured\"\n   *  error pointing at the host wiring. */\n  listAgentAdapters?: AgentAdapterLister\n  /** The daemon's own plain `/mcp` gateway URL (e.g.\n   *  `http://127.0.0.1:18790/mcp`). When set, `agent_start` for a\n   *  `hermes` adapter with no caller-supplied `mcpServers` defaults to\n   *  mounting this gateway — unlike claude-code, hermes has zero\n   *  built-in tools, so omitting `mcpServers` silently produces a\n   *  chat-only session with no error. An explicit `mcpServers: []` is\n   *  still respected as a deliberate opt-out. Omitted → no default\n   *  (today's behaviour). */\n  daemonMcpUrl?: string\n  /** Optional orchestrator-injection builder (WP3). When wired, the\n   *  `orchestrator` field on `agent_start` mints a scoped\n   *  sub-gateway token, builds the `mcpServers` entry pointing the\n   *  child at `/mcp/orchestrator?scope=<token>`, and returns a\n   *  `bindLifecycle` hook the handler calls (with the spawned session\n   *  id) so the token is revoked when that session exits. Closed over\n   *  the gateway's scope-token registry + HTTP port + session-event\n   *  bus in `createGateway`. Omitted → `orchestrator` is rejected with\n   *  a clear \"not enabled\" error. */\n  buildOrchestratorMcp?: (opts: {\n    tools?: readonly string[]\n    /** Caller orchestrator scope (WP4) — when a child orchestrator\n     *  spawns its OWN sub-orchestrator, the new token inherits depth+1\n     *  and is bounded by the caller's tools (non-re-grant). */\n    caller?: OrchestratorScope\n    /** Override max depth for the minted child scope (clamped to the\n     *  caller's, then HARD_MAX_DEPTH). */\n    maxDepth?: number\n    /** Override the child quota for the minted child scope (clamped to\n     *  the caller's). */\n    maxChildren?: number\n  }) => {\n    entry: AcpMcpServer\n    bindLifecycle: (sessionId: string) => () => void\n  }\n  /** Calling orchestrator's scope (orchestrator WP4). Present ONLY on\n   *  the scoped sub-gateway server (built per-request from a verified\n   *  scope-token), absent on the root `/mcp` server. When present it is\n   *  the identity of the orchestrator driving these tools, so:\n   *    - spawns are attributed (`parentSessionId = ownerSessionId`,\n   *      `depth = depth + 1`) and gated by the depth cap + child quota;\n   *    - `agent_sessions_list`/`agent_kill` are restricted to the caller's\n   *      subtree.\n   *  Absent → full visibility, depth-0 spawns, no parent (today's root\n   *  behaviour). */\n  callerScope?: OrchestratorScope\n  /** Optional webhook notifier — when provided, per-session `notifyUrl`\n   *  values from `agent_start` are registered on spawn and\n   *  unregistered on exit via the session-event bus. */\n  webhookNotifier?: WebhookNotifier\n}\n\nexport function registerAgentTools(\n  server: McpServer,\n  opts: RegisterAgentToolsOptions\n): void {\n  const {\n    registry,\n    resolveAgentAdapter,\n    listAgentAdapters,\n    buildOrchestratorMcp,\n    callerScope,\n    webhookNotifier,\n    daemonMcpUrl,\n  } = opts\n\n  // ── agent_start ────────────────────────────────────────\n  server.tool(\n    \"agent_start\",\n    \"Spawn a long-running agent CLI (claude-code, hermes, …) on the host. \" +\n      \"The session stays alive across multiple turns — call `agent_prompt` \" +\n      \"to continue the conversation. Returns the session id + initial descriptor. \" +\n      \"When `workspaceSlug` is set, resolves the cwd via \" +\n      \"`~/.agentproto/workspaces.json`; otherwise pass `cwd` explicitly or \" +\n      \"fall back to the active workspace.\",\n    {\n      adapter: z\n        .string()\n        .min(1)\n        .describe(\n          \"Adapter slug — one of the installed `@agentproto/adapter-*` packages \" +\n            \"(e.g. 'claude-code', 'hermes', 'aider').\"\n        ),\n      workspaceSlug: z\n        .string()\n        .optional()\n        .describe(\n          \"Workspace slug from `agentproto workspace list`. The daemon resolves it \" +\n            \"to an absolute path. Omit to use the `cwd` field or the active workspace.\"\n        ),\n      cwd: z\n        .string()\n        .optional()\n        .describe(\n          \"Absolute path to spawn the agent in. Wins over `workspaceSlug` when both are set.\"\n        ),\n      prompt: z\n        .string()\n        .optional()\n        .describe(\n          \"Optional initial prompt. The session is spawned and the prompt dispatched \" +\n            \"in one shot — equivalent to `start` then `prompt` back-to-back. Skip to spawn idle.\"\n        ),\n      label: z\n        .string()\n        .optional()\n        .describe(\n          \"Free-text label that surfaces in `agent_sessions_list` and the UI — useful \" +\n            \"for tagging sessions with a conversation id or operator name.\"\n        ),\n      mode: z\n        .string()\n        .optional()\n        .describe(\n          \"Manifest-declared mode id (AIP-45 `modes`) applied at spawn time, BEFORE \" +\n            \"the child process starts — e.g. claude-code's 'plan' (read-only: \" +\n            \"reasons and proposes but does not edit or run commands), 'accept-edits', \" +\n            \"'bypass-permissions'; codex's 'read-only' / 'full-access'; mastracode/\" +\n            \"opencode's 'plan' / 'build'. Adapters that don't declare `modes` (e.g. \" +\n            \"hermes) reject ANY value here — only pass this for adapters known to \" +\n            \"support it. Omit for the adapter's normal interactive mode.\"\n        ),\n      model: z\n        .string()\n        .optional()\n        .describe(\n          \"Model identifier to pass to the adapter (e.g. 'claude-opus-4-8'). \" +\n            \"For ACP adapters (claude-code) applied via session/set_config_option \" +\n            \"after newSession — NOT via a CLI flag. Others may ignore it.\"\n        ),\n      effort: z\n        .string()\n        .optional()\n        .describe(\n          \"Reasoning effort level (e.g. 'low', 'medium', 'high', 'xhigh', 'max', 'ultracode'). \" +\n            \"IMPORTANT: effort is calibrated per model — the same label maps to different \" +\n            \"compute budgets across models, and defaults differ by model \" +\n            \"(Sonnet 4.6 / Opus 4.8 default 'high'; Opus 4.7 default 'xhigh'). \" +\n            \"'max' and 'ultracode' are session-only. Omit to keep the model's own default.\"\n        ),\n      mcpServers: jsonTolerant(\n        z.array(\n          z.object({\n            name: z.string(),\n            transport: z.enum([\"stdio\", \"http\", \"sse\"]),\n            ref: z.string().optional(),\n          })\n        )\n      )\n        .optional()\n        .describe(\n          \"MCP servers to mount into the spawned agent's session at spawn time. \" +\n            \"Forwarded verbatim to `session/new.mcpServers` on the ACP arm — gives \" +\n            \"the child agent a host-chosen scoped toolset (e.g. the daemon's own \" +\n            \"orchestration gateway so it can spawn + supervise sub-agents). \" +\n            \"Adapters that don't model MCP mounting ignore it.\"\n        ),\n      orchestrator: jsonTolerant(\n        z.union([\n          z.boolean(),\n          z.object({\n            tools: z\n              .array(z.string())\n              .optional()\n              .describe(\n                \"Explicit allowlist — narrows the orchestration toolset to ⊆ the \" +\n                  \"default subset. Names outside the default are dropped (a child \" +\n                  \"can never widen its own scope). Omit for the full default subset.\"\n              ),\n            maxDepth: z\n              .number()\n              .int()\n              .min(1)\n              .max(8)\n              .optional()\n              .describe(\n                \"Max recursion depth reachable through this child (default 3, hard \" +\n                  \"ceiling 8). A spawn that would exceed it is rejected. For a \" +\n                  \"recursive spawn it can only LOWER the inherited cap, never raise it.\"\n              ),\n            maxChildren: z\n              .number()\n              .int()\n              .min(1)\n              .optional()\n              .describe(\n                \"Max concurrently-alive sub-agents this child may spawn (default 8). \" +\n                  \"For a recursive spawn it can only lower the inherited quota.\"\n              ),\n          }),\n        ])\n      )\n        .optional()\n        .describe(\n          \"Make this child a SCOPED orchestrator — auto-mount the daemon's own \" +\n            \"orchestration MCP tools (start/prompt/wait/poll/output + subtree \" +\n            \"list/kill) so it can spawn and supervise its OWN sub-agents. \" +\n            \"`true` = the default curated subset; `{ tools: [...] }` narrows it. \" +\n            \"The daemon mints a per-child scope-token, injects the scoped \" +\n            \"sub-gateway URL into the child's session (alongside any `mcpServers` \" +\n            \"you pass), and revokes the token when the session exits. Shell/fs/\" +\n            \"remote/import/terminal tools are NEVER exposed this way.\"\n        ),\n      notifyUrl: z\n        .string()\n        .url()\n        .optional()\n        .describe(\n          \"Optional per-session webhook URL. POSTed (fire-and-forget) on this \" +\n            \"session's turn-end / awaiting-input / exited events, in addition to \" +\n            \"any global notify URL.\"\n        ),\n      wait: mcpBool\n        .optional()\n        .describe(\n          \"Block until the spawned session's first turn completes and include the cleaned output in the response. Default false = return the descriptor immediately.\"\n        ),\n      maxCostUsd: mcpPositiveNumber\n        .optional()\n        .describe(\n          \"Hard ceiling on cumulative session cost (USD). The session is stopped at a turn-end once exceeded.\"\n        ),\n    },\n    async input => {\n      if (!resolveAgentAdapter) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text:\n                \"agent_start is not enabled — the daemon was started without \" +\n                \"an adapter resolver. Re-run the daemon with the `@agentproto/cli` \" +\n                \"shim wired (see playground/scripts/gateway.ts).\",\n            },\n          ],\n          isError: true,\n        }\n      }\n      const result = await spawnAgentSession(\n        {\n          registry,\n          resolveAgentAdapter,\n          buildOrchestratorMcp,\n          daemonMcpUrl,\n          callerScope,\n          webhookNotifier,\n        },\n        input,\n      )\n      if (result.ok) {\n        const body = result.output\n          ? { ...result.descriptor, output: result.output }\n          : result.descriptor\n        return {\n          content: [{ type: \"text\", text: JSON.stringify(body, null, 2) }],\n        }\n      }\n      // The two orchestrator guardrail errors have always been reported\n      // as a structured JSON blob (error/message/+details); every other\n      // failure is a plain-text message. Preserved verbatim here so the\n      // MCP tool's output shape doesn't change under this refactor.\n      const text =\n        result.code === \"orchestrator_max_depth_exceeded\" ||\n        result.code === \"orchestrator_child_quota_exceeded\"\n          ? JSON.stringify(\n              { error: result.code, message: result.message, ...result.details },\n              null,\n              2,\n            )\n          : result.message\n      return {\n        content: [{ type: \"text\", text }],\n        isError: true,\n      }\n    }\n  )\n\n  // ── agent_prompt ───────────────────────────────────────\n  server.tool(\n    \"agent_prompt\",\n    \"Send a follow-up prompt to a live agent session — multi-turn continuity \" +\n      \"without re-spawning. The session id comes from `agent_start` \" +\n      \"(or `agent_sessions_list`). Returns immediately; tail output via \" +\n      \"`agent_output` or the SSE /sessions/:id/stream endpoint.\",\n    {\n      sessionId: z.string().describe(\"Session id returned by agent_start.\"),\n      prompt: z.string().min(1).describe(\"The next user turn (plain text).\"),\n    },\n    async input => {\n      try {\n        // enqueuePrompt awaits admission (resume attempt + the dead/\n        // wrong-kind/busy checks) before resolving, then fires the\n        // turn itself without waiting for it to drain — long turns\n        // don't block this tool call. Only the awaited admission\n        // phase can reject, so a dead session (killed by a daemon\n        // restart, exited, errored) or a session already mid-turn\n        // surfaces here as a real tool error instead of a lying\n        // `{queued: true}` for a prompt that goes nowhere. The caller\n        // polls agent_output for the turn's actual progress/completion.\n        await registry.enqueuePrompt(input.sessionId, input.prompt)\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify(\n                { ok: true, sessionId: input.sessionId, queued: true },\n                null,\n                2\n              ),\n            },\n          ],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `agent_prompt: ${err instanceof Error ? err.message : String(err)}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n    }\n  )\n\n  // ── agent_output ───────────────────────────────────\n  server.tool(\n    \"agent_output\",\n    \"Tail the recent output of a session. Returns the last N lines of the \" +\n      \"ring buffer (stdout + stderr inter-leaved, newest last). Use this to read \" +\n      \"an agent's reply after `agent_prompt`.\",\n    {\n      sessionId: z.string().describe(\"Session id.\"),\n      lastN: z\n        .number()\n        .int()\n        .min(1)\n        .max(500)\n        .optional()\n        .describe(\"Max lines to return. Default 80, max 500.\"),\n      clean: mcpBool\n        .optional()\n        .describe(\n          \"Strip ANSI codes and drop framing/decoration lines, returning human-readable text.\"\n        ),\n    },\n    async input => {\n      const desc = registry.get(input.sessionId)\n      if (!desc) {\n        return {\n          content: [\n            { type: \"text\", text: `agent_output: no session \"${input.sessionId}\"` },\n          ],\n          isError: true,\n        }\n      }\n      // Best-effort tail — re-attach with a temp listener, capture\n      // backfill (which is the recent ring buffer), unsubscribe.\n      const limit = input.lastN ?? 80\n      const lines: string[] = []\n      const unsub = registry.attach(input.sessionId, (line, _stream) => {\n        lines.push(line)\n      })\n      if (unsub) unsub()\n      const tail = lines.slice(-limit)\n      const output = input.clean ? cleanAgentLines(tail) : tail\n      return {\n        content: [\n          {\n            type: \"text\",\n            text: JSON.stringify(\n              {\n                sessionId: input.sessionId,\n                status: desc.status,\n                lastOutputAt: desc.lastOutputAt,\n                lines: output,\n              },\n              null,\n              2\n            ),\n          },\n        ],\n      }\n    }\n  )\n\n  // ── agent_kill ─────────────────────────────────────────\n  server.tool(\n    \"agent_kill\",\n    \"Stop a session — SIGTERM the underlying child + close the agent protocol \" +\n      \"session. Use to free resources after the operator is done, or when a \" +\n      \"session is wedged.\",\n    {\n      sessionId: z.string().describe(\"Session id.\"),\n    },\n    async input => {\n      // Subtree scoping (WP4): on the scoped sub-gateway a child\n      // orchestrator may only kill sessions in its own subtree — never\n      // an arbitrary id (e.g. a sibling's, or the root operator's).\n      if (callerScope) {\n        const subtree = collectSubtree(\n          callerScope.ownerSessionId,\n          registry.list(),\n        )\n        if (!subtree.has(input.sessionId)) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify(\n                  {\n                    error: \"orchestrator_session_out_of_scope\",\n                    message:\n                      `agent_kill: session \"${input.sessionId}\" is not in ` +\n                      `your subtree — a scoped orchestrator can only kill sessions ` +\n                      `it (transitively) spawned. No action taken.`,\n                    ok: false,\n                    sessionId: input.sessionId,\n                  },\n                  null,\n                  2,\n                ),\n              },\n            ],\n            isError: true,\n          }\n        }\n      }\n      const ok = registry.kill(input.sessionId)\n      return {\n        content: [\n          {\n            type: \"text\",\n            text: JSON.stringify({ ok, sessionId: input.sessionId }, null, 2),\n          },\n        ],\n      }\n    }\n  )\n\n  // ── agent_sessions_list ───────────────────────────────────────\n  server.tool(\n    \"agent_sessions_list\",\n    \"List agent-CLI sessions tracked by the daemon. Equivalent to `session_list({kind: 'agent-cli'})`. \" +\n      \"Each entry includes `kind`, `status`, age, etc. Use this when you only want \" +\n      \"the agent-CLI subset.\",\n    {\n      kind: z\n        .enum([\"terminal\", \"agent-cli\", \"command\", \"all\"])\n        .optional()\n        .describe(\n          \"Optional override of the default `agent-cli` filter. `all` returns every kind.\"\n        ),\n      onlyAlive: z\n        .boolean()\n        .optional()\n        .describe(\"When true, only running/starting sessions. Default false.\"),\n      status: z\n        .enum([\"starting\", \"running\", \"exited\", \"killed\", \"error\"])\n        .optional()\n        .describe(\"Filter by exact status (overrides onlyAlive).\"),\n    },\n    async input => {\n      let rows = registry.list()\n      if (callerScope) {\n        const subtree = collectSubtree(callerScope.ownerSessionId, rows)\n        rows = rows.filter(s => subtree.has(s.id))\n      }\n      const kind = input.kind ?? \"agent-cli\"\n      if (kind !== \"all\") {\n        rows = rows.filter(s => s.kind === kind)\n      }\n      if (input.status) {\n        rows = rows.filter(s => s.status === input.status)\n      } else if (input.onlyAlive) {\n        rows = rows.filter(\n          s => s.status === \"running\" || s.status === \"starting\",\n        )\n      }\n      return {\n        content: [\n          { type: \"text\", text: JSON.stringify({ sessions: rows }, null, 2) },\n        ],\n      }\n    },\n  )\n\n  // ── adapter_list ──────────────────────────────────────────────\n  server.tool(\n    \"adapter_list\",\n    \"Enumerate every agent CLI adapter installed on the host (claude-code, \" +\n      \"hermes, aider, …). Returns slug + display name + version + protocol so \" +\n      \"callers can let users pick from the installed set instead of guessing. \" +\n      \"Use before `agent_start` when the model doesn't already know \" +\n      \"what's available.\",\n    {},\n    async () => {\n      if (!listAgentAdapters) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text:\n                \"adapter_list is not enabled — the daemon was started without \" +\n                \"an adapter lister. Wire `@agentproto/cli`'s \" +\n                \"`listInstalledAdapters` via `createGateway({ listAgentAdapters })`.\",\n            },\n          ],\n          isError: true,\n        }\n      }\n      try {\n        const adapters = await listAgentAdapters()\n        return {\n          content: [{ type: \"text\", text: JSON.stringify({ adapters }, null, 2) }],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `adapter_list failed: ${err instanceof Error ? err.message : String(err)}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n    }\n  )\n}\n\nexport interface ExportSessionOps {\n  registry: SessionsRegistry\n  /**\n   * Override the export function — primarily for testing so callers can inject\n   * a stub without needing real JSONL / SQLite fixtures.\n   */\n  exportFn?: (input: ExportAgentSessionInput) => Promise<ExportAgentSessionResult>\n}\n\n/**\n * Register the `agent_export` MCP tool.\n *\n * Wraps `exportAgentSession` from transcript-export.ts. Resolves the session\n * descriptor via the registry (same registry-access pattern as `summarize_session`)\n * then delegates to the per-adapter exporter (claude-code JSONL / hermes SQLite).\n * Returns the rendered transcript as a text content block.\n */\nexport function registerExportSessionTool(server: McpServer, ops: ExportSessionOps): void {\n  const doExport = ops.exportFn ?? exportAgentSession\n  server.tool(\n    \"agent_export\",\n    \"Export a clean, human-readable transcript of an agent session. \" +\n      \"Prefers the source the adapter already persists (claude-code: JSONL in \" +\n      \"~/.claude/projects/; hermes: state.db in ~/.hermes/), falling back to \" +\n      \"agentproto's own daemon-captured events.jsonl for every other adapter \" +\n      \"(or once the native store is unreadable). Returns markdown (default) or \" +\n      \"JSON. Works on stopped and running sessions alike. Use after a long \" +\n      \"agent run to review the full conversation without the ANSI noise of the \" +\n      \"ring buffer.\",\n    {\n      sessionId: z.string().describe(\n        \"agentproto session id (sess_xxx), adapter-native id, or session name.\"\n      ),\n      adapter: z.string().optional().describe(\n        \"Override adapter slug (e.g. 'claude-code', 'hermes') when the session \" +\n          \"is not in the registry. Required when passing a raw adapter-native id.\"\n      ),\n      cwd: z.string().optional().describe(\n        \"Override cwd (absolute path) — required for claude-code when the session \" +\n          \"is not in the registry (used to locate the JSONL file).\"\n      ),\n      format: z.enum([\"markdown\", \"json\"]).optional().describe(\n        \"Output format. `markdown` (default) renders a human-friendly transcript \" +\n          \"with a metadata table and role-labelled messages; `json` returns the raw \" +\n          \"ExportedSession object for programmatic processing.\"\n      ),\n      source: z.enum([\"auto\", \"native\", \"daemon\"]).optional().describe(\n        \"Which backend to read from. `auto` (default) prefers the adapter's own \" +\n          \"native store (claude-code JSONL / hermes SQLite) and falls back to \" +\n          \"agentproto's own events.jsonl capture when there isn't one; `native` / \" +\n          \"`daemon` force one and surface its own error instead of falling back.\"\n      ),\n    },\n    async input => {\n      const result = await doExport({\n        sessionId: input.sessionId,\n        registry: ops.registry,\n        ...(input.adapter ? { adapter: input.adapter } : {}),\n        ...(input.cwd ? { cwd: input.cwd } : {}),\n        ...(input.format ? { format: input.format } : {}),\n        ...(input.source ? { source: input.source } : {}),\n      })\n      const isError = result.content.startsWith(\"Error:\")\n      return {\n        content: [{ type: \"text\" as const, text: result.content }],\n        ...(isError ? { isError: true as const } : {}),\n      }\n    },\n  )\n}\n\n/**\n * Compute the set of session ids in the subtree rooted at `rootId` —\n * the root itself plus every descendant reachable through the\n * `parentSessionId` chain (orchestrator WP4). Used to scope\n * `list`/`kill` on the scoped sub-gateway so a child orchestrator only\n * ever sees/affects the sessions it (transitively) spawned, never the\n * whole daemon. Returns an empty set when `rootId` is undefined (an\n * unbound scope sees nothing — safe default).\n *\n * Shared between agent-tools.ts and session-tools.ts; declared here so\n * both modules can use it without an extra util file for this PR.\n */\nexport function collectSubtree(\n  rootId: string | undefined,\n  all: readonly import(\"./sessions.js\").SessionDescriptor[],\n): Set<string> {\n  const result = new Set<string>()\n  if (!rootId) return result\n  const childrenOf = new Map<string, string[]>()\n  for (const s of all) {\n    if (!s.parentSessionId) continue\n    const arr = childrenOf.get(s.parentSessionId)\n    if (arr) arr.push(s.id)\n    else childrenOf.set(s.parentSessionId, [s.id])\n  }\n  const queue = [rootId]\n  result.add(rootId)\n  while (queue.length > 0) {\n    const id = queue.shift() as string\n    for (const child of childrenOf.get(id) ?? []) {\n      if (!result.has(child)) {\n        result.add(child)\n        queue.push(child)\n      }\n    }\n  }\n  return result\n}\n","/**\n * Discover MCP servers already configured in the user's local agent\n * tooling — claude-code, cursor, goose, etc. — so the daemon can\n * surface them in the UI without making the user re-enter the same\n * credentials and URLs they already painstakingly configured for\n * one host.\n *\n * v1 is read-only discovery: we report what's there with source\n * attribution. Future v1.1 ships an \"import to daemon\" verb that\n * proxies the discovered server through the daemon's own /mcp\n * endpoint so every operator (cloud Guilde, local agents) sees a\n * unified set without per-host config drift.\n *\n * Sources scanned (in priority order):\n *   - ~/.claude.json (claude-code) — `mcpServers` top-level + nested\n *     under `projects[<path>].mcpServers`. Most users land here.\n *   - ~/.cursor/mcp.json (cursor) — flat `mcpServers` map.\n *   - ~/.config/goose/config.yaml (goose) — TOML/YAML hybrid; we\n *     only handle the YAML form for now.\n *   - any `.mcp.json` under the user's home that follows the\n *     standard mcpServers shape.\n *\n * Each source contributes 0..N entries. Errors are caught + logged\n * (broken JSON, missing files, permission denied) — partial\n * discovery beats failing the whole listing on one bad file.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { resolve as resolvePath } from \"node:path\"\nimport {\n  loadWorkspacesConfig,\n  type WorkspaceEntry,\n} from \"./workspaces-config.js\"\n\nexport interface DiscoveredMcp {\n  /** Stable id within (source, scope, name) — for de-dupe and\n   *  cross-call identity (UI treat as React key). */\n  id: string\n  /** Where we found it. Lets the UI render a source badge. */\n  source: \"claude-code\" | \"cursor\" | \"goose\" | \"workspace\"\n  /** \"global\" when the entry sits at the top level of the host's\n   *  config; \"project:<path>\" when it's scoped to a single\n   *  workspace. claude-code in particular nests per-project. */\n  scope: string\n  /** The host's name for the entry (key in the mcpServers map). */\n  name: string\n  /** Wire transport — `stdio` (command + args) or `http` / `sse` (url). */\n  type: \"stdio\" | \"http\" | \"sse\" | \"unknown\"\n  /** stdio entries: argv to spawn. */\n  command?: string\n  args?: string[]\n  /** stdio entries: env injected into the child. */\n  env?: Record<string, string>\n  /** http/sse entries: target URL. */\n  url?: string\n  /** http/sse entries: extra headers (Authorization, etc.). */\n  headers?: Record<string, string>\n  /** Free-form tags from the source config — claude-code's project\n   *  scope is the most common. */\n  tags?: string[]\n  /** Reason field when `type === \"unknown\"` — surfaces why the\n   *  parser couldn't classify the entry (e.g. neither command nor\n   *  url present). */\n  parseNote?: string\n}\n\nexport interface DiscoverMcpsOptions {\n  /** Override the home dir — handy for tests that pin a tmpdir. */\n  home?: string\n}\n\nexport async function discoverMcps(\n  opts: DiscoverMcpsOptions = {}\n): Promise<DiscoveredMcp[]> {\n  const home = opts.home ?? homedir()\n  const out: DiscoveredMcp[] = []\n  const errors: string[] = []\n  await Promise.all([\n    scanClaudeCode(home, out, errors),\n    scanCursor(home, out, errors),\n    scanGoose(home, out, errors),\n    scanRegisteredWorkspaces(out, errors),\n  ])\n  // De-dupe identical entries that show up in multiple scopes\n  // (e.g. user copied a project entry to global) — keep the first\n  // occurrence so the source attribution stays meaningful.\n  const seen = new Set<string>()\n  const dedup: DiscoveredMcp[] = []\n  for (const m of out) {\n    const key = `${m.source}:${m.scope}:${m.name}`\n    if (seen.has(key)) continue\n    seen.add(key)\n    dedup.push(m)\n  }\n  if (errors.length > 0) {\n    // One log line per error — operators can trace which file\n    // failed without us bubbling the whole stack into the response.\n    for (const e of errors) console.warn(`[mcp-discovery] ${e}`)\n  }\n  return dedup.sort((a, b) => {\n    if (a.source !== b.source) return a.source.localeCompare(b.source)\n    if (a.scope !== b.scope) return a.scope.localeCompare(b.scope)\n    return a.name.localeCompare(b.name)\n  })\n}\n\ninterface RawMcpEntry {\n  type?: string\n  command?: string\n  args?: string[]\n  env?: Record<string, string>\n  url?: string\n  headers?: Record<string, string>\n}\n\n/** claude-code stores entries either at top-level `mcpServers` OR\n *  per-project under `projects[<absolute-path>].mcpServers`. We\n *  surface both with `scope` set so the UI can group by project. */\nasync function scanClaudeCode(\n  home: string,\n  out: DiscoveredMcp[],\n  errors: string[]\n): Promise<void> {\n  const path = resolvePath(home, \".claude.json\")\n  let raw: string\n  try {\n    raw = await fs.readFile(path, \"utf8\")\n  } catch (err) {\n    if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return\n    errors.push(`claude-code: read ${path} — ${(err as Error).message}`)\n    return\n  }\n  let parsed: unknown\n  try {\n    parsed = JSON.parse(raw)\n  } catch (err) {\n    errors.push(`claude-code: JSON parse ${path} — ${(err as Error).message}`)\n    return\n  }\n  if (!parsed || typeof parsed !== \"object\") return\n  const root = parsed as Record<string, unknown>\n  const top = root.mcpServers\n  if (top && typeof top === \"object\") {\n    pushMcpMap({\n      out,\n      source: \"claude-code\",\n      scope: \"global\",\n      map: top as Record<string, unknown>,\n    })\n  }\n  const projects = root.projects\n  if (projects && typeof projects === \"object\") {\n    for (const [projPath, proj] of Object.entries(\n      projects as Record<string, unknown>\n    )) {\n      if (!proj || typeof proj !== \"object\") continue\n      const projMcps = (proj as Record<string, unknown>).mcpServers\n      if (!projMcps || typeof projMcps !== \"object\") continue\n      pushMcpMap({\n        out,\n        source: \"claude-code\",\n        scope: `project:${projPath}`,\n        map: projMcps as Record<string, unknown>,\n      })\n    }\n  }\n}\n\n/** cursor uses ~/.cursor/mcp.json (standard mcpServers shape).\n *  Also supports per-workspace `.cursor/mcp.json` but those need\n *  the user's project paths — out of scope for v1. */\nasync function scanCursor(\n  home: string,\n  out: DiscoveredMcp[],\n  errors: string[]\n): Promise<void> {\n  const path = resolvePath(home, \".cursor\", \"mcp.json\")\n  let raw: string\n  try {\n    raw = await fs.readFile(path, \"utf8\")\n  } catch (err) {\n    if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return\n    errors.push(`cursor: read ${path} — ${(err as Error).message}`)\n    return\n  }\n  let parsed: unknown\n  try {\n    parsed = JSON.parse(raw)\n  } catch (err) {\n    errors.push(`cursor: JSON parse ${path} — ${(err as Error).message}`)\n    return\n  }\n  if (!parsed || typeof parsed !== \"object\") return\n  const root = parsed as Record<string, unknown>\n  const map = root.mcpServers\n  if (map && typeof map === \"object\") {\n    pushMcpMap({\n      out,\n      source: \"cursor\",\n      scope: \"global\",\n      map: map as Record<string, unknown>,\n    })\n  }\n}\n\n/** goose stores config in ~/.config/goose/config.yaml. The full\n *  parser is non-trivial (yaml + extension manifests); v1 looks for\n *  the simple `extensions:` block with `mcp_servers` declarations\n *  and emits a parseNote so the user knows we found goose but\n *  punted on the details. */\nasync function scanGoose(\n  home: string,\n  out: DiscoveredMcp[],\n  errors: string[]\n): Promise<void> {\n  // ~/.config on macOS / Linux; goose hasn't shipped Windows-native yet.\n  const path = resolvePath(home, \".config\", \"goose\", \"config.yaml\")\n  try {\n    await fs.access(path)\n  } catch {\n    return\n  }\n  // We don't ship a yaml parser as a runtime dep — record presence\n  // but punt on parsing. The user sees \"goose detected — open\n  // ~/.config/goose/config.yaml to inspect entries\" which is enough\n  // signal to drive a v2 enhancement.\n  out.push({\n    id: \"goose:global:_detected\",\n    source: \"goose\",\n    scope: \"global\",\n    name: \"(goose config detected)\",\n    type: \"unknown\",\n    parseNote:\n      \"Goose config found but YAML parsing is not yet implemented. \" +\n      \"Open ~/.config/goose/config.yaml to inspect MCP entries.\",\n  })\n}\n\n/**\n * Per-workspace scan — for each registered workspace, look at the\n * common per-project MCP locations (.mcp.json, .cursor/mcp.json,\n * .vscode/mcp.json). Lets the UI surface \"this workspace ships\n * its own chrome-devtools MCP\" instead of only\n * showing what the user configured globally in claude/cursor.\n */\nasync function scanRegisteredWorkspaces(\n  out: DiscoveredMcp[],\n  errors: string[]\n): Promise<void> {\n  let workspaces: WorkspaceEntry[] = []\n  try {\n    const cfg = await loadWorkspacesConfig()\n    workspaces = cfg.workspaces\n  } catch (err) {\n    errors.push(`workspaces: load failed — ${(err as Error).message}`)\n    return\n  }\n  // Walk each workspace + each candidate path. We don't recurse —\n  // these are conventional top-level files. Errors per-file are\n  // collected; one bad file doesn't fail the rest.\n  await Promise.all(\n    workspaces.map(async ws => {\n      const candidates = [\n        resolvePath(ws.path, \".mcp.json\"),\n        resolvePath(ws.path, \".cursor\", \"mcp.json\"),\n        resolvePath(ws.path, \".vscode\", \"mcp.json\"),\n      ]\n      for (const path of candidates) {\n        let raw: string\n        try {\n          raw = await fs.readFile(path, \"utf8\")\n        } catch (err) {\n          if ((err as NodeJS.ErrnoException).code === \"ENOENT\") continue\n          errors.push(\n            `workspace ${ws.slug}: read ${path} — ${(err as Error).message}`\n          )\n          continue\n        }\n        let parsed: unknown\n        try {\n          parsed = JSON.parse(raw)\n        } catch (err) {\n          errors.push(\n            `workspace ${ws.slug}: JSON parse ${path} — ${(err as Error).message}`\n          )\n          continue\n        }\n        if (!parsed || typeof parsed !== \"object\") continue\n        const map = (parsed as Record<string, unknown>).mcpServers\n        if (!map || typeof map !== \"object\") continue\n        pushMcpMap({\n          out,\n          source: \"workspace\",\n          scope: `workspace:${ws.slug}`,\n          map: map as Record<string, unknown>,\n        })\n      }\n    })\n  )\n}\n\nfunction pushMcpMap(args: {\n  out: DiscoveredMcp[]\n  source: DiscoveredMcp[\"source\"]\n  scope: string\n  map: Record<string, unknown>\n}): void {\n  for (const [name, raw] of Object.entries(args.map)) {\n    if (!raw || typeof raw !== \"object\") continue\n    const entry = raw as RawMcpEntry\n    const id = `${args.source}:${args.scope}:${name}`\n    const declared = typeof entry.type === \"string\" ? entry.type : null\n    const url = typeof entry.url === \"string\" ? entry.url : undefined\n    const command = typeof entry.command === \"string\" ? entry.command : undefined\n    let type: DiscoveredMcp[\"type\"]\n    if (declared === \"http\" || declared === \"sse\" || declared === \"stdio\") {\n      type = declared\n    } else if (url) {\n      type = \"http\"\n    } else if (command) {\n      type = \"stdio\"\n    } else {\n      type = \"unknown\"\n    }\n    const m: DiscoveredMcp = {\n      id,\n      source: args.source,\n      scope: args.scope,\n      name,\n      type,\n    }\n    if (command !== undefined) m.command = command\n    if (Array.isArray(entry.args)) {\n      m.args = entry.args.filter((a): a is string => typeof a === \"string\")\n    }\n    if (entry.env && typeof entry.env === \"object\") {\n      m.env = stringifyValues(entry.env)\n    }\n    if (url !== undefined) m.url = url\n    if (entry.headers && typeof entry.headers === \"object\") {\n      m.headers = stringifyValues(entry.headers)\n    }\n    if (type === \"unknown\") {\n      m.parseNote =\n        \"Entry has neither `command` nor `url` — couldn't classify transport.\"\n    }\n    args.out.push(m)\n  }\n}\n\nfunction stringifyValues(\n  raw: Record<string, unknown>\n): Record<string, string> {\n  const out: Record<string, string> = {}\n  for (const [k, v] of Object.entries(raw)) {\n    if (typeof v === \"string\") out[k] = v\n    else if (v != null) out[k] = String(v)\n  }\n  return out\n}\n","/**\n * Per-adapter resume strategies — the daemon's view of \"how do I\n * continue a previous session for THIS adapter?\".\n *\n * The driver already has an `AgentCliContinuation` declaration in\n * the adapter manifest (AIP-45). That covers strategy NAMES\n * (`native-resume`, `pinned-session`, `transcript`, `none`) but is\n * silent on the mechanics that live OUTSIDE the runtime — like\n * \"where on disk does this adapter store its conversations?\" or\n * \"what argv do I pass to resume into PTY mode?\".\n *\n * This table is that practical bridge. Each entry declares three\n * optional hooks:\n *\n *   outputHint   regex matched against each output line; group 1 is\n *                the resume id. Stored as `desc.resumeMetadata[storeAs]`.\n *   fsProbe      async function that probes a per-adapter directory\n *                for a stored session id, scoped to a workspace cwd.\n *                Used when `outputHint` never matched.\n *   spawnArgs    given a captured id, returns the argv to spawn a\n *                PTY that resumes the session. agentproto then\n *                bypasses ACP/agent-cli and runs the provider\n *                directly — the most reliable resume path because\n *                it leans on the provider's native UX.\n *\n * Adapters that don't declare anything here fall back to:\n *   1. ACP-level resume via `resumeSessionId` on POST /sessions/agent\n *   2. Fresh spawn (same shape, no continuity)\n *\n * Eventually each adapter should ship its own strategy on\n * `AgentCliHandle.resumeStrategy` (driver-side). This central table\n * is the bootstrap: it lets a new adapter become resume-capable\n * without bumping its npm package; once that lands, entries\n * graduate into the adapter packages.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\n\n/** Where on disk the resume id ends up on the session descriptor. */\nexport type ResumeMetadataKey =\n  | \"claudeResumeId\"\n  | \"hermesResumeId\"\n  | \"codexResumeId\"\n  | \"openClawResumeId\"\n  | \"openCodeResumeId\"\n\nexport interface ResumeStrategy {\n  /** When set, run on every output line for this adapter. Group 1\n   *  captures the resume id. The match is saved on the descriptor\n   *  as `resumeMetadata[storeAs]`. */\n  outputHint?: RegExp\n  /** Where the matched id is recorded on the descriptor. */\n  storeAs: ResumeMetadataKey\n  /** Probe the adapter's on-disk session store for the most-recently\n   *  modified session in the given workspace. Returns the resume id\n   *  or null when nothing eligible. Files older than `prevStartedAt`\n   *  are ignored (avoids resuming an unrelated prior conversation).\n   *\n   *  Skip when the adapter doesn't persist sessions externally. */\n  fsProbe?(cwd: string, prevStartedAt: string): Promise<string | null>\n  /** Return the argv to spawn a PTY that resumes into the given id.\n   *  When omitted, the daemon falls back to ACP-level resume via\n   *  the agent-cli protocol instead of the provider's native CLI. */\n  spawnArgs?(id: string): string[]\n}\n\nexport const RESUME_STRATEGIES: Record<string, ResumeStrategy> = {\n  \"claude-code\": {\n    // Printed by claude on graceful exit when session persistence\n    // is on (default). Example: `claude --resume 0e483f81-1a44-4bec-9667-b37158450296`\n    outputHint: /claude\\s+--resume\\s+([0-9a-f-]{8,})/i,\n    storeAs: \"claudeResumeId\",\n    fsProbe: probeMtimeLatestJsonl(\".claude/projects\"),\n    spawnArgs: id => [\"claude\", \"--resume\", id],\n  },\n\n  // Stubs for other shipped adapters — fill in as we learn each\n  // provider's resume mechanism. Today they fall back to ACP-level\n  // resume (whatever the agent-cli runtime supports) or fresh spawn.\n  //\n  //   hermes: { storeAs: \"hermesResumeId\", ... }\n  //   codex: { storeAs: \"codexResumeId\", ... }\n  //   openclaw: { storeAs: \"openClawResumeId\", ... }\n  //   opencode: { storeAs: \"openCodeResumeId\", ... }\n}\n\n/**\n * Build an `fsProbe` for adapters that store one `.jsonl` per session\n * inside `~/<storeRel>/<cwd-encoded>/`. The encoded cwd is the\n * absolute path with `/` → `-` (claude's convention; others tend to\n * use the same scheme). Returns the UUID of the most-recently\n * modified `.jsonl`, filtered to files at-or-after `prevStartedAt`.\n */\nfunction probeMtimeLatestJsonl(\n  storeRel: string,\n): (cwd: string, prevStartedAt: string) => Promise<string | null> {\n  return async (cwd, prevStartedAt) => {\n    const encoded = cwd.replace(/\\//g, \"-\")\n    const dir = resolve(homedir(), storeRel, encoded)\n    let entries: string[]\n    try {\n      entries = await fs.readdir(dir)\n    } catch {\n      return null\n    }\n    const jsonl = entries.filter(e => e.endsWith(\".jsonl\"))\n    if (jsonl.length === 0) return null\n    const startedAtMs = Date.parse(prevStartedAt)\n    const candidates: { name: string; mtime: number }[] = []\n    for (const f of jsonl) {\n      try {\n        const st = await fs.stat(join(dir, f))\n        if (!Number.isFinite(startedAtMs) || st.mtimeMs >= startedAtMs - 1000) {\n          candidates.push({ name: f, mtime: st.mtimeMs })\n        }\n      } catch {\n        // ignore unreadable entry\n      }\n    }\n    if (candidates.length === 0) return null\n    candidates.sort((a, b) => b.mtime - a.mtime)\n    return candidates[0]!.name.replace(/\\.jsonl$/, \"\")\n  }\n}\n\n/**\n * Helper: which adapters declare any resume capability? Used by\n * `agentproto sessions restart` to print a helpful \"this adapter\n * doesn't support resume; falling back to fresh spawn\" hint when\n * applicable.\n */\nexport function hasResumeStrategy(adapterSlug: string | undefined): boolean {\n  if (!adapterSlug) return false\n  const s = RESUME_STRATEGIES[adapterSlug]\n  return !!(s && (s.outputHint || s.fsProbe || s.spawnArgs))\n}\n\n// ── Restart decision tree ────────────────────────────────────────\n//\n// Shared between the CLI (`agentproto sessions restart`, sessions.ts)\n// and the daemon's `session_restart` MCP tool (session-tools.ts) —\n// both need to answer \"given this dead/alive session, how do I bring\n// it back with the most continuity?\" the exact same way. Duck-typed\n// on a minimal shape rather than importing `SessionDescriptor` from\n// sessions.ts: this file is its own tsup entry (`splitting: false`),\n// so a value-level cross-entry import would inline the whole sessions\n// module here. A full `SessionDescriptor` satisfies these structurally.\n\nexport interface RestartCandidate {\n  adapterSlug?: string\n  resumeMetadata?: Record<string, string>\n  pty?: boolean\n  adapterSessionId?: string\n}\n\nexport interface FsProbeCandidate extends RestartCandidate {\n  cwd?: string\n  startedAt: string\n}\n\n/**\n * Where a restart should land. Computed once so callers never diverge:\n *\n *   1. pty-native  — the adapter has a captured resume id AND declares\n *      `spawnArgs` (e.g. claude-code): respawn a PTY running the\n *      provider's own resume command. Most reliable — works whenever\n *      the provider persisted the session, regardless of whether the\n *      ACP wrapper did.\n *   2. pty-plain   — the previous session was a real PTY with no\n *      native strategy match: re-run the same argv, no continuity.\n *   3. agent       — an agent-cli session with no native strategy:\n *      resume at the ACP level via the adapter's own session id (may\n *      still 404 if the adapter never persisted a turn — callers\n *      should retry without `resumeSessionId` on a \"not found\" error).\n *   4. unsupported — a generic command session; no history to resume\n *      and no shape to clone reliably.\n */\nexport type RestartStrategy =\n  | { kind: \"pty-native\"; argv: string[] }\n  | { kind: \"pty-plain\" }\n  | { kind: \"agent\"; resumeSessionId?: string }\n  | { kind: \"unsupported\"; reason: string }\n\nexport function decideRestartStrategy(prev: RestartCandidate): RestartStrategy {\n  // Provider-native resume takes precedence over ACP-level resume —\n  // strictly more reliable when available.\n  if (prev.adapterSlug) {\n    const strategy = RESUME_STRATEGIES[prev.adapterSlug]\n    const id = strategy?.storeAs\n      ? prev.resumeMetadata?.[strategy.storeAs]\n      : undefined\n    if (strategy?.spawnArgs && id) {\n      return { kind: \"pty-native\", argv: strategy.spawnArgs(id) }\n    }\n  }\n  if (prev.pty === true) {\n    return { kind: \"pty-plain\" }\n  }\n  if (prev.adapterSlug) {\n    return {\n      kind: \"agent\",\n      ...(prev.adapterSessionId\n        ? { resumeSessionId: prev.adapterSessionId }\n        : {}),\n    }\n  }\n  return {\n    kind: \"unsupported\",\n    reason: \"generic command session — restart only supports pty + agent-cli\",\n  }\n}\n\n/**\n * Generic filesystem-fallback: for each known adapter strategy that\n * defines an `fsProbe`, run it against this session's cwd. If a\n * resume id is found, attach it to the descriptor's resumeMetadata.\n *\n * Lets `restart` recover continuity even when our own output sniffer\n * missed the resume hint (session killed too quickly, output buffered\n * past the kill, …). Eligible only when the file is at-or-after the\n * session's `startedAt` (avoid resuming an unrelated prior session\n * in the same cwd — see ResumeStrategy.fsProbe comment).\n */\nexport async function augmentWithFsResume<T extends FsProbeCandidate>(\n  prev: T,\n): Promise<T> {\n  const slug = prev.adapterSlug\n  if (!slug) return prev\n  const strategy = RESUME_STRATEGIES[slug]\n  if (!strategy?.fsProbe) return prev\n  // If we already have a captured id for this strategy's storage key,\n  // skip the FS probe — the sniffer found it during the session.\n  if (prev.resumeMetadata?.[strategy.storeAs]) return prev\n  if (!prev.cwd) return prev\n  const id = await strategy.fsProbe(prev.cwd, prev.startedAt)\n  if (!id) return prev\n  return {\n    ...prev,\n    resumeMetadata: {\n      ...(prev.resumeMetadata ?? {}),\n      [strategy.storeAs]: id,\n    },\n  }\n}\n\n/**\n * Describe which resume path a restart used, for CLI banners / MCP\n * responses. Returns a short phrase like \"resumed via claude --resume\",\n * or \"resumed via ACP\", or \"\" when no resume was attempted.\n */\nexport function describeResumePath(prev: RestartCandidate): string {\n  if (prev.adapterSlug) {\n    const s = RESUME_STRATEGIES[prev.adapterSlug]\n    if (s?.spawnArgs && s.storeAs && prev.resumeMetadata?.[s.storeAs]) {\n      const sample = s.spawnArgs(\"…\")[0] ?? prev.adapterSlug\n      return `resumed via ${sample} --resume`\n    }\n  }\n  if (prev.adapterSlug && prev.adapterSessionId) {\n    return \"resumed via ACP\"\n  }\n  return \"\"\n}\n\n/**\n * Shell-style argv tokenizer for descriptors that don't carry `argv`\n * separately (legacy persisted rows predating that field). Same rules\n * as the spawn-dialog tokenizer in the web app: whitespace splits,\n * single + double quotes group.\n */\nexport function tokenizeCommand(s: string): string[] {\n  const out: string[] = []\n  let buf = \"\"\n  let inSingle = false\n  let inDouble = false\n  for (let i = 0; i < s.length; i++) {\n    const ch = s[i]\n    if (ch === \"'\" && !inDouble) {\n      inSingle = !inSingle\n      continue\n    }\n    if (ch === '\"' && !inSingle) {\n      inDouble = !inDouble\n      continue\n    }\n    if (!inSingle && !inDouble && /\\s/.test(ch ?? \"\")) {\n      if (buf) {\n        out.push(buf)\n        buf = \"\"\n      }\n      continue\n    }\n    buf += ch\n  }\n  if (buf) out.push(buf)\n  return out\n}\n","/**\n * `~/.agentproto/imported-mcps.json` — the user's curated set of\n * discovered MCPs they want the daemon to know about. v1 is just\n * persistence + read-side; the actual MCP-proxy implementation\n * (where the daemon's /mcp endpoint aggregates the imported\n * servers' tools under namespace prefixes) is v2 work.\n *\n * Purpose: today, \"I see you have chrome-devtools in claude\" is\n * read-only. Once a user imports it, the operator agent can refer\n * to it (\"the user said it's enabled — call it\") and a future\n * proxy layer can actually expose it. We persist the choice now so\n * the data is in place when the proxy lands.\n *\n * File shape:\n *   {\n *     \"version\": 1,\n *     \"imports\": [\n *       {\n *         \"id\":         \"claude-code:project:/path:chrome-devtools\",\n *         \"alias\":      \"chrome-devtools\",\n *         \"addedAt\":    \"2026-05-10T...\",\n *         \"snapshot\":   { ...the DiscoveredMcp at import time }\n *       }\n *     ]\n *   }\n *\n * Snapshotting at import time keeps the daemon resilient to the\n * source config getting deleted (user runs `claude mcp remove ...`).\n * The imported entry stays usable; only the next discovery pass\n * stops listing it as \"available to import.\"\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { dirname, resolve as resolvePath } from \"node:path\"\nimport type { DiscoveredMcp } from \"./mcp-discovery.js\"\n\nexport const IMPORTED_MCPS_PATH = (): string =>\n  resolvePath(homedir(), \".agentproto\", \"imported-mcps.json\")\n\nexport const IMPORTED_MCPS_VERSION = 1 as const\n\nexport interface ImportedMcpEntry {\n  id: string\n  alias: string\n  addedAt: string\n  snapshot: DiscoveredMcp\n}\n\nexport interface ImportedMcpsConfig {\n  version: typeof IMPORTED_MCPS_VERSION\n  imports: ImportedMcpEntry[]\n}\n\nconst EMPTY: ImportedMcpsConfig = {\n  version: IMPORTED_MCPS_VERSION,\n  imports: [],\n}\n\nexport async function loadImportedMcps(\n  path: string = IMPORTED_MCPS_PATH()\n): Promise<ImportedMcpsConfig> {\n  let raw: string\n  try {\n    raw = await fs.readFile(path, \"utf8\")\n  } catch (err) {\n    if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return EMPTY\n    throw err\n  }\n  let parsed: unknown\n  try {\n    parsed = JSON.parse(raw)\n  } catch (err) {\n    throw new Error(\n      `agentproto: ${path} is not valid JSON (${\n        err instanceof Error ? err.message : String(err)\n      }). Delete or fix manually.`\n    )\n  }\n  return normalize(parsed)\n}\n\nexport async function saveImportedMcps(\n  config: ImportedMcpsConfig,\n  path: string = IMPORTED_MCPS_PATH()\n): Promise<void> {\n  await fs.mkdir(dirname(path), { recursive: true })\n  const tmp = `${path}.tmp.${process.pid}`\n  await fs.writeFile(tmp, JSON.stringify(config, null, 2) + \"\\n\", \"utf8\")\n  await fs.rename(tmp, path)\n}\n\n/**\n * Add (or replace) an import. Snapshots the discovered MCP at\n * import time so the entry stays usable when the source config\n * disappears.\n */\nexport function addImport(\n  config: ImportedMcpsConfig,\n  input: { snapshot: DiscoveredMcp; alias?: string }\n): ImportedMcpsConfig {\n  const alias = (input.alias ?? input.snapshot.name).trim()\n  if (!alias) {\n    throw new Error(\"addImport: alias resolves to empty string\")\n  }\n  const addedAt = new Date().toISOString()\n  const next: ImportedMcpEntry = {\n    id: input.snapshot.id,\n    alias,\n    addedAt,\n    snapshot: input.snapshot,\n  }\n  const others = config.imports.filter(e => e.id !== input.snapshot.id)\n  return { ...config, imports: [...others, next] }\n}\n\nexport function removeImport(\n  config: ImportedMcpsConfig,\n  id: string\n): ImportedMcpsConfig {\n  return { ...config, imports: config.imports.filter(e => e.id !== id) }\n}\n\nexport function findImport(\n  config: ImportedMcpsConfig,\n  id: string\n): ImportedMcpEntry | undefined {\n  return config.imports.find(e => e.id === id)\n}\n\nfunction normalize(parsed: unknown): ImportedMcpsConfig {\n  if (!parsed || typeof parsed !== \"object\") return EMPTY\n  const obj = parsed as Record<string, unknown>\n  const imports: ImportedMcpEntry[] = []\n  if (Array.isArray(obj.imports)) {\n    for (const entry of obj.imports) {\n      if (!entry || typeof entry !== \"object\") continue\n      const e = entry as Record<string, unknown>\n      const id = typeof e.id === \"string\" ? e.id : \"\"\n      const alias = typeof e.alias === \"string\" ? e.alias : id\n      const addedAt =\n        typeof e.addedAt === \"string\" ? e.addedAt : new Date().toISOString()\n      const snapshot = e.snapshot as DiscoveredMcp | undefined\n      if (!id || !snapshot) continue\n      imports.push({ id, alias, addedAt, snapshot })\n    }\n  }\n  return { version: IMPORTED_MCPS_VERSION, imports }\n}\n","/**\n * Tool-subset guard — the single mechanism that scopes which MCP tools\n * a `register*` pass actually exposes on a server.\n *\n * `withToolSubset(server, subset)` returns a Proxy where\n * `server.tool(name, …)` is a no-op when `name ∉ subset`; every other\n * call delegates to the underlying server unchanged. The orchestrator\n * sub-gateway (ADR §4.2 / WP2) wraps its per-request server with this\n * before running the normal `registerSessionTools` /\n * `registerOrchestrationTools` passes, so a scoped child orchestrator\n * only ever sees the curated allowlist (spawn / prompt / wait / poll /\n * output / list / kill) — never `command_execute`, fs, remote, import,\n * or terminal tools.\n *\n * Backward-compatible by construction: callers that don't pass a subset\n * use the raw server and register everything, exactly as before.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\n\nexport function withToolSubset(\n  server: McpServer,\n  subset: ReadonlySet<string>,\n): McpServer {\n  return new Proxy(server, {\n    get(target, prop, receiver) {\n      if (prop === \"tool\") {\n        // One guard for every `server.tool(name, …)` call: drop the\n        // registration entirely when the name is outside the allowlist.\n        return (name: string, ...rest: unknown[]): unknown => {\n          if (!subset.has(name)) return undefined\n          return (\n            target.tool as unknown as (n: string, ...r: unknown[]) => unknown\n          )(name, ...rest)\n        }\n      }\n      const value = Reflect.get(target, prop, receiver)\n      // Bind methods to the real server so SDK internals that touch\n      // private fields keep working through the proxy.\n      return typeof value === \"function\" ? value.bind(target) : value\n    },\n  })\n}\n","/**\n * MCP tools that expose the sessions registry to agents connected to\n * the daemon. This module is now a FACADE over the agent-session,\n * terminal-session, session-tree, and MCP-import tool families.\n *\n * The agent-family tools live in `agent-tools.ts` and are imported here\n * so existing callers of `registerSessionTools` continue to work\n * unchanged.\n *\n * Lets a remote operator (Mastra agent in cloud Guilde,\n * Claude Code as a sub-agent, …) spawn + drive agent CLIs on the\n * user's machine through the same MCP connection they already use\n * for fs/exec.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { SessionDescriptor, SessionsRegistry } from \"./sessions.js\"\nimport { registerAgentTools, registerExportSessionTool, collectSubtree } from \"./agent-tools.js\"\nimport type { RegisterAgentToolsOptions } from \"./agent-tools.js\"\nimport { discoverMcps } from \"./mcp-discovery.js\"\nimport {\n  decideRestartStrategy,\n  augmentWithFsResume,\n  describeResumePath,\n  tokenizeCommand,\n} from \"./resume-strategies.js\"\nimport {\n  loadImportedMcps,\n  saveImportedMcps,\n  addImport,\n  removeImport,\n} from \"./mcp-imports.js\"\nimport type { McpProxyRegistry } from \"./mcp-proxy.js\"\nimport { withToolSubset } from \"./tool-subset.js\"\nimport type { OrchestratorScope } from \"./orchestrator-gateway.js\"\nimport type { WebhookNotifier } from \"./webhook-notifier.js\"\nimport type { AgentAdapterResolver, AgentAdapterLister } from \"./http-server.js\"\nimport {\n  loadWorkspacesConfig,\n  findWorkspace,\n  getActiveWorkspace,\n} from \"./workspaces-config.js\"\n\n/** Re-exported from agent-tools.ts for backwards compatibility. */\nexport { stripAnsi } from \"./agent-tools.js\"\n\n/**\n * One node in the session-tree output (WP5). Mirrors the descriptor\n * fields most useful for observability + recursion, plus a `children`\n * array so consumers can walk the tree without building the index\n * themselves, and an `isOrchestrator` flag that's true when the\n * session spawned at least one child (i.e. any session carries its id\n * as `parentSessionId`).\n */\nexport interface SessionTreeNode {\n  id: string\n  label?: string\n  status: string\n  depth: number\n  adapterSlug?: string\n  parentSessionId?: string\n  isOrchestrator: boolean\n  children: SessionTreeNode[]\n}\n\n/**\n * Build a nested session tree from a (scoped) flat list. Roots are\n * sessions whose `parentSessionId` is absent or points outside the\n * provided list (the list is already scoped when called from the\n * tool handler). Each root carries its descendants as nested\n * `children`, breadth-first insertion, depth-sorted within siblings.\n *\n * Exported for testing.\n */\nexport function buildSessionTree(\n  sessions: readonly import(\"./sessions.js\").SessionDescriptor[],\n): SessionTreeNode[] {\n  const idSet = new Set(sessions.map(s => s.id))\n  // Build parent→children index.\n  const childrenOf = new Map<string, import(\"./sessions.js\").SessionDescriptor[]>()\n  for (const s of sessions) {\n    if (s.parentSessionId && idSet.has(s.parentSessionId)) {\n      const arr = childrenOf.get(s.parentSessionId)\n      if (arr) arr.push(s)\n      else childrenOf.set(s.parentSessionId, [s])\n    }\n  }\n  // Identify nodes that spawned at least one child (isOrchestrator).\n  const orchestratorIds = new Set(childrenOf.keys())\n\n  const toNode = (s: import(\"./sessions.js\").SessionDescriptor): SessionTreeNode => ({\n    id: s.id,\n    ...(s.label ? { label: s.label } : {}),\n    status: s.status,\n    depth: s.depth ?? 0,\n    ...(s.adapterSlug ? { adapterSlug: s.adapterSlug } : {}),\n    ...(s.parentSessionId ? { parentSessionId: s.parentSessionId } : {}),\n    isOrchestrator: orchestratorIds.has(s.id),\n    children: (childrenOf.get(s.id) ?? [])\n      .sort((a, b) => (a.depth ?? 0) - (b.depth ?? 0))\n      .map(toNode),\n  })\n\n  // Roots: no parentSessionId, or parent is outside the scoped list.\n  return sessions\n    .filter(s => !s.parentSessionId || !idSet.has(s.parentSessionId))\n    .sort((a, b) => a.startedAt.localeCompare(b.startedAt))\n    .map(toNode)\n}\n\nexport interface RegisterSessionToolsOptions {\n  registry: SessionsRegistry\n  /** Optional adapter resolver — required for `agent_start`\n   *  (the others work with raw spawn sessions too). When unset the\n   *  start tool returns a clear error pointing at the host wiring. */\n  resolveAgentAdapter?: AgentAdapterResolver\n  /** Optional adapter lister — when wired, exposes `adapter_list`\n   *  MCP tool. Without it the tool returns a clear \"not configured\"\n   *  error pointing at the host wiring. */\n  listAgentAdapters?: AgentAdapterLister\n  /** Forwarded to `registerAgentTools` — the daemon's own plain `/mcp`\n   *  gateway URL, defaulted onto `hermes` `agent_start` spawns that\n   *  pass no `mcpServers`. See `RegisterAgentToolsOptions.daemonMcpUrl`. */\n  daemonMcpUrl?: string\n  /** Optional MCP proxy registry — when wired, exposes 3 tools that\n   *  let the operator drive imported MCPs (chrome-devtools, goose-bridge,\n   *  …) through the daemon as a single MCP entry point. */\n  mcpProxy?: McpProxyRegistry\n  /** Whether the registry was constructed with a PTY factory — when\n   *  true, expose the four terminal session tools. When false, the\n   *  tools return a clear \"not configured\" error. */\n  ptyEnabled?: boolean\n  /** Optional allowlist — when set, only tools whose name is in the\n   *  set are registered (the scoped orchestrator sub-gateway, WP2).\n   *  Omitted → register everything, today's behaviour. */\n  toolSubset?: ReadonlySet<string>\n  /** Optional orchestrator-injection builder (WP3). When wired, the\n   *  `orchestrator` field on `agent_start` mints a scoped\n   *  sub-gateway token, builds the `mcpServers` entry pointing the\n   *  child at `/mcp/orchestrator?scope=<token>`, and returns a\n   *  `bindLifecycle` hook the handler calls (with the spawned session\n   *  id) so the token is revoked when that session exits. Closed over\n   *  the gateway's scope-token registry + HTTP port + session-event\n   *  bus in `createGateway`. Omitted → `orchestrator` is rejected with\n   *  a clear \"not enabled\" error. */\n  buildOrchestratorMcp?: RegisterAgentToolsOptions[\"buildOrchestratorMcp\"]\n  /** Calling orchestrator's scope (orchestrator WP4). Present ONLY on\n   *  the scoped sub-gateway server (built per-request from a verified\n   *  scope-token), absent on the root `/mcp` server. When present it is\n   *  the identity of the orchestrator driving these tools, so:\n   *    - spawns are attributed (`parentSessionId = ownerSessionId`,\n   *      `depth = depth + 1`) and gated by the depth cap + child quota;\n   *    - `session_list`/`agent_sessions_list`/`agent_kill` are\n   *      restricted to the caller's subtree.\n   *  Absent → full visibility, depth-0 spawns, no parent (today's root\n   *  behaviour). */\n  callerScope?: OrchestratorScope\n  /** Optional webhook notifier — when provided, per-session `notifyUrl`\n   *  values from `agent_start` are registered on spawn and\n   *  unregistered on exit via the session-event bus. */\n  webhookNotifier?: WebhookNotifier\n}\n\n/** MCP clients commonly stringify scalar arguments (\"true\"/\"false\"/\"42\").\n *  These coercers let a flag work whether the client sends a real JSON\n *  boolean/number or its string form — avoids opaque \"expected boolean,\n *  received string\" validation errors over the wire. */\nconst mcpBool = z.preprocess(\n  v => (v === \"true\" ? true : v === \"false\" ? false : v),\n  z.boolean(),\n)\n\nexport function registerSessionTools(\n  rawServer: McpServer,\n  opts: RegisterSessionToolsOptions\n): void {\n  // When a subset is requested, every `server.tool(...)` below is\n  // filtered through this one guard (ADR §4.2). No subset → raw server.\n  const server = opts.toolSubset\n    ? withToolSubset(rawServer, opts.toolSubset)\n    : rawServer\n  const {\n    registry,\n    mcpProxy,\n    callerScope,\n    resolveAgentAdapter,\n  } = opts\n  const ptyEnabled = opts.ptyEnabled === true\n\n  // Delegate the agent-family tools to the dedicated module.\n  registerAgentTools(server, opts)\n\n  // ── session_list (canonical lister) ──────────────────────────\n  server.tool(\n    \"session_list\",\n    \"List sessions tracked by the daemon — agent-CLI sessions (claude-code, \" +\n      \"hermes, …), terminal/PTY sessions (claude TUI, bash, …), and raw \" +\n      \"commands. Each entry includes `kind`, `pty` (true for real PTYs), \" +\n      \"`name` (when set at spawn), `status`, `command`, age + exit code. Use \" +\n      \"this when you need to know what's already running before spawning \" +\n      \"anything new, or to discover a session id by name.\",\n    {\n      kind: z\n        .enum([\"terminal\", \"agent-cli\", \"command\", \"all\"])\n        .optional()\n        .describe(\n          \"Filter by session kind. `all` (default) returns every kind. \" +\n            \"Use `terminal` to list only PTY sessions, `agent-cli` for \" +\n            \"structured ACP agents.\",\n        ),\n      onlyAlive: z\n        .boolean()\n        .optional()\n        .describe(\"When true, only running/starting sessions. Default false.\"),\n      status: z\n        .enum([\"starting\", \"running\", \"exited\", \"killed\", \"error\"])\n        .optional()\n        .describe(\"Filter by exact status (overrides onlyAlive).\"),\n    },\n    async input => {\n      let rows = registry.list()\n      // Subtree scoping (WP4): on the scoped sub-gateway a child\n      // orchestrator only sees the sessions in its own subtree, never\n      // the whole daemon.\n      if (callerScope) {\n        const subtree = collectSubtree(callerScope.ownerSessionId, rows)\n        rows = rows.filter(s => subtree.has(s.id))\n      }\n      if (input.kind && input.kind !== \"all\") {\n        rows = rows.filter(s => s.kind === input.kind)\n      }\n      if (input.status) {\n        rows = rows.filter(s => s.status === input.status)\n      } else if (input.onlyAlive) {\n        rows = rows.filter(\n          s => s.status === \"running\" || s.status === \"starting\",\n        )\n      }\n      return {\n        content: [\n          { type: \"text\", text: JSON.stringify({ sessions: rows }, null, 2) },\n        ],\n      }\n    },\n  )\n\n  // ── terminal_sessions_list ──────────────────────────────────────\n  server.tool(\n    \"terminal_sessions_list\",\n    \"List terminal/PTY sessions tracked by the daemon. Equivalent to `session_list({kind: 'terminal'})`. \" +\n      \"Each entry includes `kind`, `pty`, `status`, age, etc. Use this when you only want \" +\n      \"the terminal subset.\",\n    {\n      kind: z\n        .enum([\"terminal\", \"agent-cli\", \"command\", \"all\"])\n        .optional()\n        .describe(\n          \"Optional override of the default `terminal` filter. `all` returns every kind.\"\n        ),\n      onlyAlive: z\n        .boolean()\n        .optional()\n        .describe(\"When true, only running/starting sessions. Default false.\"),\n      status: z\n        .enum([\"starting\", \"running\", \"exited\", \"killed\", \"error\"])\n        .optional()\n        .describe(\"Filter by exact status (overrides onlyAlive).\"),\n    },\n    async input => {\n      let rows = registry.list()\n      if (callerScope) {\n        const subtree = collectSubtree(callerScope.ownerSessionId, rows)\n        rows = rows.filter(s => subtree.has(s.id))\n      }\n      const kind = input.kind ?? \"terminal\"\n      if (kind !== \"all\") {\n        rows = rows.filter(s => s.kind === kind)\n      }\n      if (input.status) {\n        rows = rows.filter(s => s.status === input.status)\n      } else if (input.onlyAlive) {\n        rows = rows.filter(\n          s => s.status === \"running\" || s.status === \"starting\",\n        )\n      }\n      return {\n        content: [\n          { type: \"text\", text: JSON.stringify({ sessions: rows }, null, 2) },\n        ],\n      }\n    },\n  )\n\n  // ── command_list ────────────────────────────────────────────────\n  server.tool(\n    \"command_list\",\n    \"List command sessions tracked by the daemon. Equivalent to `session_list({kind: 'command'})`. \" +\n      \"Each entry includes `kind`, `status`, age, exit code, etc. Use this when you only want \" +\n      \"the command subset.\",\n    {\n      kind: z\n        .enum([\"terminal\", \"agent-cli\", \"command\", \"all\"])\n        .optional()\n        .describe(\n          \"Optional override of the default `command` filter. `all` returns every kind.\"\n        ),\n      onlyAlive: z\n        .boolean()\n        .optional()\n        .describe(\"When true, only running/starting sessions. Default false.\"),\n      status: z\n        .enum([\"starting\", \"running\", \"exited\", \"killed\", \"error\"])\n        .optional()\n        .describe(\"Filter by exact status (overrides onlyAlive).\"),\n    },\n    async input => {\n      let rows = registry.list()\n      if (callerScope) {\n        const subtree = collectSubtree(callerScope.ownerSessionId, rows)\n        rows = rows.filter(s => subtree.has(s.id))\n      }\n      const kind = input.kind ?? \"command\"\n      if (kind !== \"all\") {\n        rows = rows.filter(s => s.kind === kind)\n      }\n      if (input.status) {\n        rows = rows.filter(s => s.status === input.status)\n      } else if (input.onlyAlive) {\n        rows = rows.filter(\n          s => s.status === \"running\" || s.status === \"starting\",\n        )\n      }\n      return {\n        content: [\n          { type: \"text\", text: JSON.stringify({ sessions: rows }, null, 2) },\n        ],\n      }\n    },\n  )\n\n  // ── mcp_discovered_list ───────────────────────────────────────\n  server.tool(\n    \"mcp_discovered_list\",\n    \"Discover MCP servers already configured in the user's other agent \" +\n      \"tooling (claude-code, cursor, goose). Returns the union with source \" +\n      \"attribution so the operator can suggest 'I see you have a chrome-devtools \" +\n      \"MCP set up in claude — want me to use it?' instead of asking the user \" +\n      \"to re-configure. Read-only — does not modify any host's config.\",\n    {},\n    async () => {\n      try {\n        const mcps = await discoverMcps()\n        return {\n          content: [{ type: \"text\", text: JSON.stringify({ mcps }, null, 2) }],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `mcp_discovered_list failed: ${err instanceof Error ? err.message : String(err)}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n    }\n  )\n\n  // ── mcp_imported_list ─────────────────────────────────────────\n  server.tool(\n    \"mcp_imported_list\",\n    \"Return the user's curated set of MCP servers — the ones they've \" +\n      \"imported from claude / cursor / workspace configs into the daemon. \" +\n      \"Use to know which MCPs the operator may freely call vs. ones still \" +\n      \"showing up in `mcp_discovered_list` waiting on the user's blessing.\",\n    {},\n    async () => {\n      try {\n        const config = await loadImportedMcps()\n        return {\n          content: [\n            { type: \"text\", text: JSON.stringify(config, null, 2) },\n          ],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `mcp_imported_list failed: ${err instanceof Error ? err.message : String(err)}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n    }\n  )\n\n  // ── mcp_import ─────────────────────────────────────────────────\n  server.tool(\n    \"mcp_import\",\n    \"Import a discovered MCP into the daemon's curated set. The agent \" +\n      \"calls `mcp_discovered_list` first, asks the user, then commits the \" +\n      \"choice via this tool. The snapshot is captured at import time so \" +\n      \"the entry stays usable if the source config (claude/cursor) is \" +\n      \"later removed.\",\n    {\n      sourceMcpId: z\n        .string()\n        .min(1)\n        .describe(\n          \"The discovered MCP id from `mcp_discovered_list` \" +\n            \"(e.g. 'claude-code:project:/path:chrome-devtools').\"\n        ),\n      alias: z\n        .string()\n        .optional()\n        .describe(\n          \"Optional friendly name to display. Defaults to the source MCP's name.\"\n        ),\n    },\n    async input => {\n      try {\n        const discovered = await discoverMcps()\n        const snapshot = discovered.find(d => d.id === input.sourceMcpId)\n        if (!snapshot) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: `mcp_import: discovered MCP \"${input.sourceMcpId}\" not found. Re-run mcp_discovered_list to get current ids.`,\n              },\n            ],\n            isError: true,\n          }\n        }\n        const cfg = await loadImportedMcps()\n        const next = addImport(cfg, {\n          snapshot,\n          ...(input.alias ? { alias: input.alias } : {}),\n        })\n        await saveImportedMcps(next)\n        const entry = next.imports.find(e => e.id === snapshot.id)\n        return {\n          content: [{ type: \"text\", text: JSON.stringify(entry, null, 2) }],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `mcp_import failed: ${err instanceof Error ? err.message : String(err)}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n    }\n  )\n\n  // ── mcp_imported_remove ────────────────────────────────────────\n  server.tool(\n    \"mcp_imported_remove\",\n    \"Remove a previously-imported MCP from the daemon's curated set. \" +\n      \"Use when the user no longer wants the operator referencing it.\",\n    {\n      id: z\n        .string()\n        .min(1)\n        .describe(\n          \"The imported MCP id (matches the discovered MCP id at import time).\"\n        ),\n    },\n    async input => {\n      try {\n        const cfg = await loadImportedMcps()\n        if (!cfg.imports.some(e => e.id === input.id)) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: `mcp_imported_remove: id \"${input.id}\" not in imports. Use mcp_imported_list to see current entries.`,\n              },\n            ],\n            isError: true,\n          }\n        }\n        await saveImportedMcps(removeImport(cfg, input.id))\n        return {\n          content: [\n            { type: \"text\", text: JSON.stringify({ ok: true, id: input.id }, null, 2) },\n          ],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `mcp_imported_remove failed: ${err instanceof Error ? err.message : String(err)}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n    }\n  )\n\n  // ── mcp_imported_status ────────────────────────────────────────\n  // The 3 proxy tools share the same wiring guard — register them\n  // only when the host injected a proxy registry, otherwise emit a\n  // clear \"not enabled\" error so the agent doesn't think the daemon\n  // silently dropped the call.\n  server.tool(\n    \"mcp_imported_status\",\n    \"Snapshot every imported MCP server with its connection status, \" +\n      \"transport type, and tool count. Use this first when an operator \" +\n      \"wonders 'what MCPs do I actually have access to right now?' — the \" +\n      \"answer covers both 'imported but not yet connected' and 'connected \" +\n      \"with N tools'. Errors during connect surface in `lastError`.\",\n    {},\n    async () => {\n      if (!mcpProxy) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text:\n                \"mcp_imported_status is not enabled — daemon was started without \" +\n                \"an MCP proxy. The host must wire `mcpProxy` in createGateway.\",\n            },\n          ],\n          isError: true,\n        }\n      }\n      try {\n        const aliases = await mcpProxy.listAliases()\n        return {\n          content: [\n            { type: \"text\", text: JSON.stringify({ imports: aliases }, null, 2) },\n          ],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `mcp_imported_status failed: ${err instanceof Error ? err.message : String(err)}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n    }\n  )\n\n  // ── mcp_imported_tool_list ────────────────────────────────────\n  server.tool(\n    \"mcp_imported_tool_list\",\n    \"List the tools exposed by one imported MCP server. The proxy \" +\n      \"lazily connects on first call — first-use latency includes the \" +\n      \"transport handshake (stdio: ~1-2s for npx-spawned servers; \" +\n      \"http/sse: <100ms). Returns the upstream `inputSchema` (JSON \" +\n      \"Schema) verbatim so the operator can build a valid `arguments` \" +\n      \"object for the follow-up `mcp_imported_call` invocation.\",\n    {\n      alias: z\n        .string()\n        .min(1)\n        .describe(\n          \"Alias from `mcp_imported_list` / `mcp_imported_status` \" +\n            \"(typically the original MCP name, e.g. 'chrome-devtools').\"\n        ),\n    },\n    async input => {\n      if (!mcpProxy) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: \"mcp_imported_tool_list is not enabled — see mcp_imported_status.\",\n            },\n          ],\n          isError: true,\n        }\n      }\n      const out = await mcpProxy.listTools(input.alias)\n      if (!out.ok) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `mcp_imported_tool_list \"${input.alias}\": ${out.error}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      return {\n        content: [\n          { type: \"text\", text: JSON.stringify({ alias: input.alias, tools: out.tools }, null, 2) },\n        ],\n      }\n    }\n  )\n\n  // ── mcp_imported_call ──────────────────────────────────────────\n  server.tool(\n    \"mcp_imported_call\",\n    \"Invoke a tool on an imported MCP server. The daemon proxies the \" +\n      \"call through the live client connection — the upstream server \" +\n      \"validates `arguments` against its own input schema (which you \" +\n      \"can fetch via `mcp_imported_tool_list`). The full upstream \" +\n      \"result is returned verbatim, including `isError` flags so the \" +\n      \"operator sees the original failure shape.\",\n    {\n      alias: z.string().min(1).describe(\"Imported MCP alias.\"),\n      toolName: z\n        .string()\n        .min(1)\n        .describe(\n          \"Tool name as it appears in `mcp_imported_tool_list` \" +\n            \"(NOT a namespaced version — pass the upstream's own name).\"\n        ),\n      args: z\n        .record(z.string(), z.unknown())\n        .optional()\n        .describe(\n          \"Tool arguments as a JSON object. Schema is the upstream's \" +\n            \"— the proxy doesn't validate, only forwards. Default: empty object.\"\n        ),\n    },\n    async input => {\n      if (!mcpProxy) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: \"mcp_imported_call is not enabled — see mcp_imported_status.\",\n            },\n          ],\n          isError: true,\n        }\n      }\n      const out = await mcpProxy.callTool(\n        input.alias,\n        input.toolName,\n        input.args ?? {}\n      )\n      if (!out.ok) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `mcp_imported_call \"${input.alias}\".${input.toolName}: ${out.error}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      // Forward the upstream result. The MCP SDK's CallToolResult is\n      // already in the {content, isError?} shape we return — pass it\n      // through with a note that it came from the proxy.\n      return out.result as {\n        content: Array<{ type: \"text\"; text: string }>\n        isError?: boolean\n      }\n    }\n  )\n\n  // ── session_tree (WP5) ────────────────────────────────────────\n  server.tool(\n    \"session_tree\",\n    \"Return the orchestrator session hierarchy as a nested tree. Each root \" +\n      \"is a session with no parent (or whose parent is outside the visible scope); \" +\n      \"its `children` array holds direct sub-sessions, recursively. Each node \" +\n      \"carries `id`, `label`, `status`, `depth`, `adapterSlug`, `parentSessionId`, \" +\n      \"and `isOrchestrator` (true when the session itself spawned sub-agents). \" +\n      \"Via a scoped orchestrator token only the caller's subtree is returned; \" +\n      \"from the root `/mcp` endpoint the full daemon tree is visible.\",\n    {\n      onlyAlive: z\n        .boolean()\n        .optional()\n        .describe(\n          \"When true, only include sessions with status running/starting. \" +\n            \"Pruned nodes also hide their subtree. Default false.\",\n        ),\n    },\n    async input => {\n      let rows = registry.list()\n      // Subtree scoping (WP5 / WP4): same gate as session_list.\n      if (callerScope) {\n        const subtree = collectSubtree(callerScope.ownerSessionId, rows)\n        rows = rows.filter(s => subtree.has(s.id))\n      }\n      if (input.onlyAlive) {\n        rows = rows.filter(\n          s => s.status === \"running\" || s.status === \"starting\",\n        )\n      }\n      const tree = buildSessionTree(rows)\n      return {\n        content: [\n          { type: \"text\", text: JSON.stringify({ tree }, null, 2) },\n        ],\n      }\n    },\n  )\n\n  // ── Terminal session tools ─────────────────────────────────────\n  // Four tools that mirror the agent-session set but operate on raw\n  // PTY sessions (real terminal, ANSI bytes, multi-subscriber). Use\n  // these to drive interactive CLIs like `claude` in TUI mode, or\n  // for one agent to orchestrate other shells. Read/write/exit\n  // happen over the byte ring buffer; the WS at /sessions/:id/pty\n  // is the streaming alternative.\n\n  const ptyNotConfigured = (toolName: string): {\n    content: Array<{ type: \"text\"; text: string }>\n    isError: true\n  } => ({\n    content: [\n      {\n        type: \"text\",\n        text:\n          `${toolName}: PTY support not enabled — the daemon was started without ` +\n          \"a node-pty factory. Re-run `agentproto serve` from a build that ships \" +\n          \"node-pty (the optional dep ships with @agentproto/cli).\",\n      },\n    ],\n    isError: true,\n  })\n\n  // ── session_restart ──────────────────────────────────────────────\n  // In-process equivalent of `agentproto sessions restart <id>` — the\n  // CLI has to shape an HTTP body and POST it back to this same daemon\n  // because it's a separate process; here we can go straight to the\n  // registry + adapter resolver. Both sides share `decideRestartStrategy`\n  // (resume-strategies.ts) so the two surfaces never diverge on which\n  // resume path wins.\n  server.tool(\n    \"session_restart\",\n    \"Respawn a session that has exited or been killed, preferring conversation \" +\n      \"continuity over a blank restart. Looks up the (possibly historical) \" +\n      \"descriptor by id or name — same lookup as `session_list` — and picks \" +\n      \"the same resume strategy `agentproto sessions restart` uses on the CLI: \" +\n      \"provider-native resume (spawns a PTY running the provider's own resume \" +\n      \"command, e.g. `claude --resume <id>`) when the adapter persisted one; \" +\n      \"else ACP-level resume via the adapter's own session id (retried as a \" +\n      \"fresh spawn if the adapter rejects the id with \\\"not found\\\" — typical \" +\n      \"when the prior session died before its first turn); else a plain PTY \" +\n      \"re-run for raw terminal sessions with no adapter match. Generic \" +\n      \"`command` sessions have no resume path and return an error. Returns \" +\n      \"the NEW session's descriptor plus `resumedFrom` (the prior id) and \" +\n      \"`resumeVia` (which path was used, empty string for a fresh respawn).\",\n    {\n      idOrName: z\n        .string()\n        .min(1)\n        .describe(\n          \"Session id or name to restart — from `session_list`, alive or \" +\n            \"historical (killed/exited/error).\"\n        ),\n      cols: z\n        .number()\n        .int()\n        .min(1)\n        .max(500)\n        .optional()\n        .describe(\n          \"PTY cols — only used when the restart resolves to a provider-native \" +\n            \"or plain PTY resume. Default 80.\"\n        ),\n      rows: z\n        .number()\n        .int()\n        .min(1)\n        .max(200)\n        .optional()\n        .describe(\"PTY rows — same case as `cols`. Default 24.\"),\n    },\n    async input => {\n      const prev = registry.findByIdOrName(input.idOrName)\n      if (!prev) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify({ error: `no session \"${input.idOrName}\" found` }),\n            },\n          ],\n          isError: true,\n        }\n      }\n      // Subtree scoping (WP4): mirrors agent_kill — a child orchestrator\n      // may only restart sessions it (transitively) spawned.\n      if (callerScope) {\n        const subtree = collectSubtree(callerScope.ownerSessionId, registry.list())\n        if (!subtree.has(prev.id)) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify({\n                  error: \"orchestrator_session_out_of_scope\",\n                  message:\n                    `session_restart: session \"${prev.id}\" is not in your subtree — ` +\n                    \"a scoped orchestrator can only restart sessions it (transitively) spawned.\",\n                  ok: false,\n                  sessionId: prev.id,\n                }),\n              },\n            ],\n            isError: true,\n          }\n        }\n      }\n\n      const augmented = await augmentWithFsResume(prev)\n      const strategy = decideRestartStrategy(augmented)\n\n      if (strategy.kind === \"unsupported\") {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify({ error: strategy.reason, sessionId: prev.id }),\n            },\n          ],\n          isError: true,\n        }\n      }\n\n      // cwd resolution mirrors /sessions/agent + /sessions/terminal:\n      // the prior descriptor's cwd is authoritative (it's how the\n      // session was actually running); fall back to the daemon's own\n      // cwd only for a legacy row that predates the field.\n      let cwd = prev.cwd\n      if (!cwd) {\n        cwd = process.cwd()\n        console.warn(\n          `[session_restart] no cwd on prior descriptor ${prev.id} — falling back to daemon's cwd ${cwd}`\n        )\n      }\n\n      try {\n        if (strategy.kind === \"pty-native\" || strategy.kind === \"pty-plain\") {\n          if (!ptyEnabled) return ptyNotConfigured(\"session_restart\")\n          const argv =\n            strategy.kind === \"pty-native\"\n              ? strategy.argv\n              : Array.isArray(prev.argv) && prev.argv.length > 0\n                ? [...prev.argv]\n                : tokenizeCommand(prev.command)\n          const desc = registry.spawnPty({\n            argv,\n            cwd,\n            workspaceSlug: prev.workspaceSlug,\n            cols: input.cols ?? 80,\n            rows: input.rows ?? 24,\n            ...(prev.name ? { name: prev.name } : {}),\n            ...(prev.label ? { label: prev.label } : {}),\n          })\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify(\n                  { ...desc, resumedFrom: prev.id, resumeVia: describeResumePath(augmented) },\n                  null,\n                  2\n                ),\n              },\n            ],\n          }\n        }\n\n        // strategy.kind === \"agent\" — decideRestartStrategy only returns\n        // this when `adapterSlug` is set, but TS can't see across the\n        // two objects, so re-check at runtime rather than casting.\n        const adapterSlug = prev.adapterSlug\n        if (!adapterSlug) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: \"session_restart: internal error — agent resume strategy without adapterSlug\",\n              },\n            ],\n            isError: true,\n          }\n        }\n        if (!resolveAgentAdapter) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text:\n                  \"session_restart: agent_start is not enabled — the daemon was started \" +\n                  \"without an adapter resolver.\",\n              },\n            ],\n            isError: true,\n          }\n        }\n        const resolved = await resolveAgentAdapter(adapterSlug)\n        if (!resolved) {\n          return {\n            content: [\n              { type: \"text\", text: `session_restart: adapter \"${adapterSlug}\" not found.` },\n            ],\n            isError: true,\n          }\n        }\n        const spawnWithResume = async (\n          resumeSessionId?: string\n        ): Promise<SessionDescriptor> => {\n          let liveSessionId: string | undefined\n          const agentSession = await resolved.startSession({\n            cwd,\n            ...(resumeSessionId ? { resumeSessionId } : {}),\n            ...(prev.model ? { model: prev.model } : {}),\n            ...(prev.mcpServers ? { mcpServers: prev.mcpServers } : {}),\n            onActivity: () => {\n              if (liveSessionId) registry.pulseActivity(liveSessionId)\n            },\n          })\n          const desc = registry.spawnAgent({\n            workspaceSlug: prev.workspaceSlug,\n            cwd,\n            agentSession,\n            adapterSlug,\n            ...(prev.label ? { label: prev.label } : {}),\n            ...(prev.mcpServers ? { mcpServers: prev.mcpServers } : {}),\n            ...(prev.model ? { model: prev.model } : {}),\n            ...(resolved.commandPreview ? { commandPreview: resolved.commandPreview } : {}),\n          })\n          liveSessionId = desc.id\n          return desc\n        }\n\n        let desc: SessionDescriptor\n        let resumeFallback = false\n        try {\n          desc = await spawnWithResume(strategy.resumeSessionId)\n        } catch (err) {\n          const msg = err instanceof Error ? err.message : String(err)\n          // Adapter doesn't recognize the resume id — typically means the\n          // prior session never got past the spawn (no turn happened).\n          // Retry as a fresh spawn so the caller at least gets the agent\n          // back, same fallback the CLI's `sessions restart` applies.\n          if (strategy.resumeSessionId && /not found|Resource not found/i.test(msg)) {\n            desc = await spawnWithResume(undefined)\n            resumeFallback = true\n          } else {\n            throw err\n          }\n        }\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify(\n                {\n                  ...desc,\n                  resumedFrom: prev.id,\n                  resumeVia: resumeFallback ? \"\" : describeResumePath(augmented),\n                  ...(resumeFallback ? { resumeFallback: true } : {}),\n                },\n                null,\n                2\n              ),\n            },\n          ],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `session_restart: ${err instanceof Error ? err.message : String(err)}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n    }\n  )\n\n  server.tool(\n    \"terminal_start\",\n    \"Spawn a process under a real PTY (node-pty) on the host. Bytes (including \" +\n      \"ANSI escapes, alt-screen sequences) flow through the daemon's byte ring \" +\n      \"buffer; subscribers attach via the WS at /sessions/:id/pty. Use for \" +\n      \"interactive TUIs (claude, vim, htop) or to orchestrate shells from another \" +\n      \"agent. Returns the session descriptor.\",\n    {\n      argv: z\n        .array(z.string())\n        .min(1)\n        .describe(\n          \"Argv array. First element is the binary, rest are arguments. \" +\n            \"e.g. ['claude'] or ['bash', '-l'].\"\n        ),\n      workspaceSlug: z\n        .string()\n        .optional()\n        .describe(\n          \"Workspace slug from `agentproto workspace list`. Resolves cwd. Omit \" +\n            \"to use `cwd` explicitly or the active workspace.\"\n        ),\n      cwd: z\n        .string()\n        .optional()\n        .describe(\"Absolute cwd. Wins over workspaceSlug when both set.\"),\n      cols: z.number().int().min(1).max(500).optional().describe(\"Initial cols. Default 80.\"),\n      rows: z.number().int().min(1).max(200).optional().describe(\"Initial rows. Default 24.\"),\n      name: z\n        .string()\n        .optional()\n        .describe(\n          \"User-friendly slug. Becomes an alias for the session id in \" +\n            \"subsequent tool calls (read/write/kill accept either).\"\n        ),\n      label: z\n        .string()\n        .optional()\n        .describe(\n          \"Free-text label surfaced in agent_sessions_list and the UI.\"\n        ),\n    },\n    async input => {\n      if (!ptyEnabled) return ptyNotConfigured(\"terminal_start\")\n      let cwd = input.cwd\n      let resolvedSlug = input.workspaceSlug ?? \"default\"\n      if (!cwd) {\n        try {\n          const config = await loadWorkspacesConfig()\n          const ws = input.workspaceSlug\n            ? findWorkspace(config, input.workspaceSlug)\n            : getActiveWorkspace(config)\n          if (ws) {\n            cwd = ws.path\n            resolvedSlug = ws.slug\n          }\n        } catch {\n          // fall through to error\n        }\n      }\n      if (!cwd) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text:\n                \"terminal_start: no cwd resolvable. Pass `cwd` explicitly \" +\n                \"or `workspaceSlug` matching `agentproto workspace list`.\",\n            },\n          ],\n          isError: true,\n        }\n      }\n      try {\n        const desc = registry.spawnPty({\n          argv: input.argv,\n          cwd,\n          workspaceSlug: resolvedSlug,\n          cols: input.cols ?? 80,\n          rows: input.rows ?? 24,\n          ...(input.name ? { name: input.name } : {}),\n          ...(input.label ? { label: input.label } : {}),\n        })\n        return {\n          content: [{ type: \"text\", text: JSON.stringify(desc, null, 2) }],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `terminal_start: ${err instanceof Error ? err.message : String(err)}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n    }\n  )\n\n  server.tool(\n    \"terminal_input\",\n    \"Send keystrokes to a PTY session's stdin. The text is forwarded verbatim — \" +\n      \"include trailing newlines if the target needs them (e.g. shell commands). \" +\n      \"Use after `terminal_start` to drive an interactive CLI.\",\n    {\n      sessionId: z\n        .string()\n        .describe(\"Session id OR name from terminal_start.\"),\n      text: z.string().describe(\"Text to write. Sent as-is to the PTY's stdin.\"),\n    },\n    async input => {\n      if (!ptyEnabled) return ptyNotConfigured(\"terminal_input\")\n      const desc = registry.findByIdOrName(input.sessionId)\n      if (!desc) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `terminal_input: no session \"${input.sessionId}\"`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      const ok = registry.writeTerminalInput(desc.id, input.text)\n      return {\n        content: [\n          {\n            type: \"text\",\n            text: JSON.stringify({ ok, sessionId: desc.id }, null, 2),\n          },\n        ],\n        ...(ok ? {} : { isError: true as const }),\n      }\n    }\n  )\n\n  server.tool(\n    \"terminal_output\",\n    \"Snapshot the recent byte buffer of a PTY session. Returns base64-encoded \" +\n      \"bytes (the buffer is RAW including ANSI escapes — strip with a regex if \" +\n      \"you want plain text). `lastBytes` caps the read from the tail.\",\n    {\n      sessionId: z\n        .string()\n        .describe(\"Session id OR name from terminal_start.\"),\n      lastBytes: z\n        .number()\n        .int()\n        .min(1)\n        .max(64 * 1024)\n        .optional()\n        .describe(\"Max bytes from the tail. Default: full ring buffer (~64 KiB).\"),\n    },\n    async input => {\n      if (!ptyEnabled) return ptyNotConfigured(\"terminal_output\")\n      const desc = registry.findByIdOrName(input.sessionId)\n      if (!desc) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `terminal_output: no session \"${input.sessionId}\"`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      const buf = registry.readTerminalOutput(\n        desc.id,\n        input.lastBytes,\n      )\n      if (!buf) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `terminal_output: session \"${desc.id}\" is not a PTY`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      return {\n        content: [\n          {\n            type: \"text\",\n            text: JSON.stringify(\n              {\n                sessionId: desc.id,\n                status: desc.status,\n                bytes: buf.byteLength,\n                b64: buf.toString(\"base64\"),\n              },\n              null,\n              2,\n            ),\n          },\n        ],\n      }\n    }\n  )\n\n  server.tool(\n    \"terminal_kill\",\n    \"SIGTERM a PTY session and drop it from the alive set. Same effect as \" +\n      \"`agent_kill` for the PTY family — separate name so it's obvious \" +\n      \"what's being stopped.\",\n    {\n      sessionId: z\n        .string()\n        .describe(\"Session id OR name from terminal_start.\"),\n    },\n    async input => {\n      if (!ptyEnabled) return ptyNotConfigured(\"terminal_kill\")\n      const desc = registry.findByIdOrName(input.sessionId)\n      if (!desc) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `terminal_kill: no session \"${input.sessionId}\"`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      const ok = registry.kill(desc.id)\n      return {\n        content: [\n          {\n            type: \"text\",\n            text: JSON.stringify({ ok, sessionId: desc.id }, null, 2),\n          },\n        ],\n      }\n    }\n  )\n}\n\n/**\n * Re-exported from agent-tools.ts for backwards compatibility.\n * The canonical definition lives there; callers importing from this\n * module still compile.\n */\nexport { registerExportSessionTool, collectSubtree } from \"./agent-tools.js\"\nexport type { ExportSessionOps } from \"./agent-tools.js\"\n","/**\n * MCP tools that expose browser service adapters (Camofox, Bureau, …) to\n * agents connected to the daemon. Lets a remote operator start, stop, and\n * inspect browser service sessions through the same MCP connection it uses\n * for fs/exec/agent-cli.\n *\n * Five tools:\n *   browser_adapter_list   discover available browser adapter ids + metadata\n *   start_browser           ensure a browser adapter is up, register as a session\n *   stop_browser            kill a running browser session\n *   list_browsers           browse alive/recent browser sessions\n *   browser_status          descriptor + live health probe for one session\n *\n * Auth: same as every other daemon tool — gated by the gateway's auth source.\n *\n * Injection pattern: `resolveBrowserAdapter` is passed in, not imported.\n * This keeps the runtime package free of a hard dep on @agentproto/adapter-browser.\n * The types below are minimal structural shapes — equivalent to `AgentSessionLike`\n * in sessions.ts.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { AdapterLister } from \"@agentproto/adapter-kit\"\nimport type { SessionsRegistry } from \"./sessions.js\"\n\n// ── Minimal structural types (no dep on @agentproto/adapter-browser) ──────────\n\n/**\n * Minimal shape of a BrowserAdapterInstance — structurally compatible with\n * @agentproto/adapter-browser's BrowserAdapterInstance. Kept local so the\n * runtime package stays free of a hard dependency on the adapter package.\n */\ninterface BrowserInstanceLike {\n  id: string\n  port: number\n  baseUrl: string\n  pid?: number\n  wasAlreadyRunning: boolean\n  /** False when a non-blocking cold start returned before the service\n   *  finished converging (background health-wait still running). */\n  healthy: boolean\n  stop(): Promise<void>\n}\n\n/**\n * Minimal shape of a BrowserAdapterHandle — structurally compatible with\n * @agentproto/adapter-browser's BrowserAdapterHandle.\n */\ninterface BrowserAdapterLike {\n  id: string\n  name: string\n  description: string\n  defaultPort: number\n  healthPath: string\n  /** Where this adapter runs — \"local\" (default) or \"cloud\". */\n  location?: \"local\" | \"cloud\"\n  ensure(opts: {\n    port?: number\n    /** forwarded to dependent adapters (e.g. bureau→camofox) */\n    camofoxPort?: number\n    launchCmd?: string\n    env?: Record<string, string>\n    timeoutMs?: number\n    /** Opt-in non-blocking cold start: wait only this long for a freshly\n     *  spawned service before returning `healthy:false` and converging\n     *  in the background. */\n    initialWaitMs?: number\n    log?: (s: string) => void\n    /** Override execution location (\"local\" or \"cloud\"). */\n    location?: \"local\" | \"cloud\"\n    /** Base URL of the remote service when location=\"cloud\". */\n    baseUrl?: string\n    /** Override the binary path for a local spawn. */\n    binPath?: string\n  }): Promise<BrowserInstanceLike>\n}\n\n/**\n * Bounded window `start_browser` waits for a freshly-spawned service to become\n * healthy before returning `starting`. Heavy services (chromium, bureau) take\n * >60s to boot (pnpm + Chrome launch) and would otherwise time out the MCP\n * request; we return promptly and let health converge in the background.\n */\nconst START_BROWSER_INITIAL_WAIT_MS = 6_000\n\nexport type BrowserAdapterResolver = (id: string) => BrowserAdapterLike | undefined\nexport type BrowserAdapterLister = () => {\n  id: string\n  name: string\n  description: string\n  defaultPort: number\n  /** Where this adapter runs — \"local\" (default) or \"cloud\". */\n  location?: \"local\" | \"cloud\"\n  /** Install methods — informational metadata from the adapter manifest. */\n  install?: unknown[]\n  /** Config prompts — informational metadata from the adapter manifest. */\n  config?: unknown[]\n}[]\n\n/**\n * Family-specific descriptor surfaced in the kit-path `browser_adapter_list`\n * response. Fields match the legacy lister shape so the tool output is\n * unchanged regardless of which path is active.\n */\nexport interface BrowserAdapterInfo {\n  id: string\n  name: string\n  description: string\n  defaultPort: number\n}\n\n// ── Shared result helpers ─────────────────────────────────────────────────────\n\nconst okResult = (r: Record<string, unknown>) => ({\n  content: [{ type: \"text\" as const, text: JSON.stringify(r, null, 2) }],\n  structuredContent: r,\n})\n\nconst errResult = (text: string) => ({\n  content: [{ type: \"text\" as const, text }],\n  isError: true as const,\n})\n\n// ── Registration ──────────────────────────────────────────────────────────────\n\ninterface RegisterBrowserToolsOptions {\n  registry: SessionsRegistry\n  /** Resolver for browser adapters — injected by the serve/CLI layer (P6).\n   *  Required for `start_browser`; the tool returns a clear error when unset. */\n  resolveBrowserAdapter?: BrowserAdapterResolver\n  /** Lister for available browser adapters — when unset, `browser_adapter_list`\n   *  returns a \"not configured\" message. */\n  listBrowserAdapters?: BrowserAdapterLister\n  /**\n   * Kit-path lister (Phase 3). When provided, `browser_adapter_list` calls\n   * this async lister and extracts `AdapterEntry.info` fields for the response,\n   * preserving the existing `{ id, name, description, defaultPort }[]` shape.\n   * When absent, the legacy `listBrowserAdapters` path is used.\n   */\n  lister?: AdapterLister<BrowserAdapterInfo>\n  log?: (msg: string) => void\n}\n\nexport function registerBrowserTools(\n  server: McpServer,\n  opts: RegisterBrowserToolsOptions\n): void {\n  const { registry, resolveBrowserAdapter, listBrowserAdapters, lister, log } = opts\n\n  // ── browser_adapter_list ────────────────────────────────────────────────────\n  server.tool(\n    \"browser_adapter_list\",\n    \"List available browser adapter ids and their metadata (name, description, default port). \" +\n      \"Use the `id` field to reference an adapter in `start_browser`.\",\n    {},\n    async () => {\n      // Kit path: async lister supplied — extract info fields to preserve the\n      // existing { id, name, description, defaultPort }[] response shape.\n      if (lister) {\n        const entries = await lister()\n        const adapters = entries.flatMap(e => (e.info ? [e.info] : []))\n        return {\n          content: [{ type: \"text\" as const, text: JSON.stringify(adapters, null, 2) }],\n        }\n      }\n      // Legacy path: synchronous injected lister.\n      if (!listBrowserAdapters) {\n        return {\n          content: [\n            {\n              type: \"text\" as const,\n              text:\n                \"browser_adapter_list is not enabled — the daemon was started without \" +\n                \"a browser adapter lister. Re-run with `listBrowserAdapters` wired.\",\n            },\n          ],\n          isError: true,\n        }\n      }\n      const adapters = listBrowserAdapters()\n      return {\n        content: [{ type: \"text\" as const, text: JSON.stringify(adapters, null, 2) }],\n      }\n    }\n  )\n\n  // ── start_browser ────────────────────────────────────────────────────────────\n  server.tool(\n    \"start_browser\",\n    \"Ensure a browser adapter service is running, then register it as a tracked session. \" +\n      \"Idempotent: if the service is already healthy, returns wasAlreadyRunning=true without spawning. \" +\n      \"Returns the session descriptor (sessionId, browserBaseUrl, …) for subsequent calls.\",\n    {\n      adapter: z\n        .string()\n        .min(1)\n        .describe(\n          \"Browser adapter id — one of the ids returned by `browser_adapter_list` \" +\n            \"(e.g. 'camofox', 'bureau').\"\n        ),\n      port: z\n        .number()\n        .int()\n        .optional()\n        .describe(\"Override the adapter's default port.\"),\n      camofoxPort: z\n        .number()\n        .int()\n        .optional()\n        .describe(\n          \"For adapters that depend on Camofox (e.g. 'bureau'): override the Camofox port (default 9377).\"\n        ),\n      label: z\n        .string()\n        .optional()\n        .describe(\"Free-text label surfaced in `list_browsers` and the UI.\"),\n      location: z\n        .enum([\"local\", \"cloud\"])\n        .optional()\n        .describe(\n          \"Override execution location. 'local' spawns the adapter process on this machine (default). \" +\n            \"'cloud' health-checks a remote endpoint at `baseUrl` without spawning anything.\"\n        ),\n      baseUrl: z\n        .string()\n        .optional()\n        .describe(\n          \"Base URL of the remote service when location='cloud' \" +\n            \"(e.g. 'https://browser-service.example.com'). Required when location='cloud'.\"\n        ),\n      binPath: z\n        .string()\n        .optional()\n        .describe(\n          \"Override the binary path used for the local spawn. \" +\n            \"When unset, the adapter resolves its own default binary.\"\n        ),\n    },\n    async input => {\n      if (!resolveBrowserAdapter) {\n        return {\n          content: [\n            {\n              type: \"text\" as const,\n              text:\n                \"start_browser is not enabled — the daemon was started without \" +\n                \"a browser adapter resolver. Re-run with `resolveBrowserAdapter` wired.\",\n            },\n          ],\n          isError: true,\n        }\n      }\n      const adapter = resolveBrowserAdapter(input.adapter)\n      if (!adapter) {\n        const available = listBrowserAdapters\n          ? listBrowserAdapters()\n              .map(a => a.id)\n              .join(\", \")\n          : \"camofox, bureau\"\n        return {\n          content: [\n            {\n              type: \"text\" as const,\n              text: `start_browser: adapter \"${input.adapter}\" not found. Available adapters: ${available}.`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      try {\n        const instance = await adapter.ensure({\n          port: input.port,\n          camofoxPort: input.camofoxPort,\n          location: input.location,\n          baseUrl: input.baseUrl,\n          binPath: input.binPath,\n          // Non-blocking cold start: if the freshly spawned service isn't\n          // healthy within this bounded window, register it as `starting`\n          // and let health converge in the background instead of blocking\n          // the MCP request until the full health timeout.\n          initialWaitMs: START_BROWSER_INITIAL_WAIT_MS,\n          log: msg => log?.(`[start_browser:${input.adapter}] ${msg}`),\n        })\n        const desc = registry.registerBrowser({\n          adapterId: instance.id,\n          port: instance.port,\n          baseUrl: instance.baseUrl,\n          location: input.location ?? adapter.location,\n          pid: instance.pid,\n          wasAlreadyRunning: instance.wasAlreadyRunning,\n          status: instance.healthy ? \"running\" : \"starting\",\n          stop: instance.stop.bind(instance),\n          label: input.label,\n        })\n        const stillStarting = !instance.healthy\n        return {\n          content: [\n            {\n              type: \"text\" as const,\n              text: JSON.stringify(\n                {\n                  sessionId: desc.id,\n                  browserAdapterId: desc.browserAdapterId,\n                  browserPort: desc.browserPort,\n                  browserBaseUrl: desc.browserBaseUrl,\n                  wasAlreadyRunning: instance.wasAlreadyRunning,\n                  status: desc.status,\n                  ...(stillStarting\n                    ? {\n                        hint:\n                          `Service is still booting (cold start). It was spawned successfully ` +\n                          `and is converging to healthy in the background — poll ` +\n                          `\\`browser_status\\` with sessionId \"${desc.id}\" until status is \"running\".`,\n                      }\n                    : {}),\n                },\n                null,\n                2\n              ),\n            },\n          ],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\" as const,\n              text: `start_browser: ${err instanceof Error ? err.message : String(err)}`,\n            },\n          ],\n          isError: true,\n        }\n      }\n    }\n  )\n\n  // ── stop_browser ─────────────────────────────────────────────────────────────\n  server.tool(\n    \"stop_browser\",\n    \"Stop a browser session registered by `start_browser`. \" +\n      \"Calls the adapter's stop() (best-effort SIGTERM) and marks the session as killed.\",\n    {\n      sessionId: z\n        .string()\n        .min(1)\n        .describe(\"Session id returned by `start_browser` or `list_browsers`.\"),\n    },\n    async input => {\n      const desc = registry.get(input.sessionId)\n      if (!desc) {\n        return {\n          content: [\n            {\n              type: \"text\" as const,\n              text: `stop_browser: session \"${input.sessionId}\" not found.`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      if (desc.kind !== \"browser\") {\n        return {\n          content: [\n            {\n              type: \"text\" as const,\n              text: `stop_browser: session \"${input.sessionId}\" is not a browser session (kind=${desc.kind}).`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      const ok = registry.kill(input.sessionId)\n      return {\n        content: [\n          {\n            type: \"text\" as const,\n            text: JSON.stringify({ ok, sessionId: input.sessionId }, null, 2),\n          },\n        ],\n      }\n    }\n  )\n\n  // ── list_browsers ────────────────────────────────────────────────────────────\n  server.tool(\n    \"list_browsers\",\n    \"List browser sessions tracked by the daemon (all or alive-only).\",\n    {\n      onlyAlive: z\n        .boolean()\n        .optional()\n        .describe(\n          \"When true, return only sessions with status='running'. Default false (all including killed/exited).\"\n        ),\n    },\n    async input => {\n      const all = registry\n        .list()\n        .filter(d => d.kind === \"browser\")\n      const result = input.onlyAlive\n        ? all.filter(d => d.status === \"running\")\n        : all\n      return {\n        content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n      }\n    }\n  )\n\n  // ── browser_status ───────────────────────────────────────────────────────────\n  server.tool(\n    \"browser_status\",\n    \"Get the descriptor and live health status for a specific browser session. \" +\n      \"Probes the service's /health endpoint to confirm it is still responding.\",\n    {\n      sessionId: z\n        .string()\n        .min(1)\n        .describe(\"Session id returned by `start_browser` or `list_browsers`.\"),\n    },\n    async input => {\n      const desc = registry.get(input.sessionId)\n      if (!desc) {\n        return {\n          content: [\n            {\n              type: \"text\" as const,\n              text: `browser_status: session \"${input.sessionId}\" not found.`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      if (desc.kind !== \"browser\") {\n        return {\n          content: [\n            {\n              type: \"text\" as const,\n              text: `browser_status: session \"${input.sessionId}\" is not a browser session (kind=${desc.kind}).`,\n            },\n          ],\n          isError: true,\n        }\n      }\n\n      let healthy: boolean | null = null\n      let healthBody: unknown = null\n      if (desc.browserBaseUrl) {\n        const healthUrl = `${desc.browserBaseUrl}/health`\n        const ac = new AbortController()\n        const t = setTimeout(() => ac.abort(), 3000)\n        try {\n          const r = await fetch(healthUrl, { signal: ac.signal })\n          healthy = r.ok\n          if (r.ok) {\n            try { healthBody = await r.json() } catch { /* non-JSON health */ }\n          }\n        } catch {\n          healthy = false\n        } finally {\n          clearTimeout(t)\n        }\n      }\n\n      return {\n        content: [\n          {\n            type: \"text\" as const,\n            text: JSON.stringify({ descriptor: desc, healthy, healthBody }, null, 2),\n          },\n        ],\n      }\n    }\n  )\n\n  // ── browser_screenshot ───────────────────────────────────────────────────────\n  server.tool(\n    \"browser_screenshot\",\n    \"Capture a base64-encoded screenshot of what an agent's browser session is currently showing. \" +\n      \"Dispatches to the correct backend by the session's browserAdapterId: \" +\n      \"camofox → GET /tabs/:tabId/screenshot, \" +\n      \"bureau → POST /mcp browser_screenshot, \" +\n      \"chromium → POST /sessions/:id/screenshot. \" +\n      \"Returns { data (base64, no data: prefix), format, width?, height? } in both text and structuredContent.\",\n    {\n      sessionId: z\n        .string()\n        .min(1)\n        .describe(\"Browser session id returned by `start_browser` or `list_browsers`.\"),\n      tabId: z\n        .string()\n        .optional()\n        .describe(\n          \"Camofox: tabId to screenshot (default: first active tab). \" +\n            \"Chromium: service-internal session id (default: first listed session). \" +\n            \"Bureau: ignored (bureau screenshots its current tab).\"\n        ),\n    },\n    async input => {\n      const desc = registry.get(input.sessionId)\n      if (!desc)\n        return errResult(`browser_screenshot: session \"${input.sessionId}\" not found.`)\n      if (desc.kind !== \"browser\")\n        return errResult(\n          `browser_screenshot: session \"${input.sessionId}\" is not a browser session (kind=${desc.kind}).`\n        )\n      if (!desc.browserBaseUrl)\n        return errResult(`browser_screenshot: session \"${input.sessionId}\" has no browserBaseUrl.`)\n\n      // Normalise to IPv4 — node/undici resolves localhost→::1 first but these\n      // services bind IPv4 only.\n      const rawUrl = new URL(desc.browserBaseUrl)\n      if (rawUrl.hostname === \"localhost\") rawUrl.hostname = \"127.0.0.1\"\n      const base = rawUrl.href.replace(/\\/$/, \"\")\n      const adapterId = desc.browserAdapterId ?? \"\"\n\n      // AbortController created after all guard-returns so the finally block\n      // below covers every path that reaches the network.\n      const ac = new AbortController()\n      const timer = setTimeout(() => ac.abort(), 15_000)\n\n      try {\n        // ── camofox (port 9377): GET /tabs/:tabId/screenshot ────────────────────\n        if (adapterId === \"camofox\") {\n          let tabId = input.tabId\n          if (!tabId) {\n            const tabsRes = await fetch(`${base}/tabs?userId=main`, { signal: ac.signal })\n            if (!tabsRes.ok) throw new Error(`camofox /tabs: HTTP ${tabsRes.status}`)\n            const tabsBody = (await tabsRes.json()) as { tabs?: { tabId: string }[] }\n            tabId = tabsBody.tabs?.[0]?.tabId\n            if (!tabId) throw new Error(\"camofox: no active tabs found\")\n          }\n          const shotRes = await fetch(\n            `${base}/tabs/${encodeURIComponent(tabId)}/screenshot?userId=main&format=png`,\n            { signal: ac.signal }\n          )\n          if (!shotRes.ok) throw new Error(`camofox screenshot: HTTP ${shotRes.status}`)\n          const data = Buffer.from(await shotRes.arrayBuffer()).toString(\"base64\")\n          return okResult({ data, format: \"png\" as const })\n        }\n\n        // ── bureau (port 8830): POST /mcp → browser_screenshot MCP tool ─────────\n        if (adapterId === \"bureau\") {\n          const mcpBody = {\n            jsonrpc: \"2.0\",\n            id: 1,\n            method: \"tools/call\",\n            params: { name: \"browser_screenshot\", arguments: { format: \"png\" } },\n          }\n          const mcpRes = await fetch(`${base}/mcp`, {\n            method: \"POST\",\n            headers: { \"content-type\": \"application/json\", accept: \"application/json, text/event-stream\" },\n            body: JSON.stringify(mcpBody),\n            signal: ac.signal,\n          })\n          if (!mcpRes.ok) throw new Error(`bureau /mcp: HTTP ${mcpRes.status}`)\n          const envelope = (await mcpRes.json()) as {\n            result?: { content?: { type: string; text?: string }[] }\n            error?: { message?: string }\n          }\n          if (envelope.error)\n            throw new Error(`bureau MCP error: ${envelope.error.message ?? \"unknown\"}`)\n          const textBlock = envelope.result?.content?.find(c => c.type === \"text\")\n          if (!textBlock?.text) throw new Error(\"bureau MCP: no text content block in response\")\n          const shot = JSON.parse(textBlock.text) as {\n            base64?: string\n            format?: string\n            width?: number\n            height?: number\n          }\n          if (!shot.base64) throw new Error(\"bureau MCP: screenshot result missing base64 field\")\n          return okResult({\n            data: shot.base64,\n            format: (shot.format ?? \"png\") as \"png\" | \"jpeg\",\n            ...(shot.width != null ? { width: shot.width } : {}),\n            ...(shot.height != null ? { height: shot.height } : {}),\n          })\n        }\n\n        // ── chromium (port 3200): POST /sessions/:id/screenshot ─────────────────\n        if (adapterId === \"chromium\") {\n          let chromiumSessionId = input.tabId\n          if (!chromiumSessionId) {\n            const listRes = await fetch(`${base}/sessions`, { signal: ac.signal })\n            if (!listRes.ok) throw new Error(`chromium /sessions: HTTP ${listRes.status}`)\n            const listBody = (await listRes.json()) as { sessions?: { id: string }[] }\n            chromiumSessionId = listBody.sessions?.[0]?.id\n            if (!chromiumSessionId) throw new Error(\"chromium: no active sessions found\")\n          }\n          const shotRes = await fetch(\n            `${base}/sessions/${encodeURIComponent(chromiumSessionId)}/screenshot`,\n            {\n              method: \"POST\",\n              headers: { \"content-type\": \"application/json\" },\n              body: JSON.stringify({ format: \"png\" }),\n              signal: ac.signal,\n            }\n          )\n          if (!shotRes.ok) throw new Error(`chromium screenshot: HTTP ${shotRes.status}`)\n          const data = Buffer.from(await shotRes.arrayBuffer()).toString(\"base64\")\n          return okResult({ data, format: \"png\" as const })\n        }\n\n        return errResult(\n          `browser_screenshot: adapter \"${adapterId}\" is not supported. ` +\n            \"Supported adapters: camofox, bureau, chromium.\"\n        )\n      } catch (err) {\n        return errResult(\n          `browser_screenshot: ${err instanceof Error ? err.message : String(err)}`\n        )\n      } finally {\n        clearTimeout(timer)\n      }\n    }\n  )\n}\n","/**\n * Adapter: registers AgnoMcpApp[] on a @modelcontextprotocol/sdk McpServer.\n *\n * Mirrors the @agstudio/mcp-apps platform pattern but without the Mastra\n * dependency (agentproto is a standalone pnpm workspace that cannot import\n * @agstudio/* packages). Both sides follow the same invariant:\n *\n *   _meta.ui.resourceUri lives at the TOOL DEFINITION level (registerTool\n *   config), NOT in the handler return value. This is because the SDK\n *   serialises the handler result as MCP content, and any _meta returned\n *   there would be buried inside the text payload and invisible to the host.\n *\n * Usage:\n *   import { registerMcpApps } from \"./mcp-apps-adapter.js\"\n *   import { makeSessionsPanelApp } from \"./sessions-panel-app.js\"\n *\n *   registerMcpApps(server, [\n *     makeSessionsPanelApp({ listSessions: () => sessions.list() }),\n *   ])\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport type { AgnoMcpApp } from \"./sessions-panel-app.js\"\n\nconst MIME_TYPE = \"text/html;profile=mcp-app\"\n\n/**\n * Register every AgnoMcpApp on the MCP server:\n *   • A resource at ui://<id>/view serving the HTML panel.\n *   • A tool named <id> that links to the resource via _meta.ui.resourceUri\n *     and optionally returns a JSON snapshot from execute().\n */\nexport function registerMcpApps(\n  server: McpServer,\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  apps: AgnoMcpApp<any, any>[],\n): void {\n  for (const app of apps) {\n    const resourceUri = `ui://${app.id}/view`\n    const html =\n      typeof app.html === \"string\" ? app.html : app.html({} as never)\n\n    // 1. Resource — HTML panel served at ui://<id>/view\n    server.registerResource(\n      app.id,\n      resourceUri,\n      {\n        mimeType: MIME_TYPE,\n        description: app.description,\n        _meta: { ui: { prefersBorder: true } },\n      },\n      async () => ({\n        contents: [\n          {\n            uri: resourceUri,\n            mimeType: MIME_TYPE,\n            text: html,\n          },\n        ],\n      }),\n    )\n\n    // 2. Tool — _meta.ui.resourceUri at definition level so the host\n    //    can pre-associate the panel before the handler even runs.\n    server.registerTool(\n      app.id,\n      {\n        description: app.description ?? app.title,\n        inputSchema: app.inputSchema.shape,\n        annotations: {\n          readOnlyHint: true,\n          openWorldHint: false,\n        },\n        _meta: {\n          ui: {\n            resourceUri,\n            visibility: [\"model\", \"app\"],\n          },\n        },\n      },\n      async (args) => {\n        const initData = app.execute ? await app.execute(args) : {}\n        return {\n          content: [\n            {\n              type: \"text\" as const,\n              text: JSON.stringify(initData, null, 2),\n            },\n          ],\n        }\n      },\n    )\n  }\n}\n","/**\n * MCP App resource: agentproto sessions panel.\n *\n * Declares a `ui://agentproto/sessions-panel` resource (mimeType\n * `text/html;profile=mcp-app`) and an `open_sessions_panel` tool that\n * links to it via `_meta.ui.resourceUri`.\n *\n * Protocol: MCP Apps ext spec 2026-01-26\n *   – Bridge: JSON-RPC 2.0 over window.parent.postMessage\n *   – Handshake: ui/initialize → host result → ui/notifications/initialized\n *   – Data: tools/call → session_list + agent_output (3 s poll)\n *   – Kill action: tools/call → agent_kill | terminal_kill\n *     (goes through Claude's normal tool approval flow)\n *\n * The HTML bundle is fully autonomous (zero CDN, zero external deps).\n * ANSI-to-HTML renderer handles SGR codes (colors 0-15, bold, dim,\n * italic, underline, reset). CR-overwrite sequences are stripped so\n * progress bars don't corrupt the output.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\n\nconst RESOURCE_URI = \"ui://agentproto/sessions-panel\"\nconst MIME_TYPE = \"text/html;profile=mcp-app\"\n\n// ── HTML bundle ─────────────────────────────────────────────────────────────\n\nexport const PANEL_HTML = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>agentproto sessions</title>\n<style>\n*{box-sizing:border-box;margin:0;padding:0}\n:root{\n  --bg:#0d1117;--bg2:#161b22;--bg3:#21262d;--border:#30363d;\n  --text:#e6edf3;--text2:#8b949e;\n  --green:#3fb950;--yellow:#d29922;--red:#f85149;--blue:#58a6ff;--purple:#bc8cff;\n}\nhtml,body{height:100%;font-family:Menlo,Monaco,'Courier New',monospace;font-size:13px;background:var(--bg);color:var(--text);overflow:hidden}\n#app{display:flex;height:100%}\n#sidebar{width:220px;min-width:180px;background:var(--bg2);border-right:1px solid var(--border);display:flex;flex-direction:column;flex-shrink:0}\n#sidebar-hdr{padding:10px 12px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between}\n#sidebar-hdr h1{font-size:11px;font-weight:600;color:var(--text2);text-transform:uppercase;letter-spacing:.06em}\n#refresh-btn{background:none;border:none;cursor:pointer;color:var(--text2);font-size:15px;line-height:1;padding:2px 4px;border-radius:4px;font-family:inherit}\n#refresh-btn:hover{color:var(--text);background:var(--bg3)}\n#session-list{flex:1;overflow-y:auto;padding:4px 0}\n.si{padding:8px 12px;cursor:pointer;border-left:2px solid transparent}\n.si:hover{background:var(--bg3)}\n.si.active{background:var(--bg3);border-left-color:var(--blue)}\n.sn{font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sm{font-size:11px;color:var(--text2);margin-top:2px;display:flex;gap:6px;align-items:center}\n.badge{display:inline-block;padding:1px 5px;border-radius:10px;font-size:10px;font-weight:600}\n.br{background:rgba(63,185,80,.15);color:var(--green)}\n.bs{background:rgba(88,166,255,.15);color:var(--blue)}\n.be{background:rgba(139,148,158,.1);color:var(--text2)}\n.bk{background:rgba(248,81,73,.1);color:var(--red)}\n.berr{background:rgba(248,81,73,.2);color:var(--red)}\n#main{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0}\n#toolbar{padding:8px 12px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;background:var(--bg2)}\n#session-title{font-size:12px;font-weight:500;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.abtn{background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:4px 10px;border-radius:4px;cursor:pointer;font-size:12px;font-family:inherit}\n.abtn:hover{background:var(--border)}\n.abtn:disabled{opacity:.4;cursor:default}\n.abtn.danger{border-color:var(--red);color:var(--red)}\n.abtn.danger:hover{background:rgba(248,81,73,.1)}\n#output{flex:1;overflow-y:auto;padding:8px 12px;background:var(--bg);font-size:12px;line-height:1.6}\n.line{white-space:pre-wrap;word-break:break-all}\n#empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--text2);gap:8px;text-align:center;padding:24px}\n#empty .ico{font-size:32px}\n#statusbar{padding:4px 12px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}\n.errmsg{color:var(--red);padding:12px}\n/* ANSI SGR */\n.ab{font-weight:bold}.ad{opacity:.6}.ai{font-style:italic}.au{text-decoration:underline}\n.f0{color:#21262d}.f1{color:#f85149}.f2{color:#3fb950}.f3{color:#d29922}\n.f4{color:#58a6ff}.f5{color:#bc8cff}.f6{color:#39d353}.f7{color:#e6edf3}\n.f8{color:#8b949e}.f9{color:#ff7b72}.f10{color:#56d364}.f11{color:#e3b341}\n.f12{color:#79c0ff}.f13{color:#d2a8ff}.f14{color:#56d364}.f15{color:#f0f6fc}\n</style>\n</head>\n<body>\n<div id=\"app\">\n  <div id=\"sidebar\">\n    <div id=\"sidebar-hdr\">\n      <h1>Sessions</h1>\n      <button id=\"refresh-btn\" title=\"Refresh\" onclick=\"doRefresh()\">&#8635;</button>\n    </div>\n    <div id=\"session-list\"></div>\n  </div>\n  <div id=\"main\">\n    <div id=\"toolbar\" style=\"display:none\">\n      <span id=\"session-title\"></span>\n      <button class=\"abtn danger\" id=\"kill-btn\" onclick=\"doKill()\">Kill</button>\n    </div>\n    <div id=\"output\">\n      <div id=\"empty\"><div class=\"ico\">&#9889;</div><div>Select a session</div></div>\n    </div>\n    <div id=\"statusbar\">Connecting to bridge&#8230;</div>\n  </div>\n</div>\n<script>\n// ============================================================\n// MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage\n// Spec: io.modelcontextprotocol/ui 2026-01-26\n// ============================================================\n\nvar _nextId = 1;\nvar _pending = {};   // id -> {resolve, reject}\n\nfunction post(msg) {\n  window.parent.postMessage(msg, '*');\n}\n\nfunction rpcRequest(method, params) {\n  return new Promise(function(resolve, reject) {\n    var id = _nextId++;\n    _pending[id] = {resolve: resolve, reject: reject};\n    post({jsonrpc: '2.0', id: id, method: method, params: params || {}});\n  });\n}\n\nfunction rpcNotify(method, params) {\n  post({jsonrpc: '2.0', method: method, params: params || {}});\n}\n\nwindow.addEventListener('message', function(evt) {\n  var msg = evt.data;\n  if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') return;\n  // Responses have an id and are not requests (no method)\n  if (msg.id != null && msg.method == null) {\n    var p = _pending[msg.id];\n    if (!p) return;\n    delete _pending[msg.id];\n    if (msg.error) {\n      p.reject(new Error(msg.error.message || 'rpc error ' + msg.error.code));\n    } else {\n      p.resolve(msg.result);\n    }\n  }\n  // Host notifications (ui/notifications/tool-input, ui/resource-teardown, etc.)\n  // — ignored for now; panel drives via poll\n});\n\n// Initialize bridge per spec 2026-01-26\nfunction initBridge() {\n  return rpcRequest('ui/initialize', {\n    capabilities: {},\n    clientInfo: {name: 'agentproto-sessions-panel', version: '0.1.0'},\n    protocolVersion: '2026-01-26',\n    appCapabilities: {\n      tools: {listChanged: false},\n      availableDisplayModes: ['inline', 'fullscreen']\n    }\n  }).then(function() {\n    rpcNotify('ui/notifications/initialized', {});\n  });\n}\n\n// Call an MCP tool through the bridge and parse the JSON result text\nfunction callTool(name, args) {\n  return rpcRequest('tools/call', {name: name, arguments: args || {}}).then(function(result) {\n    if (result.isError) {\n      var errText = (result.content && result.content[0] && result.content[0].text) || 'tool error';\n      throw new Error(errText);\n    }\n    var text = (result.content && result.content[0] && result.content[0].text) || '{}';\n    return JSON.parse(text);\n  });\n}\n\n// ============================================================\n// ANSI-to-HTML renderer (SGR codes: colors 0-15, bold/dim/italic/underline)\n// ============================================================\n\nfunction escHtml(s) {\n  return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n}\n\nfunction ansiToHtml(raw) {\n  // Strip CR overwrite sequences (progress bars: \\r without \\n)\n  var text = raw.replace(/[^\\n]*\\r([^\\n])/g, '$1').replace(/\\r/g, '');\n  var bold = false, dim = false, italic = false, underline = false, fg = -1;\n  var out = '';\n  // Split on ESC [ ... m (SGR) sequences; keep delimiters\n  var ESC = '\u001b';\n  var parts = text.split(/([\u001b]\\[[0-9;]*m)/);\n  for (var pi = 0; pi < parts.length; pi++) {\n    var part = parts[pi];\n    if (part.length === 0) continue;\n    if (part.charCodeAt(0) === 0x1b && part[1] === '[') {\n      // Parse SGR parameters\n      var inner = part.slice(2, part.length - 1); // strip ESC[ and m\n      var codes = inner === '' ? [0] : inner.split(';').map(Number);\n      for (var ci = 0; ci < codes.length; ci++) {\n        var c = codes[ci];\n        if (c === 0) { bold = false; dim = false; italic = false; underline = false; fg = -1; }\n        else if (c === 1) bold = true;\n        else if (c === 2) dim = true;\n        else if (c === 3) italic = true;\n        else if (c === 4) underline = true;\n        else if (c === 22) { bold = false; dim = false; }\n        else if (c === 23) italic = false;\n        else if (c === 24) underline = false;\n        else if (c >= 30 && c <= 37) fg = c - 30;\n        else if (c === 39) fg = -1;\n        else if (c >= 90 && c <= 97) fg = c - 90 + 8;\n      }\n    } else {\n      // Text segment — strip any remaining non-printable ESC sequences\n      var safe = escHtml(part).replace(/\u001b\\[[^m]*[A-Za-z]/g, '');\n      if (safe === '') continue;\n      var cls = '';\n      if (bold) cls += ' ab';\n      if (dim) cls += ' ad';\n      if (italic) cls += ' ai';\n      if (underline) cls += ' au';\n      if (fg >= 0 && fg <= 15) cls += ' f' + fg;\n      cls = cls.trim();\n      out += cls ? '<span class=\"' + cls + '\">' + safe + '</span>' : safe;\n    }\n  }\n  return out;\n}\n\n// ============================================================\n// App state\n// ============================================================\n\nvar sessions = [];\nvar activeId = null;\nvar outputLines = [];\nvar nextCursor = 0;\nvar pollTimer = null;\nvar pollActive = false;\n\nfunction setStatus(msg) {\n  document.getElementById('statusbar').textContent = msg;\n}\n\n// ============================================================\n// Session list\n// ============================================================\n\nfunction badgeClass(status) {\n  if (status === 'running') return 'br';\n  if (status === 'starting') return 'bs';\n  if (status === 'killed') return 'bk';\n  if (status === 'error') return 'berr';\n  return 'be'; // exited\n}\n\nfunction renderSidebar() {\n  var el = document.getElementById('session-list');\n  if (sessions.length === 0) {\n    el.innerHTML = '<div style=\"padding:12px;color:var(--text2);font-size:11px\">No sessions</div>';\n    return;\n  }\n  var html = '';\n  for (var i = 0; i < sessions.length; i++) {\n    var s = sessions[i];\n    var label = s.label || s.name || (s.command ? s.command.split('/').pop() : null) || s.id.slice(0, 8);\n    var bc = badgeClass(s.status);\n    var active = s.id === activeId ? ' active' : '';\n    html += '<div class=\"si' + active + '\" onclick=\"selectSession(\\'' + s.id + '\\')\">'\n          + '<div class=\"sn\">' + escHtml(label) + '</div>'\n          + '<div class=\"sm\">'\n          + '<span class=\"badge ' + bc + '\">' + s.status + '</span>'\n          + '<span>' + escHtml(s.kind || '') + '</span>'\n          + '</div></div>';\n  }\n  el.innerHTML = html;\n}\n\nfunction loadSessions() {\n  return callTool('session_list', {kind: 'all'}).then(function(data) {\n    sessions = data.sessions || [];\n    renderSidebar();\n    setStatus(sessions.length + ' session' + (sessions.length === 1 ? '' : 's') + ' · ' + new Date().toLocaleTimeString());\n  }).catch(function(e) {\n    setStatus('Error: ' + e.message);\n  });\n}\n\n// ============================================================\n// Output panel\n// ============================================================\n\nfunction renderOutputFull() {\n  var el = document.getElementById('output');\n  if (outputLines.length === 0) {\n    el.innerHTML = '<div id=\"empty\"><div class=\"ico\">&#9889;</div><div>No output yet</div></div>';\n    return;\n  }\n  var html = '';\n  for (var i = 0; i < outputLines.length; i++) {\n    html += '<div class=\"line\">' + ansiToHtml(outputLines[i]) + '</div>';\n  }\n  el.innerHTML = html;\n  el.scrollTop = el.scrollHeight;\n}\n\nfunction appendLines(lines) {\n  var el = document.getElementById('output');\n  // Remove empty-state placeholder if present\n  var empty = el.querySelector('#empty');\n  if (empty) empty.parentNode.removeChild(empty);\n  var frag = document.createDocumentFragment();\n  for (var i = 0; i < lines.length; i++) {\n    var div = document.createElement('div');\n    div.className = 'line';\n    div.innerHTML = ansiToHtml(lines[i]);\n    frag.appendChild(div);\n  }\n  el.appendChild(frag);\n  el.scrollTop = el.scrollHeight;\n}\n\nfunction selectSession(id) {\n  activeId = id;\n  outputLines = [];\n  nextCursor = 0;\n  renderSidebar();\n\n  var s = null;\n  for (var i = 0; i < sessions.length; i++) {\n    if (sessions[i].id === id) { s = sessions[i]; break; }\n  }\n\n  var toolbar = document.getElementById('toolbar');\n  toolbar.style.display = 'flex';\n  document.getElementById('session-title').textContent = (s && (s.label || s.name)) || id.slice(0, 12);\n\n  var killBtn = document.getElementById('kill-btn');\n  killBtn.disabled = !s || (s.status !== 'running' && s.status !== 'starting');\n\n  document.getElementById('output').innerHTML = '<div style=\"padding:12px;color:var(--text2)\">Loading&#8230;</div>';\n\n  // Initial load\n  callTool('agent_output', {sessionId: id, lastN: 200}).then(function(data) {\n    outputLines = data.lines || [];\n    nextCursor = data.nextCursor || 0;\n    renderOutputFull();\n  }).catch(function(e) {\n    document.getElementById('output').innerHTML = '<div class=\"errmsg\">Error: ' + escHtml(e.message) + '</div>';\n  });\n}\n\n// ============================================================\n// Kill\n// ============================================================\n\nfunction doKill() {\n  if (!activeId) return;\n  var s = null;\n  for (var i = 0; i < sessions.length; i++) {\n    if (sessions[i].id === activeId) { s = sessions[i]; break; }\n  }\n  var toolName = (s && s.pty) ? 'terminal_kill' : 'agent_kill';\n  callTool(toolName, {sessionId: activeId}).then(function() {\n    return doRefresh();\n  }).catch(function(e) {\n    setStatus('Kill failed: ' + e.message);\n  });\n}\n\n// ============================================================\n// Poll\n// ============================================================\n\nfunction doPoll() {\n  if (pollActive) return;\n  pollActive = true;\n  var p = loadSessions();\n  if (activeId) {\n    var capturedId = activeId;\n    var capturedCursor = nextCursor;\n    p = p.then(function() {\n      return callTool('agent_output', {sessionId: capturedId, since: capturedCursor});\n    }).then(function(data) {\n      if (capturedId !== activeId) return; // user switched sessions\n      var newLines = data.lines || [];\n      if (newLines.length > 0) {\n        outputLines = outputLines.concat(newLines);\n        if (outputLines.length > 2000) outputLines = outputLines.slice(-2000);\n        nextCursor = data.nextCursor || nextCursor;\n        appendLines(newLines);\n      }\n    }).catch(function() {});\n  }\n  p.then(function() {\n    pollActive = false;\n    pollTimer = setTimeout(doPoll, 3000);\n  }).catch(function() {\n    pollActive = false;\n    pollTimer = setTimeout(doPoll, 3000);\n  });\n}\n\nfunction doRefresh() {\n  return loadSessions().then(function() {\n    if (activeId) {\n      return callTool('agent_output', {sessionId: activeId, lastN: 200}).then(function(data) {\n        outputLines = data.lines || [];\n        nextCursor = data.nextCursor || 0;\n        renderOutputFull();\n      });\n    }\n  });\n}\n\n// ============================================================\n// Boot\n// ============================================================\n\ninitBridge().then(function() {\n  return loadSessions();\n}).then(function() {\n  pollTimer = setTimeout(doPoll, 3000);\n}).catch(function(e) {\n  setStatus('Bridge error: ' + e.message);\n  document.getElementById('output').innerHTML = '<div class=\"errmsg\">Failed to connect to MCP bridge: ' + escHtml(e.message) + '</div>';\n});\n</script>\n</body>\n</html>`\n\n// ── MCP registration ─────────────────────────────────────────────────────────\n\nexport function registerSessionsPanelResource(server: McpServer): void {\n  // Resource — MCP Apps host (Claude) reads this and renders the HTML\n  // in a sandboxed iframe.\n  server.registerResource(\n    \"sessions-panel\",\n    RESOURCE_URI,\n    {\n      mimeType: MIME_TYPE,\n      description:\n        \"Interactive sessions panel — browse, inspect output, and kill \" +\n        \"agentproto daemon sessions. Rendered as an MCP App in the host UI.\",\n      _meta: {\n        ui: {\n          // No external CSP domains needed — fully autonomous bundle.\n          prefersBorder: true,\n        },\n      },\n    },\n    async () => ({\n      contents: [\n        {\n          uri: RESOURCE_URI,\n          mimeType: MIME_TYPE,\n          text: PANEL_HTML,\n        },\n      ],\n    }),\n  )\n\n  // Tool — links to the panel resource via _meta.ui.resourceUri so the\n  // host pre-associates the panel with this tool call and can show it\n  // immediately when the tool is invoked.\n  server.registerTool(\n    \"open_sessions_panel\",\n    {\n      description:\n        \"Open the agentproto sessions panel — an interactive UI that shows all \" +\n        \"running and recent sessions (agent-CLI, terminal/PTY, commands). \" +\n        \"The panel polls live data and lets you inspect output or kill sessions. \" +\n        \"Rendered as an MCP App in the host interface.\",\n      inputSchema: undefined,\n      annotations: {\n        readOnlyHint: true,\n        openWorldHint: false,\n      },\n      _meta: {\n        ui: {\n          resourceUri: RESOURCE_URI,\n          visibility: [\"model\", \"app\"],\n        },\n      },\n    },\n    async () => ({\n      content: [\n        {\n          type: \"text\" as const,\n          text: JSON.stringify(\n            {\n              ok: true,\n              panel: RESOURCE_URI,\n              message: \"Sessions panel available. The host should render it as an MCP App.\",\n            },\n            null,\n            2,\n          ),\n        },\n      ],\n    }),\n  )\n}\n","/**\n * McpApp definition for the agentproto sessions panel.\n *\n * Uses the AgnoMcpApp contract (a local McpApp-compatible shape that does\n * NOT depend on @agstudio/mcp-apps or Mastra — agentproto is a separate\n * pnpm workspace). Wire via `registerMcpApps` from mcp-apps-adapter.ts.\n *\n * Protocol flow:\n *   1. Tool `agentproto_sessions` is called by the host.\n *   2. execute() returns a sessions snapshot → injected into the HTML as\n *      window.__APP_INIT__ (static initial render, no bridge needed).\n *   3. The HTML panel opens a JSON-RPC bridge (postMessage) and polls\n *      `session_list` + `agent_output` every 3 s for live data.\n */\n\nimport { z } from \"zod\"\nimport { PANEL_HTML } from \"./sessions-panel.js\"\nimport type { SessionDescriptor } from \"./sessions.js\"\n\nexport const sessionsPanelInputSchema = z.object({\n  filter: z\n    .enum([\"running\", \"all\"])\n    .optional()\n    .describe(\n      \"Which sessions to return. `running` = only alive; `all` = running + recent (default).\",\n    ),\n})\n\nexport type SessionsInput = z.infer<typeof sessionsPanelInputSchema>\nexport type SessionsOutput = { sessions: SessionDescriptor[] }\n\nexport interface SessionsPanelOps {\n  listSessions(filter?: \"running\" | \"all\"): SessionDescriptor[]\n}\n\n/**\n * Local McpApp-compatible shape — mirrors @agstudio/mcp-apps McpApp<TIn,TOut>\n * without importing it (cross-workspace isolation).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface AgnoMcpApp<TInput = unknown, TOutput = unknown> {\n  id: string\n  title: string\n  description?: string\n  /** Must be a z.object({...}) so registerMcpApps can extract .shape. */\n  inputSchema: z.ZodObject<z.ZodRawShape>\n  execute?: (input: TInput) => Promise<TOutput>\n  html: string | ((initData: TOutput) => string)\n}\n\n/**\n * Factory: close over the sessions registry so execute() doesn't need\n * an AppContext (agentproto has no userId/guildId concept).\n */\nexport function makeSessionsPanelApp(\n  ops: SessionsPanelOps,\n): AgnoMcpApp<SessionsInput, SessionsOutput> {\n  return {\n    id: \"agentproto_sessions\",\n    title: \"Agent Sessions\",\n    description:\n      \"Open the agentproto sessions panel — an interactive UI that shows all \" +\n      \"running and recent sessions (agent-CLI, terminal/PTY, commands). \" +\n      \"The panel polls live data and lets you inspect output or kill sessions.\",\n    inputSchema: sessionsPanelInputSchema,\n    execute: async (input) => ({\n      sessions: ops.listSessions(input.filter),\n    }),\n    html: PANEL_HTML,\n  }\n}\n","/**\n * McpApp definition for the agentproto \"agents — vue claire\" panel.\n *\n * A plain-language overview of agent-cli sessions: one card per session\n * with a single human sentence (what the agent is doing/last said) plus a\n * coarse state — `à traiter` / `au travail` / `en attente` / `terminé`.\n *\n * Uses the same AgnoMcpApp contract as sessions-panel-app.ts (a local\n * McpApp-compatible shape that does NOT depend on @agstudio/mcp-apps —\n * agentproto is a separate pnpm workspace). Wire via `registerMcpApps`.\n *\n * Protocol flow:\n *   1. Tool `agentproto_agents_overview` is called by the host.\n *   2. execute() returns the agent-session snapshot → injected into the\n *      HTML as the initial render via the tool result JSON.\n *   3. The HTML panel opens a JSON-RPC bridge (postMessage) and polls\n *      `session_list` every ~12 s, then calls `summarize_session` for\n *      each visible session to fetch the plain sentence + state.\n *\n * The per-session summary is generated SERVER-SIDE by the\n * `summarize_session` tool (see registerSummarizeSessionTool below).\n * Today it is HEURISTIC — last meaningful output line + a state derived\n * from lifecycle/awaitingInput/recency. There is no LLM client wired into\n * @agentproto/runtime (egress/providers.ts is a proxy allowlist, not an\n * inference client; driver-agent-cli's `ModelLike.complete` would spawn a\n * fresh agent session per call — too heavy, and it would pollute the very\n * session list we render). When a real summarizer is wanted, swap the body\n * of `summarizeSession` for a `ModelLike.complete({system, prompt})` call;\n * the tool contract (1 sentence + state) stays the same.\n */\n\nimport { z } from \"zod\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport type { SessionDescriptor } from \"./sessions.js\"\nimport type { AgnoMcpApp } from \"./sessions-panel-app.js\"\n\n// ── Heuristic summary (pure, server-side) ────────────────────────────────────\n\nexport type SessionState = \"à traiter\" | \"au travail\" | \"en attente\" | \"terminé\"\n\nconst ANSI_RE = /\\x1b\\[[0-9;?]*[A-Za-z]/g\n/** Chrome-only lines we never want as a summary (spinners, box-drawing,\n *  bare prompts, separators). */\nconst CHROME_RE = /^[\\s>$#*✻✶✳·•.\\-=_|~╭╰╮╯│─├┤┌┐└┘]+$/u\n\nfunction strip(s: string): string {\n  return s.replace(ANSI_RE, \"\").replace(/\\r/g, \"\")\n}\n\n/**\n * Pick the last meaningful output line as a one-sentence summary.\n * Falls back to the session label/command when there's no usable output.\n */\nexport function summarizeLines(\n  lines: readonly string[],\n  desc: Pick<SessionDescriptor, \"command\" | \"label\" | \"name\">,\n): string {\n  for (let i = lines.length - 1; i >= 0; i--) {\n    const t = strip(lines[i] ?? \"\").trim()\n    if (t.length < 3) continue\n    if (CHROME_RE.test(t)) continue\n    return t.length > 160 ? `${t.slice(0, 157)}…` : t\n  }\n  return desc.label || desc.name || desc.command || \"Aucune sortie pour le moment.\"\n}\n\n/**\n * Coarse state from lifecycle + recency. Heuristic, no LLM:\n *   terminé      — exited / killed / error\n *   à traiter    — alive and the agent flagged awaiting-input (your turn)\n *   au travail   — alive and produced output recently (< staleMs)\n *   en attente   — alive but idle (no recent output, not awaiting input)\n */\nexport function deriveSessionState(\n  desc: Pick<SessionDescriptor, \"status\" | \"awaitingInput\" | \"lastOutputAt\">,\n  nowMs: number,\n  staleMs = 30_000,\n): SessionState {\n  if (desc.status === \"exited\" || desc.status === \"killed\" || desc.status === \"error\") {\n    return \"terminé\"\n  }\n  if (desc.awaitingInput) return \"à traiter\"\n  const last = desc.lastOutputAt ? Date.parse(desc.lastOutputAt) : Number.NaN\n  if (!Number.isNaN(last) && nowMs - last < staleMs) return \"au travail\"\n  return \"en attente\"\n}\n\nexport interface SessionSummary {\n  sessionId: string\n  summary: string\n  state: SessionState\n  status: SessionDescriptor[\"status\"]\n  label?: string\n  lastOutputAt?: string\n}\n\n/** Build the full per-session summary from a descriptor + recent lines. */\nexport function summarizeSession(\n  desc: SessionDescriptor,\n  lines: readonly string[],\n  nowMs: number,\n): SessionSummary {\n  return {\n    sessionId: desc.id,\n    summary: summarizeLines(lines, desc),\n    state: deriveSessionState(desc, nowMs),\n    status: desc.status,\n    ...(desc.label ? { label: desc.label } : {}),\n    ...(desc.lastOutputAt ? { lastOutputAt: desc.lastOutputAt } : {}),\n  }\n}\n\n// ── summarize_session tool ───────────────────────────────────────────────────\n\nexport interface SummarizeOps {\n  getSession(id: string): SessionDescriptor | undefined\n  /** Tail the recent ring buffer for a session (same source as\n   *  agent_output). Returns [] for unknown sessions. */\n  tailLines(id: string, lastN: number): string[]\n  /** Current epoch-ms, injectable for tests. Defaults to Date.now. */\n  now?: () => number\n}\n\n/**\n * Register the server-side `summarize_session` tool. The agents-overview\n * panel calls this via the bridge (callTool) for each visible session.\n */\nexport function registerSummarizeSessionTool(server: McpServer, ops: SummarizeOps): void {\n  server.tool(\n    \"summarize_session\",\n    \"Summarise a session in one plain sentence plus a coarse state \" +\n      \"(à traiter / au travail / en attente / terminé). Heuristic today \" +\n      \"(last meaningful output line + lifecycle/recency) — no LLM. Used by \" +\n      \"the agents overview panel.\",\n    {\n      sessionId: z.string().describe(\"Session id to summarise.\"),\n      lastN: z\n        .number()\n        .int()\n        .min(1)\n        .max(500)\n        .optional()\n        .describe(\"Max recent lines to scan. Default 120.\"),\n    },\n    async input => {\n      const desc = ops.getSession(input.sessionId)\n      if (!desc) {\n        return {\n          content: [\n            { type: \"text\" as const, text: `summarize_session: no session \"${input.sessionId}\"` },\n          ],\n          isError: true,\n        }\n      }\n      const lines = ops.tailLines(input.sessionId, input.lastN ?? 120)\n      const nowMs = (ops.now ?? Date.now)()\n      return {\n        content: [\n          { type: \"text\" as const, text: JSON.stringify(summarizeSession(desc, lines, nowMs), null, 2) },\n        ],\n      }\n    },\n  )\n}\n\n// ── McpApp factory ───────────────────────────────────────────────────────────\n\nexport const agentsOverviewInputSchema = z.object({\n  filter: z\n    .enum([\"running\", \"all\"])\n    .optional()\n    .describe(\"`running` = only alive agent sessions; `all` = running + recent (default).\"),\n})\n\nexport type AgentsOverviewInput = z.infer<typeof agentsOverviewInputSchema>\nexport type AgentsOverviewOutput = { sessions: SessionDescriptor[] }\n\nexport interface AgentsOverviewOps {\n  listSessions(filter?: \"running\" | \"all\"): SessionDescriptor[]\n}\n\nexport function makeAgentsOverviewApp(\n  ops: AgentsOverviewOps,\n): AgnoMcpApp<AgentsOverviewInput, AgentsOverviewOutput> {\n  return {\n    id: \"agentproto_agents_overview\",\n    title: \"Agents — vue claire\",\n    description:\n      \"Open the agents overview — a plain-language card per agent session \" +\n      \"with one human sentence (what it's doing / last said) and a coarse \" +\n      \"state (à traiter / au travail / en attente / terminé). Polls live and \" +\n      \"asks the server to summarise each session.\",\n    inputSchema: agentsOverviewInputSchema,\n    execute: async input => ({ sessions: ops.listSessions(input.filter) }),\n    html: AGENTS_OVERVIEW_HTML,\n  }\n}\n\n// ── HTML bundle (zero CDN, CSP-safe inline) ──────────────────────────────────\n\nexport const AGENTS_OVERVIEW_HTML = `<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>agents — vue claire</title>\n<style>\n*{box-sizing:border-box;margin:0;padding:0}\n:root{\n  --bg:#0d1117;--bg2:#161b22;--bg3:#21262d;--border:#30363d;\n  --text:#e6edf3;--text2:#8b949e;\n  --green:#3fb950;--yellow:#d29922;--red:#f85149;--blue:#58a6ff;--purple:#bc8cff;\n}\nhtml,body{height:100%;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;font-size:13px;background:var(--bg);color:var(--text);overflow:hidden}\n#app{display:flex;flex-direction:column;height:100%}\n#hdr{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;background:var(--bg2);flex-shrink:0}\n#hdr h1{font-size:13px;font-weight:600;letter-spacing:.02em}\n#hdr .sub{font-size:11px;color:var(--text2);margin-top:2px}\n#refresh-btn{background:none;border:none;cursor:pointer;color:var(--text2);font-size:16px;line-height:1;padding:4px 6px;border-radius:6px}\n#refresh-btn:hover{color:var(--text);background:var(--bg3)}\n#grid{flex:1;overflow-y:auto;padding:14px 16px;display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;align-content:start}\n.card{background:var(--bg2);border:1px solid var(--border);border-left:3px solid var(--border);border-radius:8px;padding:12px 14px;display:flex;flex-direction:column;gap:8px;min-height:96px}\n.card.s-todo{border-left-color:var(--purple)}\n.card.s-work{border-left-color:var(--green)}\n.card.s-wait{border-left-color:var(--yellow)}\n.card.s-done{border-left-color:var(--text2)}\n.card-top{display:flex;align-items:center;justify-content:space-between;gap:8px}\n.title{font-size:12px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}\n.state{font-size:10px;font-weight:700;padding:2px 8px;border-radius:11px;white-space:nowrap;letter-spacing:.02em}\n.state.s-todo{background:rgba(188,140,255,.16);color:var(--purple)}\n.state.s-work{background:rgba(63,185,80,.16);color:var(--green)}\n.state.s-wait{background:rgba(210,153,34,.16);color:var(--yellow)}\n.state.s-done{background:rgba(139,148,158,.14);color:var(--text2)}\n.summary{font-size:12.5px;line-height:1.5;color:var(--text);word-break:break-word}\n.summary.muted{color:var(--text2);font-style:italic}\n.meta{font-size:10.5px;color:var(--text2);display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:auto}\n.dot{width:5px;height:5px;border-radius:50%;background:var(--text2);display:inline-block}\n#empty{grid-column:1/-1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--text2);gap:8px;padding:48px;text-align:center}\n#empty .ico{font-size:30px}\n#statusbar{padding:5px 16px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}\n</style>\n</head>\n<body>\n<div id=\"app\">\n  <div id=\"hdr\">\n    <div>\n      <h1>Agents — vue claire</h1>\n      <div class=\"sub\">une carte par agent · résumé + état</div>\n    </div>\n    <button id=\"refresh-btn\" title=\"Rafraîchir\" onclick=\"doRefresh()\">&#8635;</button>\n  </div>\n  <div id=\"grid\"><div id=\"empty\"><div class=\"ico\">&#9889;</div><div>Connexion au bridge&#8230;</div></div></div>\n  <div id=\"statusbar\">Connexion&#8230;</div>\n</div>\n<script>\n// ── MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ──\n// Spec: io.modelcontextprotocol/ui 2026-01-26\nvar _nextId = 1, _pending = {};\nfunction post(msg){ window.parent.postMessage(msg, '*'); }\nfunction rpcRequest(method, params){\n  return new Promise(function(resolve, reject){\n    var id = _nextId++;\n    _pending[id] = {resolve: resolve, reject: reject};\n    post({jsonrpc:'2.0', id:id, method:method, params:params||{}});\n  });\n}\nfunction rpcNotify(method, params){ post({jsonrpc:'2.0', method:method, params:params||{}}); }\nwindow.addEventListener('message', function(evt){\n  var msg = evt.data;\n  if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') return;\n  if (msg.id != null && msg.method == null){\n    var p = _pending[msg.id];\n    if (!p) return;\n    delete _pending[msg.id];\n    if (msg.error) p.reject(new Error(msg.error.message || ('rpc error ' + msg.error.code)));\n    else p.resolve(msg.result);\n  }\n});\nfunction initBridge(){\n  return rpcRequest('ui/initialize', {\n    capabilities: {},\n    clientInfo: {name:'agentproto-agents-overview', version:'0.1.0'},\n    protocolVersion: '2026-01-26',\n    appCapabilities: {tools:{listChanged:false}, availableDisplayModes:['inline','fullscreen']}\n  }).then(function(){ rpcNotify('ui/notifications/initialized', {}); });\n}\nfunction callTool(name, args){\n  return rpcRequest('tools/call', {name:name, arguments:args||{}}).then(function(result){\n    if (result.isError){\n      var e = (result.content && result.content[0] && result.content[0].text) || 'tool error';\n      throw new Error(e);\n    }\n    var text = (result.content && result.content[0] && result.content[0].text) || '{}';\n    return JSON.parse(text);\n  });\n}\n\n// ── State ──\nvar REFRESH_MS = 12000;\nvar pollTimer = null, polling = false;\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }\nfunction setStatus(m){ document.getElementById('statusbar').textContent = m; }\n\nvar STATE_CLASS = {\n  'à traiter':'s-todo', 'au travail':'s-work', 'en attente':'s-wait', 'terminé':'s-done'\n};\nfunction stateClass(st){ return STATE_CLASS[st] || 's-wait'; }\n\nfunction fmtAgo(iso){\n  if (!iso) return '';\n  var t = Date.parse(iso);\n  if (isNaN(t)) return '';\n  var s = Math.max(0, Math.round((Date.now() - t) / 1000));\n  if (s < 60) return 'il y a ' + s + 's';\n  var m = Math.round(s/60);\n  if (m < 60) return 'il y a ' + m + 'min';\n  var h = Math.round(m/60);\n  return 'il y a ' + h + 'h';\n}\n\nfunction titleOf(s){\n  return s.label || s.name || (s.command ? s.command.split(/\\\\s+/)[0].split('/').pop() : null) || s.id.slice(0,8);\n}\n\nfunction render(sessions, summaries){\n  var grid = document.getElementById('grid');\n  if (!sessions.length){\n    grid.innerHTML = '<div id=\"empty\"><div class=\"ico\">&#128564;</div><div>Aucune session d\\\\'agent</div></div>';\n    return;\n  }\n  var html = '';\n  for (var i=0;i<sessions.length;i++){\n    var s = sessions[i];\n    var sum = summaries[s.id] || {};\n    var st = sum.state || 'en attente';\n    var cls = stateClass(st);\n    var summary = sum.summary || 'Résumé indisponible.';\n    var muted = !sum.summary ? ' muted' : '';\n    html += '<div class=\"card ' + cls + '\">'\n      + '<div class=\"card-top\">'\n      +   '<span class=\"title\">' + esc(titleOf(s)) + '</span>'\n      +   '<span class=\"state ' + cls + '\">' + esc(st) + '</span>'\n      + '</div>'\n      + '<div class=\"summary' + muted + '\">' + esc(summary) + '</div>'\n      + '<div class=\"meta\">'\n      +   '<span>' + esc(s.kind || '') + '</span><span class=\"dot\"></span>'\n      +   '<span>' + esc(s.status || '') + '</span>'\n      +   (s.lastOutputAt ? '<span class=\"dot\"></span><span>' + esc(fmtAgo(s.lastOutputAt)) + '</span>' : '')\n      + '</div>'\n      + '</div>';\n  }\n  grid.innerHTML = html;\n}\n\nfunction loadAndRender(){\n  return callTool('session_list', {kind:'all'}).then(function(data){\n    var all = data.sessions || [];\n    var agents = all.filter(function(s){ return s.kind === 'agent-cli'; });\n    // Render shells immediately, then fill summaries as they arrive.\n    var summaries = {};\n    render(agents, summaries);\n    setStatus(agents.length + ' agent' + (agents.length===1?'':'s') + ' · ' + new Date().toLocaleTimeString('fr-FR'));\n    return Promise.all(agents.map(function(s){\n      return callTool('summarize_session', {sessionId: s.id}).then(function(sum){\n        summaries[s.id] = sum;\n      }).catch(function(){ /* leave shell */ });\n    })).then(function(){ render(agents, summaries); });\n  }).catch(function(e){ setStatus('Erreur : ' + e.message); });\n}\n\nfunction doPoll(){\n  if (polling) return;\n  polling = true;\n  loadAndRender().then(function(){\n    polling = false;\n    pollTimer = setTimeout(doPoll, REFRESH_MS);\n  }).catch(function(){\n    polling = false;\n    pollTimer = setTimeout(doPoll, REFRESH_MS);\n  });\n}\nfunction doRefresh(){ if (pollTimer) clearTimeout(pollTimer); return loadAndRender().then(function(){ pollTimer = setTimeout(doPoll, REFRESH_MS); }); }\n\ninitBridge().then(loadAndRender).then(function(){\n  pollTimer = setTimeout(doPoll, REFRESH_MS);\n}).catch(function(e){\n  setStatus('Bridge : ' + e.message);\n  document.getElementById('grid').innerHTML = '<div id=\"empty\"><div class=\"ico\">&#9888;</div><div>Échec connexion bridge : ' + esc(e.message) + '</div></div>';\n});\n</script>\n</body>\n</html>`\n","/**\n * McpApp definition for the agentproto \"bureau — sessions navigateur\" panel.\n *\n * Shows the browser sessions (kind === \"browser\"): adapter, base URL, port,\n * status and uptime. One row per live/recent browser service so you can see\n * what's bound where at a glance.\n *\n * Uses the same AgnoMcpApp contract as sessions-panel-app.ts (no\n * @agstudio/mcp-apps dependency — agentproto is a standalone workspace).\n * Wire via `registerMcpApps`.\n *\n * Protocol flow:\n *   1. Tool `agentproto_bureau_sessions` is called by the host.\n *   2. execute() returns the browser-session snapshot.\n *   3. The HTML panel opens a JSON-RPC bridge (postMessage) and polls\n *      `session_list {kind:'all'}` every ~5 s, filtering to kind===\"browser\".\n *\n * Data only — no server LLM. The whole bundle is inline (zero CDN).\n */\n\nimport { z } from \"zod\"\nimport type { SessionDescriptor } from \"./sessions.js\"\nimport type { AgnoMcpApp } from \"./sessions-panel-app.js\"\n\nexport const bureauSessionsInputSchema = z.object({\n  filter: z\n    .enum([\"running\", \"all\"])\n    .optional()\n    .describe(\"`running` = only alive browser sessions; `all` = running + recent (default).\"),\n})\n\nexport type BureauSessionsInput = z.infer<typeof bureauSessionsInputSchema>\nexport type BureauSessionsOutput = { sessions: SessionDescriptor[] }\n\nexport interface BureauSessionsOps {\n  listSessions(filter?: \"running\" | \"all\"): SessionDescriptor[]\n}\n\nexport function makeBureauSessionsApp(\n  ops: BureauSessionsOps,\n): AgnoMcpApp<BureauSessionsInput, BureauSessionsOutput> {\n  return {\n    id: \"agentproto_bureau_sessions\",\n    title: \"Bureau — sessions navigateur\",\n    description:\n      \"Open the browser-sessions panel — one row per browser service \" +\n      \"(adapter, base URL, port, status, uptime). Polls live every ~5 s.\",\n    inputSchema: bureauSessionsInputSchema,\n    execute: async input => ({\n      sessions: ops.listSessions(input.filter).filter(s => s.kind === \"browser\"),\n    }),\n    html: BUREAU_SESSIONS_HTML,\n  }\n}\n\n// ── HTML bundle (zero CDN, CSP-safe inline) ──────────────────────────────────\n\nexport const BUREAU_SESSIONS_HTML = `<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>bureau — sessions navigateur</title>\n<style>\n*{box-sizing:border-box;margin:0;padding:0}\n:root{\n  --bg:#0d1117;--bg2:#161b22;--bg3:#21262d;--border:#30363d;\n  --text:#e6edf3;--text2:#8b949e;\n  --green:#3fb950;--yellow:#d29922;--red:#f85149;--blue:#58a6ff;--purple:#bc8cff;\n}\n*{box-sizing:border-box}\nhtml,body{height:100%;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;font-size:13px;background:var(--bg);color:var(--text);overflow:hidden}\n#app{display:flex;flex-direction:column;height:100%}\n#hdr{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;background:var(--bg2);flex-shrink:0}\n#hdr h1{font-size:13px;font-weight:600}\n#hdr .sub{font-size:11px;color:var(--text2);margin-top:2px}\n#refresh-btn{background:none;border:none;cursor:pointer;color:var(--text2);font-size:16px;line-height:1;padding:4px 6px;border-radius:6px}\n#refresh-btn:hover{color:var(--text);background:var(--bg3)}\n#list{flex:1;overflow-y:auto;padding:14px 16px;display:flex;flex-direction:column;gap:10px}\n.row{background:var(--bg2);border:1px solid var(--border);border-radius:8px;padding:11px 14px;display:flex;align-items:center;gap:14px}\n.icon{font-size:20px;flex-shrink:0}\n.body{flex:1;min-width:0}\n.r1{display:flex;align-items:center;gap:8px}\n.adapter{font-size:12.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.url{font-family:Menlo,Monaco,'Courier New',monospace;font-size:11.5px;color:var(--blue);margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.meta{font-size:10.5px;color:var(--text2);margin-top:3px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}\n.dot{width:5px;height:5px;border-radius:50%;background:var(--text2);display:inline-block}\n.badge{font-size:10px;font-weight:700;padding:2px 8px;border-radius:11px;white-space:nowrap}\n.br{background:rgba(63,185,80,.16);color:var(--green)}\n.bs{background:rgba(88,166,255,.16);color:var(--blue)}\n.bk{background:rgba(248,81,73,.14);color:var(--red)}\n.be{background:rgba(139,148,158,.14);color:var(--text2)}\n.berr{background:rgba(248,81,73,.22);color:var(--red)}\n.port{font-family:Menlo,Monaco,'Courier New',monospace}\n#empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--text2);gap:8px;padding:48px;text-align:center}\n#empty .ico{font-size:30px}\n#statusbar{padding:5px 16px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}\n</style>\n</head>\n<body>\n<div id=\"app\">\n  <div id=\"hdr\">\n    <div>\n      <h1>Bureau — sessions navigateur</h1>\n      <div class=\"sub\">services navigateur actifs · URL / port / statut</div>\n    </div>\n    <button id=\"refresh-btn\" title=\"Rafraîchir\" onclick=\"doRefresh()\">&#8635;</button>\n  </div>\n  <div id=\"list\"><div id=\"empty\"><div class=\"ico\">&#127760;</div><div>Connexion au bridge&#8230;</div></div></div>\n  <div id=\"statusbar\">Connexion&#8230;</div>\n</div>\n<script>\n// ── MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ──\n// Spec: io.modelcontextprotocol/ui 2026-01-26\nvar _nextId = 1, _pending = {};\nfunction post(msg){ window.parent.postMessage(msg, '*'); }\nfunction rpcRequest(method, params){\n  return new Promise(function(resolve, reject){\n    var id = _nextId++;\n    _pending[id] = {resolve: resolve, reject: reject};\n    post({jsonrpc:'2.0', id:id, method:method, params:params||{}});\n  });\n}\nfunction rpcNotify(method, params){ post({jsonrpc:'2.0', method:method, params:params||{}}); }\nwindow.addEventListener('message', function(evt){\n  var msg = evt.data;\n  if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') return;\n  if (msg.id != null && msg.method == null){\n    var p = _pending[msg.id];\n    if (!p) return;\n    delete _pending[msg.id];\n    if (msg.error) p.reject(new Error(msg.error.message || ('rpc error ' + msg.error.code)));\n    else p.resolve(msg.result);\n  }\n});\nfunction initBridge(){\n  return rpcRequest('ui/initialize', {\n    capabilities: {},\n    clientInfo: {name:'agentproto-bureau-sessions', version:'0.1.0'},\n    protocolVersion: '2026-01-26',\n    appCapabilities: {tools:{listChanged:false}, availableDisplayModes:['inline','fullscreen']}\n  }).then(function(){ rpcNotify('ui/notifications/initialized', {}); });\n}\nfunction callTool(name, args){\n  return rpcRequest('tools/call', {name:name, arguments:args||{}}).then(function(result){\n    if (result.isError){\n      var e = (result.content && result.content[0] && result.content[0].text) || 'tool error';\n      throw new Error(e);\n    }\n    var text = (result.content && result.content[0] && result.content[0].text) || '{}';\n    return JSON.parse(text);\n  });\n}\n\n// ── State ──\nvar REFRESH_MS = 5000;\nvar pollTimer = null, polling = false;\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }\nfunction setStatus(m){ document.getElementById('statusbar').textContent = m; }\n\nfunction badgeClass(st){\n  if (st === 'running') return 'br';\n  if (st === 'starting') return 'bs';\n  if (st === 'killed') return 'bk';\n  if (st === 'error') return 'berr';\n  return 'be';\n}\nfunction fmtUptime(iso, end){\n  if (!iso) return '';\n  var start = Date.parse(iso);\n  if (isNaN(start)) return '';\n  var ref = end ? Date.parse(end) : Date.now();\n  var s = Math.max(0, Math.round((ref - start) / 1000));\n  if (s < 60) return s + 's';\n  var m = Math.floor(s/60), rs = s%60;\n  if (m < 60) return m + 'm ' + rs + 's';\n  var h = Math.floor(m/60), rm = m%60;\n  return h + 'h ' + rm + 'm';\n}\n\nfunction render(rows){\n  var list = document.getElementById('list');\n  if (!rows.length){\n    list.innerHTML = '<div id=\"empty\"><div class=\"ico\">&#127760;</div><div>Aucune session navigateur</div></div>';\n    return;\n  }\n  var html = '';\n  for (var i=0;i<rows.length;i++){\n    var s = rows[i];\n    var bc = badgeClass(s.status);\n    var url = s.browserBaseUrl || (s.browserPort ? ('http://127.0.0.1:' + s.browserPort) : '');\n    var adapter = s.browserAdapterId || s.label || s.name || 'navigateur';\n    var up = fmtUptime(s.startedAt, s.endedAt);\n    html += '<div class=\"row\">'\n      + '<div class=\"icon\">&#127760;</div>'\n      + '<div class=\"body\">'\n      +   '<div class=\"r1\"><span class=\"adapter\">' + esc(adapter) + '</span>'\n      +     '<span class=\"badge ' + bc + '\">' + esc(s.status || '') + '</span></div>'\n      +   (url ? '<div class=\"url\">' + esc(url) + '</div>' : '')\n      +   '<div class=\"meta\">'\n      +     (s.browserPort ? '<span>port <span class=\"port\">' + esc(s.browserPort) + '</span></span><span class=\"dot\"></span>' : '')\n      +     '<span>' + (up ? 'uptime ' + esc(up) : '') + '</span>'\n      +   '</div>'\n      + '</div>'\n      + '</div>';\n  }\n  list.innerHTML = html;\n}\n\nfunction loadAndRender(){\n  return callTool('session_list', {kind:'all'}).then(function(data){\n    var all = data.sessions || [];\n    var browsers = all.filter(function(s){ return s.kind === 'browser'; });\n    render(browsers);\n    setStatus(browsers.length + ' session' + (browsers.length===1?'':'s') + ' · ' + new Date().toLocaleTimeString('fr-FR'));\n  }).catch(function(e){ setStatus('Erreur : ' + e.message); });\n}\n\nfunction doPoll(){\n  if (polling) return;\n  polling = true;\n  loadAndRender().then(function(){\n    polling = false;\n    pollTimer = setTimeout(doPoll, REFRESH_MS);\n  }).catch(function(){\n    polling = false;\n    pollTimer = setTimeout(doPoll, REFRESH_MS);\n  });\n}\nfunction doRefresh(){ if (pollTimer) clearTimeout(pollTimer); return loadAndRender().then(function(){ pollTimer = setTimeout(doPoll, REFRESH_MS); }); }\n\ninitBridge().then(loadAndRender).then(function(){\n  pollTimer = setTimeout(doPoll, REFRESH_MS);\n}).catch(function(e){\n  setStatus('Bridge : ' + e.message);\n  document.getElementById('list').innerHTML = '<div id=\"empty\"><div class=\"ico\">&#9888;</div><div>Échec connexion bridge : ' + esc(e.message) + '</div></div>';\n});\n</script>\n</body>\n</html>`\n","/**\n * HEARTBEAT.md autonomy loop.\n *\n * A workspace can ship a `HEARTBEAT.md` at its root. Frontmatter:\n *\n *   schema: heartbeat/v1\n *   agent: <id>           (matches `<workspace>/.agents/<id>/AGENT.md`)\n *   every: \"60s\"          (Ns | Nm | Nh | Nd; cron support TODO)\n *   enabled: true         (default true; set false to register-but-skip)\n *   conversation: heartbeat-{date}   (templated id; defaults to per-day)\n *\n * Body = the prompt body the agent receives each tick. Reread fresh\n * on every tick so editing HEARTBEAT.md takes effect without restart.\n *\n * Ticks resolve the agent via the injected `buildAgent` callback,\n * call `agent.generate(prompt)`, and append the prompt + reply to a\n * conversation (default: daily-rolling `heartbeat-YYYY-MM-DD`).\n *\n * When the file is missing, frontmatter is invalid, `enabled: false`,\n * or the resolved agent has no usable model — the runner skips the\n * tick silently and emits a `heartbeat-error` event. The daemon\n * stays up.\n */\n\nimport matter from \"gray-matter\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport type { ConversationStore } from \"./conversations.js\"\nimport type { RuntimeEvents } from \"./events.js\"\n\nexport interface HeartbeatAgent {\n  generate(prompt: string): Promise<{ text: string }>\n}\n\nexport interface BuildHeartbeatAgent {\n  (id: string): Promise<HeartbeatAgent | null>\n}\n\nexport interface HeartbeatRunnerOptions {\n  workspace: string\n  conversations: ConversationStore\n  events: RuntimeEvents\n  /** Resolves a heartbeat-runnable agent from its workspace id. */\n  buildAgent: BuildHeartbeatAgent\n  /** Filename inside the workspace root. Default `HEARTBEAT.md`. */\n  filename?: string\n  /** Skip ticks while this returns false. Default: always true. */\n  shouldFire?: () => boolean\n  /** Override clock for tests. */\n  now?: () => Date\n}\n\nexport interface HeartbeatRunner {\n  /** Start the timer loop. Idempotent. */\n  start(): void\n  /** Stop the timer loop. Pending ticks finish out. */\n  stop(): void\n  /** Force-fire one tick now (used by `POST /heartbeat/tick`). */\n  fireNow(): Promise<void>\n}\n\ninterface ParsedHeartbeat {\n  agent: string\n  everyMs: number\n  enabled: boolean\n  conversationTemplate: string\n  body: string\n}\n\nexport function startHeartbeat(opts: HeartbeatRunnerOptions): HeartbeatRunner {\n  const filename = opts.filename ?? \"HEARTBEAT.md\"\n  const path = join(opts.workspace, filename)\n  const now = opts.now ?? (() => new Date())\n\n  let timer: NodeJS.Timeout | null = null\n  let currentEveryMs: number | null = null\n  let firing = false\n\n  async function load(): Promise<ParsedHeartbeat | null> {\n    if (!existsSync(path)) return null\n    let source: string\n    try {\n      source = await readFile(path, \"utf8\")\n    } catch {\n      return null\n    }\n    const parsed = matter(source)\n    const fm = parsed.data as Record<string, unknown>\n    const agent = typeof fm.agent === \"string\" ? fm.agent : null\n    if (!agent) return null\n    const enabled = fm.enabled === undefined ? true : Boolean(fm.enabled)\n    const everyRaw = typeof fm.every === \"string\" ? fm.every : \"60s\"\n    const everyMs = parseDuration(everyRaw)\n    if (!everyMs) return null\n    const conversationTemplate =\n      typeof fm.conversation === \"string\"\n        ? fm.conversation\n        : \"heartbeat-{date}\"\n    return {\n      agent,\n      everyMs,\n      enabled,\n      conversationTemplate,\n      body: parsed.content.trim(),\n    }\n  }\n\n  async function tick(): Promise<void> {\n    if (firing) return\n    if (opts.shouldFire && !opts.shouldFire()) return\n    firing = true\n    let agentId: string | undefined\n    try {\n      const hb = await load()\n      if (!hb || !hb.enabled) return\n      agentId = hb.agent\n      const agent = await opts.buildAgent(hb.agent)\n      if (!agent) {\n        opts.events.emit({\n          type: \"heartbeat-error\",\n          at: now().toISOString(),\n          agent: hb.agent,\n          error: `buildAgent('${hb.agent}') returned null`,\n        })\n        return\n      }\n      if (!hb.body) {\n        opts.events.emit({\n          type: \"heartbeat-error\",\n          at: now().toISOString(),\n          agent: hb.agent,\n          error: \"HEARTBEAT.md body is empty\",\n        })\n        return\n      }\n\n      const conversationId = expandTemplate(hb.conversationTemplate, now())\n      await opts.conversations.open(conversationId, { agent: hb.agent })\n\n      const startedAt = now()\n      await opts.conversations.appendTurn(\n        conversationId,\n        \"user\",\n        hb.body,\n        { at: startedAt.toISOString(), attribution: \"heartbeat\" },\n      )\n      opts.events.emit({\n        type: \"conv-turn-appended\",\n        at: startedAt.toISOString(),\n        conversationId,\n        role: \"user\",\n        contentPreview: preview(hb.body),\n      })\n\n      const t0 = Date.now()\n      const reply = await agent.generate(hb.body)\n      const durationMs = Date.now() - t0\n\n      const finishedAt = now()\n      await opts.conversations.appendTurn(\n        conversationId,\n        \"assistant\",\n        reply.text,\n        { at: finishedAt.toISOString(), attribution: hb.agent },\n      )\n      opts.events.emit({\n        type: \"conv-turn-appended\",\n        at: finishedAt.toISOString(),\n        conversationId,\n        role: \"assistant\",\n        contentPreview: preview(reply.text),\n      })\n      opts.events.emit({\n        type: \"heartbeat-fired\",\n        at: finishedAt.toISOString(),\n        agent: hb.agent,\n        conversationId,\n        prompt: hb.body,\n        reply: reply.text,\n        durationMs,\n      })\n\n      // Adapt the timer if `every` changed since we started.\n      if (currentEveryMs !== null && currentEveryMs !== hb.everyMs) {\n        reschedule(hb.everyMs)\n      }\n    } catch (err) {\n      opts.events.emit({\n        type: \"heartbeat-error\",\n        at: now().toISOString(),\n        agent: agentId,\n        error: err instanceof Error ? err.message : String(err),\n      })\n    } finally {\n      firing = false\n    }\n  }\n\n  function reschedule(everyMs: number): void {\n    if (timer) clearInterval(timer)\n    currentEveryMs = everyMs\n    timer = setInterval(() => {\n      void tick()\n    }, everyMs)\n  }\n\n  return {\n    start() {\n      if (timer) return\n      // Bootstrap interval from the file (or fall back to 60s if\n      // unreadable — first real tick will refresh from disk).\n      void load().then((hb) => {\n        const everyMs = hb?.everyMs ?? 60_000\n        reschedule(everyMs)\n      })\n    },\n    stop() {\n      if (timer) {\n        clearInterval(timer)\n        timer = null\n        currentEveryMs = null\n      }\n    },\n    async fireNow() {\n      await tick()\n    },\n  }\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nconst DURATION_RE = /^(\\d+)\\s*(s|m|h|d)$/\n\n/**\n * Parse `Ns | Nm | Nh | Nd` into milliseconds. Returns `null` if the\n * string doesn't match. (AIP-41 supports more units, but the daemon's\n * heartbeat sticks to coarse durations to keep ticks observable.)\n */\nexport function parseDuration(input: string): number | null {\n  const trimmed = input.trim()\n  const match = trimmed.match(DURATION_RE)\n  if (!match) return null\n  const n = Number(match[1])\n  if (!Number.isFinite(n) || n <= 0) return null\n  switch (match[2]) {\n    case \"s\":\n      return n * 1_000\n    case \"m\":\n      return n * 60_000\n    case \"h\":\n      return n * 3_600_000\n    case \"d\":\n      return n * 86_400_000\n    default:\n      return null\n  }\n}\n\n/**\n * Replace `{date}` with `YYYY-MM-DD` (UTC) in conversation templates.\n * Other tokens pass through unchanged — extend later if needed.\n */\nfunction expandTemplate(template: string, when: Date): string {\n  const date = when.toISOString().slice(0, 10)\n  return template.replace(/\\{date\\}/g, date)\n}\n\nfunction preview(text: string, max = 120): string {\n  const flat = text.replace(/\\s+/g, \" \").trim()\n  return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat\n}\n","/**\n * Sessions registry — tracks long-lived child processes spawned by\n * the agentproto daemon (terminals, agent CLIs, custom commands).\n *\n * The registry lives in-memory for the daemon's lifetime; a recent\n * snapshot also persists to `~/.agentproto/sessions.json` so a fresh\n * daemon restart can show \"you had these running before\" instead of\n * losing all visibility on a crash.\n *\n * Each session owns:\n *   - identity: id, kind, workspace slug, command + args, started time\n *   - lifecycle: status (starting/running/exited/killed/error)\n *   - output:    last N lines (ring buffer) for instant attach + a\n *                Node EventEmitter for live streaming consumers\n *\n * Consumers:\n *   - HTTP routes (GET /sessions, /sessions/:id, /sessions/:id/stream,\n *     POST /sessions/:id/kill)\n *   - CLI `agentproto sessions` (TUI navigation + attach)\n *   - guilde-web Active tab (session cards + terminal viewer)\n */\n\nimport type { AcpMcpServer } from \"@agentproto/acp\"\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { EventEmitter } from \"node:events\"\nimport { mkdirSync, writeFileSync, promises as fs, readFileSync } from \"node:fs\"\nimport { RESUME_STRATEGIES } from \"./resume-strategies.js\"\nimport type { SessionEventBus, SessionAwaitingQuestion } from \"./session-event-bus.js\"\nimport { formatToolCall, formatToolResult } from \"./tool-presenter.js\"\nimport { createTranscriptWriter } from \"./transcript-writer.js\"\nimport { dirname, join, resolve } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { randomUUID } from \"node:crypto\"\n\n/**\n * Minimal shape we need from a driver-agent-cli session — kept as a\n * structural type so the runtime package doesn't take a hard\n * dependency on @agentproto/driver-agent-cli (the http-server route\n * imports it and passes the constructed session in).\n */\nexport interface AgentSessionLike {\n  sessionId: string\n  /** OS-level process id of the spawned child, when the driver owns a\n   *  real subprocess. Mirrored onto `SessionDescriptor.pid` at\n   *  `spawnAgent` time so `processAlive` can be computed without\n   *  adapter-specific forensics. Undefined for drivers that don't\n   *  expose a process (e.g. a future non-subprocess transport). */\n  pid?: number\n  send(message: unknown): AsyncIterable<AgentStreamEvent>\n  cancel(): Promise<void>\n  close(): Promise<void>\n}\n\n/**\n * Minimal PTY surface — structurally compatible with\n * @agentproto/acp/tunnel's PtyProcess (node-pty's IPty wrapper). The\n * runtime declares its own so this package stays native-free; the\n * cli's pty-factory util constructs values that satisfy both.\n */\nexport interface PtyProcess {\n  readonly pid: number\n  write(data: string): void\n  resize(cols: number, rows: number): void\n  kill(signal?: string): void\n  onData(handler: (data: string) => void): void\n  onExit(handler: (event: { exitCode: number; signal?: number }) => void): void\n}\n\nexport interface PtyFactoryOptions {\n  command: string\n  args: string[]\n  cwd?: string\n  env?: Record<string, string>\n  cols: number\n  rows: number\n}\n\nexport type PtyFactory = (opts: PtyFactoryOptions) => PtyProcess\n\nexport interface AgentStreamEvent {\n  kind: string\n  text?: string\n  /** Correlates a \"tool-call\" with its later \"tool-result\" (and an\n   *  \"agent-prompt\" with the permission it's asking about) — see\n   *  @agentproto/acp's `StreamEvent`. */\n  toolCallId?: string\n  toolName?: string\n  /** Tool-call input, e.g. an ACP `tool_call`'s `arguments` — see @agentproto/acp's `StreamEvent`. */\n  arguments?: unknown\n  /** Tool-call output, e.g. an ACP `tool_call_update`'s `result` — see @agentproto/acp's `StreamEvent`. */\n  result?: unknown\n  isError?: boolean\n  reason?: string\n  error?: { message: string; code?: number; data?: unknown }\n  /** Structured options offered by an \"agent-prompt\" event (e.g. an ACP\n   *  `requestPermission` callback surfaced as a clarifying question rather\n   *  than auto-answered). Typed `unknown` — like `@agentproto/acp`'s own\n   *  `StreamEvent[\"options\"]` — so this structural type stays assignable\n   *  from any driver's runtime session without a hard dependency on its\n   *  exact option shape (`{optionId,name,kind}` for ACP, or whatever a\n   *  future driver reports); `normalizeAgentPromptOptions` narrows it\n   *  defensively at the one place it's consumed. */\n  options?: unknown\n  /** \"plan\" event entries — see @agentproto/acp's `StreamEvent`'s `plan` kind. */\n  entries?: Array<{ content: string; priority: string; status: string }>\n  /** \"usage_update\" context-window size (tokens). */\n  size?: number\n  /** \"usage_update\" tokens currently in context. */\n  used?: number\n  /** \"usage_update\" cumulative session cost, when the adapter reports one. */\n  cost?: { amount: number; currency: string }\n}\n\n/**\n * Defensively narrow an \"agent-prompt\" event's `options` (typed `unknown`\n * — see `AgentStreamEvent.options`) into a flat label list. Accepts plain\n * strings, or objects exposing `label`/`name`/`id`/`optionId` (covers both\n * a hypothetical `{id,label}` shape and ACP's actual `{optionId,name,kind}`\n * `requestPermission` options) without assuming either driver-specific\n * shape at the type level.\n */\nfunction normalizeAgentPromptOptions(raw: unknown): string[] | undefined {\n  if (!Array.isArray(raw)) return undefined\n  const labels = raw\n    .map(o => {\n      if (typeof o === \"string\") return o\n      if (o && typeof o === \"object\") {\n        const r = o as Record<string, unknown>\n        const label = r.label ?? r.name ?? r.id ?? r.optionId\n        if (typeof label === \"string\") return label\n      }\n      return undefined\n    })\n    .filter((s): s is string => typeof s === \"string\")\n  return labels.length > 0 ? labels : undefined\n}\n\nexport const SESSIONS_FILE_PATH = (): string =>\n  resolve(homedir(), \".agentproto\", \"sessions.json\")\n\nexport type SessionKind = \"terminal\" | \"agent-cli\" | \"command\" | \"browser\"\nexport type SessionStatus =\n  | \"starting\"\n  | \"running\"\n  | \"exited\"\n  | \"killed\"\n  | \"error\"\n\n/**\n * Thrown by `sendPrompt` / `enqueuePrompt` when the target agent-cli\n * session is dead (status exited/killed/error) and either isn't\n * resumable or its resume attempt already failed. Carries the actual\n * `status` so ingress layers (MCP `agent_prompt`, HTTP\n * `POST /sessions/:id/prompt`) can report a truthful, structured error\n * instead of the prompt silently going nowhere — see the \"prompt to a\n * dead session\" bug this type fixes at its throw site in\n * `validateAgentTurn`.\n */\nexport class SessionNotAliveError extends Error {\n  readonly sessionId: string\n  readonly status: SessionStatus\n  constructor(sessionId: string, status: SessionStatus, caller: string) {\n    super(`${caller}: session \"${sessionId}\" is not alive (status=${status})`)\n    this.name = \"SessionNotAliveError\"\n    this.sessionId = sessionId\n    this.status = status\n  }\n}\n\nexport interface SessionDescriptor {\n  id: string\n  kind: SessionKind\n  workspaceSlug: string\n  /** What was actually run — quoted joined for display purposes\n   *  (`bash -lc \"claude --resume xyz\"`). */\n  command: string\n  pid: number | null\n  status: SessionStatus\n  startedAt: string\n  endedAt?: string\n  exitCode?: number\n  /** Last time anything was written to stdout/stderr. Lets the UI\n   *  spot stuck sessions (\"running for 2h, last output 12min ago\"). */\n  lastOutputAt?: string\n  /** Last time ANY adapter-process activity was observed — ACP\n   *  JSON-RPC traffic, protocol-level events, not just ring-buffer\n   *  output lines. Stays current during long tool-call chains where\n   *  `lastOutputAt` goes stale. Updated on incoming session/update\n   *  notifications AND on outbound RPC calls. ISO 8601. */\n  lastActivityAt?: string\n  /** Whether the underlying OS process is still alive. Computed via\n   *  `process.kill(pid, 0)` at read time (list()/get()) — cheap,\n   *  zero-overhead, standard POSIX check. Absent when `pid` is null\n   *  (no process to check). Never persisted — recomputed fresh on\n   *  every read since it's a live OS query, stale the instant it's\n   *  written to disk. */\n  processAlive?: boolean\n  /** Free-text label the spawner can attach (e.g. conversation id,\n   *  operator name) so the UI can group/filter. */\n  label?: string\n  /** True when the session was spawned under a real PTY (node-pty)\n   *  instead of `child_process.spawn`. PTY sessions carry raw ANSI\n   *  bytes (alt-screen, key bindings, colors); attach goes through\n   *  WS /sessions/:id/pty rather than SSE /sessions/:id/stream. */\n  pty?: boolean\n  /** User-friendly slug supplied at spawn time. Optional; when set,\n   *  attach/stop/kill commands accept it as an alias for the id. */\n  name?: string\n  /** Argv that was spawned. Persisted so `agentproto sessions restart`\n   *  can clone the original shape without re-tokenizing the display\n   *  `command` string. Empty for agent-cli sessions (we record\n   *  `adapterSlug` separately). */\n  argv?: readonly string[]\n  /** Working directory the session was spawned in. Cloned by restart. */\n  cwd?: string\n  /** Adapter slug for agent-cli sessions — restart uses this with\n   *  `/sessions/agent` to spin up a fresh ACP runtime. Undefined for\n   *  pty/command kinds. */\n  adapterSlug?: string\n  /** The model the session was requested to run (echoed back at spawn). */\n  model?: string\n  /** Cumulative estimated USD cost of the session — best-effort, refreshed\n   *  on each turn-end from the adapter's usage reader (e.g. hermes reads its\n   *  state.db). Absent for adapters with no usage source. */\n  costUsd?: number\n  /** Cumulative input / output token counts (same source + cadence as costUsd). */\n  tokensIn?: number\n  tokensOut?: number\n  /** ACP-level session id (the adapter's own handle — claude-code's\n   *  conversation id, hermes' chat id, …). Set at spawnAgent time\n   *  from `agentSession.sessionId`. Survives across daemon restarts\n   *  via sessions.json so `restart` can pass it as `resumeSessionId`\n   *  and reattach to the prior conversation history. */\n  adapterSessionId?: string\n  /** MCP servers mounted into the agent's session at spawn time\n   *  (orchestrator WP1). Persisted so the resume/re-spawn path can\n   *  re-mount the same host-chosen toolset instead of resuming a\n   *  capability-stripped agent. The current `AcpMcpServer` shape is\n   *  `{ name, transport, ref? }` — a reference, NOT inline credentials\n   *  — so this carries no secrets today. Should the shape ever grow\n   *  headers/tokens, NEVER log this field's contents. */\n  mcpServers?: AcpMcpServer[]\n  /** Provider-specific resume hints sniffed from the session's\n   *  output. claude-code prints `claude --resume <uuid>` on exit;\n   *  we capture that uuid as `claudeResumeId`. On `restart`, when a\n   *  hint is present, agentproto prefers a PTY spawn with the\n   *  provider's native resume command (`claude --resume <id>`) over\n   *  the ACP-level resume — works wherever the provider persisted\n   *  the session, not just when the ACP wrapper did.\n   *\n   *  Keys are adapter-specific so future adapters can add their own\n   *  (\"hermesResumeId\", etc.) without changing this type. */\n  resumeMetadata?: Record<string, string>\n  /** Set by the orchestration layer when the agent emits an\n   *  \"awaiting-input\" turn-end. Cleared on the next turn start.\n   *  Used by `session_monitor` to fast-return without subscribing. */\n  awaitingInput?: boolean\n  /**\n   * Structured detail on WHY the session is awaiting input, when it can be\n   * determined — lets an orchestrator distinguish \"blocked on a real\n   * question\" from \"just finished a turn\" without re-reading raw output.\n   * `source: \"structured\"` comes from a driver-reported ACP-style prompt\n   * (`AgentStreamEvent.options`, e.g. a tool permission request);\n   * `source: \"heuristic\"` is a best-effort guess from the tail of the\n   * transcript (trailing \"?\" + an optional enumerated option list) for\n   * drivers that don't report structured prompts. Cleared alongside\n   * `awaitingInput` on the next turn start. */\n  awaitingQuestion?: SessionAwaitingQuestion\n  /** Count of turns that have fully completed (turn-end emitted) on this\n   *  session. Lets `session_monitor` fast-return for a session that already\n   *  finished its turn before the wait subscribed — a fast turn that ends\n   *  in \"completed\" (not \"awaiting-input\") leaves no other persisted\n   *  signal (status stays \"running\", busy clears). 0 = never ran a turn,\n   *  so a freshly-spawned idle session is NOT mistaken for done. */\n  turnsCompleted?: number\n  /** True while a turn is actively running (mirror of the internal\n   *  runtime `busy` flag). Lets `session_monitor` distinguish \"idle after a\n   *  finished turn\" from \"mid-turn\" so it doesn't fast-return a stale\n   *  turn-end while the NEXT turn is still generating. */\n  busy?: boolean\n  /** Session id of the orchestrator that spawned this session, set when\n   *  the spawn arrived via the scoped orchestrator sub-gateway (the\n   *  token carried the spawner's identity). Absent for direct `/mcp`\n   *  spawns (the root operator). Powers the subtree scoping of\n   *  list/kill and the per-parent child quota (orchestrator WP4).\n   *  Persisted so the tree survives a daemon restart. */\n  parentSessionId?: string\n  /** Recursion depth in the orchestrator tree: a direct (root) spawn is\n   *  depth 0; a session spawned by a depth-d orchestrator is d+1. Used\n   *  by the depth-cap guard. Persisted alongside `parentSessionId`.\n   *  Treated as 0 when absent (legacy rows / direct spawns that predate\n   *  WP4). */\n  depth?: number\n  // ── Browser-session fields (kind=\"browser\") ──────────────────────────────\n  /** Adapter id that drives this session (e.g. \"camofox\", \"bureau\"). */\n  browserAdapterId?: string\n  /** Port the browser service listens on. */\n  browserPort?: number\n  /** Base URL of the browser service (e.g. \"http://127.0.0.1:9377\"). */\n  browserBaseUrl?: string\n  /** Execution location — \"local\" (default) or \"cloud\". */\n  browserLocation?: \"local\" | \"cloud\"\n}\n\ninterface SessionRuntime {\n  desc: SessionDescriptor\n  /** Set when the session is a raw spawn (`kind: \"command\"|\"terminal\"`).\n   *  Agent sessions don't expose the underlying process — the\n   *  driver-agent-cli runtime owns it. */\n  child?: ChildProcess\n  /** Set when the session is an agent-cli (multi-turn). The registry\n   *  keeps it alive across turns; sendPrompt(id, prompt) re-uses it. */\n  agentSession?: AgentSessionLike\n  /** Adapter slug — only set for agent sessions, helps the UI render\n   *  \"claude-code\" / \"hermes\" badges. */\n  adapterSlug?: string\n  /** Set when the session is a PTY (spawnPty). Bytes flow through\n   *  pty.onData → recentBytes ring + emitter \"data\" event. */\n  pty?: PtyProcess\n  /** Per-subscriber size requests for the PTY. Min cols/rows\n   *  across the live set is what we actually call pty.resize with\n   *  (mirrors tmux's \"smallest attached client wins\" rule). */\n  ptySubscribers?: Map<number, { cols: number; rows: number }>\n  /** Ring buffer of recent stdout+stderr lines. Capped so a runaway\n   *  child can't blow the daemon's heap. */\n  recentLines: string[]\n  /** Ring buffer of recent PTY bytes for replay-on-attach. Total\n   *  size capped at RECENT_BYTES_CAP — oldest chunks dropped first. */\n  recentBytes: Buffer[]\n  recentBytesSize: number\n  emitter: EventEmitter\n  /** True while a turn is in flight. POST /sessions/:id/prompt rejects\n   *  with 409 when busy — the agent can only handle one turn at a\n   *  time per session. */\n  busy: boolean\n  /** Buffer for partial text-delta fragments — agent text events\n   *  arrive as chunks, we coalesce them across deltas and split on\n   *  newlines so each line lands as a discrete ring-buffer entry. */\n  textBuf: string\n  /** Same as textBuf but for `thought` events. Some agents (hermes)\n   *  stream chain-of-thought as one delta per token, which made the\n   *  ring buffer unreadable when each token got its own\n   *  `[thought]` line — coalesce the same way text-delta does. */\n  thoughtBuf: string\n  /** In-flight resume promise. Deduplicates concurrent prompt\n   *  attempts on a dead agent session — only one resume call hits\n   *  the adapter, the rest await this promise. Cleared once\n   *  resolved (success or failure). */\n  resumePromise?: Promise<void>\n  /** Async stop callback for browser sessions (kind=\"browser\").\n   *  Called by kill() best-effort — the descriptor is already flipped\n   *  to \"killed\" before this fires. */\n  browserStop?: () => Promise<void>\n  /** Guard: true once session:exited has been emitted to sessionEvents.\n   *  Prevents duplicate emissions when both kill() and an OS exit event fire. */\n  exitedEmitted?: boolean\n  /** Per-session cost cap. When set, the turn-end finally block checks\n   *  the accumulated costUsd against this ceiling and kills the session\n   *  if exceeded. */\n  maxCostUsd?: number\n  /** Best-effort usage reader called after each turn. The adapter returns\n   *  accumulated cost/token counts which are mirrored onto the descriptor. */\n  readUsage?: () => Promise<{ costUsd?: number; tokensIn?: number; tokensOut?: number } | null>\n}\n\nconst RECENT_LINES_CAP = 500\nconst RECENT_BYTES_CAP = 64 * 1024\nconst PERSIST_DEBOUNCE_MS = 1_500\n/** Cap on the number of historical descriptors loaded from\n *  sessions.json at boot. Older entries (by startedAt) are dropped\n *  on overflow — newest history wins. Adjust upward if the file\n *  starts feeling sparse; downward if the dashboard takes too long\n *  to render. */\nconst HISTORY_CAP = 200\n\n/** Compute `desc.processAlive` from `desc.pid` via the standard POSIX\n *  \"signal 0\" check — `process.kill(pid, 0)` throws `ESRCH` (or\n *  `EPERM`, treated as \"exists but not ours\") when the process is\n *  dead, and is a no-op (no actual signal delivered) when it succeeds.\n *  Mutates `desc` in place; called at read time (list()/get()) rather\n *  than persisted, since it's a live OS query that goes stale the\n *  instant it's written to disk. */\nfunction stampProcessAlive(desc: SessionDescriptor): void {\n  if (desc.pid === null || desc.pid === undefined) {\n    delete desc.processAlive\n    return\n  }\n  try {\n    process.kill(desc.pid, 0)\n    desc.processAlive = true\n  } catch {\n    desc.processAlive = false\n  }\n}\n\n/** Strip CSI / SGR ANSI sequences so resume-pattern matching works\n *  on dim/coloured output. Liberal regex covering most cases — we\n *  don't need byte-perfect parsing here. */\nfunction stripAnsiCodes(s: string): string {\n  return s.replace(/\\x1b\\[[0-9;?]*[A-Za-z]/g, \"\")\n}\n\n/** Lines the ring buffer itself injects (turn separators, [tool] /\n *  [thought] / [awaiting input] markers) — never real transcript content,\n *  so the heuristic below skips them when looking for a trailing question. */\nconst SYNTHETIC_LINE = /^(?:──|\\[)/\n\nconst OPTION_LINE_PATTERN = /^(?:[-*•]|\\d+[.)]|[a-zA-Z][.)])\\s+(.+)$/\n\n/** Best-effort fallback for drivers that never report a structured\n *  \"agent-prompt\" (i.e. every currently-supported adapter — none emits\n *  ACP's `requestPermission` as a surfaced clarifying question today, they\n *  auto-answer it). A clarifying question's shape in a transcript is the\n *  question line followed by its enumerated options (\"1. yes\", \"- retry\",\n *  \"a) skip\", ...), so this scans backwards from the end of the transcript\n *  collecting a trailing run of option-shaped lines, then checks whether\n *  the line just before that run ends in \"?\". Always tagged\n *  `source: \"heuristic\"` so callers know this is a guess, not an\n *  authoritative signal. */\nfunction deriveHeuristicQuestion(\n  recentLines: string[],\n): SessionAwaitingQuestion | undefined {\n  const visible = recentLines\n    .map(stripAnsiCodes)\n    .map(l => l.trim())\n    .filter(l => l.length > 0 && !SYNTHETIC_LINE.test(l))\n  if (visible.length === 0) return undefined\n\n  const options: string[] = []\n  let i = visible.length - 1\n  while (i >= 0 && options.length < 6) {\n    const m = OPTION_LINE_PATTERN.exec(visible[i]!)\n    if (!m) break\n    options.unshift(m[1]!.trim())\n    i--\n  }\n  if (i < 0) return undefined\n  const candidate = visible[i]!\n  if (!candidate.endsWith(\"?\")) return undefined\n  return { text: candidate, ...(options.length > 0 ? { options } : {}), source: \"heuristic\" }\n}\n\nexport interface SessionsRegistry {\n  spawn(input: SpawnSessionInput): SessionDescriptor\n  /** Adopt a ChildProcess that was spawned outside the registry —\n   *  e.g. by the tunnel server when the host dispatches a spawn\n   *  frame. The registry attaches its stdout/stderr listeners and\n   *  tracks the descriptor so the child shows up in /sessions and\n   *  the LocalDaemonSessionsCard. The caller keeps lifecycle\n   *  ownership (kill / wait); this is purely for observability.\n   *  Returns the descriptor for the registered session. */\n  register(input: RegisterSessionInput): SessionDescriptor\n  /** Register an already-built agent session (caller resolves the\n   *  adapter + builds the runtime). Sets kind=\"agent-cli\", consumes\n   *  the optional initial prompt synchronously, returns the\n   *  descriptor. The agent stays alive — call `sendPrompt(id, ...)`\n   *  for follow-up turns until `kill(id)` closes it. */\n  spawnAgent(input: SpawnAgentInput): SessionDescriptor\n  /** Spawn a process under a real PTY (node-pty). Bytes flow through\n   *  the registry's byte ring buffer + emitter; attach with\n   *  `attachPty(id, ...)`. Throws when the registry was constructed\n   *  without a `spawnPty` factory (node-pty optional dep missing). */\n  spawnPty(input: SpawnPtyInput): SessionDescriptor\n  /** Register an already-running browser service adapter as a tracked\n   *  session (kind=\"browser\"). Idempotent by identity — each call\n   *  mints a fresh session id. The `stop` callback is invoked by\n   *  `kill()` best-effort. */\n  registerBrowser(input: RegisterBrowserInput): SessionDescriptor\n  /** Send a follow-up turn to a live agent session. Throws when the\n   *  session is missing, not an agent-cli kind, dead (exited/killed/\n   *  error and unresumable — `SessionNotAliveError`), or busy\n   *  (mid-turn). The events stream into the existing ring buffer +\n   *  line emitter so /stream consumers see them as they arrive. */\n  sendPrompt(id: string, message: unknown): Promise<void>\n  /** Fire-and-forget variant of `sendPrompt` for the TURN ITSELF only.\n   *  Admission (resume attempt + the missing/wrong-kind/dead/busy\n   *  checks `sendPrompt` throws) is AWAITED before this resolves, so a\n   *  dead or busy session rejects instead of silently reporting\n   *  success — only resolves once the turn has actually started.\n   *  Errors during the turn's own execution (network drop, child died\n   *  mid-turn) are pushed into the ring buffer as `[error]` lines so\n   *  `/stream` subscribers see them. Used by the web UI's chat input\n   *  and MCP `agent_prompt`, where a long turn would otherwise freeze\n   *  the caller. */\n  enqueuePrompt(id: string, message: unknown): Promise<void>\n  /** Stamp `lastActivityAt` on a live agent-cli session's descriptor\n   *  and schedule a debounced persist. Called from the `onActivity`\n   *  callback threaded down through the driver → ACP client, which\n   *  fires on ANY adapter-process traffic (not just ring-buffer\n   *  output) — see `SessionDescriptor.lastActivityAt`. No-op when the\n   *  id is unknown (session already forgotten). */\n  pulseActivity(id: string): void\n  list(): SessionDescriptor[]\n  get(id: string): SessionDescriptor | undefined\n  /** Subscribe to a session's output. Returns an unsubscribe fn.\n   *  Initial backfill: synchronously invokes `onLine` once for each\n   *  line currently in the ring buffer so attaches show context. */\n  attach(\n    id: string,\n    onLine: (line: string, stream: \"stdout\" | \"stderr\") => void\n  ): (() => void) | null\n  /** Subscribe to a PTY session's byte stream. Returns a control\n   *  handle (write/resize/detach) and null when the session is\n   *  missing or not a PTY kind. Replays the ring buffer\n   *  synchronously before live frames start. Initial `cols`/`rows`\n   *  are required so the registry can compute min-size across\n   *  subscribers; recompute on every `resize` call. */\n  attachPty(\n    id: string,\n    initial: { cols: number; rows: number },\n    onData: (chunk: Buffer) => void,\n    onExit: (event: { exitCode: number; signal?: number }) => void\n  ): {\n    write(data: string): void\n    resize(cols: number, rows: number): void\n    detach(): void\n  } | null\n  /** Find a session by exact id OR exact name match. Returns the\n   *  descriptor or undefined. Used by HTTP/MCP routes so callers\n   *  can refer to \"claude-main\" instead of \"sess_a3f8c1b2\". */\n  findByIdOrName(query: string): SessionDescriptor | undefined\n  /** Write a chunk of text to a PTY session's stdin. Returns true\n   *  on success, false when the session is missing or not a PTY.\n   *  Single-shot variant of attachPty().write — useful for MCP\n   *  tools that drive a session through tool calls. */\n  writeTerminalInput(id: string, data: string): boolean\n  /** Snapshot the recent PTY byte buffer as one Buffer. Newest\n   *  bytes at the end; `lastBytes` caps the returned size from the\n   *  tail. Returns null when the session is missing or not a PTY. */\n  readTerminalOutput(id: string, lastBytes?: number): Buffer | null\n  kill(id: string, signal?: NodeJS.Signals): boolean\n  /** Stop tracking a session (after it exited and the user clicked\n   *  \"clear\"). Doesn't kill — use `kill` first. */\n  forget(id: string): boolean\n  /** Stop persisting + close all sessions. Killed children are not\n   *  awaited — the daemon shutdown loop handles process tree teardown. */\n  shutdown(): void\n}\n\nexport interface RegisterBrowserInput {\n  /** Adapter id (e.g. \"camofox\", \"bureau\", \"chromium\"). */\n  adapterId: string\n  /** Port the browser service listens on. */\n  port: number\n  /** Base URL of the browser service (e.g. \"http://127.0.0.1:9377\"). */\n  baseUrl: string\n  /** Execution location — \"local\" (default) or \"cloud\". Included in the\n   *  dedup key so a cloud call never returns a pre-existing local session. */\n  location?: \"local\" | \"cloud\"\n  /** PID of the service process — undefined when managed by launchd/systemd. */\n  pid?: number\n  /** True when the service was already healthy before this call (idempotent start). */\n  wasAlreadyRunning: boolean\n  /** Initial lifecycle status. \"running\" when the service is confirmed\n   *  healthy; \"starting\" when a non-blocking cold start returned before the\n   *  service finished converging (health-wait continues in the background and\n   *  `browser_status` / `list_browsers` flip it to running once up).\n   *  Defaults to \"running\" when omitted. */\n  status?: Extract<SessionStatus, \"running\" | \"starting\">\n  /** Async shutdown callback — called by kill() best-effort. */\n  stop: () => Promise<void>\n  label?: string\n}\n\nexport interface RegisterSessionInput {\n  /** Pre-existing child process to adopt (e.g. from a tunnel spawn). */\n  child: ChildProcess\n  /** Stable id — typically the tunnel's execId so callers cross-ref. */\n  id: string\n  workspaceSlug: string\n  /** Display label for the descriptor's `command` field. */\n  command: string\n  kind?: SessionKind\n  label?: string\n}\n\nexport interface SpawnAgentInput {\n  workspaceSlug: string\n  cwd: string\n  /** Driver-built session ready to receive turns. Caller resolves\n   *  the adapter, calls createAgentCliRuntime(handle).start({cwd}),\n   *  and hands the result here. */\n  agentSession: AgentSessionLike\n  /** Adapter slug for the descriptor (display only). */\n  adapterSlug: string\n  /** Optional initial prompt to dispatch immediately. The promise\n   *  the registry returns resolves AFTER the spawn — the prompt\n   *  runs in the background, projecting events into the ring\n   *  buffer. Skip to spawn idle. */\n  initialPrompt?: string\n  label?: string\n  /** Pretty command for the descriptor (display only). */\n  commandPreview?: string\n  /** MCP servers mounted at spawn time. Persisted on the descriptor so\n   *  the resume/re-spawn path can re-mount the same toolset (orchestrator\n   *  WP1). */\n  mcpServers?: AcpMcpServer[]\n  /** Spawning orchestrator's session id — set when the spawn arrived\n   *  through the scoped sub-gateway (orchestrator WP4). Recorded on the\n   *  descriptor for subtree scoping + quota accounting. */\n  parentSessionId?: string\n  /** Recursion depth for the new session (orchestrator WP4). Defaults to\n   *  0 when omitted (direct/root spawn). */\n  depth?: number\n  /** Requested model id — recorded on the descriptor for display + echo. */\n  model?: string\n  /** Hard ceiling on cumulative session cost (USD). When set and the\n   *  adapter's usage reader reports a higher cost at a turn-end, the session\n   *  is stopped (best-effort, turn-granular — caps continuation, can't abort\n   *  a turn mid-flight). */\n  maxCostUsd?: number\n  /** Best-effort usage reader, called on each turn-end to refresh the\n   *  cost/token fields on the descriptor. Adapter-specific (e.g. hermes\n   *  reads its state.db keyed by the adapter session id). Omit for adapters\n   *  with no usage source. */\n  readUsage?: () => Promise<{ costUsd?: number; tokensIn?: number; tokensOut?: number } | null>\n}\n\nexport interface SpawnSessionInput {\n  kind: SessionKind\n  workspaceSlug: string\n  /** Path of the workspace root (for the child's cwd). The registry\n   *  doesn't validate it against the workspaces config — caller has\n   *  already resolved this. */\n  cwd: string\n  /** Argv. First element is the binary; rest are passed verbatim. */\n  argv: string[]\n  /** Extra env on top of the daemon's process.env. */\n  env?: Record<string, string>\n  /** Optional pre-set id (lets the spawner reference the session\n   *  before the spawn returns — useful for telemetry). */\n  id?: string\n  label?: string\n  /** Keep the child's stdin open (default: closed). Most spawned\n   *  agents are non-interactive and emit a warning when stdin is a\n   *  pipe with no writer (claude-code prints \"no stdin data\n   *  received in 3s, proceeding without it\"). Closing stdin lets\n   *  them skip the wait. PTY/terminal kinds that genuinely need\n   *  bidirectional IO should opt in via `keepStdin: true` and the\n   *  caller is then responsible for writing to `child.stdin`. */\n  keepStdin?: boolean\n}\n\nexport interface SpawnPtyInput {\n  workspaceSlug: string\n  cwd: string\n  argv: string[]\n  /** Initial PTY dimensions. The registry uses min(cols, rows) across\n   *  active subscribers thereafter — these are the seed values used\n   *  before anyone attaches. */\n  cols: number\n  rows: number\n  /** Extra env on top of process.env. TERM/LANG/PATH are forced by\n   *  the factory layer (node-pty.spawn options); don't try to clear\n   *  them here. */\n  env?: Record<string, string>\n  /** User-friendly slug. Used by `findByIdOrName(query)`. Must not\n   *  collide with an existing session's name. */\n  name?: string\n  label?: string\n}\n\n/**\n * Hook the registry uses to rebuild a dead agent session on demand.\n * Invoked when a prompt arrives for an agent-cli session whose\n * `agentSession` was lost (typically daemon restart). Returns a fresh\n * `AgentSessionLike` bound to the same upstream conversation via\n * `resumeSessionId`, OR null if resume isn't possible (adapter gone,\n * upstream rejected). When null, the prompt path surfaces the same\n * \"not an agent session\" error as before — caller knows the row is a\n * ghost.\n *\n * The CLI wires this into the registry by passing in a closure that\n * calls `resolveAgentAdapter(slug)?.startSession({cwd, resumeSessionId})`,\n * which is the same path the gateway's POST /sessions/agent uses.\n */\nexport type AgentSessionResumer = (input: {\n  adapterSlug: string\n  cwd: string\n  resumeSessionId: string\n  /** MCP servers to re-mount on the resumed session — threaded from the\n   *  descriptor's persisted `mcpServers` so the re-spawned agent keeps the\n   *  same host-chosen toolset it had on the initial spawn (orchestrator\n   *  WP1). Omitted for legacy rows spawned before this was persisted. */\n  mcpServers?: AcpMcpServer[]\n  /** Forwarded to the re-spawned adapter's `startSession({ onActivity })`\n   *  so the resumed session keeps pulsing `lastActivityAt` the same way\n   *  the original spawn did. */\n  onActivity?: () => void\n}) => Promise<AgentSessionLike | null>\n\nexport function createSessionsRegistry(opts?: {\n  /** Override the persistence path — tests pin a tmpdir. */\n  persistPath?: string\n  /** Disable persistence entirely. */\n  persist?: boolean\n  /** PTY factory (node-pty wrapper). When omitted, `spawnPty()`\n   *  throws — the daemon advertises PTY support only when the cli\n   *  layer resolved node-pty successfully. */\n  spawnPty?: PtyFactory\n  /** Hook called when a prompt arrives for an agent-cli session whose\n   *  agentSession binding is gone (daemon restart). When provided,\n   *  the registry transparently resumes the session via the adapter's\n   *  resumeSessionId before dispatching the turn. When omitted,\n   *  killed agent-cli sessions surface the legacy \"not an agent\n   *  session\" error and the user must spawn fresh. */\n  resumeAgent?: AgentSessionResumer\n  /** When provided, the registry translates internal lifecycle transitions\n   *  (turn-end, awaiting-input, exit) into SessionEvents on this bus. */\n  sessionEvents?: SessionEventBus\n  /** Override the structured-transcript base directory. Defaults to a\n   *  `sessions` sibling of `persistPath` (`~/.agentproto/sessions` in\n   *  production) — tests that already pin `persistPath` to a tmpdir get\n   *  transcript isolation for free without also having to pass this. */\n  transcriptDir?: string\n}): SessionsRegistry {\n  const persistPath = opts?.persistPath ?? SESSIONS_FILE_PATH()\n  const persist = opts?.persist ?? true\n  const transcriptWriter = createTranscriptWriter({\n    baseDir: opts?.transcriptDir ?? join(dirname(persistPath), \"sessions\"),\n  })\n  const ptyFactory = opts?.spawnPty\n  const resumeAgent = opts?.resumeAgent\n  const sessionEvents = opts?.sessionEvents\n  const sessions = new Map<string, SessionRuntime>()\n  let persistTimer: ReturnType<typeof setTimeout> | null = null\n  // Monotonically-growing PTY-subscriber id. Detach is O(1) on\n  // Map.delete(subId), so we never reuse — overflow at Number.MAX_-\n  // SAFE_INTEGER would take ~285 years at 1M attaches/sec.\n  let nextSubId = 1\n  // Guards `shutdown()` from running twice — double-stop happens in\n  // serve --interactive's Ctrl-C race; without this, the second\n  // call writes an empty snapshot over the real one.\n  let shutdownDone = false\n\n  // ── boot-time history load ──\n  // Read sessions.json synchronously at construction so the dashboard\n  // shows historical sessions immediately on daemon restart. Anything\n  // that was \"running\" or \"starting\" when the daemon last died gets\n  // marked \"killed\" — we have no way to know if the orphan child\n  // survived the daemon's exit, and pretending it's still alive would\n  // make attach calls fail mysteriously.\n  //\n  // Historical entries are GHOSTS: descriptor only, no child / no\n  // agentSession / no pty. Calls like kill(id) / attach(id) work on\n  // them but degrade to no-ops (the underlying process is gone). The\n  // session's `endedAt` is set to now when we infer a kill, so the\n  // dashboard ages them from this boot rather than the daemon's last\n  // life.\n  if (persist) {\n    loadHistorySnapshot(persistPath, sessions)\n  }\n\n  // Belt-and-suspenders: `process.on(\"exit\")` runs even on uncaught\n  // throws, terminal-close (SIGHUP), and any termination path that\n  // bypassed the regular SIGINT/SIGTERM cleanup. The handler must be\n  // sync (Node won't await async there); we already use sync IO in\n  // `shutdown()` so this is safe. Idempotency guard inside shutdown\n  // prevents a double-write when both this handler and the explicit\n  // SIGINT path fire.\n  const onProcessExit = (): void => {\n    shutdownImpl()\n  }\n  if (persist) {\n    process.on(\"exit\", onProcessExit)\n  }\n\n  // Emit session:exited once per session, deduplicated via exitedEmitted flag.\n  const emitExited = (rt: SessionRuntime): void => {\n    if (!sessionEvents || rt.exitedEmitted) return\n    rt.exitedEmitted = true\n    sessionEvents.emit({\n      type: \"session:exited\",\n      sessionId: rt.desc.id,\n      exitCode: rt.desc.exitCode,\n      status: rt.desc.status as \"exited\" | \"killed\" | \"error\",\n      label: rt.desc.label,\n      ts: new Date().toISOString(),\n    })\n  }\n\n  const schedulePersist = (): void => {\n    if (!persist) return\n    if (persistTimer) clearTimeout(persistTimer)\n    persistTimer = setTimeout(() => {\n      void persistSnapshot()\n    }, PERSIST_DEBOUNCE_MS)\n  }\n\n  const persistSnapshot = async (): Promise<void> => {\n    try {\n      const snapshot = {\n        savedAt: new Date().toISOString(),\n        // `processAlive` is a live OS query (see stampProcessAlive) —\n        // strip it before writing so a restored descriptor is never\n        // seen with a stale value before the next list()/get() call\n        // recomputes it fresh.\n        sessions: Array.from(sessions.values()).map(s => {\n          const { processAlive: _processAlive, ...rest } = s.desc\n          return rest\n        }),\n      }\n      await fs.mkdir(dirname(persistPath), { recursive: true })\n      await fs.writeFile(persistPath, JSON.stringify(snapshot, null, 2) + \"\\n\")\n    } catch (err) {\n      // Persistence is best-effort — log only, never throw.\n      console.warn(\n        `[sessions] persist failed: ${\n          err instanceof Error ? err.message : String(err)\n        }`\n      )\n    }\n  }\n\n  const appendLine = (\n    rt: SessionRuntime,\n    line: string,\n    stream: \"stdout\" | \"stderr\"\n  ): void => {\n    rt.recentLines.push(line)\n    if (rt.recentLines.length > RECENT_LINES_CAP) {\n      rt.recentLines.splice(0, rt.recentLines.length - RECENT_LINES_CAP)\n    }\n    rt.desc.lastOutputAt = new Date().toISOString()\n    sniffResumeHints(rt, line)\n    rt.emitter.emit(\"line\", { line, stream })\n  }\n\n  /**\n   * Provider-specific resume-hint sniffer. Looks up the adapter's\n   * strategy in `RESUME_STRATEGIES` and runs its `outputHint` regex\n   * against each agent-cli line. The captured id is recorded on the\n   * descriptor so `agentproto sessions restart` can use it.\n   *\n   * ANSI-stripped before matching so dim/color codes don't break the\n   * pattern. Adapters without a strategy entry (or without an\n   * outputHint) are skipped — they fall back to ACP-level resume.\n   */\n  const sniffResumeHints = (rt: SessionRuntime, line: string): void => {\n    if (rt.desc.kind !== \"agent-cli\") return\n    const strategy = rt.desc.adapterSlug\n      ? RESUME_STRATEGIES[rt.desc.adapterSlug]\n      : undefined\n    if (!strategy?.outputHint) return\n    const plain = stripAnsiCodes(line)\n    const m = plain.match(strategy.outputHint)\n    if (m && m[1]) {\n      rt.desc.resumeMetadata = {\n        ...(rt.desc.resumeMetadata ?? {}),\n        [strategy.storeAs]: m[1],\n      }\n      schedulePersist()\n    }\n  }\n\n  /**\n   * PTY byte ring buffer. Keeps the last ~64 KiB of raw bytes so a\n   * fresh attacher sees the current screenful (alt-screen apps like\n   * Claude TUI / vim repaint on next interaction but a snapshot is\n   * still better than blank). Drops oldest chunks when over cap;\n   * never splits within a chunk — Buffer arithmetic on UTF-8 mid-\n   * sequence would corrupt multi-byte glyphs.\n   */\n  const appendBytes = (rt: SessionRuntime, chunk: Buffer): void => {\n    rt.recentBytes.push(chunk)\n    rt.recentBytesSize += chunk.byteLength\n    while (\n      rt.recentBytesSize > RECENT_BYTES_CAP &&\n      rt.recentBytes.length > 1\n    ) {\n      const dropped = rt.recentBytes.shift()\n      if (dropped) rt.recentBytesSize -= dropped.byteLength\n    }\n    rt.desc.lastOutputAt = new Date().toISOString()\n    rt.emitter.emit(\"data\", chunk)\n  }\n\n  /**\n   * Recompute the smallest cols/rows across the active subscriber\n   * set and resize the PTY accordingly (tmux's \"smallest attached\n   * client wins\" rule). No-op when the subscriber map is empty.\n   */\n  const reconcilePtySize = (rt: SessionRuntime): void => {\n    if (!rt.pty || !rt.ptySubscribers || rt.ptySubscribers.size === 0) return\n    let cols = Infinity\n    let rows = Infinity\n    for (const dim of rt.ptySubscribers.values()) {\n      if (dim.cols < cols) cols = dim.cols\n      if (dim.rows < rows) rows = dim.rows\n    }\n    if (!Number.isFinite(cols) || !Number.isFinite(rows)) return\n    try {\n      rt.pty.resize(cols, rows)\n    } catch {\n      // pty may have exited between the emit and the resize — swallow.\n    }\n  }\n\n  /**\n   * Project ACP-style stream events into ring-buffer lines. Keeps\n   * the line shape simple so the existing /stream SSE consumer\n   * (and the xterm panel) just renders them as-is.\n   */\n  const projectEvent = (rt: SessionRuntime, evt: AgentStreamEvent): void => {\n    switch (evt.kind) {\n      case \"text-delta\":\n        if (evt.text) {\n          // text-delta is a stream of chunks — split on newlines so\n          // each line lands in the ring buffer separately. Coalesce\n          // a trailing fragment via rt.textBuf.\n          const combined = rt.textBuf + evt.text\n          const lines = combined.split(/\\r?\\n/)\n          rt.textBuf = lines.pop() ?? \"\"\n          for (const line of lines) appendLine(rt, line, \"stdout\")\n        }\n        break\n      case \"thought\":\n        if (evt.text) {\n          // Same coalescing as text-delta — some adapters stream\n          // chain-of-thought one token at a time, which would\n          // otherwise produce ~100 [thought] lines per turn.\n          const combined = rt.thoughtBuf + evt.text\n          const lines = combined.split(/\\r?\\n/)\n          rt.thoughtBuf = lines.pop() ?? \"\"\n          for (const line of lines) {\n            if (line.trim()) {\n              appendLine(rt, `\\x1b[2m[thought] ${line}\\x1b[0m`, \"stdout\")\n            }\n          }\n        }\n        break\n      case \"tool-call\":\n        appendLine(\n          rt,\n          `\\x1b[36m[tool] ${formatToolCall(evt.toolName ?? \"?\", evt.arguments)}\\x1b[0m`,\n          \"stdout\"\n        )\n        break\n      case \"tool-result\": {\n        // Keep this to ONE line per result — some drivers stream huge\n        // payloads (file dumps, search hits) and the ring buffer is a\n        // fixed-size window, not a log store.\n        const summary = formatToolResult(evt.toolName, evt.result, evt.isError ?? false)\n        if (summary) {\n          appendLine(\n            rt,\n            evt.isError\n              ? `\\x1b[31m[tool-error] ${summary}\\x1b[0m`\n              : `\\x1b[2m[tool-result] ${summary}\\x1b[0m`,\n            evt.isError ? \"stderr\" : \"stdout\"\n          )\n        } else if (evt.isError) {\n          appendLine(rt, `\\x1b[31m[tool-error]\\x1b[0m`, \"stderr\")\n        }\n        break\n      }\n      case \"agent-prompt\": {\n        rt.desc.awaitingInput = true\n        const options = normalizeAgentPromptOptions(evt.options)\n        if (options) {\n          rt.desc.awaitingQuestion = {\n            text: evt.text ?? (evt.toolName ? `Allow \"${evt.toolName}\"?` : \"Agent is requesting input.\"),\n            options,\n            source: \"structured\",\n          }\n        }\n        appendLine(rt, `\\x1b[33m[awaiting input]\\x1b[0m`, \"stdout\")\n        break\n      }\n      case \"turn-end\": {\n        if (evt.reason === \"awaiting-input\") rt.desc.awaitingInput = true\n        // Flush any buffered text/thought fragments as final lines.\n        if (rt.thoughtBuf.trim()) {\n          appendLine(\n            rt,\n            `\\x1b[2m[thought] ${rt.thoughtBuf}\\x1b[0m`,\n            \"stdout\"\n          )\n        }\n        rt.thoughtBuf = \"\"\n        if (rt.textBuf) {\n          appendLine(rt, rt.textBuf, \"stdout\")\n          rt.textBuf = \"\"\n        }\n        appendLine(\n          rt,\n          `\\x1b[2m── turn-end (${evt.reason ?? \"completed\"}) ──\\x1b[0m`,\n          \"stdout\"\n        )\n        break\n      }\n      case \"error\": {\n        const code =\n          typeof evt.error?.code === \"number\" ? ` (code ${evt.error.code})` : \"\"\n        appendLine(\n          rt,\n          `\\x1b[31m[error]${code} ${evt.error?.message ?? \"unknown\"}\\x1b[0m`,\n          \"stderr\"\n        )\n        // Project the child's stderr tail when define-agent-cli\n        // attached it — otherwise the user sees only \"Invalid\n        // params\" and has to dig into the daemon log for context.\n        const data = evt.error?.data as\n          | { stderr?: unknown }\n          | null\n          | undefined\n        if (data && typeof data === \"object\" && typeof data.stderr === \"string\") {\n          for (const line of data.stderr.split(/\\r?\\n/)) {\n            if (line) appendLine(rt, `\\x1b[2m  ${line}\\x1b[0m`, \"stderr\")\n          }\n        }\n        break\n      }\n      case \"plan\": {\n        const entries = evt.entries ?? []\n        const done = entries.filter(e => e.status === \"completed\").length\n        appendLine(\n          rt,\n          `\\x1b[35m[plan] ${done}/${entries.length} ${entries.map(e => e.content).join(\"; \")}\\x1b[0m`,\n          \"stdout\"\n        )\n        break\n      }\n      // \"usage_update\" is high-frequency telemetry (context size/cost) —\n      // the ring buffer isn't the right place for it (cost is already\n      // surfaced via rt.desc.costUsd at turn-end); it still lands in\n      // events.jsonl via the transcript writer tap point.\n      case \"usage_update\":\n        break\n    }\n  }\n\n  /**\n   * Drive one agent turn. Sets busy=true, drains the event stream\n   * into the ring buffer, clears busy on completion. Bumps the\n   * descriptor status to \"error\" if the iteration throws (network\n   * drop, child died mid-turn).\n   */\n  /**\n   * Shared sync validation for sendPrompt + enqueuePrompt. Throws on\n   * missing session / wrong kind / dead session / busy so both code\n   * paths surface the exact same error messages — the only difference\n   * is whether the caller awaits the turn.\n   *\n   * Must be called AFTER `maybeResumeAgent(rt)` has already been\n   * awaited — a dead-but-resumable agent-cli session only regains\n   * `rt.agentSession` there.\n   *\n   * Liveness is checked via `rt.desc.status`, NOT merely\n   * `!rt.agentSession` — `kill()` flips status to \"killed\" but leaves\n   * `rt.agentSession` referencing the now-closed session object (it\n   * only calls `.close()`, it doesn't clear the field), so a\n   * `!rt.agentSession` check alone would miss a live-killed session\n   * and let `runAgentTurn` call `.send()` on a dead connection. Status\n   * catches that case too, not just the daemon-restart/dead-and-\n   * unresumable case where `agentSession` really is absent. Either way\n   * this throws `SessionNotAliveError` (not a generic Error) so\n   * ingress can report status/409 truthfully instead of the caller\n   * getting back a lie like `{queued: true}`.\n   */\n  const validateAgentTurn = (id: string, caller: string): SessionRuntime => {\n    const rt = sessions.get(id)\n    if (!rt) throw new Error(`${caller}: no session \"${id}\"`)\n    if (rt.desc.kind !== \"agent-cli\") {\n      throw new Error(\n        `${caller}: session \"${id}\" is not an agent session (kind=${rt.desc.kind})`\n      )\n    }\n    const isAlive = rt.desc.status === \"running\" || rt.desc.status === \"starting\"\n    if (!isAlive || !rt.agentSession) {\n      throw new SessionNotAliveError(id, rt.desc.status, caller)\n    }\n    if (rt.busy) {\n      throw new Error(\n        `${caller}: session \"${id}\" is mid-turn — wait for it to finish or cancel`\n      )\n    }\n    return rt\n  }\n\n  /**\n   * Attempt to resume a dead agent-cli session by re-spawning the\n   * adapter with the persisted `adapterSessionId`. The conversation\n   * continues from where it left off — ACP's `resumeSessionId`\n   * contract guarantees the adapter rehydrates state from the\n   * upstream provider (Anthropic / OpenAI / etc.) when supported.\n   *\n   * Returns silently when:\n   *   - resumeAgent hook wasn't provided (older daemon embedding)\n   *   - session is already alive (binding present)\n   *   - session is a non-agent kind (terminal/command can't resume)\n   *   - descriptor lacks adapterSessionId or adapterSlug (legacy row\n   *     persisted before resume metadata was tracked)\n   *\n   * Concurrent prompt arrivals share one resume attempt via\n   * `rt.resumePromise`.\n   */\n  const maybeResumeAgent = async (rt: SessionRuntime): Promise<void> => {\n    if (rt.agentSession) return\n    if (!resumeAgent) return\n    if (rt.desc.kind !== \"agent-cli\") return\n    const adapterSlug = rt.desc.adapterSlug ?? rt.adapterSlug\n    const adapterSessionId = rt.desc.adapterSessionId\n    const cwd = rt.desc.cwd\n    if (!adapterSlug || !adapterSessionId || !cwd) return\n    if (rt.resumePromise) {\n      await rt.resumePromise\n      return\n    }\n    rt.resumePromise = (async () => {\n      appendLine(\n        rt,\n        `── resuming ${adapterSlug} session ${adapterSessionId} ──`,\n        \"stdout\"\n      )\n      try {\n        const fresh = await resumeAgent({\n          adapterSlug,\n          cwd,\n          resumeSessionId: adapterSessionId,\n          // Re-mount the persisted spawn-time toolset (orchestrator WP1).\n          ...(rt.desc.mcpServers ? { mcpServers: rt.desc.mcpServers } : {}),\n          // Keep pulsing lastActivityAt across a resume the same way the\n          // original spawn did.\n          onActivity: () => {\n            rt.desc.lastActivityAt = new Date().toISOString()\n            schedulePersist()\n          },\n        })\n        if (!fresh) {\n          appendLine(\n            rt,\n            `[error] resume failed: adapter '${adapterSlug}' returned null`,\n            \"stderr\"\n          )\n          return\n        }\n        rt.agentSession = fresh\n        rt.adapterSlug = adapterSlug\n        rt.desc.adapterSessionId = fresh.sessionId\n        // The resumed session is a fresh child process — refresh pid so\n        // `processAlive` reflects the new process, not the dead one that\n        // triggered this resume.\n        rt.desc.pid = fresh.pid ?? null\n        if (rt.desc.status !== \"running\") {\n          rt.desc.status = \"running\"\n          delete rt.desc.endedAt\n          delete rt.desc.exitCode\n          rt.emitter.emit(\"status\", rt.desc.status)\n        }\n        schedulePersist()\n      } catch (err) {\n        const msg = err instanceof Error ? err.message : String(err)\n        appendLine(rt, `[error] resume failed: ${msg}`, \"stderr\")\n      }\n    })()\n    try {\n      await rt.resumePromise\n    } finally {\n      rt.resumePromise = undefined\n    }\n  }\n\n  const runAgentTurn = async (\n    rt: SessionRuntime,\n    message: unknown\n  ): Promise<void> => {\n    if (!rt.agentSession) {\n      throw new Error(\"runAgentTurn: session has no agentSession\")\n    }\n    rt.busy = true\n    rt.desc.busy = true             // mirror onto the public descriptor for session_monitor\n    rt.desc.awaitingInput = false  // clear stale awaiting-input flag from prior turn\n    rt.desc.awaitingQuestion = undefined\n    let turnCompleted = false\n    // Captures the driver's reported `turn-end` reason (e.g.\n    // \"completed\", \"watchdog-timeout\") so it can ride along on the\n    // `session:turn-end` bus event below — otherwise it's dropped after\n    // `projectEvent` renders it into the ring buffer.\n    let turnEndReason: string | undefined\n    try {\n      appendLine(\n        rt,\n        `\\x1b[2m── ▶ ${typeof message === \"string\" ? message : JSON.stringify(message)} ──\\x1b[0m`,\n        \"stdout\"\n      )\n      transcriptWriter.recordPrompt(rt.desc.id, message)\n      // ACP's `prompt` field expects ContentBlock[] (or a single\n      // block). Hosts that send a raw string get auto-wrapped into\n      // `{type: \"text\", text: \"...\"}` so callers can hand us\n      // human-friendly prompts without shaping the wire format.\n      const wrapped =\n        typeof message === \"string\" ? { type: \"text\", text: message } : message\n      for await (const evt of rt.agentSession.send(wrapped)) {\n        // Capture the structured event to events.jsonl BEFORE\n        // projectEvent flattens it into an ANSI ring-buffer line — the\n        // only point downstream of the driver where the original\n        // shape (tool arguments, plan entries, ...) still exists.\n        transcriptWriter.recordEvent(rt.desc.id, evt)\n        projectEvent(rt, evt)\n        if (evt.kind === \"turn-end\") turnEndReason = evt.reason\n      }\n      turnCompleted = true\n    } catch (err) {\n      rt.desc.status = \"error\"\n      rt.desc.endedAt = new Date().toISOString()\n      appendLine(\n        rt,\n        `[turn error] ${err instanceof Error ? err.message : String(err)}`,\n        \"stderr\"\n      )\n      schedulePersist()\n      emitExited(rt)\n    } finally {\n      rt.busy = false\n      rt.desc.busy = false           // mirror onto the public descriptor for session_monitor\n      if (turnCompleted && sessionEvents) {\n        // Record that a turn finished so a late `session_monitor` (subscribed\n        // after a fast turn already ended) can still fast-return.\n        rt.desc.turnsCompleted = (rt.desc.turnsCompleted ?? 0) + 1\n\n        // ── Cost refresh + cap (best-effort) ─────────────────────────\n        if (rt.readUsage) {\n          try {\n            const usage = await rt.readUsage()\n            if (usage) {\n              if (usage.costUsd !== undefined) rt.desc.costUsd = usage.costUsd\n              if (usage.tokensIn !== undefined) rt.desc.tokensIn = usage.tokensIn\n              if (usage.tokensOut !== undefined) rt.desc.tokensOut = usage.tokensOut\n            }\n          } catch {\n            // best-effort — swallow\n          }\n        }\n        const overBudget =\n          rt.maxCostUsd !== undefined &&\n          rt.desc.costUsd !== undefined &&\n          rt.desc.costUsd > rt.maxCostUsd\n        if (overBudget) {\n          appendLine(\n            rt,\n            `[cost-cap] cost $${rt.desc.costUsd} exceeds max $${rt.maxCostUsd} — killing session`,\n            \"stderr\",\n          )\n          rt.desc.status = \"killed\"\n          rt.desc.endedAt = new Date().toISOString()\n          void rt.agentSession?.close().catch(() => undefined)\n          void transcriptWriter.close(rt.desc.id)\n        }\n\n        // No driver reports a structured \"agent-prompt\" today (every\n        // currently-supported adapter auto-answers ACP permission\n        // requests rather than surfacing them) — fall back to a\n        // best-effort scan of the transcript tail so awaiting-input still\n        // carries SOME signal beyond a bare boolean.\n        if (rt.desc.awaitingInput && !rt.desc.awaitingQuestion) {\n          rt.desc.awaitingQuestion = deriveHeuristicQuestion(rt.recentLines)\n        }\n\n        const ts = new Date().toISOString()\n        sessionEvents.emit({\n          type: \"session:turn-end\",\n          sessionId: rt.desc.id,\n          awaitingInput: rt.desc.awaitingInput ?? false,\n          label: rt.desc.label,\n          ts,\n          ...(rt.desc.awaitingQuestion ? { question: rt.desc.awaitingQuestion } : {}),\n          ...(turnEndReason ? { reason: turnEndReason } : {}),\n        })\n        if (rt.desc.awaitingInput) {\n          sessionEvents.emit({\n            type: \"session:awaiting-input\",\n            sessionId: rt.desc.id,\n            label: rt.desc.label,\n            ts,\n            ...(rt.desc.awaitingQuestion ? { question: rt.desc.awaitingQuestion } : {}),\n          })\n        }\n        if (overBudget) emitExited(rt)\n      }\n    }\n  }\n\n  const wireOutputStreams = (rt: SessionRuntime): void => {\n    const onChunk =\n      (stream: \"stdout\" | \"stderr\") =>\n      (chunk: Buffer | string): void => {\n        const text = typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\")\n        for (const line of text.split(/\\r?\\n/)) {\n          if (line.length > 0) appendLine(rt, line, stream)\n        }\n      }\n    // Only called from spawn() which always sets rt.child — narrow\n    // here so the stream listeners don't trip the optional-chain.\n    if (!rt.child) return\n    rt.child.stdout?.on(\"data\", onChunk(\"stdout\"))\n    rt.child.stderr?.on(\"data\", onChunk(\"stderr\"))\n  }\n\n  return {\n    spawn(input) {\n      const id = input.id ?? `sess_${randomUUID().slice(0, 8)}`\n      if (sessions.has(id)) {\n        throw new Error(`sessions.spawn: id \"${id}\" already in use`)\n      }\n      const env = { ...process.env, ...(input.env ?? {}) }\n      // Filter out Node bookkeeping that confuses subprocesses.\n      delete env.NODE_OPTIONS\n      const [bin, ...args] = input.argv\n      if (!bin) throw new Error(\"sessions.spawn: argv must include a binary\")\n      // Close stdin by default — most agent CLIs spawn-and-prompt\n      // (claude/codex/aider/etc.) read argv for the prompt and will\n      // otherwise sit waiting for piped input. Caller opts in to a\n      // writeable stdin via `keepStdin: true` (terminal/PTY kinds).\n      const stdinMode = input.keepStdin ? \"pipe\" : \"ignore\"\n      const child = spawn(bin, args, {\n        cwd: input.cwd,\n        env: env as NodeJS.ProcessEnv,\n        stdio: [stdinMode, \"pipe\", \"pipe\"],\n      })\n      const desc: SessionDescriptor = {\n        id,\n        kind: input.kind,\n        workspaceSlug: input.workspaceSlug,\n        command: [bin, ...args].map(quoteArg).join(\" \"),\n        pid: child.pid ?? null,\n        status: \"starting\",\n        startedAt: new Date().toISOString(),\n        argv: input.argv,\n        cwd: input.cwd,\n        ...(input.label ? { label: input.label } : {}),\n      }\n      const rt: SessionRuntime = {\n        desc,\n        child,\n        recentLines: [],\n        recentBytes: [],\n        recentBytesSize: 0,\n        emitter: new EventEmitter(),\n        busy: false,\n        textBuf: \"\",\n        thoughtBuf: \"\",\n      }\n      // Don't crash the daemon when no listener is attached — the\n      // emitter's \"error\" event would otherwise propagate.\n      rt.emitter.setMaxListeners(50)\n\n      sessions.set(id, rt)\n      wireOutputStreams(rt)\n\n      child.once(\"spawn\", () => {\n        desc.status = \"running\"\n        rt.emitter.emit(\"status\", desc.status)\n        schedulePersist()\n      })\n      child.once(\"error\", err => {\n        desc.status = \"error\"\n        desc.endedAt = new Date().toISOString()\n        appendLine(rt, `[spawn error] ${err.message}`, \"stderr\")\n        rt.emitter.emit(\"status\", desc.status)\n        schedulePersist()\n        emitExited(rt)\n      })\n      child.once(\"exit\", (code, signal) => {\n        if (signal && desc.status !== \"killed\") desc.status = \"killed\"\n        else if (desc.status === \"running\" || desc.status === \"starting\") {\n          desc.status = \"exited\"\n        }\n        desc.endedAt = new Date().toISOString()\n        if (typeof code === \"number\") desc.exitCode = code\n        rt.emitter.emit(\"status\", desc.status)\n        schedulePersist()\n        emitExited(rt)\n      })\n      schedulePersist()\n      return desc\n    },\n    register(input) {\n      if (sessions.has(input.id)) {\n        // Already adopted (re-tracking is a noop). Return the\n        // existing descriptor so callers don't have to special-case.\n        const existing = sessions.get(input.id)\n        if (existing) return existing.desc\n      }\n      const desc: SessionDescriptor = {\n        id: input.id,\n        kind: input.kind ?? \"command\",\n        workspaceSlug: input.workspaceSlug,\n        command: input.command,\n        pid: input.child.pid ?? null,\n        status: input.child.killed ? \"killed\" : \"running\",\n        startedAt: new Date().toISOString(),\n        ...(input.label ? { label: input.label } : {}),\n      }\n      const rt: SessionRuntime = {\n        desc,\n        child: input.child,\n        recentLines: [],\n        recentBytes: [],\n        recentBytesSize: 0,\n        emitter: new EventEmitter(),\n        busy: false,\n        textBuf: \"\",\n        thoughtBuf: \"\",\n      }\n      rt.emitter.setMaxListeners(50)\n      sessions.set(input.id, rt)\n      wireOutputStreams(rt)\n      // Wire exit so the descriptor flips when the adopted child\n      // dies — same handlers as spawn() but registered post-hoc\n      // because the child is already alive.\n      input.child.once(\"exit\", (code, signal) => {\n        if (signal && desc.status !== \"killed\") desc.status = \"killed\"\n        else if (desc.status === \"running\") desc.status = \"exited\"\n        desc.endedAt = new Date().toISOString()\n        if (typeof code === \"number\") desc.exitCode = code\n        rt.emitter.emit(\"status\", desc.status)\n        schedulePersist()\n        emitExited(rt)\n      })\n      input.child.once(\"error\", err => {\n        desc.status = \"error\"\n        desc.endedAt = new Date().toISOString()\n        appendLine(rt, `[child error] ${err.message}`, \"stderr\")\n        rt.emitter.emit(\"status\", desc.status)\n        schedulePersist()\n        emitExited(rt)\n      })\n      schedulePersist()\n      return desc\n    },\n    spawnAgent(input) {\n      const id = `sess_${randomUUID().slice(0, 8)}`\n      const desc: SessionDescriptor = {\n        id,\n        kind: \"agent-cli\",\n        workspaceSlug: input.workspaceSlug,\n        command: input.commandPreview ?? `${input.adapterSlug} (agent)`,\n        pid: input.agentSession.pid ?? null,\n        status: \"running\", // driver already started the session\n        startedAt: new Date().toISOString(),\n        cwd: input.cwd,\n        adapterSlug: input.adapterSlug,\n        // ACP-level session id — sticks across daemon restart so\n        // `agentproto sessions restart <id>` can pass it as\n        // `resumeSessionId` and the adapter reattaches to the prior\n        // conversation rather than starting blank.\n        adapterSessionId: input.agentSession.sessionId,\n        ...(input.label ? { label: input.label } : {}),\n        // Persist the spawn-time MCP mounts so resume re-mounts the same\n        // toolset (orchestrator WP1). Reference-only shape — no secrets.\n        ...(input.mcpServers ? { mcpServers: input.mcpServers } : {}),\n        // Parent attribution + depth (orchestrator WP4). Depth is always\n        // recorded (defaults to 0) so subtree/depth logic never has to\n        // distinguish \"absent\" from \"root\".\n        ...(input.parentSessionId\n          ? { parentSessionId: input.parentSessionId }\n          : {}),\n        depth: input.depth ?? 0,\n        ...(input.model ? { model: input.model } : {}),\n      }\n      const rt: SessionRuntime = {\n        desc,\n        agentSession: input.agentSession,\n        adapterSlug: input.adapterSlug,\n        recentLines: [],\n        recentBytes: [],\n        recentBytesSize: 0,\n        emitter: new EventEmitter(),\n        busy: false,\n        textBuf: \"\",\n        thoughtBuf: \"\",\n        maxCostUsd: input.maxCostUsd,\n        readUsage: input.readUsage,\n      }\n      rt.emitter.setMaxListeners(50)\n      sessions.set(id, rt)\n      appendLine(\n        rt,\n        `── ${input.adapterSlug} agent session ${input.agentSession.sessionId} (cwd ${input.cwd}) ──`,\n        \"stdout\"\n      )\n      schedulePersist()\n      // Fire-and-forget the initial prompt (if any). Errors land in\n      // the ring buffer + bump status to \"error\" but don't reject\n      // the spawn — the descriptor was already returned.\n      if (input.initialPrompt) {\n        void runAgentTurn(rt, input.initialPrompt).catch(err => {\n          appendLine(\n            rt,\n            `[turn error] ${err instanceof Error ? err.message : String(err)}`,\n            \"stderr\"\n          )\n        })\n      }\n      return desc\n    },\n    spawnPty(input) {\n      if (!ptyFactory) {\n        throw new Error(\n          \"sessions.spawnPty: no PTY factory configured (node-pty optional dep missing in the daemon)\"\n        )\n      }\n      const id = `sess_${randomUUID().slice(0, 8)}`\n      // Reject the name only when the prior holder is still alive —\n      // killed/exited/error sessions keep their descriptor in the\n      // registry for history, but their name is free to reuse so\n      // `stop X && terminal --name X` round-trips cleanly.\n      if (input.name) {\n        for (const rt of sessions.values()) {\n          if (rt.desc.name !== input.name) continue\n          const status = rt.desc.status\n          if (status === \"running\" || status === \"starting\") {\n            throw new Error(\n              `sessions.spawnPty: name \"${input.name}\" already in use by ${rt.desc.id} (status=${status})`,\n            )\n          }\n          // Free the name on the dead session so id-or-name lookup\n          // resolves to the NEW one. The old descriptor stays in the\n          // registry (you can still find it by id in the list).\n          rt.desc.name = undefined\n        }\n      }\n      const [bin, ...args] = input.argv\n      if (!bin) {\n        throw new Error(\"sessions.spawnPty: argv must include a binary\")\n      }\n      // node-pty forces its own minimal env unless we forward — pass\n      // process.env merged with caller overrides. The factory layer\n      // also forces TERM=xterm-256color so alt-screen apps render.\n      const env = { ...(process.env as Record<string, string>), ...(input.env ?? {}) }\n      delete env.NODE_OPTIONS\n      const pty: PtyProcess = ptyFactory({\n        command: bin,\n        args,\n        cwd: input.cwd,\n        env,\n        cols: input.cols,\n        rows: input.rows,\n      })\n      const desc: SessionDescriptor = {\n        id,\n        kind: \"terminal\",\n        workspaceSlug: input.workspaceSlug,\n        command: [bin, ...args].map(quoteArg).join(\" \"),\n        pid: pty.pid,\n        status: \"running\",\n        startedAt: new Date().toISOString(),\n        pty: true,\n        argv: input.argv,\n        cwd: input.cwd,\n        ...(input.name ? { name: input.name } : {}),\n        ...(input.label ? { label: input.label } : {}),\n      }\n      const rt: SessionRuntime = {\n        desc,\n        pty,\n        ptySubscribers: new Map(),\n        recentLines: [],\n        recentBytes: [],\n        recentBytesSize: 0,\n        emitter: new EventEmitter(),\n        busy: false,\n        textBuf: \"\",\n        thoughtBuf: \"\",\n      }\n      rt.emitter.setMaxListeners(50)\n      sessions.set(id, rt)\n      pty.onData((chunk: string) => {\n        // node-pty emits utf-8 strings. Convert once at the boundary\n        // so the ring buffer + emitter consumers all see Buffer.\n        appendBytes(rt, Buffer.from(chunk, \"utf8\"))\n      })\n      pty.onExit(evt => {\n        if (rt.desc.status !== \"killed\") {\n          rt.desc.status = \"exited\"\n        }\n        rt.desc.endedAt = new Date().toISOString()\n        if (typeof evt.exitCode === \"number\") rt.desc.exitCode = evt.exitCode\n        rt.emitter.emit(\"exit\", evt)\n        rt.emitter.emit(\"status\", rt.desc.status)\n        schedulePersist()\n        emitExited(rt)\n      })\n      schedulePersist()\n      return desc\n    },\n    registerBrowser(input) {\n      const inputLocation = input.location ?? \"local\"\n      // Idempotent: reuse an alive session for the same (adapterId, port, location).\n      // Location is part of the key so a cloud call never returns a local session.\n      for (const rt of sessions.values()) {\n        if (\n          rt.desc.kind === \"browser\" &&\n          rt.desc.browserAdapterId === input.adapterId &&\n          rt.desc.browserPort === input.port &&\n          (rt.desc.browserLocation ?? \"local\") === inputLocation &&\n          (rt.desc.status === \"running\" || rt.desc.status === \"starting\")\n        ) {\n          // Update label on idempotent hit so callers can stamp correlation\n          // context (guild/op/workItem) onto a long-lived browser session.\n          if (input.label !== undefined) {\n            rt.desc.label = input.label\n            schedulePersist()\n          }\n          return rt.desc\n        }\n      }\n      const id = `sess_${randomUUID().slice(0, 8)}`\n      const desc: SessionDescriptor = {\n        id,\n        kind: \"browser\",\n        workspaceSlug: \"\",\n        command: `${input.adapterId} (browser)`,\n        pid: input.pid ?? null,\n        status: input.status ?? \"running\",\n        startedAt: new Date().toISOString(),\n        browserAdapterId: input.adapterId,\n        browserPort: input.port,\n        browserBaseUrl: input.baseUrl,\n        browserLocation: inputLocation,\n        ...(input.label ? { label: input.label } : {}),\n      }\n      const rt: SessionRuntime = {\n        desc,\n        browserStop: input.stop,\n        recentLines: [],\n        recentBytes: [],\n        recentBytesSize: 0,\n        emitter: new EventEmitter(),\n        busy: false,\n        textBuf: \"\",\n        thoughtBuf: \"\",\n      }\n      rt.emitter.setMaxListeners(50)\n      sessions.set(id, rt)\n      schedulePersist()\n      return desc\n    },\n    async sendPrompt(id, message) {\n      const rtPre = sessions.get(id)\n      if (rtPre) await maybeResumeAgent(rtPre)\n      const rt = validateAgentTurn(id, \"sendPrompt\")\n      await runAgentTurn(rt, message)\n    },\n    async enqueuePrompt(id, message) {\n      // Admission phase — AWAITED, unlike the turn itself below. This\n      // is what makes `{queued: true}` truthful: a dead (exited/\n      // killed/error) session gets one resume attempt, then\n      // validateAgentTurn throws `SessionNotAliveError` (or the busy /\n      // wrong-kind errors) synchronously enough for the caller (MCP\n      // `agent_prompt`, HTTP `?wait=false`) to surface it instead of\n      // reporting success for a prompt that will never be dispatched.\n      const rtPre = sessions.get(id)\n      if (!rtPre) {\n        throw new Error(`enqueuePrompt: no session \"${id}\"`)\n      }\n      await maybeResumeAgent(rtPre)\n      const rt = validateAgentTurn(id, \"enqueuePrompt\")\n      // Execution phase — fire-and-forget from here on. Errors during\n      // the turn itself (network drop, child died mid-turn) land in\n      // the ring buffer as `[error]` lines so the SSE consumer sees\n      // them; admission already succeeded so there's nothing else to\n      // report back to the original caller.\n      void runAgentTurn(rt, message).catch(err => {\n        appendLine(\n          rtPre,\n          `[error] ${err instanceof Error ? err.message : String(err)}`,\n          \"stderr\"\n        )\n      })\n    },\n    pulseActivity(id) {\n      const rt = sessions.get(id)\n      if (!rt) return\n      rt.desc.lastActivityAt = new Date().toISOString()\n      schedulePersist()\n    },\n    list() {\n      return Array.from(sessions.values())\n        .map(s => s.desc)\n        .sort((a, b) => b.startedAt.localeCompare(a.startedAt))\n        .map(desc => {\n          stampProcessAlive(desc)\n          return desc\n        })\n    },\n    get(id) {\n      const desc = sessions.get(id)?.desc\n      if (desc) stampProcessAlive(desc)\n      return desc\n    },\n    attach(id, onLine) {\n      const rt = sessions.get(id)\n      if (!rt) return null\n      // Backfill: synchronously replay the ring buffer so attaches\n      // see the recent context, then subscribe for new lines.\n      for (const line of rt.recentLines) onLine(line, \"stdout\")\n      const handler = (evt: {\n        line: string\n        stream: \"stdout\" | \"stderr\"\n      }): void => onLine(evt.line, evt.stream)\n      rt.emitter.on(\"line\", handler)\n      return () => rt.emitter.off(\"line\", handler)\n    },\n    attachPty(id, initial, onData, onExit) {\n      const rt = sessions.get(id)\n      if (!rt || !rt.pty || !rt.ptySubscribers) return null\n      // Backfill: flush the byte ring buffer so a fresh attach lands\n      // on the recent screenful. Alt-screen apps repaint on next\n      // input but a snapshot is still better than blank.\n      for (const chunk of rt.recentBytes) onData(chunk)\n      // Subscriber registration: a monotonically-growing key so the\n      // size map can hold the per-subscriber dims and detach is O(1).\n      const subId = nextSubId++\n      rt.ptySubscribers.set(subId, { cols: initial.cols, rows: initial.rows })\n      reconcilePtySize(rt)\n      const dataHandler = (chunk: Buffer): void => onData(chunk)\n      const exitHandler = (evt: {\n        exitCode: number\n        signal?: number\n      }): void => onExit(evt)\n      rt.emitter.on(\"data\", dataHandler)\n      rt.emitter.once(\"exit\", exitHandler)\n      return {\n        write(data: string): void {\n          if (!rt.pty) return\n          try {\n            rt.pty.write(data)\n          } catch {\n            // PTY already exited — drop the input silently.\n          }\n        },\n        resize(cols: number, rows: number): void {\n          if (!rt.ptySubscribers) return\n          rt.ptySubscribers.set(subId, { cols, rows })\n          reconcilePtySize(rt)\n        },\n        detach(): void {\n          rt.emitter.off(\"data\", dataHandler)\n          rt.emitter.off(\"exit\", exitHandler)\n          rt.ptySubscribers?.delete(subId)\n          reconcilePtySize(rt)\n        },\n      }\n    },\n    findByIdOrName(query) {\n      const direct = sessions.get(query)\n      if (direct) {\n        stampProcessAlive(direct.desc)\n        return direct.desc\n      }\n      for (const rt of sessions.values()) {\n        if (rt.desc.name === query) {\n          stampProcessAlive(rt.desc)\n          return rt.desc\n        }\n      }\n      return undefined\n    },\n    writeTerminalInput(id, data) {\n      const rt = sessions.get(id)\n      if (!rt || !rt.pty) return false\n      try {\n        rt.pty.write(data)\n        return true\n      } catch {\n        return false\n      }\n    },\n    readTerminalOutput(id, lastBytes) {\n      const rt = sessions.get(id)\n      if (!rt || !rt.pty) return null\n      const joined = Buffer.concat(rt.recentBytes, rt.recentBytesSize)\n      if (typeof lastBytes === \"number\" && lastBytes > 0 && joined.byteLength > lastBytes) {\n        return joined.subarray(joined.byteLength - lastBytes)\n      }\n      return joined\n    },\n    kill(id, signal = \"SIGTERM\") {\n      const rt = sessions.get(id)\n      if (!rt) return false\n      if (\n        rt.desc.status === \"exited\" ||\n        rt.desc.status === \"killed\" ||\n        rt.desc.status === \"error\"\n      ) {\n        return false\n      }\n      rt.desc.status = \"killed\"\n      rt.desc.endedAt = new Date().toISOString()\n      // Close agent session first (graceful protocol shutdown), then\n      // SIGTERM the underlying child/pty if any. Either branch is a\n      // best-effort — the descriptor flip is what the UI surfaces.\n      if (rt.agentSession) {\n        void rt.agentSession.close().catch(() => undefined)\n        void transcriptWriter.close(rt.desc.id)\n      }\n      if (rt.pty) {\n        try {\n          rt.pty.kill(signal)\n        } catch {\n          // pty already gone — fall through\n        }\n      }\n      rt.child?.kill(signal)\n      if (rt.browserStop) {\n        void rt.browserStop().catch(() => undefined)\n      }\n      schedulePersist()\n      // Agent-cli sessions have no OS exit event — emit here.\n      // Child/PTY sessions emit from their exit handlers; the\n      // exitedEmitted guard prevents a duplicate from kill() AND exit.\n      emitExited(rt)\n      return true\n    },\n    forget(id) {\n      const rt = sessions.get(id)\n      if (!rt) return false\n      // Don't leak: tear down the emitter so backfill listeners stop.\n      rt.emitter.removeAllListeners()\n      void transcriptWriter.close(id)\n      sessions.delete(id)\n      schedulePersist()\n      return true\n    },\n    shutdown() {\n      shutdownImpl()\n    },\n  }\n\n  /**\n   * The actual shutdown logic, hoisted so both the explicit\n   * `shutdown()` method AND the `process.on(\"exit\")` safety net\n   * can call it. Sync (no awaits) so it works in the `exit` event\n   * handler.\n   *\n   * Idempotent — `serve --interactive` calls gateway.stop() twice in\n   * some Ctrl-C race paths (parent SIGINT handler + the child-exit\n   * promise both fire), and `process.on(\"exit\")` ALSO fires at the\n   * end of every termination path. Without the guard, the second\n   * call clears the already-empty sessions Map and writes an empty\n   * snapshot back to sessions.json, wiping history.\n   */\n  function shutdownImpl(): void {\n    if (shutdownDone) return\n    shutdownDone = true\n    if (persistTimer) clearTimeout(persistTimer)\n    if (persist) {\n      try {\n        process.off(\"exit\", onProcessExit)\n      } catch {\n        // ignore — handler may not be installed\n      }\n    }\n    // Mark any still-alive sessions as killed BEFORE the final\n    // flush so the snapshot accurately reflects what happened. On\n    // the next boot, load reads these and we won't have to guess\n    // (\"was running last time → assume killed\" is then a no-op).\n    const nowIso = new Date().toISOString()\n    for (const rt of sessions.values()) {\n      rt.emitter.removeAllListeners()\n      if (\n        rt.desc.status === \"running\" ||\n        rt.desc.status === \"starting\"\n      ) {\n        rt.desc.status = \"killed\"\n        rt.desc.endedAt = nowIso\n        if (rt.agentSession) {\n          void rt.agentSession.close().catch(() => undefined)\n        }\n        if (rt.pty) {\n          try {\n            rt.pty.kill(\"SIGTERM\")\n          } catch {\n            // already exited\n          }\n        }\n        rt.child?.kill(\"SIGTERM\")\n      }\n    }\n    void transcriptWriter.closeAll()\n    // Sync flush so quick sessions (spawned + ended in less than\n    // PERSIST_DEBOUNCE_MS) aren't lost. The debounced async write\n    // may have been cancelled by clearTimeout above, but a 200-byte\n    // sync write at shutdown is cheap and the data needs to land.\n    if (persist) {\n      try {\n        const snapshot = {\n          savedAt: nowIso,\n          // Strip processAlive — see the matching comment in\n          // persistSnapshot(), same live-OS-query rationale applies here.\n          sessions: Array.from(sessions.values()).map(s => {\n            const { processAlive: _processAlive, ...rest } = s.desc\n            return rest\n          }),\n        }\n        mkdirSync(dirname(persistPath), { recursive: true })\n        writeFileSync(persistPath, JSON.stringify(snapshot, null, 2) + \"\\n\")\n      } catch {\n        // best-effort — same policy as the async path\n      }\n    }\n    sessions.clear()\n  }\n}\n\n/**\n * Read the persisted snapshot at boot and reinflate session\n * descriptors as historical \"ghost\" entries. Sync-read because this\n * runs once at construction, the file is small (~200 entries), and\n * keeping it sync avoids making createSessionsRegistry async (would\n * cascade through createGateway + every embedding host).\n *\n * Anything that was \"running\"/\"starting\" when the daemon last died\n * gets re-classified as \"killed\" with endedAt=now — we can't tell\n * if the orphan PID survived the daemon's exit, and pretending it's\n * still alive would make attach/kill calls fail mysteriously. The\n * descriptor stays in the registry for history; the dashboard sees\n * it under SESSIONS, the user can `d` to forget.\n *\n * Ghosts carry NO live child / agentSession / pty — calls that\n * would interact with the underlying process degrade to no-ops.\n * Output ring buffers (lines + bytes) are empty: we don't persist\n * those, only the descriptor metadata.\n */\nfunction loadHistorySnapshot(\n  persistPath: string,\n  sessions: Map<string, SessionRuntime>,\n): void {\n  let raw: string\n  try {\n    raw = readFileSync(persistPath, \"utf8\")\n  } catch {\n    return // ENOENT etc. — first boot, no history.\n  }\n  let parsed: { sessions?: SessionDescriptor[] }\n  try {\n    parsed = JSON.parse(raw)\n  } catch {\n    console.warn(\n      `[sessions] history file ${persistPath} is malformed — ignoring`,\n    )\n    return\n  }\n  if (!Array.isArray(parsed.sessions)) return\n  // Newest first so the FIFO cap drops oldest.\n  const sorted = parsed.sessions\n    .filter((s): s is SessionDescriptor => !!s && typeof s.id === \"string\")\n    .sort((a, b) => b.startedAt.localeCompare(a.startedAt))\n    .slice(0, HISTORY_CAP)\n  const now = new Date().toISOString()\n  for (const desc of sorted) {\n    if (sessions.has(desc.id)) continue // collision with a live entry — keep live\n    const wasAlive = desc.status === \"running\" || desc.status === \"starting\"\n    const reclassified: SessionDescriptor = wasAlive\n      ? {\n          ...desc,\n          status: \"killed\",\n          endedAt: desc.endedAt ?? now,\n        }\n      : desc\n    const rt: SessionRuntime = {\n      desc: reclassified,\n      recentLines: [],\n      recentBytes: [],\n      recentBytesSize: 0,\n      emitter: new EventEmitter(),\n      busy: false,\n      textBuf: \"\",\n      thoughtBuf: \"\",\n    }\n    rt.emitter.setMaxListeners(50)\n    sessions.set(desc.id, rt)\n  }\n}\n\n/** Minimal shell-quote — wraps args containing whitespace or quotes\n *  so the rendered `command` field is copy-pasteable. */\nfunction quoteArg(arg: string): string {\n  if (arg === \"\") return '\"\"'\n  if (/^[a-zA-Z0-9._/=:@,+-]+$/.test(arg)) return arg\n  return `\"${arg.replace(/([\"\\\\$`])/g, \"\\\\$1\")}\"`\n}\n","/**\n * MCP tools for event-driven orchestration:\n *   - session_events_poll — cheap cursor-based snapshot of session events\n *   - session_monitor     — multiplexed long-poll (1 call for N sessions)\n *\n * These complement the existing per-session waitForTurnEnd inside\n * agent_output. The new tools handle multi-session fan-in\n * and external-client retrigger without burning polling tokens.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type {\n  SessionEventBus,\n  SessionEventType,\n  SessionAwaitingQuestion,\n} from \"./session-event-bus.js\"\nimport type { EventRing } from \"./event-ring.js\"\nimport type { RoutineRunner } from \"./routine-runner.js\"\nimport type { WorkflowRunner } from \"./workflow-runner.js\"\nimport type { CompletionPolicySupervisor, AttachPolicyInput } from \"./supervisor.js\"\nimport { withToolSubset } from \"./tool-subset.js\"\nimport { jsonTolerant } from \"./json-tolerant.js\"\nimport { collectSubtree } from \"./session-tools.js\"\nimport type { PolicyRunState } from \"./supervisor.js\"\nimport type { InboundWatcher } from \"./inbound-watcher.js\"\nimport type { CronScheduler } from \"./cron-scheduler.js\"\n\n/**\n * Zod schema for the `gate` field of `policy_attach`.\n * Exported so tests can validate the schema directly.\n *\n * Union of two variants:\n *   • shell  — `{ command, args?, cwd?, timeoutMs? }`\n *   • judge  — `{ judge: { adapter, model?, prompt, timeoutMs? } }` (WP7)\n */\nexport const gateInputSchema = z.union([\n  z.object({\n    command: z.string().min(1).describe(\"Gate command basename (must be allowlisted).\"),\n    args: z.array(z.string()).optional().describe(\"Argv passed verbatim.\"),\n    cwd: z.string().optional().describe(\"Working directory for the gate. Defaults to the session's cwd.\"),\n    timeoutMs: z.number().int().positive().optional().describe(\"Gate timeout in ms. Default 60 000.\"),\n  }),\n  z.object({\n    judge: z.object({\n      adapter: z.string().min(1).describe(\"Agent adapter slug to spawn (e.g. \\\"claude-code\\\").\"),\n      model: z.string().optional().describe(\"Optional model identifier forwarded to the adapter.\"),\n      prompt: z.string().min(1).describe(\"Rubric / instructions for the judge. The supervisor appends a VERDICT instruction.\"),\n      timeoutMs: z.number().int().positive().optional().describe(\"Max wall-clock for the judge before kill + FAIL. Default 120 000.\"),\n    }),\n  }),\n])\n\n// ── Shared long-poll service functions ─────────────────────────────\n//\n// `monitorSessionWait` and `monitorPolicyWait` are the single source of\n// truth for the blocking-wait semantics exposed by BOTH the MCP tool\n// surface (`session_monitor`, `policy_status` fast-path) AND the REST\n// HTTP surface (`GET /sessions/:id/wait`, `GET /policies/:id/wait`).\n// Each MCP/REST handler is a thin adapter over these — no duplicated\n// long-poll logic between the two transports.\n\n/**\n * Event kind a session wait can target. Mirrors the `session_monitor`\n * `event` parameter. `turn-end` also matches `awaiting-input` (both\n * signal end-of-turn), matching the MCP tool's semantics.\n */\nexport type SessionWaitEvent = \"turn-end\" | \"awaiting-input\" | \"exited\" | \"any\"\n\n/**\n * Result of a single-session wait. On a hit, carries the session id, the\n * matched event (ring-bus form, without the `session:` prefix), the\n * session's current status, and whether it's awaiting input. On a\n * timeout, `timedOut: true` and the watched id list.\n */\nexport interface SessionWaitResult {\n  timedOut?: boolean\n  sessionId?: string\n  event?: string\n  source?: \"ring\" | \"state\" | \"bus\"\n  awaitingInput?: boolean\n  status?: string\n  turnsCompleted?: number\n  sessionIds?: string[]\n  since?: number\n  /** Structured awaiting-input question (harness-parity). Surface on\n   *  turn-end / awaiting-input matches so callers (MCP session_monitor +\n   *  REST /sessions/:id/wait) can read the question without a separate\n   *  transcript fetch. Mirrors desc.awaitingQuestion / ev.question. */\n  question?: SessionAwaitingQuestion\n}\n\n/**\n * Block until one of the listed sessions fires a matching lifecycle event\n * (turn-end / awaiting-input / exited / any), or until `timeoutMs` elapses.\n *\n * This is the single-session-capable core that the MCP `session_monitor`\n * tool and the REST `GET /sessions/:id/wait` route both call. The MCP tool\n * passes N ids (multiplexed fan-in); the REST route passes exactly one.\n * The semantics are identical: race-free cursor replay → synchronous\n * already-in-target-state check → bus long-poll → timeout.\n *\n * `since` is an EventRing cursor: when provided, already-emitted matching\n * events for the watched sessions that occurred after that cursor are\n * returned immediately (race-free replay) before subscribing to the bus.\n */\nexport async function monitorSessionWait(opts: {\n  registry: SessionsRegistry\n  sessionEvents: SessionEventBus\n  eventRing: EventRing\n  sessionIds: string[]\n  event?: SessionWaitEvent\n  timeoutMs?: number\n  since?: number\n}): Promise<SessionWaitResult> {\n  const {\n    registry,\n    sessionEvents,\n    eventRing,\n    sessionIds,\n    timeoutMs = 25_000,\n  } = opts\n  const targetEvent: SessionWaitEvent = opts.event ?? \"any\"\n\n  // Resolve id-or-name → canonical id (mirrors the MCP tool exactly).\n  const resolvedIds = sessionIds.map(q => {\n    const desc = registry.findByIdOrName(q)\n    return desc?.id ?? q\n  })\n\n  // Race-free replay: if a cursor is provided, check the event ring for\n  // already-emitted matching events before descriptor checks.\n  if (opts.since !== undefined) {\n    const ringResult = eventRing.since(opts.since, {\n      sessionIds: resolvedIds,\n    })\n    const matchTypes: Set<string> =\n      targetEvent === \"any\"\n        ? new Set([\"session:turn-end\", \"session:awaiting-input\", \"session:exited\"])\n        : targetEvent === \"turn-end\"\n          ? new Set([\"session:turn-end\", \"session:awaiting-input\"])\n          : targetEvent === \"awaiting-input\"\n            ? new Set([\"session:awaiting-input\"])\n            : new Set([\"session:exited\"])\n    for (const ev of ringResult.events) {\n      if (!matchTypes.has(ev.type)) continue\n      // `ev.type` is one of the session:* literals filtered by `matchTypes`\n      // above, but `Set.has` isn't a type guard — TS still sees the full\n      // `SessionEvent` union (which now also includes sessionId-less\n      // `cron:*` members, see session-event-bus.ts), so `sessionId` needs\n      // a defensive cast here.\n      const evWithSid = ev as { sessionId?: string; type: string }\n      const question =\n        ev.type === \"session:turn-end\" || ev.type === \"session:awaiting-input\"\n          ? ev.question\n          : undefined\n      return {\n        sessionId: evWithSid.sessionId,\n        event: ev.type.replace(\"session:\", \"\"),\n        source: \"ring\",\n        since: opts.since,\n        ...(question ? { question } : {}),\n      }\n    }\n  }\n\n  // Synchronous check: return immediately if a session is already in the\n  // target state (same rules as the MCP tool — a fast session can finish\n  // its turn before this wait subscribes).\n  for (const sid of resolvedIds) {\n    const desc = registry.get(sid)\n    if (!desc) continue\n    if (\n      desc.awaitingInput &&\n      (targetEvent === \"any\" || targetEvent === \"turn-end\" || targetEvent === \"awaiting-input\")\n    ) {\n      return {\n        sessionId: sid,\n        event: \"awaiting-input\",\n        source: \"state\",\n        awaitingInput: true,\n        status: desc.status,\n        ...(desc.awaitingQuestion ? { question: desc.awaitingQuestion } : {}),\n      }\n    }\n    // Already-finished turn: turnsCompleted > 0 && !busy && running.\n    if (\n      (desc.turnsCompleted ?? 0) > 0 &&\n      !desc.busy &&\n      desc.status === \"running\" &&\n      (targetEvent === \"any\" || targetEvent === \"turn-end\")\n    ) {\n      return {\n        sessionId: sid,\n        event: \"turn-end\",\n        source: \"state\",\n        awaitingInput: false,\n        status: desc.status,\n        turnsCompleted: desc.turnsCompleted,\n      }\n    }\n    const terminal =\n      desc.status === \"exited\" || desc.status === \"killed\" || desc.status === \"error\"\n    if (terminal && (targetEvent === \"any\" || targetEvent === \"exited\")) {\n      return {\n        sessionId: sid,\n        event: \"exited\",\n        source: \"state\",\n        awaitingInput: false,\n        status: desc.status,\n      }\n    }\n  }\n\n  // Long-poll: subscribe to the bus, resolve on the first matching event.\n  return new Promise<SessionWaitResult>(resolve => {\n    const unsubs: Array<() => void> = []\n    let settled = false\n\n    const finish = (result: SessionWaitResult): void => {\n      if (settled) return\n      settled = true\n      clearTimeout(timer)\n      for (const u of unsubs) u()\n      resolve(result)\n    }\n\n    const relevantTypes: SessionEventType[] =\n      targetEvent === \"any\"\n        ? [\"session:turn-end\", \"session:awaiting-input\", \"session:exited\"]\n        : targetEvent === \"turn-end\"\n          ? [\"session:turn-end\", \"session:awaiting-input\"]\n          : targetEvent === \"awaiting-input\"\n            ? [\"session:awaiting-input\"]\n            : [\"session:exited\"]\n\n    const idSet = new Set(resolvedIds)\n\n    for (const evType of relevantTypes) {\n      unsubs.push(\n        sessionEvents.on(evType, ev => {\n          // Same defensive cast as the ring-replay branch above — `evType`\n          // is only known to be one of the session:* literals at the\n          // call-site, not narrowed by `on`'s signature, so `ev` is still\n          // typed as the full (now cron:*-inclusive) SessionEvent union.\n          const sessionId = (ev as { sessionId?: string }).sessionId\n          if (!sessionId || !idSet.has(sessionId)) return\n          const desc = registry.get(sessionId)\n          finish({\n            sessionId,\n            event: ev.type.replace(\"session:\", \"\"),\n            source: \"bus\",\n            awaitingInput: desc?.awaitingInput ?? false,\n            status: desc?.status ?? \"unknown\",\n            ...(desc?.awaitingQuestion ? { question: desc.awaitingQuestion } : {}),\n          })\n        }),\n      )\n    }\n\n    const timer = setTimeout(() => {\n      finish({ timedOut: true, sessionIds: resolvedIds })\n    }, timeoutMs)\n  })\n}\n\n/**\n * Block until the named policy's status transitions out of the active\n * `watching` / `queued` / `gating` / `nudging` states — i.e. reaches\n * `done`, `blocked`, `awaiting-ack`, or `cancelled` — then return the\n * full PolicyRunState. Returns `{ timedOut: true }` on timeout.\n *\n * Hooks into the supervisor's `onSettle` callback (the single reliable\n * signal — some terminal transitions like `cancel()` / `ack(false)` /\n * single-session-exit emit no SessionEventBus event). The MCP\n * `policy_status` tool and the REST `GET /policies/:id/wait` route both\n * delegate here, so the wait semantics are shared across transports.\n */\nexport async function monitorPolicyWait(opts: {\n  supervisor: CompletionPolicySupervisor\n  policyId: string\n  timeoutMs?: number\n}): Promise<{ timedOut: true } | { timedOut: false; state: PolicyRunState }> {\n  const { supervisor, policyId, timeoutMs = 25_000 } = opts\n\n  // Fast path: already settled (done / blocked / cancelled / awaiting-ack).\n  const initial = supervisor.getStatus(policyId)\n  if (!initial) {\n    return { timedOut: false, state: undefined as unknown as PolicyRunState }\n  }\n  const isSettledStatus = (s: string): boolean =>\n    s === \"done\" || s === \"blocked\" || s === \"cancelled\" || s === \"awaiting-ack\"\n  if (isSettledStatus(initial.status)) {\n    return { timedOut: false, state: initial }\n  }\n\n  return new Promise(resolve => {\n    let settled = false\n    const timer = setTimeout(() => {\n      if (settled) return\n      settled = true\n      unsub()\n      resolve({ timedOut: true })\n    }, timeoutMs)\n\n    const unsub = supervisor.onSettle(id => {\n      if (id !== policyId) return\n      const state = supervisor.getStatus(policyId)\n      if (!state || !isSettledStatus(state.status)) return\n      if (settled) return\n      settled = true\n      clearTimeout(timer)\n      unsub()\n      resolve({ timedOut: false, state })\n    })\n  })\n}\n\nexport interface RegisterOrchestrationToolsOptions {\n  registry: SessionsRegistry\n  sessionEvents: SessionEventBus\n  eventRing: EventRing\n  routineRunner?: RoutineRunner\n  workflowRunner?: WorkflowRunner\n  supervisor?: CompletionPolicySupervisor\n  /** When wired, exposes start/stop/list_inbound_watcher tools. */\n  inboundWatcher?: InboundWatcher\n  /**\n   * When wired, exposes cron_create / cron_list / cron_delete / cron_run\n   * tools. NOT added to DEFAULT_ORCHESTRATOR_TOOLS — this installs\n   * persistent host-level recurring jobs (bigger privilege than session/\n   * policy tools). Opt-in via explicit orchestrator.tools allowlist only.\n   */\n  cronScheduler?: CronScheduler\n  /** Optional allowlist — when set, only tools whose name is in the\n   *  set are registered (the scoped orchestrator sub-gateway, WP2).\n   *  Omitted → register everything, today's behaviour. */\n  toolSubset?: ReadonlySet<string>\n  /**\n   * When set, this is the calling orchestrator's scope (WP6 supervisor\n   * composition). Enables subtree-scoped policy operations:\n   *   - policy_attach may only target sessions in the caller's subtree\n   *   - then:\"commit\" is refused (host commit is an operator gesture)\n   *   - policy_status / policy_list / policy_cancel only see\n   *     policies whose watched sessions are all within the caller's subtree\n   * Absent → operator/root context, no additional restrictions.\n   */\n  callerScope?: { ownerSessionId?: string }\n}\n\nexport function registerOrchestrationTools(\n  rawServer: McpServer,\n  opts: RegisterOrchestrationToolsOptions,\n): void {\n  // When a subset is requested, every `server.tool(...)` below is\n  // filtered through this one guard (ADR §4.2). No subset → raw server.\n  const server = opts.toolSubset\n    ? withToolSubset(rawServer, opts.toolSubset)\n    : rawServer\n  const { registry, sessionEvents, eventRing, callerScope, inboundWatcher } = opts\n\n  /**\n   * WP6: check whether ALL watched sessions of a policy fall within the\n   * subtree rooted at `ownerId`. Rebuilds the subtree from the live\n   * registry on each call so newly-spawned children are visible without\n   * any explicit invalidation. The subtree is tiny and the build is O(n)\n   * over all sessions — cheap relative to any surrounding I/O.\n   */\n  const isPolicyInSubtree = (policy: PolicyRunState, ownerId: string): boolean => {\n    const subtree = collectSubtree(ownerId, registry.list())\n    const ids = policy.sessionIds.length > 0 ? policy.sessionIds : [policy.sessionId]\n    return ids.every(id => subtree.has(id))\n  }\n\n  // ── session_events_poll ───────────────────────────────────────────\n  server.tool(\n    \"session_events_poll\",\n    \"Lightweight cursor-based snapshot of session lifecycle events \" +\n      \"(turn-end, awaiting-input, exited). Returns only what changed since \" +\n      \"the last call — cheap, no transcript. Use `session_monitor` to block \" +\n      \"efficiently; use this for a quick status sweep between other work.\",\n    {\n      since: z\n        .number()\n        .int()\n        .min(0)\n        .optional()\n        .describe(\n          \"Opaque cursor from a prior call's `nextCursor`. Omit (or pass 0) \" +\n            \"to start from the current tail — returns events emitted after this call.\",\n        ),\n      sessionIds: z\n        .array(z.string())\n        .optional()\n        .describe(\"Filter to these session ids. Omit → all sessions.\"),\n      types: z\n        .array(z.enum([\"turn-end\", \"awaiting-input\", \"exited\", \"command-done\", \"policy:passed\", \"policy:failed\", \"policy:commit-ready\", \"policy:committed\", \"cron:fired\", \"cron:succeeded\", \"cron:failed\"]))\n        .optional()\n        .describe(\"Filter to these event types. Omit → all types.\"),\n      limit: z\n        .number()\n        .int()\n        .min(1)\n        .max(200)\n        .optional()\n        .describe(\"Max events to return. Default 50.\"),\n    },\n    async input => {\n      const cursor = input.since ?? eventRing.since(0).nextCursor\n      const { events, nextCursor } = eventRing.since(cursor, {\n        sessionIds: input.sessionIds,\n        types: input.types as SessionEventType[] | undefined,\n        limit: input.limit,\n      })\n      return {\n        content: [\n          { type: \"text\", text: JSON.stringify({ events, nextCursor }, null, 2) },\n        ],\n      }\n    },\n  )\n\n  // ── Routine tools (optional — only registered when routineRunner is provided) ─\n  const { routineRunner } = opts\n  if (routineRunner) {\n    server.tool(\n      \"routine_start\",\n      \"Start a routine — a named sequence of steps that spawn agent sessions \" +\n        \"and fan-in on their turn-end events. Returns a runId immediately; \" +\n        \"the routine executes in the background. Poll with `routine_status`.\",\n      {\n        routineId: z.string().describe(\"Arbitrary label for this routine type (e.g. 'daily-brief').\"),\n        steps: z\n          .array(\n            z.object({\n              label: z.string(),\n              adapter: z.string().optional().describe(\"Agent adapter slug to spawn.\"),\n              prompt: z.string().optional().describe(\"Prompt to send after spawning.\"),\n              waitFor: z\n                .array(z.string())\n                .optional()\n                .describe(\"Session ids that must fire turn-end before this step runs.\"),\n              policy: z\n                .discriminatedUnion(\"awaiting\", [\n                  z.object({\n                    awaiting: z.literal(\"auto-allow\"),\n                    prompt: z.string(),\n                  }),\n                  z.object({\n                    awaiting: z.literal(\"escalate\"),\n                    webhookUrl: z.string().url().optional(),\n                    timeoutMs: z.number().int().positive().optional(),\n                  }),\n                  z.object({ awaiting: z.literal(\"fail\") }),\n                ])\n                .optional()\n                .describe(\"What to do when a session asks for input mid-step.\"),\n            }),\n          )\n          .min(1)\n          .max(50)\n          .describe(\"Ordered list of steps. Steps with `waitFor` block until those sessions finish.\"),\n        workspaceSlug: z\n          .string()\n          .optional()\n          .describe(\"Workspace slug passed to each spawned session.\"),\n        cwd: z.string().optional().describe(\"Working directory for spawned sessions.\"),\n        notifyUrl: z\n          .string()\n          .url()\n          .optional()\n          .describe(\"Webhook URL to call on run completion or escalation.\"),\n      },\n      async input => {\n        const run = await routineRunner.start(input)\n        return {\n          content: [{ type: \"text\", text: JSON.stringify({ runId: run.runId, status: run.status }, null, 2) }],\n        }\n      },\n    )\n\n    server.tool(\n      \"routine_status\",\n      \"Poll the status of a background routine run started with `routine_start`.\",\n      {\n        runId: z.string().describe(\"Run id returned by `routine_start`.\"),\n      },\n      async input => {\n        const run = routineRunner.status(input.runId)\n        if (!run) {\n          return {\n            content: [{ type: \"text\", text: JSON.stringify({ error: \"run not found\", runId: input.runId }) }],\n          }\n        }\n        return { content: [{ type: \"text\", text: JSON.stringify(run, null, 2) }] }\n      },\n    )\n\n    server.tool(\n      \"routine_cancel\",\n      \"Cancel a running routine. Steps already in flight will finish, but no \" +\n        \"new steps will be started.\",\n      {\n        runId: z.string().describe(\"Run id to cancel.\"),\n      },\n      async input => {\n        routineRunner.cancel(input.runId)\n        const run = routineRunner.status(input.runId)\n        return { content: [{ type: \"text\", text: JSON.stringify({ runId: input.runId, status: run?.status ?? \"not_found\" }) }] }\n      },\n    )\n\n    server.tool(\n      \"routine_escalation_resolve\",\n      \"Provide an external answer to a routine step that escalated because a \" +\n        \"session asked for human input (policy=escalate).\",\n      {\n        runId: z.string().describe(\"Run id.\"),\n        stepIndex: z.number().int().min(0).describe(\"Step index to resolve (0-based).\"),\n        response: z.string().describe(\"The answer to inject into the awaiting session.\"),\n      },\n      async input => {\n        routineRunner.resolve(input.runId, input.stepIndex, input.response)\n        return { content: [{ type: \"text\", text: JSON.stringify({ ok: true }) }] }\n      },\n    )\n\n    server.tool(\n      \"routine_list\",\n      \"List all routine runs (running, done, failed, cancelled).\",\n      {},\n      async () => {\n        const runs = routineRunner.list()\n        return { content: [{ type: \"text\", text: JSON.stringify(runs, null, 2) }] }\n      },\n    )\n  }\n\n  // ── Workflow tools (optional — only registered when workflowRunner is provided) ─\n  // Sibling primitive to routine_*: a workflow is an ordered list of STAGES,\n  // each stage a group of steps that run in parallel with an explicit\n  // barrier before the next stage starts (routine_* stays a flat sequential\n  // list with per-step waitFor fan-in — see PLAN.md \"Design decision\").\n  const { workflowRunner } = opts\n  if (workflowRunner) {\n    const workflowStepSchema = z.object({\n      label: z.string(),\n      adapter: z.string().optional().describe(\"Agent adapter slug to spawn a NEW session for this step.\"),\n      prompt: z.string().optional().describe(\"Prompt to send after spawning/reusing a session.\"),\n      sessionRef: z\n        .string()\n        .optional()\n        .describe(\n          \"Reuse the session spawned by an earlier step (any prior stage), by that step's `label`. \" +\n            \"Ignored if `adapter` is set. Lets a later-stage step act on an earlier stage's output \" +\n            \"(e.g. a 'verify' step reusing a 'produce' step's session).\",\n        ),\n      cacheable: z.boolean().optional().describe(\"Cache this step's output under the run's cacheKey (opt-in; for idempotent/pure steps only).\"),\n      policy: z\n        .discriminatedUnion(\"awaiting\", [\n          z.object({ awaiting: z.literal(\"auto-allow\"), prompt: z.string() }),\n          z.object({\n            awaiting: z.literal(\"escalate\"),\n            webhookUrl: z.string().url().optional(),\n            timeoutMs: z.number().int().positive().optional(),\n          }),\n          z.object({ awaiting: z.literal(\"fail\") }),\n        ])\n        .optional()\n        .describe(\"What to do when this step's session asks for input mid-stage.\"),\n    })\n\n    server.tool(\n      \"workflow_start\",\n      \"Start a workflow — an ordered list of STAGES, each stage a group of steps \" +\n        \"that spawn/reuse agent sessions and run CONCURRENTLY. An explicit barrier \" +\n        \"gates entry into the next stage: stage N+1 does not start until every step \" +\n        \"of stage N has finished (or failed). This is the `parallel()` half of a \" +\n        \"harness-style workflow primitive — for a flat sequential list with fan-in, \" +\n        \"use `routine_start` instead. Returns a runId immediately; the workflow \" +\n        \"executes in the background. Poll with `workflow_status`.\",\n      {\n        workflowId: z.string().describe(\"Arbitrary label for this workflow type (e.g. 'review-then-fix').\"),\n        stages: z\n          .array(\n            z.object({\n              label: z.string().optional().describe(\"Optional label for this stage.\"),\n              steps: z.array(workflowStepSchema).min(1).describe(\"Steps in this stage — all run in parallel.\"),\n            }),\n          )\n          .min(1)\n          .max(20)\n          .describe(\"Ordered list of stages. Each stage's steps run concurrently; stages run sequentially.\"),\n        workspaceSlug: z.string().optional().describe(\"Workspace slug passed to each spawned session.\"),\n        cwd: z.string().optional().describe(\"Working directory for spawned sessions.\"),\n        notifyUrl: z.string().url().optional().describe(\"Webhook URL to call on run completion or escalation.\"),\n        cacheKey: z.string().optional().describe(\"Enable journal caching for this run. On a re-invocation with the same cacheKey, cacheable steps whose inputs are unchanged replay their cached output instead of re-spawning.\"),\n      },\n      async input => {\n        const run = await workflowRunner.start(input)\n        return {\n          content: [{ type: \"text\", text: JSON.stringify({ runId: run.runId, status: run.status }, null, 2) }],\n        }\n      },\n    )\n\n    server.tool(\n      \"workflow_status\",\n      \"Poll the status of a background workflow run started with `workflow_start`. \" +\n        \"Each stage reports its steps' status/sessionId so later work can inspect \" +\n        \"what an earlier stage produced (e.g. via `agent_output` on that sessionId).\",\n      {\n        runId: z.string().describe(\"Run id returned by `workflow_start`.\"),\n      },\n      async input => {\n        const run = workflowRunner.status(input.runId)\n        if (!run) {\n          return {\n            content: [{ type: \"text\", text: JSON.stringify({ error: \"run not found\", runId: input.runId }) }],\n          }\n        }\n        return { content: [{ type: \"text\", text: JSON.stringify(run, null, 2) }] }\n      },\n    )\n\n    server.tool(\n      \"workflow_cancel\",\n      \"Cancel a running workflow. Steps already in flight will finish, but no \" +\n        \"new stages will be started.\",\n      {\n        runId: z.string().describe(\"Run id to cancel.\"),\n      },\n      async input => {\n        workflowRunner.cancel(input.runId)\n        const run = workflowRunner.status(input.runId)\n        return { content: [{ type: \"text\", text: JSON.stringify({ runId: input.runId, status: run?.status ?? \"not_found\" }) }] }\n      },\n    )\n\n    server.tool(\n      \"workflow_escalation_resolve\",\n      \"Provide an external answer to a workflow step that escalated because a \" +\n        \"session asked for human input (policy=escalate).\",\n      {\n        runId: z.string().describe(\"Run id.\"),\n        stageIndex: z.number().int().min(0).describe(\"Stage index containing the escalated step (0-based).\"),\n        stepIndex: z.number().int().min(0).describe(\"Step index within the stage to resolve (0-based).\"),\n        response: z.string().describe(\"The answer to inject into the awaiting session.\"),\n      },\n      async input => {\n        workflowRunner.resolve(input.runId, input.stageIndex, input.stepIndex, input.response)\n        return { content: [{ type: \"text\", text: JSON.stringify({ ok: true }) }] }\n      },\n    )\n\n    server.tool(\n      \"workflow_list\",\n      \"List all workflow runs (running, done, failed, cancelled).\",\n      {},\n      async () => {\n        const runs = workflowRunner.list()\n        return { content: [{ type: \"text\", text: JSON.stringify(runs, null, 2) }] }\n      },\n    )\n  }\n\n  // ── Supervisor tools ─────────────────────────────────────────────────────────\n  // policy_attach / policy_status / policy_list / policy_cancel are\n  // registered UNCONDITIONALLY because they appear in DEFAULT_ORCHESTRATOR_TOOLS\n  // and therefore in every scoped subset. A tool declared in the subset but not\n  // registered on the server causes the MCP handshake to hang indefinitely\n  // (empirically verified). When no supervisor is wired the handlers return a\n  // structured error instead of a live result — clean fail, no hang.\n  const { supervisor } = opts\n\n  // Base shape of a completion policy (shared by policy_attach and, via\n  // z.lazy, the recursive `next` DAG chain — WP6).\n  {\n    const policyShapeBase = {\n      sessionId: z\n        .string()\n        .optional()\n        .describe(\n          \"Session id to watch (single-session form). Provide this OR \" +\n            \"`sessionIds`. Equivalent to `sessionIds: [sessionId]`.\",\n        ),\n      sessionIds: jsonTolerant(\n        z.array(z.string()).min(1),\n      )\n        .optional()\n        .describe(\n          \"Fan-in group: the gate runs once, only after EVERY listed session \" +\n            \"has finished its turn (turn-end or exit). Supersedes `sessionId`.\",\n        ),\n      gate: jsonTolerant(gateInputSchema)\n        .optional()\n        .describe(\n          \"Gate: shell (exit 0 = pass) or judge-agent (WP7 — `{ judge: { adapter, prompt } }`). \" +\n            \"Absent → always passes immediately after turn-end.\",\n        ),\n      then: z\n        .enum([\"emit\", \"commit\"])\n        .describe(\n          \"Action on a GREEN gate. 'emit' → emits policy:passed. 'commit' → \" +\n            \"stages the explicit `commit.paths` and commits on the host \" +\n            \"(requires `commit`; git must be allowlisted).\",\n        ),\n      commit: jsonTolerant(\n        z.object({\n          paths: z\n            .array(z.string().min(1))\n            .min(1)\n            .describe(\n              \"Explicit literal paths to stage (workspace-relative). Staged \" +\n                \"via `git add -- <paths>` — never `-A`, never a glob.\",\n            ),\n          message: z.string().min(1).describe(\"Commit message (passed as argv, no shell).\"),\n          requireHumanAck: z\n            .boolean()\n            .optional()\n            .describe(\n              \"Default TRUE. When true, the green gate parks in awaiting-ack \" +\n                \"and emits policy:commit-ready; the commit runs only on \" +\n                \"policy_ack(approve:true). When false, commits directly. \" +\n                \"Never pushes, never --force.\",\n            ),\n        }),\n      )\n        .optional()\n        .describe(\"Required when then === 'commit' (WP5).\"),\n      onFail: jsonTolerant(\n        z.object({\n          nudge: z\n            .string()\n            .optional()\n            .describe(\n              \"Message sent to the session when the gate fails. \" +\n                \"Use {code} as a placeholder for the exit code. \" +\n                \"Default: built-in message in French.\",\n            ),\n          maxRetries: z\n            .number()\n            .int()\n            .min(1)\n            .max(10)\n            .optional()\n            .describe(\n              \"Maximum consecutive gate failures before blocking. Default: 2.\",\n            ),\n        }),\n      )\n        .optional()\n        .describe(\n          \"What to do when the gate fails (WP2). Absent → immediately blocked. \" +\n            \"Present → re-prompt the session up to maxRetries times then block. \" +\n            \"The session must still be running to receive a nudge.\",\n        ),\n    }\n\n    // WP6: a policy may declare `next` — a full (recursive) completion policy\n    // attached automatically when this policy reaches `done`. Chains over\n    // already-running sessions named in the child's own spec.\n    const policyInputSchema: z.ZodTypeAny = z.lazy(() =>\n      z.object({\n        ...policyShapeBase,\n        next: jsonTolerant(policyInputSchema).optional(),\n      }),\n    )\n    const nextField = {\n      next: jsonTolerant(policyInputSchema)\n        .optional()\n        .describe(\n          \"DAG chaining (WP6): a full completion policy (recursive) attached \" +\n            \"automatically when THIS policy reaches done. It watches the \" +\n            \"session(s) named in its own spec. Chains policies over existing \" +\n            \"sessions — does not spawn new sessions.\",\n        ),\n    }\n\n    server.tool(\n      \"policy_attach\",\n      \"Attach a completion policy to a running session (or a fan-in group). When \" +\n        \"the watched session emits turn-end — or, for a group, once EVERY member \" +\n        \"has finished its turn — an optional shell gate runs (exit 0 = pass). The \" +\n        \"result is emitted as `policy:passed` or `policy:failed` on the event bus \" +\n        \"(readable via session_events_poll). A policy may declare `next` to chain another \" +\n        \"policy when it completes (WP6 DAG). Returns the policyId immediately.\",\n      {\n        ...policyShapeBase,\n        ...nextField,\n      },\n      async input => {\n        if (!supervisor) {\n          return { content: [{ type: \"text\", text: JSON.stringify({ error: \"supervisor not available\" }) }] }\n        }\n        if (!input.sessionId && !(input.sessionIds && input.sessionIds.length > 0)) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify({ error: \"policy_attach requires sessionId or a non-empty sessionIds\" }),\n              },\n            ],\n          }\n        }\n        if (input.then === \"commit\" && !input.commit) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify({ error: 'then:\"commit\" requires a commit spec' }),\n              },\n            ],\n          }\n        }\n        // WP6 scoping: a child orchestrator may only attach policies on\n        // sessions within its own subtree, and may not request a commit\n        // action (host commits are an operator/human gesture).\n        if (callerScope) {\n          if (input.then === \"commit\") {\n            return {\n              content: [\n                {\n                  type: \"text\",\n                  text: JSON.stringify({\n                    error: 'then:\"commit\" is not permitted from a child orchestrator scope; use then:\"emit\" and let the operator or human ack the commit',\n                  }),\n                },\n              ],\n            }\n          }\n          if (!callerScope.ownerSessionId) {\n            return {\n              content: [\n                {\n                  type: \"text\",\n                  text: JSON.stringify({ error: \"scope is not yet bound to a session; cannot attach policy\" }),\n                },\n              ],\n            }\n          }\n          const targetIds =\n            input.sessionIds && input.sessionIds.length > 0\n              ? input.sessionIds\n              : input.sessionId\n                ? [input.sessionId]\n                : []\n          const subtree = collectSubtree(callerScope.ownerSessionId, registry.list())\n          const outside = targetIds.filter(id => !subtree.has(id))\n          if (outside.length > 0) {\n            return {\n              content: [\n                {\n                  type: \"text\",\n                  text: JSON.stringify({\n                    error: `policy_attach denied: sessions not in caller subtree: ${outside.join(\", \")}`,\n                    forbidden: outside,\n                  }),\n                },\n              ],\n            }\n          }\n        }\n        try {\n          const state = supervisor.attach({\n            sessionId: input.sessionId,\n            sessionIds: input.sessionIds,\n            gate: input.gate,\n            then: input.then,\n            commit: input.commit,\n            onFail: input.onFail,\n            next: input.next as AttachPolicyInput[\"next\"],\n          })\n          return {\n            content: [{ type: \"text\", text: JSON.stringify({ policyId: state.policyId, status: state.status }, null, 2) }],\n          }\n        } catch (err) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify({ error: err instanceof Error ? err.message : String(err) }),\n              },\n            ],\n          }\n        }\n      },\n    )\n\n    server.tool(\n      \"policy_status\",\n      \"Get the current status of a completion policy attached with `policy_attach`. \" +\n        \"Includes `awaitingQuestions` for any watched session currently blocked on \" +\n        \"input, so a caller can distinguish \\\"still legitimately running\\\" from \" +\n        \"\\\"stuck, needs a human/orchestrator answer\\\" without a separate call.\",\n      {\n        policyId: z.string().describe(\"Policy id returned by `policy_attach`.\"),\n      },\n      async input => {\n        if (!supervisor) {\n          return { content: [{ type: \"text\", text: JSON.stringify({ error: \"supervisor not available\" }) }] }\n        }\n        const state = supervisor.getStatus(input.policyId)\n        if (!state) {\n          return {\n            content: [{ type: \"text\", text: JSON.stringify({ error: \"policy not found\", policyId: input.policyId }) }],\n          }\n        }\n        // WP6 scoping: only reveal policies whose watched sessions are all\n        // within the caller's subtree. Return \"not found\" for out-of-scope\n        // policies (no information leak about existence).\n        if (callerScope) {\n          if (!callerScope.ownerSessionId || !isPolicyInSubtree(state, callerScope.ownerSessionId)) {\n            return {\n              content: [{ type: \"text\", text: JSON.stringify({ error: \"policy not found\", policyId: input.policyId }) }],\n            }\n          }\n        }\n        // Read-only enrichment: cross-reference the watched sessions' live\n        // awaitingQuestion (set by sessions.ts, structured or heuristic) —\n        // does not touch the policy state machine itself.\n        const awaitingQuestions = state.sessionIds\n          .map(id => ({ sessionId: id, desc: registry.get(id) }))\n          .filter((s): s is { sessionId: string; desc: NonNullable<ReturnType<typeof registry.get>> } => !!s.desc?.awaitingInput)\n          .map(s => ({ sessionId: s.sessionId, question: s.desc.awaitingQuestion }))\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify(\n                awaitingQuestions.length > 0 ? { ...state, awaitingQuestions } : state,\n                null,\n                2,\n              ),\n            },\n          ],\n        }\n      },\n    )\n\n    server.tool(\n      \"policy_cancel\",\n      \"Cancel a watching or gating completion policy. No-op on done/blocked policies.\",\n      {\n        policyId: z.string().describe(\"Policy id to cancel.\"),\n      },\n      async input => {\n        if (!supervisor) {\n          return { content: [{ type: \"text\", text: JSON.stringify({ error: \"supervisor not available\" }) }] }\n        }\n        // WP6 scoping: a child may only cancel policies on its own subtree.\n        if (callerScope) {\n          const state = supervisor.getStatus(input.policyId)\n          if (!state || !callerScope.ownerSessionId || !isPolicyInSubtree(state, callerScope.ownerSessionId)) {\n            return {\n              content: [{ type: \"text\", text: JSON.stringify({ error: \"policy_cancel denied: policy not found or outside caller subtree\", policyId: input.policyId }) }],\n            }\n          }\n        }\n        supervisor.cancel(input.policyId)\n        const state = supervisor.getStatus(input.policyId)\n        return {\n          content: [{ type: \"text\", text: JSON.stringify({ policyId: input.policyId, status: state?.status ?? \"not_found\" }) }],\n        }\n      },\n    )\n\n    // policy_ack is intentionally absent from DEFAULT_ORCHESTRATOR_TOOLS (host\n    // commits are an operator gesture, not a child-orchestrator one — WP6).\n    // Register it only when a supervisor is present, consistent with the\n    // declared ≡ registered invariant.\n    if (supervisor) {\n    server.tool(\n      \"policy_ack\",\n      \"Acknowledge a `then:\\\"commit\\\"` policy parked in `awaiting-ack` (WP5). \" +\n        \"`approve:true` runs the prepared host commit (git add <paths> + git \" +\n        \"commit; never -A/push/--force) → emits policy:committed (+sha) → done. \" +\n        \"`approve:false` cancels it (no commit). No-op on any other state.\",\n      {\n        policyId: z.string().describe(\"Policy id returned by `policy_attach`.\"),\n        approve: z\n          .boolean()\n          .describe(\"true → run the commit; false → cancel without committing.\"),\n      },\n      async input => {\n        const state = await supervisor.ack(input.policyId, input.approve)\n        if (!state) {\n          return {\n            content: [{ type: \"text\", text: JSON.stringify({ error: \"policy not found\", policyId: input.policyId }) }],\n          }\n        }\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify(\n                {\n                  policyId: state.policyId,\n                  status: state.status,\n                  ...(state.commitSha ? { sha: state.commitSha } : {}),\n                  ...(state.error ? { error: state.error } : {}),\n                },\n                null,\n                2,\n              ),\n            },\n          ],\n        }\n      },\n    )\n    } // end if (supervisor) for policy_ack\n\n    server.tool(\n      \"policy_list\",\n      \"List all completion policies (watching, gating, done, blocked, cancelled).\",\n      {},\n      async () => {\n        if (!supervisor) {\n          return { content: [{ type: \"text\", text: JSON.stringify({ error: \"supervisor not available\" }) }] }\n        }\n        let policies = supervisor.list()\n        // WP6 scoping: a child orchestrator only sees policies whose watched\n        // sessions are all within its own subtree. An unbound scope (no\n        // ownerSessionId yet) sees nothing — safe default.\n        if (callerScope) {\n          if (!callerScope.ownerSessionId) {\n            policies = []\n          } else {\n            const ownerId = callerScope.ownerSessionId\n            policies = policies.filter(p => isPolicyInSubtree(p, ownerId))\n          }\n        }\n        return { content: [{ type: \"text\", text: JSON.stringify(policies, null, 2) }] }\n      },\n    )\n  }\n\n  // ── session_monitor ──────────────────────────────────────────────\n  server.tool(\n    \"session_monitor\",\n    \"Multiplexed long-poll: block until ANY of the listed sessions fires a \" +\n      \"lifecycle event. Returns immediately when a session is already in the \" +\n      \"target state. Eliminates polling in multi-session fan-in orchestration — \" +\n      \"one call replaces N concurrent waitForTurnEnd calls.\",\n    {\n      sessionIds: z\n        .array(z.string())\n        .min(1)\n        .max(20)\n        .describe(\"Session ids (or names) to watch. Returns on the first hit.\"),\n      timeoutMs: z\n        .number()\n        .int()\n        .min(1_000)\n        .max(49_000)\n        .optional()\n        .describe(\"Max wait in ms. Default 25 000. Stays under MCP request timeout.\"),\n      event: z\n        .enum([\"turn-end\", \"awaiting-input\", \"exited\", \"any\"])\n        .optional()\n        .describe(\n          \"Event type to wait for. Default 'any'. 'turn-end' also matches \" +\n            \"'awaiting-input' (both signal end-of-turn).\",\n        ),\n      since: z\n        .number()\n        .int()\n        .min(0)\n        .optional()\n        .describe(\n          \"Event-ring cursor (from a prior session_events_poll nextCursor). When set, an already-emitted matching event for a watched session is returned immediately — race-free — before long-polling.\"\n        ),\n    },\n    async input => {\n      const timeout = input.timeoutMs ?? 25_000\n      const targetEvent = input.event ?? \"any\"\n\n      const result = await monitorSessionWait({\n        registry,\n        sessionEvents,\n        eventRing,\n        sessionIds: input.sessionIds,\n        event: targetEvent,\n        timeoutMs: timeout,\n        ...(input.since !== undefined ? { since: input.since } : {}),\n      })\n\n      // The MCP tool's contract: a ring-replay hit echoes back the cursor\n      // (so callers can chain); the state/bus hit returns the event shape.\n      // monitorSessionWait returns the same fields — forward verbatim,\n      // including the `question` field (harness-parity) when present.\n      const payload: Record<string, unknown> = { ...result }\n      if (result.source === \"ring\" && input.since !== undefined) {\n        payload.since = input.since\n      }\n      return {\n        content: [{ type: \"text\", text: JSON.stringify(payload) }],\n      }\n    },\n  )\n\n  // ── inbound_watcher_start ────────────────────────────────────────\n  if (inboundWatcher) {\n    server.tool(\n      \"inbound_watcher_start\",\n      \"Start a background poller that watches an agentpush source for new inbound \" +\n        \"messages and spawns one agent per contact_ref. The agent receives the \" +\n        \"inbound events inline via the prompt template. Returns a watcherId you \" +\n        \"can pass to inbound_watcher_stop or inbound_watcher_list.\",\n      {\n        alias: z\n          .string()\n          .min(1)\n          .describe(\n            \"Imported MCP alias for the agentpush server (e.g. 'agentpush'). \" +\n              \"Import it first with mcp_import.\",\n          ),\n        source: z\n          .string()\n          .min(1)\n          .describe(\n            \"Contact ref / channel to poll — forwarded as `source` to poll_inbound \" +\n              \"(e.g. a phone number '+33612345678' or a webhook channel name).\",\n          ),\n        adapter: z\n          .string()\n          .min(1)\n          .describe(\n            \"Agent adapter slug to spawn when new messages arrive (e.g. 'claude-code').\",\n          ),\n        promptTemplate: z\n          .string()\n          .min(1)\n          .describe(\n            \"Prompt sent to the spawned agent. Placeholders: \" +\n              \"{{source}} (watched source), {{contact_ref}} (sender), \" +\n              \"{{messages_json}} (JSON array of new events), {{count}} (message count).\",\n          ),\n        pollIntervalMs: z\n          .number()\n          .int()\n          .min(1_000)\n          .max(60_000)\n          .optional()\n          .describe(\"Poll interval in ms. Default 5 000.\"),\n        cwd: z\n          .string()\n          .optional()\n          .describe(\n            \"Working directory for spawned agents. Defaults to the daemon's cwd.\",\n          ),\n        label: z\n          .string()\n          .optional()\n          .describe(\"Optional label suffix on spawned session names.\"),\n        mcpServersForChild: jsonTolerant(\n          z.array(\n            z.object({\n              name: z.string(),\n              transport: z.enum([\"stdio\", \"http\", \"sse\"]),\n              ref: z.string().optional(),\n            }),\n          ),\n        )\n          .optional()\n          .describe(\n            \"MCP servers to mount in each spawned agent. Pass the agentpush entry \" +\n              \"here (e.g. [{name:'agentpush',transport:'http',ref:'http://localhost:8080/mcp'}]) \" +\n              \"so the agent can call dispatch_request to reply.\",\n          ),\n      },\n      async input => {\n        const desc = inboundWatcher.start(input)\n        return { content: [{ type: \"text\", text: JSON.stringify(desc, null, 2) }] }\n      },\n    )\n\n    server.tool(\n      \"inbound_watcher_stop\",\n      \"Stop a running inbound watcher. The watcher's cursor position is preserved \" +\n        \"in memory (and flushed to disk on daemon shutdown) so a new watcher \" +\n        \"started later can pick up where it left off.\",\n      {\n        watcherId: z\n          .string()\n          .min(1)\n          .describe(\"Watcher id returned by inbound_watcher_start.\"),\n      },\n      async input => {\n        const ok = inboundWatcher.stop(input.watcherId)\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify(\n                ok\n                  ? { ok: true, watcherId: input.watcherId, status: \"stopped\" }\n                  : {\n                      ok: false,\n                      error: `watcher \"${input.watcherId}\" not found`,\n                    },\n                null,\n                2,\n              ),\n            },\n          ],\n          ...(ok ? {} : { isError: true }),\n        }\n      },\n    )\n\n    server.tool(\n      \"inbound_watcher_list\",\n      \"List all inbound watchers (running and stopped) with their cursor position, \" +\n        \"last poll time, last fire time, and total spawned session count.\",\n      {},\n      async () => {\n        const watchers = inboundWatcher.list()\n        return { content: [{ type: \"text\", text: JSON.stringify(watchers, null, 2) }] }\n      },\n    )\n  }\n\n  // ── Cron scheduler tools (optional — only registered when cronScheduler is provided) ──\n  // NOT in DEFAULT_ORCHESTRATOR_TOOLS: installing host-level recurring jobs is a\n  // materially bigger privilege than session/policy tools. Opt-in only via explicit\n  // orchestrator.tools allowlist.\n  const { cronScheduler } = opts\n  if (cronScheduler) {\n    const cronActionSchema = z.union([\n      z.object({\n        kind: z.literal(\"command\"),\n        command: z.string().min(1).describe(\"Executable basename (must be allowlisted in .agentproto/allowed-commands.json).\"),\n        args: z.array(z.string()).optional().describe(\"Argv array passed verbatim.\"),\n        cwd: z.string().optional().describe(\"Working directory. Defaults to workspace root.\"),\n        timeoutMs: z.number().int().positive().optional().describe(\"Hard kill timeout in ms. Default 60 000.\"),\n      }),\n      z.object({\n        kind: z.literal(\"agent\"),\n        adapter: z.string().min(1).describe(\"Agent adapter slug (e.g. 'claude-code', 'hermes').\"),\n        prompt: z.string().min(1).describe(\"Prompt to send to the spawned agent.\"),\n        cwd: z.string().optional().describe(\"Working directory for the spawned session.\"),\n        model: z.string().optional().describe(\"Optional model identifier forwarded to the adapter.\"),\n      }),\n      z.object({\n        kind: z.literal(\"prompt-session\"),\n        sessionId: z.string().min(1).describe(\n          \"Id of an existing, already-running session (from agent_start or agent_sessions_list) to re-prompt.\",\n        ),\n        prompt: z.string().min(1).describe(\"Prompt to send to the existing session.\"),\n      }),\n    ])\n\n    server.tool(\n      \"cron_create\",\n      \"Schedule a recurring or one-shot cron job on the daemon. \" +\n        \"Accepts a 5-field cron expression (minute hour day-of-month month day-of-week, local time) \" +\n        \"and a command, agent-spawn, or session-reprompt action. \" +\n        \"Returns the created job id and nextRunAt. \" +\n        \"WARNING: this installs a persistent host-level job that survives daemon restarts.\",\n      {\n        schedule: z.string().min(1).describe(\n          \"5-field cron expression in local time. e.g. '0 9 * * 1-5' (weekdays at 9am). \" +\n          \"Fields: minute(0-59) hour(0-23) day-of-month(1-31) month(1-12) day-of-week(0-7,0=Sun).\",\n        ),\n        recurring: z.boolean().optional().describe(\n          \"When false, fires once then deactivates. Default true.\",\n        ),\n        label: z.string().optional().describe(\"Human-readable label for the job.\"),\n        action: cronActionSchema.describe(\n          \"What to do when the job fires. 'command' runs an allowlisted shell command; \" +\n          \"'agent' spawns a brand-new agent session; 'prompt-session' re-prompts an \" +\n          \"existing, already-running session in place (for durable check-in jobs).\",\n        ),\n      },\n      async input => {\n        try {\n          const job = cronScheduler.create({\n            label: input.label,\n            schedule: input.schedule,\n            recurring: input.recurring ?? true,\n            action: input.action,\n          })\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify({\n                  jobId: job.id,\n                  schedule: job.schedule,\n                  recurring: job.recurring,\n                  nextRunAt: job.nextRunAt,\n                  active: job.active,\n                }),\n              },\n            ],\n          }\n        } catch (err) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify({ error: err instanceof Error ? err.message : String(err) }),\n              },\n            ],\n            isError: true,\n          }\n        }\n      },\n    )\n\n    server.tool(\n      \"cron_list\",\n      \"List all cron jobs (active and inactive) with their schedule, last result, and next fire time.\",\n      {},\n      async () => {\n        const jobs = cronScheduler.list()\n        return { content: [{ type: \"text\", text: JSON.stringify(jobs, null, 2) }] }\n      },\n    )\n\n    server.tool(\n      \"cron_delete\",\n      \"Permanently remove a cron job. Throws if the job is not found.\",\n      {\n        jobId: z.string().min(1).describe(\"Job id returned by cron_create or cron_list.\"),\n      },\n      async input => {\n        try {\n          cronScheduler.delete(input.jobId)\n          return { content: [{ type: \"text\", text: JSON.stringify({ ok: true, jobId: input.jobId }) }] }\n        } catch (err) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify({ error: err instanceof Error ? err.message : String(err) }),\n              },\n            ],\n            isError: true,\n          }\n        }\n      },\n    )\n\n    server.tool(\n      \"cron_run\",\n      \"Manually fire a cron job immediately, bypassing its schedule. \" +\n        \"Useful for testing and debugging. Returns the job's lastResult.\",\n      {\n        jobId: z.string().min(1).describe(\"Job id returned by cron_create or cron_list.\"),\n      },\n      async input => {\n        try {\n          const result = await cronScheduler.run(input.jobId)\n          return { content: [{ type: \"text\", text: JSON.stringify({ jobId: input.jobId, result }) }] }\n        } catch (err) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify({ error: err instanceof Error ? err.message : String(err) }),\n              },\n            ],\n            isError: true,\n          }\n        }\n      },\n    )\n  }\n}\n","/**\n * Tiny node:http server that fronts the runtime gateway.\n *\n * Routes:\n *   GET  /health              — { status, workspace, registered, uptime }\n *   GET  /events              — SSE stream of RuntimeEvent\n *   POST /mcp                 — MCP Streamable HTTP transport (POST)\n *   GET  /mcp                 — MCP SSE response stream (GET)\n *   DELETE /mcp               — close MCP session\n *   GET  /conversations       — JSON list of conversation summaries\n *   GET  /conversations/<id>  — markdown body of one conversation\n *   POST /heartbeat/tick      — force-fire one heartbeat tick\n *\n * No auth in `mode: \"none\"` (loopback default). `mode: \"bearer\"`\n * checks `Authorization: Bearer <token>` against the configured\n * token. Health is always public so external monitors can probe.\n *\n * MCP transport: stateless mode for v1 — each request is independent.\n * Stateful session pinning can come later when long-running streaming\n * tool calls become a real use case.\n */\n\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\"\nimport type { Duplex } from \"node:stream\"\nimport { mkdir, stat, writeFile } from \"node:fs/promises\"\nimport { isAbsolute, join, resolve as resolvePath } from \"node:path\"\nimport type { AcpMcpServer } from \"@agentproto/acp\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\"\nimport { WebSocketServer, type WebSocket } from \"ws\"\nimport type { ConversationStore } from \"./conversations.js\"\nimport type { HeartbeatRunner } from \"./heartbeat.js\"\nimport type { RuntimeEvents, RuntimeEvent } from \"./events.js\"\nimport type { SessionsRegistry, AgentSessionLike } from \"./sessions.js\"\nimport { SessionNotAliveError } from \"./sessions.js\"\nimport type { TunnelRegistry } from \"./tunnel-registry.js\"\nimport type { RoutineRunner, RoutineStep } from \"./routine-runner.js\"\nimport type { WorkflowRunner, WorkflowStage } from \"./workflow-runner.js\"\nimport {\n  loadWorkspacesConfig,\n  findWorkspace,\n  getActiveWorkspace,\n} from \"./workspaces-config.js\"\nimport { discoverMcps } from \"./mcp-discovery.js\"\nimport type { McpProxyRegistry } from \"./mcp-proxy.js\"\nimport type {\n  BrowserAdapterResolver,\n  BrowserAdapterLister,\n} from \"./browser-tools.js\"\nimport type {\n  OrchestratorScope,\n  OrchestratorMcpServerFactory,\n} from \"./orchestrator-gateway.js\"\nimport {\n  loadImportedMcps,\n  saveImportedMcps,\n  addImport,\n  removeImport,\n} from \"./mcp-imports.js\"\nimport { exportAgentSession } from \"./transcript-export.js\"\nimport { sessionEventsPath } from \"./transcript-writer.js\"\nimport { createReadStream } from \"node:fs\"\nimport { createInterface } from \"node:readline\"\nimport {\n  monitorSessionWait,\n  monitorPolicyWait,\n  type SessionWaitEvent,\n} from \"./orchestration-tools.js\"\nimport type {\n  SessionEventBus,\n  SessionEventType,\n} from \"./session-event-bus.js\"\nimport type { EventRing } from \"./event-ring.js\"\nimport type { CompletionPolicySupervisor, AttachPolicyInput } from \"./supervisor.js\"\nimport { spawnAgentSession, type BuildOrchestratorMcp } from \"./session-spawn.js\"\nimport { tryParseJson } from \"./json-tolerant.js\"\n\n/**\n * Default Origin allowlist used when `RuntimeHttpServerOptions.allowedOrigins`\n * is undefined. Localhost on any port covers the user's own dev environments\n * (Guilde web dev server, playground demos, embedded panels). Production\n * origins (https://guilde.work, …) are NOT included by default — those are\n * opt-in via `agentproto serve --allow-origin <url>`.\n */\nconst DEFAULT_ALLOWED_ORIGINS: readonly string[] = [\n  \"http://localhost:*\",\n  \"http://127.0.0.1:*\",\n  \"https://localhost:*\",\n]\n\n/**\n * Pluggable adapter resolver — keeps the runtime package free of any\n * @agentproto/cli dep. The host (cli `serve`, playground, embedding\n * apps) builds the resolver and hands it in. Returning null means\n * \"adapter not found\" → 404.\n */\nexport type AgentAdapterResolver = (slug: string) => Promise<{\n  /** Build a fresh AgentSessionLike for the given cwd. The driver\n   *  spawns the adapter binary, opens the protocol, and the\n   *  registry holds the result.\n   *\n   *  When `resumeSessionId` is set, the driver reattaches to that\n   *  pre-existing adapter session (claude-code's conversation id,\n   *  hermes' chat handle, …) rather than starting blank. Same\n   *  mechanism as `agentproto run --resume <id>` — exposed over\n   *  HTTP so `agentproto sessions restart` works on agent-cli\n   *  sessions, not just PTY ones. */\n  startSession(opts: {\n    cwd: string\n    resumeSessionId?: string\n    /**\n     * Manifest-declared mode id forwarded from `agent_start` (AIP-45\n     * `AgentCliHandle.modes` — e.g. claude-code's `plan` /\n     * `accept-edits` / `bypass-permissions`, codex's `read-only`,\n     * mastracode/opencode's `plan`). Applied at spawn time via\n     * `composeSpawn`'s mode patch (`bin_args_append` / `env`) — BEFORE\n     * the child process is exec'd, unlike `model`/`effort` below.\n     * Adapters with no declared `modes` (e.g. hermes) ignore it; an\n     * unknown id for an adapter that DOES declare modes throws\n     * `RuntimeConfigError` (composeSpawn validates against the\n     * manifest, so a typo fails the spawn rather than silently no-op).\n     */\n    mode?: string\n    /** Model identifier forwarded from `agent_start`. For ACP\n     *  adapters this is applied via session/set_config_option after\n     *  newSession (the ACP wrapper does not forward CLI args to claude).\n     *  Adapters that don't support model selection ignore it. */\n    model?: string\n    /** Effort level forwarded from `agent_start`. Effort is\n     *  model-dependent — same label ≠ same budget across models; defaults\n     *  differ by model. Omit to keep the model's own default. Applied\n     *  via session/set_config_option on ACP adapters; others ignore it. */\n    effort?: string\n    /** MCP servers to mount into the spawned agent's session at spawn\n     *  time. Forwarded verbatim to the driver's `start({ mcpServers })`\n     *  → the ACP arm's `session/new.mcpServers`, giving the child agent\n     *  a host-chosen scoped toolset (e.g. the daemon's own orchestration\n     *  gateway). Adapters that don't model MCP mounting ignore it. */\n    mcpServers?: AcpMcpServer[]\n    /** Called on any adapter-process activity (ACP JSON-RPC traffic in\n     *  either direction) — forwarded to the driver's\n     *  `runtime.start({ onActivity })`. The caller (agent_start's MCP\n     *  handler, POST /sessions/agent) wires this to pulse\n     *  `SessionDescriptor.lastActivityAt` via `registry.pulseActivity(id)`. */\n    onActivity?: () => void\n  }): Promise<AgentSessionLike>\n  /** Display label for the descriptor's `command` field. */\n  commandPreview?: string\n  /** Best-effort per-session usage reader (adapter-specific, e.g. hermes state.db). */\n  readUsage?: (adapterSessionId: string) => Promise<{ costUsd?: number; tokensIn?: number; tokensOut?: number } | null>\n} | null>\n\n/**\n * Compact adapter metadata for the discovery endpoints. Independent\n * of the resolver function above — hosts that can list installed\n * adapters wire this; hosts that can only resolve by-slug skip it\n * (the routes 501).\n */\nexport interface AdapterListEntry {\n  slug: string\n  name: string\n  version: string\n  description: string\n  protocol: string\n  streaming: boolean\n  packageName: string\n}\n\nexport type AgentAdapterLister = () => Promise<AdapterListEntry[]>\n\nexport interface AuthOptions {\n  mode: \"none\" | \"bearer\"\n  token?: string\n}\n\n/**\n * Auth can be a fixed value (set at startup) or a getter (re-read on\n * every request). The getter form lets `remote_enable` flip bearer on\n * at runtime without restarting the gateway.\n */\nexport type AuthSource = AuthOptions | (() => AuthOptions)\n\nexport interface RuntimeHttpServerOptions {\n  port: number\n  bind?: string\n  auth?: AuthSource\n  /**\n   * Per-request McpServer factory.\n   *\n   * The SDK's `StreamableHTTPServerTransport` is single-use — once a\n   * transport has handled one request, the underlying `Protocol`\n   * cannot be reattached, so subsequent requests on a shared transport\n   * 500. The official stateless pattern (see SDK\n   * `examples/server/simpleStatelessStreamableHttp.js`) builds a\n   * fresh `McpServer` and `StreamableHTTPServerTransport` per request,\n   * connects them, and tears both down on `res.close`. We follow that.\n   *\n   * The factory is invoked once per `/mcp` POST. It must register\n   * tools / resources / prompts on the returned server before\n   * resolving — by the time the transport's `handleRequest` fires,\n   * the server is locked in.\n   */\n  mcpServerFactory: () => Promise<McpServer>\n  /**\n   * Optional scoped orchestrator sub-gateway (WP2). When BOTH this and\n   * `verifyOrchestratorScope` are wired, the server mounts a second MCP\n   * endpoint at `/mcp/orchestrator` that — unlike `/mcp` — has NO\n   * loopback auth bypass: every request must present a valid scope-token\n   * (`?scope=<token>` query or `X-Orchestrator-Scope` header). The token\n   * resolves to a scope, and the factory builds a server exposing only\n   * that scope's curated tool subset. This is what makes it safe to\n   * point a child agent at the daemon (WP3 auto-injects the URL).\n   */\n  orchestratorMcpServerFactory?: OrchestratorMcpServerFactory\n  /** Resolve a presented scope-token to its scope, or null when\n   *  unknown/missing. Paired with `orchestratorMcpServerFactory`. */\n  verifyOrchestratorScope?: (\n    token: string | null | undefined,\n  ) => OrchestratorScope | null\n  conversations: ConversationStore\n  events: RuntimeEvents\n  heartbeat: HeartbeatRunner\n  /** Optional — when wired, exposes /sessions routes for the CLI\n   *  TUI and the guilde-web Active tab to navigate live child\n   *  processes. Daemons that don't spawn anything (pure MCP servers)\n   *  can omit this and the routes 404. */\n  sessions?: SessionsRegistry\n  /** Optional — when wired alongside `sessions`, enables\n   *  `POST /sessions/agent` and `POST /sessions/:id/prompt` routes.\n   *  Hosts that ship adapters (`agentproto serve`, playground)\n   *  pass the cli's `resolveAdapter` via a thin shim. */\n  resolveAgentAdapter?: AgentAdapterResolver\n  /** Optional — mirrors `RegisterAgentToolsOptions.buildOrchestratorMcp`\n   *  (agent-tools.ts). When wired, `POST /sessions/agent`'s\n   *  `orchestrator` field mints a scoped sub-gateway token the same way\n   *  the MCP `agent_start` tool does. Omitted → `orchestrator` on the\n   *  HTTP route is rejected with a 501. */\n  buildOrchestratorMcp?: BuildOrchestratorMcp\n  /** Optional — mirrors `RegisterAgentToolsOptions.daemonMcpUrl`. When\n   *  wired, a `POST /sessions/agent` spawn for a `hermes` adapter with\n   *  no caller-supplied `mcpServers` defaults to mounting this gateway\n   *  (same hermes safety net as the MCP tool). */\n  daemonMcpUrl?: string\n  /** Optional — when wired, enables `GET /adapters` route + the\n   *  MCP `adapter_list` tool so UIs can discover what's installed\n   *  without trial-and-error against the resolver. Hosts ship the\n   *  cli's `listInstalledAdapters` via a thin shim. */\n  listAgentAdapters?: AgentAdapterLister\n  /** Optional — when wired alongside `sessions`, enables\n   *  `POST /sessions/browser` (same operation as MCP `start_browser`,\n   *  exposed as an HTTP route for the CLI surface). */\n  resolveBrowserAdapter?: BrowserAdapterResolver\n  /** Optional — passed to error messages on `POST /sessions/browser`\n   *  to list available adapter ids when the requested one isn't found. */\n  listBrowserAdapters?: BrowserAdapterLister\n  /** Optional — MCP proxy registry. When wired, exposes\n   *  `/mcps/proxy/*` routes that let the browser drive imported MCPs\n   *  without going through the MCP wire protocol (useful for the\n   *  /providers/mcp page's \"Local\" tab). */\n  mcpProxy?: McpProxyRegistry\n  /** Per-boot bearer token. When set, mutating /sessions/* routes\n   *  + the /sessions/:id/pty WebSocket upgrade require either\n   *  `Authorization: Bearer <token>` or an `Origin` header that\n   *  matches `allowedOrigins`. Read-only routes (GET, SSE stream)\n   *  stay open since the CORS surface already restricts origins\n   *  enough for them. */\n  token?: string\n  /** Trusted browser origins. When a mutating request carries an\n   *  `Origin: <url>` header (browser-set, JS can't forge), and that\n   *  url is in this list, the request is allowed without a Bearer\n   *  token. Browsers can't read the daemon's runtime.json (mode 0600)\n   *  so they can't send the token — Origin-based auth lets a trusted\n   *  page (Guilde web UI, local dev) drive the daemon. Non-browser\n   *  callers (curl, the CLI) still use the token.\n   *\n   *  Match policy: exact origin (`https://guilde.work`) OR prefix\n   *  with `:*` for any-port match (`http://localhost:*` matches\n   *  `http://localhost:3000`).\n   *\n   *  Default (when undefined): localhost on any port is allowed via\n   *  `DEFAULT_ALLOWED_ORIGINS`. Production origins are opt-in via\n   *  `agentproto serve --allow-origin <url>`. Pair with `strictOrigins`\n   *  to remove the localhost defaults entirely. */\n  allowedOrigins?: readonly string[]\n  /** When true, skip the localhost-wildcard defaults — only the\n   *  explicit `allowedOrigins` list is honoured. Useful for daemons\n   *  on shared hosts or when the user wants to lock dev to a\n   *  specific port. Default false (current behaviour — any browser\n   *  on `localhost` is trusted). */\n  strictOrigins?: boolean\n  /** Whether `POST /sessions/terminal` + WS upgrade are advertised.\n   *  Reflects whether the host injected a PTY factory into the\n   *  SessionsRegistry. When false, the terminal HTTP route returns\n   *  501 and the WS upgrade rejects. */\n  ptyEnabled?: boolean\n  /** Optional — when wired, exposes /tunnels/* routes for creating and\n   *  managing public tunnels for local ports. Without it the routes 404. */\n  tunnels?: TunnelRegistry\n  /** Optional — the session lifecycle event bus. When wired alongside\n   *  `sessions`, `eventRing`, enables `GET /sessions/:id/wait` (a blocking\n   *  long-poll that resolves when the session fires a lifecycle event).\n   *  Same machinery the MCP `session_monitor` tool uses. */\n  sessionEvents?: SessionEventBus\n  /** Optional — the cursor ring buffer over `sessionEvents`. Paired with\n   *  `sessionEvents` to enable `GET /sessions/:id/wait` (cursor-based\n   *  race-free replay via the `since` query param). */\n  eventRing?: EventRing\n  /** Optional — the completion-policy supervisor. When wired, enables\n   *  `GET /policies/:id/wait` (a blocking long-poll that resolves when the\n   *  policy leaves watching/gating → done/blocked/awaiting-ack/cancelled).\n   *  Same state the MCP `policy_status` tool reports. */\n  supervisor?: CompletionPolicySupervisor\n  /** Optional — when wired, exposes /cron routes for creating and\n   *  managing durable cron jobs. Without it the routes 404. */\n  cronScheduler?: import(\"./cron-scheduler.js\").CronScheduler\n  /** Optional — when wired, exposes /routines/* routes for starting and\n   *  managing background routine runs (sequential steps with per-step\n   *  fan-in). Same service the MCP `routine_start/status/cancel/\n   *  escalation_resolve/list` tools call. Without it the routes 404. */\n  routineRunner?: RoutineRunner\n  /** Optional — when wired, exposes /workflows/* routes for starting and\n   *  managing background workflow runs (stage-barrier parallel steps).\n   *  Same service the MCP `workflow_start/status/cancel/\n   *  escalation_resolve/list` tools call. Without it the routes 404. */\n  workflowRunner?: WorkflowRunner\n  /** Static fields surfaced via `/health`. */\n  meta: {\n    workspace: string\n    registered: readonly string[]\n  }\n}\n\nexport interface RuntimeHttpServerHandle {\n  url: string\n  stop(): Promise<void>\n}\n\nexport async function startHttpServer(\n  opts: RuntimeHttpServerOptions,\n): Promise<RuntimeHttpServerHandle> {\n  const startedAt = Date.now()\n  const authSource: AuthSource = opts.auth ?? { mode: \"none\" }\n  const readAuth = (): AuthOptions =>\n    typeof authSource === \"function\" ? authSource() : authSource\n\n  /**\n   * Loopback bypass — requests originating from 127.0.0.1 / ::1 with\n   * no `X-Forwarded-For` header skip the bearer check even when one is\n   * configured. Rationale:\n   *\n   *   1. The bearer is meant to gate the *public tunnel*, not the\n   *      loopback socket. Without this, calling `remote_enable` from a\n   *      local MCP client immediately 401s that same local client —\n   *      the user locks themselves out and the only recovery is a\n   *      gateway restart. Hit this in real use; not a theoretical edge.\n   *\n   *   2. Cloudflared (and any reasonable tunnel) sets X-Forwarded-For\n   *      when forwarding a public request to the loopback origin. So\n   *      \"loopback AND no XFF\" is a tight characterisation of \"this\n   *      request never left the machine.\"\n   *\n   *   3. Local FS access already trumps bearer (the user can read\n   *      runtime.json, kill -9 the daemon, etc.). Adding another check\n   *      here doesn't raise the bar for someone with shell on the box.\n   *\n   * If your threat model is \"untrusted users on the same loopback\n   * interface\" (unusual — usually a multi-tenant container scenario),\n   * pass `auth: { mode: \"bearer\", … }` at startup instead of relying\n   * on the controller's runtime flip; the auth getter will return the\n   * stricter of the two and the bypass still applies (intentional —\n   * the operator opted in to bearer with full knowledge of the trade).\n   */\n  function isLoopback(req: IncomingMessage): boolean {\n    const addr = req.socket.remoteAddress ?? \"\"\n    const isLocalAddr =\n      addr === \"127.0.0.1\" || addr === \"::1\" || addr === \"::ffff:127.0.0.1\"\n    if (!isLocalAddr) return false\n    // X-Forwarded-For present ⇒ a tunnel is in front of us; the\n    // request crossed the public internet to reach this socket.\n    if (req.headers[\"x-forwarded-for\"]) return false\n    return true\n  }\n\n  function authorize(req: IncomingMessage, res: ServerResponse): boolean {\n    const auth = readAuth()\n    if (auth.mode === \"none\") return true\n    if (isLoopback(req)) return true\n    const header = req.headers.authorization\n    const expected = `Bearer ${auth.token}`\n    if (header !== expected) {\n      res.writeHead(401, { \"content-type\": \"application/json\" })\n      res.end(JSON.stringify({ error: \"unauthorized\" }))\n      return false\n    }\n    return true\n  }\n\n  /**\n   * Per-boot auth gate for mutating /sessions/* routes and the WS\n   * upgrade for /sessions/:id/pty. Accepts EITHER:\n   *\n   *   1. `Authorization: Bearer <token>` matching the per-boot token\n   *      (the CLI path — reads runtime.json mode 0600).\n   *   2. A WS-upgrade query-string `?token=<token>` (browser\n   *      WebSocket can't set headers; some non-browser clients use\n   *      this too).\n   *   3. An `Origin: <url>` header matching `allowedOrigins` — the\n   *      browser path. Origin is browser-set, JS can't forge.\n   *\n   * UNLIKE `authorize()`, this does NOT have a loopback bypass: the\n   * threat we're defending against (browser drive-by spawning shells\n   * via fetch to 127.0.0.1) IS loopback. Browsers can't read\n   * runtime.json (mode 0600); a same-origin trusted page can rely on\n   * its Origin instead.\n   *\n   * When `opts.token` is unset (older host integrations), this is a\n   * no-op so existing call sites keep working.\n   */\n  function checkSessionsToken(req: IncomingMessage): \"ok\" | \"missing\" | \"bad\" {\n    if (!opts.token) return \"ok\"\n\n    // 1. Header bearer token.\n    const header = req.headers.authorization\n    const expected = `Bearer ${opts.token}`\n    if (header === expected) return \"ok\"\n\n    // 2. ?token=<token> in the URL (WS upgrade convenience).\n    const urlStr = req.url ?? \"\"\n    if (urlStr.includes(\"?\")) {\n      const qs = new URLSearchParams(urlStr.slice(urlStr.indexOf(\"?\") + 1))\n      const qsToken = qs.get(\"token\")\n      if (qsToken && qsToken === opts.token) return \"ok\"\n    }\n\n    // 3. Origin allowlist (browser path).\n    const origin = req.headers.origin\n    if (typeof origin === \"string\" && originAllowed(origin)) return \"ok\"\n\n    return header ? \"bad\" : \"missing\"\n  }\n\n  function originAllowed(origin: string): boolean {\n    // Defaults are normally in effect — `opts.allowedOrigins` extends\n    // them rather than replacing. Otherwise setting one production\n    // origin via config silently locks out `http://localhost:*`,\n    // breaking local dev. Users who genuinely want a curated list\n    // (shared host, paranoid local-only ports) set `strictOrigins:true`\n    // which drops the defaults entirely.\n    const list = opts.strictOrigins\n      ? (opts.allowedOrigins ?? [])\n      : [...DEFAULT_ALLOWED_ORIGINS, ...(opts.allowedOrigins ?? [])]\n    for (const pattern of list) {\n      if (pattern === origin) return true\n      // `http://localhost:*` style: match the host prefix, any port.\n      if (pattern.endsWith(\":*\")) {\n        const prefix = pattern.slice(0, -2) // drop \":*\"\n        if (origin === prefix || origin.startsWith(prefix + \":\")) return true\n      }\n    }\n    return false\n  }\n\n  function rejectUnauthorizedSession(\n    req: IncomingMessage,\n    res: ServerResponse,\n    kind: \"missing\" | \"bad\",\n  ): void {\n    const origin = req.headers.origin ?? null\n    const allowList = opts.strictOrigins\n      ? (opts.allowedOrigins ?? [])\n      : [...DEFAULT_ALLOWED_ORIGINS, ...(opts.allowedOrigins ?? [])]\n    res.writeHead(401, { \"content-type\": \"application/json\" })\n    const message =\n      kind === \"missing\"\n        ? origin\n          ? `Origin \"${origin}\" not in the daemon's allowlist, and no Bearer token sent. ` +\n            `Either add it (\\`agentproto config set daemon.allowedOrigins ${origin}\\` then restart the daemon), ` +\n            `or send Authorization: Bearer <token> read from <workspace>/.agentproto/runtime.json.`\n          : `Authorization: Bearer <token> required on mutating /sessions/* routes. ` +\n            `Read the token from <workspace>/.agentproto/runtime.json. ` +\n            `(Browser callers can use an Origin in the allowlist instead.)`\n        : `Invalid bearer token. The daemon regenerated its token on its last boot — ` +\n          `re-read <workspace>/.agentproto/runtime.json.`\n    res.end(\n      JSON.stringify({\n        error: \"sessions_unauthorized\",\n        message,\n        // Debug data so a UI / network-tab inspection points the user\n        // straight at the fix without needing the daemon's stderr.\n        rejectedOrigin: origin,\n        allowedOrigins: allowList,\n        // We never echo the token; only the absence-or-presence flag.\n        receivedAuthHeader: typeof req.headers.authorization === \"string\",\n      }),\n    )\n  }\n\n  /**\n   * Returns true when this `path` + `method` is a mutating /sessions/*\n   * route that should require the per-boot token. Kept narrow: GETs\n   * (list, get, SSE stream) stay open for read-only telemetry from\n   * existing tools that haven't learned about the token yet.\n   */\n  function isMutatingSessionsRoute(method: string, path: string): boolean {\n    if (!path.startsWith(\"/sessions\")) return false\n    if (method === \"POST\" || method === \"DELETE\" || method === \"PUT\" || method === \"PATCH\") {\n      return true\n    }\n    return false\n  }\n\n  /**\n   * Drive one MCP request over a fresh server+transport pair, per the\n   * SDK's stateless pattern. Sharing either across requests breaks after\n   * the first one because `Protocol.connect` rejects re-attachment.\n   * Shared by `/mcp` and the scoped `/mcp/orchestrator` endpoint.\n   */\n  async function serveMcp(\n    req: IncomingMessage,\n    res: ServerResponse,\n    server: McpServer,\n  ): Promise<void> {\n    const transport = new StreamableHTTPServerTransport({\n      sessionIdGenerator: undefined,\n    })\n    // `onerror` is an unofficial SDK hook — guard before assigning so\n    // a future SDK rename doesn't silently drop transport error logs.\n    const transportInternal = transport as unknown as Record<string, unknown>\n    if (\"onerror\" in (transport as object)) {\n      transportInternal[\"onerror\"] = (err: unknown) => {\n        console.error(\"[mcp transport.onerror]\", err)\n      }\n    }\n\n    res.on(\"close\", () => {\n      void transport.close()\n      void server.close()\n    })\n\n    try {\n      await server.connect(transport)\n      await transport.handleRequest(req, res)\n    } catch (err) {\n      console.error(\"[mcp] handleRequest threw:\", err)\n      if (!res.headersSent) {\n        res.writeHead(500, { \"content-type\": \"application/json\" })\n        res.end(\n          JSON.stringify({\n            error: \"mcp_transport_failed\",\n            message: err instanceof Error ? err.message : String(err),\n          }),\n        )\n      }\n    }\n  }\n\n  async function handleMcp(req: IncomingMessage, res: ServerResponse): Promise<void> {\n    if (!authorize(req, res)) return\n    const server = await opts.mcpServerFactory()\n    await serveMcp(req, res, server)\n  }\n\n  /**\n   * Scoped orchestrator sub-gateway (WP2). Mounted at\n   * `/mcp/orchestrator`. CRITICALLY this does NOT call `authorize()`:\n   * the loopback bypass that makes `/mcp` open to any local process is\n   * exactly what we must not inherit here — a child gets the\n   * orchestration subset ONLY by presenting a valid scope-token. The\n   * token arrives via `?scope=<token>` (the injected URL form) or the\n   * `X-Orchestrator-Scope` header.\n   */\n  async function handleOrchestratorMcp(\n    req: IncomingMessage,\n    res: ServerResponse,\n  ): Promise<void> {\n    if (!opts.orchestratorMcpServerFactory || !opts.verifyOrchestratorScope) {\n      res.writeHead(501, { \"content-type\": \"application/json\" })\n      res.end(\n        JSON.stringify({\n          error: \"orchestrator_gateway_not_configured\",\n          message:\n            \"The daemon was started without the scoped orchestrator \" +\n            \"sub-gateway. Wire `orchestratorMcpServerFactory` + \" +\n            \"`verifyOrchestratorScope` in createGateway.\",\n        }),\n      )\n      return\n    }\n    const urlStr = req.url ?? \"\"\n    let token: string | null = null\n    if (urlStr.includes(\"?\")) {\n      token = new URLSearchParams(urlStr.slice(urlStr.indexOf(\"?\") + 1)).get(\n        \"scope\",\n      )\n    }\n    if (!token) {\n      const headerTok = req.headers[\"x-orchestrator-scope\"]\n      if (typeof headerTok === \"string\") token = headerTok\n    }\n    const scope = opts.verifyOrchestratorScope(token)\n    if (!scope) {\n      res.writeHead(401, { \"content-type\": \"application/json\" })\n      res.end(\n        JSON.stringify({\n          error: \"orchestrator_scope_required\",\n          message:\n            \"A valid scope-token is required on /mcp/orchestrator \" +\n            \"(pass `?scope=<token>` or the `X-Orchestrator-Scope` header). \" +\n            \"Unlike /mcp, this endpoint has no loopback bypass.\",\n        }),\n      )\n      return\n    }\n    const server = await opts.orchestratorMcpServerFactory(scope)\n    await serveMcp(req, res, server)\n  }\n\n  function handleHealth(_req: IncomingMessage, res: ServerResponse): void {\n    res.writeHead(200, { \"content-type\": \"application/json\" })\n    res.end(\n      JSON.stringify({\n        status: \"ok\",\n        workspace: opts.meta.workspace,\n        registered: opts.meta.registered,\n        uptimeMs: Date.now() - startedAt,\n      }),\n    )\n  }\n\n  function handleEvents(req: IncomingMessage, res: ServerResponse): void {\n    if (!authorize(req, res)) return\n    res.writeHead(200, {\n      \"content-type\": \"text/event-stream\",\n      \"cache-control\": \"no-cache, no-transform\",\n      connection: \"keep-alive\",\n    })\n    res.write(`: connected\\n\\n`)\n    const off = opts.events.onAny((ev: RuntimeEvent) => {\n      res.write(`data: ${JSON.stringify(ev)}\\n\\n`)\n    })\n    req.on(\"close\", off)\n  }\n\n  async function handleListConversations(\n    req: IncomingMessage,\n    res: ServerResponse,\n  ): Promise<void> {\n    if (!authorize(req, res)) return\n    const list = await opts.conversations.list()\n    res.writeHead(200, { \"content-type\": \"application/json\" })\n    res.end(JSON.stringify(list))\n  }\n\n  async function handleGetConversation(\n    req: IncomingMessage,\n    res: ServerResponse,\n    id: string,\n  ): Promise<void> {\n    if (!authorize(req, res)) return\n    try {\n      const data = await opts.conversations.read(id)\n      res.writeHead(200, { \"content-type\": \"application/json\" })\n      res.end(JSON.stringify(data))\n    } catch (err) {\n      res.writeHead(404, { \"content-type\": \"application/json\" })\n      res.end(\n        JSON.stringify({\n          error: \"not_found\",\n          message: err instanceof Error ? err.message : String(err),\n        }),\n      )\n    }\n  }\n\n  async function handleHeartbeatTick(\n    req: IncomingMessage,\n    res: ServerResponse,\n  ): Promise<void> {\n    if (!authorize(req, res)) return\n    await opts.heartbeat.fireNow()\n    res.writeHead(202, { \"content-type\": \"application/json\" })\n    res.end(JSON.stringify({ status: \"fired\" }))\n  }\n\n  /**\n   * POST /files/upload?cwd=<abs-dir>&name=<filename>\n   *\n   * Writes the raw request body bytes to\n   * `{cwd}/.agentproto-attachments/{safe-name}`, creating the\n   * subdirectory on demand, and returns `{path}` with the absolute\n   * path the agent CLI can read. Used by the host UI's terminal\n   * drag-drop: the browser can't read the dragged file's source path\n   * (security), so we copy the bytes to a known location and tell the\n   * UI to paste THAT path into the terminal — claude-code (and any\n   * CLI with a Read tool) picks it up natively.\n   *\n   * Gated by `checkSessionsToken` so a drive-by HTTP request can't\n   * write arbitrary files: only sessions-authorized callers (CLI or\n   * an allow-listed browser origin) can hit it.\n   *\n   * Hardening:\n   *   - `cwd` must be absolute and exist as a directory.\n   *   - `name` is basename-sanitized (no `/`, `..`, NULs).\n   *   - The resolved write target must stay within\n   *     `{cwd}/.agentproto-attachments/` (defense-in-depth in case the\n   *     name sanitizer ever drifts).\n   *   - Body capped at 32 MiB. Larger uploads error 413 instead of\n   *     filling the daemon's disk.\n   */\n  async function handleFileUpload(\n    req: IncomingMessage,\n    res: ServerResponse,\n    url: string,\n  ): Promise<void> {\n    const reply = (status: number, body: unknown): void => {\n      res.writeHead(status, { \"content-type\": \"application/json\" })\n      res.end(JSON.stringify(body))\n    }\n    const qs = new URLSearchParams(url.includes(\"?\") ? url.slice(url.indexOf(\"?\") + 1) : \"\")\n    const cwd = qs.get(\"cwd\")\n    const rawName = qs.get(\"name\")\n    if (!cwd || !rawName) {\n      reply(400, { error: \"missing_cwd_or_name\" })\n      return\n    }\n    if (!isAbsolute(cwd)) {\n      reply(400, { error: \"cwd_not_absolute\" })\n      return\n    }\n    // basename-style sanitize: strip path separators + parent refs +\n    // NUL bytes; collapse leading dots so the file is visible. The\n    // resolvePath check below catches anything this misses.\n    const safeName = rawName\n      .replace(/[\\x00/\\\\]/g, \"_\")\n      .replace(/\\.\\.+/g, \".\")\n      .replace(/^\\.+/, \"\")\n      .slice(0, 200)\n    if (safeName.length === 0) {\n      reply(400, { error: \"invalid_name\" })\n      return\n    }\n    try {\n      const st = await stat(cwd)\n      if (!st.isDirectory()) {\n        reply(400, { error: \"cwd_not_a_directory\" })\n        return\n      }\n    } catch {\n      reply(400, { error: \"cwd_not_found\" })\n      return\n    }\n    const dir = join(cwd, \".agentproto-attachments\")\n    const target = resolvePath(dir, safeName)\n    // Defense-in-depth: the sanitized name should never escape `dir`,\n    // but if the sanitizer ever drifts, this catches the escape.\n    if (!target.startsWith(resolvePath(dir) + (dir.endsWith(\"/\") ? \"\" : \"/\"))) {\n      reply(400, { error: \"path_traversal_blocked\" })\n      return\n    }\n    const MAX_BYTES = 32 * 1024 * 1024 // 32 MiB\n    const chunks: Buffer[] = []\n    let total = 0\n    let aborted = false\n    await new Promise<void>((resolveBody, rejectBody) => {\n      req.on(\"data\", chunk => {\n        if (aborted) return\n        const buf = chunk as Buffer\n        total += buf.length\n        if (total > MAX_BYTES) {\n          aborted = true\n          reply(413, { error: \"file_too_large\", maxBytes: MAX_BYTES })\n          rejectBody(new Error(\"too_large\"))\n          return\n        }\n        chunks.push(buf)\n      })\n      req.on(\"end\", () => {\n        if (!aborted) resolveBody()\n      })\n      req.on(\"error\", err => rejectBody(err))\n    }).catch(() => undefined)\n    if (aborted) return\n    try {\n      await mkdir(dir, { recursive: true })\n      await writeFile(target, Buffer.concat(chunks))\n      reply(200, { path: target, bytes: total })\n    } catch (err) {\n      reply(500, {\n        error: \"write_failed\",\n        message: err instanceof Error ? err.message : String(err),\n      })\n    }\n  }\n\n  // Permissive CORS for the loopback gateway. The Guilde web app\n  // (localhost:3041) probes /health from the browser; without these\n  // headers the browser blocks the response and the panel says\n  // \"not reachable\" even though curl works. Auth still gates the\n  // sensitive routes — this just lifts the cross-origin block.\n  //\n  // Private Network Access (Chrome 105+): when an HTTPS page like\n  // https://guilde.work fetches a loopback URL, Chrome sends a\n  // preflight with `Access-Control-Request-Private-Network: true`.\n  // Without `Access-Control-Allow-Private-Network: true` in the\n  // response, the browser blocks the actual GET. Mirror the flag\n  // when the request asked for it.\n  function applyCors(req: IncomingMessage, res: ServerResponse): void {\n    const origin = (req.headers.origin as string | undefined) ?? \"*\"\n    res.setHeader(\"Access-Control-Allow-Origin\", origin)\n    res.setHeader(\"Vary\", \"Origin\")\n    res.setHeader(\"Access-Control-Allow-Credentials\", \"true\")\n    res.setHeader(\n      \"Access-Control-Allow-Headers\",\n      req.headers[\"access-control-request-headers\"] ??\n        \"authorization,content-type,mcp-session-id\",\n    )\n    res.setHeader(\n      \"Access-Control-Allow-Methods\",\n      \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n    )\n    if (req.headers[\"access-control-request-private-network\"] === \"true\") {\n      res.setHeader(\"Access-Control-Allow-Private-Network\", \"true\")\n    }\n  }\n\n  const server: Server = createServer((req, res) => {\n    void (async () => {\n      try {\n        const url = req.url ?? \"/\"\n        const path = url.split(\"?\")[0] ?? \"/\"\n        // Diagnostic: emit forwarded requests (those carrying XFF) onto\n        // the events stream so /events tailers can see what cloudflared\n        // actually sends. Loopback-only traffic stays quiet to avoid\n        // flooding subscribers during normal local use.\n        if (req.headers[\"x-forwarded-for\"]) {\n          opts.events.emit({\n            type: \"remote-log\",\n            at: new Date().toISOString(),\n            line: `[http-in] ${req.method} ${url} host=${req.headers.host ?? \"?\"} xff=${String(req.headers[\"x-forwarded-for\"])}`,\n          })\n        }\n\n        applyCors(req, res)\n        if (req.method === \"OPTIONS\") {\n          res.writeHead(204)\n          res.end()\n          return\n        }\n\n        if (path === \"/health\" && req.method === \"GET\") {\n          handleHealth(req, res)\n          return\n        }\n        if (path === \"/events\" && req.method === \"GET\") {\n          handleEvents(req, res)\n          return\n        }\n        if (path === \"/mcp/orchestrator\") {\n          await handleOrchestratorMcp(req, res)\n          return\n        }\n        if (path === \"/mcp\") {\n          await handleMcp(req, res)\n          return\n        }\n        if (path === \"/conversations\" && req.method === \"GET\") {\n          await handleListConversations(req, res)\n          return\n        }\n        if (path.startsWith(\"/conversations/\") && req.method === \"GET\") {\n          const id = path.slice(\"/conversations/\".length)\n          await handleGetConversation(req, res, id)\n          return\n        }\n        if (path === \"/heartbeat/tick\" && req.method === \"POST\") {\n          await handleHeartbeatTick(req, res)\n          return\n        }\n\n        if (path === \"/files/upload\" && req.method === \"POST\") {\n          // Same auth gate as the mutating /sessions/* routes — drive-by\n          // HTTP shouldn't be able to write arbitrary files to disk.\n          const gate = checkSessionsToken(req)\n          if (gate !== \"ok\") {\n            rejectUnauthorizedSession(req, res, gate)\n            return\n          }\n          await handleFileUpload(req, res, url)\n          return\n        }\n\n        // Sessions routes — only registered when the gateway was\n        // built with a SessionsRegistry. /sessions, /sessions/:id,\n        // /sessions/:id/stream (SSE), POST /sessions/:id/kill,\n        // DELETE /sessions/:id (forget after exit).\n        if (opts.sessions && path.startsWith(\"/sessions\")) {\n          if (isMutatingSessionsRoute(req.method ?? \"GET\", path)) {\n            const gate = checkSessionsToken(req)\n            if (gate !== \"ok\") {\n              rejectUnauthorizedSession(req, res, gate)\n              return\n            }\n          }\n          const handled = await handleSessions(\n            req,\n            res,\n            path,\n            opts.sessions,\n            opts.resolveAgentAdapter,\n            opts.ptyEnabled === true,\n            opts.resolveBrowserAdapter,\n            opts.listBrowserAdapters,\n            opts.sessionEvents,\n            opts.eventRing,\n            opts.buildOrchestratorMcp,\n            opts.daemonMcpUrl,\n          )\n          if (handled) return\n        }\n\n        if (path === \"/workspaces\" && req.method === \"GET\") {\n          // Surface ~/.agentproto/workspaces.json for UIs that\n          // want a workspace dropdown (spawn dialog, MCP discovery\n          // grouping, etc.). Read-only; mutate via the CLI's\n          // `agentproto workspace add/remove/use` verbs.\n          try {\n            const config = await loadWorkspacesConfig()\n            res.writeHead(200, { \"content-type\": \"application/json\" })\n            res.end(JSON.stringify(config))\n          } catch (err) {\n            res.writeHead(500, { \"content-type\": \"application/json\" })\n            res.end(\n              JSON.stringify({\n                error: \"workspaces_load_failed\",\n                message: err instanceof Error ? err.message : String(err),\n              })\n            )\n          }\n          return\n        }\n\n        if (path === \"/mcps/imports\" && req.method === \"GET\") {\n          const config = await loadImportedMcps()\n          res.writeHead(200, { \"content-type\": \"application/json\" })\n          res.end(JSON.stringify(config))\n          return\n        }\n        if (path === \"/mcps/imports\" && req.method === \"POST\") {\n          const body = (await readJsonBody(req)) as {\n            sourceMcpId?: string\n            alias?: string\n          } | null\n          if (!body || typeof body.sourceMcpId !== \"string\") {\n            res.writeHead(400, { \"content-type\": \"application/json\" })\n            res.end(JSON.stringify({ error: \"missing_sourceMcpId\" }))\n            return\n          }\n          const discovered = await discoverMcps()\n          const snapshot = discovered.find(d => d.id === body.sourceMcpId)\n          if (!snapshot) {\n            res.writeHead(404, { \"content-type\": \"application/json\" })\n            res.end(\n              JSON.stringify({\n                error: \"discovered_mcp_not_found\",\n                sourceMcpId: body.sourceMcpId,\n              })\n            )\n            return\n          }\n          const cfg = await loadImportedMcps()\n          const next = addImport(cfg, {\n            snapshot,\n            ...(body.alias ? { alias: body.alias } : {}),\n          })\n          await saveImportedMcps(next)\n          res.writeHead(201, { \"content-type\": \"application/json\" })\n          res.end(JSON.stringify(next.imports.find(e => e.id === snapshot.id)))\n          return\n        }\n        const importMatch = path.match(/^\\/mcps\\/imports\\/(.+)$/)\n        if (importMatch && req.method === \"DELETE\") {\n          // The id is URL-encoded since it contains colons + slashes\n          // (e.g. claude-code:project:/path:name).\n          const id = decodeURIComponent(importMatch[1] ?? \"\")\n          const cfg = await loadImportedMcps()\n          if (!cfg.imports.some(e => e.id === id)) {\n            res.writeHead(404, { \"content-type\": \"application/json\" })\n            res.end(JSON.stringify({ error: \"import_not_found\", id }))\n            return\n          }\n          await saveImportedMcps(removeImport(cfg, id))\n          res.writeHead(200, { \"content-type\": \"application/json\" })\n          res.end(JSON.stringify({ ok: true, id }))\n          return\n        }\n\n        if (path === \"/mcps/discovered\" && req.method === \"GET\") {\n          // No host wiring needed — the scanner reads\n          // ~/.claude.json + ~/.cursor/mcp.json + goose config\n          // directly. Always available; cheap (~5ms typical).\n          try {\n            const mcps = await discoverMcps()\n            res.writeHead(200, { \"content-type\": \"application/json\" })\n            res.end(JSON.stringify({ mcps }))\n          } catch (err) {\n            res.writeHead(500, { \"content-type\": \"application/json\" })\n            res.end(\n              JSON.stringify({\n                error: \"discovery_failed\",\n                message: err instanceof Error ? err.message : String(err),\n              })\n            )\n          }\n          return\n        }\n\n        // Browser-friendly proxy surface — same operations the MCP\n        // tools expose (mcp_imported_status / list_tools / call) but\n        // over plain HTTP so the /providers/mcp page can render them\n        // without embedding an MCP client.\n        if (path === \"/mcps/proxy/status\" && req.method === \"GET\") {\n          if (!opts.mcpProxy) {\n            res.writeHead(501, { \"content-type\": \"application/json\" })\n            res.end(JSON.stringify({ error: \"mcp_proxy_not_configured\" }))\n            return\n          }\n          try {\n            const imports = await opts.mcpProxy.listAliases()\n            res.writeHead(200, { \"content-type\": \"application/json\" })\n            res.end(JSON.stringify({ imports }))\n          } catch (err) {\n            res.writeHead(500, { \"content-type\": \"application/json\" })\n            res.end(\n              JSON.stringify({\n                error: \"proxy_status_failed\",\n                message: err instanceof Error ? err.message : String(err),\n              })\n            )\n          }\n          return\n        }\n        const proxyToolsMatch = path.match(/^\\/mcps\\/proxy\\/tools\\/(.+)$/)\n        if (proxyToolsMatch && req.method === \"GET\") {\n          if (!opts.mcpProxy) {\n            res.writeHead(501, { \"content-type\": \"application/json\" })\n            res.end(JSON.stringify({ error: \"mcp_proxy_not_configured\" }))\n            return\n          }\n          const alias = decodeURIComponent(proxyToolsMatch[1] ?? \"\")\n          const out = await opts.mcpProxy.listTools(alias)\n          res.writeHead(out.ok ? 200 : 502, {\n            \"content-type\": \"application/json\",\n          })\n          res.end(JSON.stringify(out))\n          return\n        }\n        if (path === \"/mcps/proxy/call\" && req.method === \"POST\") {\n          if (!opts.mcpProxy) {\n            res.writeHead(501, { \"content-type\": \"application/json\" })\n            res.end(JSON.stringify({ error: \"mcp_proxy_not_configured\" }))\n            return\n          }\n          const body = (await readJsonBody(req)) as {\n            alias?: unknown\n            toolName?: unknown\n            args?: unknown\n          } | null\n          if (\n            !body ||\n            typeof body.alias !== \"string\" ||\n            typeof body.toolName !== \"string\"\n          ) {\n            res.writeHead(400, { \"content-type\": \"application/json\" })\n            res.end(\n              JSON.stringify({\n                error: \"invalid_body\",\n                message: \"expected { alias, toolName, args? }\",\n              })\n            )\n            return\n          }\n          const result = await opts.mcpProxy.callTool(\n            body.alias,\n            body.toolName,\n            body.args ?? {}\n          )\n          res.writeHead(result.ok ? 200 : 502, {\n            \"content-type\": \"application/json\",\n          })\n          res.end(JSON.stringify(result))\n          return\n        }\n\n        if (path === \"/adapters\" && req.method === \"GET\") {\n          if (!opts.listAgentAdapters) {\n            res.writeHead(501, { \"content-type\": \"application/json\" })\n            res.end(\n              JSON.stringify({\n                error: \"lister_not_configured\",\n                message:\n                  \"Daemon was started without `listAgentAdapters` — see \" +\n                  \"@agentproto/cli's `listInstalledAdapters` for the canonical impl.\",\n              })\n            )\n            return\n          }\n          try {\n            const adapters = await opts.listAgentAdapters()\n            res.writeHead(200, { \"content-type\": \"application/json\" })\n            res.end(JSON.stringify({ adapters }))\n          } catch (err) {\n            res.writeHead(500, { \"content-type\": \"application/json\" })\n            res.end(\n              JSON.stringify({\n                error: \"list_failed\",\n                message: err instanceof Error ? err.message : String(err),\n              })\n            )\n          }\n          return\n        }\n\n        // Tunnel routes — only registered when the gateway was built with\n        // a TunnelRegistry. /tunnels, /tunnels/:id.\n        if (opts.tunnels && path.startsWith(\"/tunnels\")) {\n          const handled = await handleTunnels(req, res, path, opts.tunnels)\n          if (handled) return\n        }\n\n        // Routine routes — only registered when the gateway was built with\n        // a RoutineRunner. /routines, /routines/:id, /routines/:id/cancel,\n        // /routines/:id/escalation/resolve. Mirrors the MCP `routine_*`\n        // tools (orchestration-tools.ts) — same RoutineRunner instance.\n        if (\n          opts.routineRunner &&\n          (path === \"/routines\" || path.startsWith(\"/routines/\"))\n        ) {\n          const handled = await handleRoutines(req, res, path, opts.routineRunner)\n          if (handled) return\n        }\n\n        // Workflow routes — only registered when the gateway was built with\n        // a WorkflowRunner. /workflows, /workflows/:id, /workflows/:id/cancel,\n        // /workflows/:id/escalation/resolve. Mirrors the MCP `workflow_*`\n        // tools (orchestration-tools.ts) — same WorkflowRunner instance.\n        if (\n          opts.workflowRunner &&\n          (path === \"/workflows\" || path.startsWith(\"/workflows/\"))\n        ) {\n          const handled = await handleWorkflows(req, res, path, opts.workflowRunner)\n          if (handled) return\n        }\n\n        // Policy routes — POST /policies (attach), GET /policies (list),\n        // POST /policies/:id/cancel, POST /policies/:id/ack, and the\n        // blocking long-poll `GET /policies/:id/wait` (resolves when the\n        // policy leaves watching/gating → done/blocked/awaiting-ack/\n        // cancelled, or timeoutMs elapses). Mirrors the MCP `policy_attach/\n        // status/cancel/ack/list` tools — same CompletionPolicySupervisor\n        // instance. Only mounted when a supervisor is wired.\n        if (\n          opts.supervisor &&\n          (path === \"/policies\" || path.startsWith(\"/policies/\"))\n        ) {\n          const handled = await handlePolicies(\n            req,\n            res,\n            path,\n            opts.supervisor,\n            opts.sessions,\n          )\n          if (handled) return\n        }\n\n        // Cron routes — only registered when the gateway was built with\n        // a CronScheduler. /cron, /cron/:id, /cron/:id/run.\n        if (opts.cronScheduler && path.startsWith(\"/cron\")) {\n          const handled = await handleCron(req, res, path, opts.cronScheduler)\n          if (handled) return\n        }\n\n        res.writeHead(404, { \"content-type\": \"application/json\" })\n        res.end(JSON.stringify({ error: \"not_found\", path }))\n      } catch (err) {\n        if (!res.headersSent) {\n          res.writeHead(500, { \"content-type\": \"application/json\" })\n          res.end(\n            JSON.stringify({\n              error: \"internal_error\",\n              message: err instanceof Error ? err.message : String(err),\n            }),\n          )\n        }\n      }\n    })()\n  })\n\n  // ── WebSocket upgrade: /sessions/:id/pty ──\n  // Single WSS bound to the HTTP server's `upgrade` event. Connections\n  // are accepted only when the SessionsRegistry is wired AND PTY\n  // support is advertised. Frames are JSON-encoded over text WS\n  // messages (binary mode is a future optimization — JSON keeps\n  // wireshark/devtools debuggable):\n  //   server → client: {kind:\"data\", b64:\"...\"}\n  //   server → client: {kind:\"exit\", exitCode:0, signal?:1}\n  //   client → server: {kind:\"input\", b64:\"...\"}  (or {kind:\"input\", text:\"...\"})\n  //   client → server: {kind:\"resize\", cols:80, rows:24}\n  //   client → server: {kind:\"ping\"}              (no-op keepalive)\n  const wss = new WebSocketServer({ noServer: true })\n  server.on(\"upgrade\", (req, socket, head) => {\n    const url = req.url ?? \"/\"\n    const path = url.split(\"?\")[0] ?? \"/\"\n    const ptyMatch = path.match(/^\\/sessions\\/([^/]+)\\/pty$/)\n    if (!ptyMatch) {\n      socket.destroy()\n      return\n    }\n    if (!opts.sessions || opts.ptyEnabled !== true) {\n      rejectUpgrade(socket, 501, \"pty_not_configured\")\n      return\n    }\n    // Per-boot token gate, no loopback bypass — see comment on\n    // checkSessionsToken for why.\n    const gate = checkSessionsToken(req)\n    if (gate !== \"ok\") {\n      rejectUpgrade(socket, 401, gate === \"missing\" ? \"missing_token\" : \"bad_token\")\n      return\n    }\n    const id = ptyMatch[1]\n    if (!id) {\n      rejectUpgrade(socket, 400, \"missing_id\")\n      return\n    }\n    // Resolve id-or-name BEFORE upgrading so a typo returns a clean\n    // 404 instead of a successful WS that immediately closes.\n    const desc = opts.sessions.findByIdOrName(id)\n    if (!desc) {\n      rejectUpgrade(socket, 404, \"session_not_found\")\n      return\n    }\n    if (desc.pty !== true) {\n      rejectUpgrade(socket, 400, \"session_not_pty\")\n      return\n    }\n    // A descriptor for an exited/killed/error session lives on as\n    // history — its PTY child is gone. Reject the upgrade with a\n    // clear reason so the CLI/web client can suggest `restart`\n    // instead of letting the user see a generic 1011 mid-attach.\n    if (\n      desc.status === \"exited\" ||\n      desc.status === \"killed\" ||\n      desc.status === \"error\"\n    ) {\n      rejectUpgrade(\n        socket,\n        410,\n        `session_${desc.status}`,\n        `Session ${desc.id}${desc.name ? ` (${desc.name})` : \"\"} has ${desc.status}. ` +\n          `Spawn a fresh one with: agentproto sessions restart ${desc.name ?? desc.id}`,\n      )\n      return\n    }\n    wss.handleUpgrade(req, socket, head, ws => {\n      handlePtyWebSocket(ws, req, desc.id, opts.sessions!)\n    })\n  })\n\n  const bind = opts.bind ?? \"127.0.0.1\"\n  await new Promise<void>((resolve, reject) => {\n    server.once(\"error\", reject)\n    server.listen(opts.port, bind, () => resolve())\n  })\n\n  return {\n    url: `http://${bind}:${opts.port}`,\n    async stop() {\n      // Per-request transports/servers are torn down on `res.close`,\n      // so we only need to stop the HTTP listener here. The WSS is\n      // bound `noServer:true` so closing the HTTP server also tears\n      // down its underlying TCP socket; live WS connections receive\n      // a close frame from the kernel.\n      wss.close()\n      await new Promise<void>((resolve) => server.close(() => resolve()))\n    },\n  }\n}\n\n/**\n * Reject an HTTP upgrade attempt with a structured plaintext body.\n * `ws.handleUpgrade` is meant to be the success path — if we can't\n * accept the upgrade we write a minimal HTTP response and destroy\n * the socket, matching ws's own internal error path.\n */\nfunction rejectUpgrade(\n  socket: Duplex,\n  status: number,\n  reason: string,\n  message?: string,\n): void {\n  const reasonText = `${status} ${reason}`\n  const body: { error: string; message?: string } = { error: reason }\n  if (message) body.message = message\n  try {\n    socket.write(\n      `HTTP/1.1 ${reasonText}\\r\\n` +\n        `Content-Type: application/json\\r\\n` +\n        `Connection: close\\r\\n\\r\\n` +\n        JSON.stringify(body) +\n        `\\n`,\n    )\n  } catch {\n    // socket already gone — fall through\n  }\n  socket.destroy()\n}\n\n/**\n * Per-connection WS handler for /sessions/:id/pty. Attaches as a\n * subscriber to the SessionsRegistry; bridges JSON frames in both\n * directions. Per-subscriber backpressure: if the WS's `bufferedAmount`\n * exceeds a threshold, the next chunk is dropped (slow client must\n * not stall the daemon's fan-out to other subscribers).\n */\nfunction handlePtyWebSocket(\n  ws: WebSocket,\n  req: IncomingMessage,\n  sessionId: string,\n  registry: SessionsRegistry,\n): void {\n  // Parse cols/rows from the query string for the initial dimension\n  // hint. Real clients will send a {kind:\"resize\"} immediately after\n  // connecting; this seeds the registry's min-size calculation so the\n  // first replay frames render at a sensible width if no resize comes.\n  const query = new URLSearchParams(\n    (req.url ?? \"\").includes(\"?\") ? (req.url ?? \"\").split(\"?\")[1] : \"\",\n  )\n  const cols = clampPositiveInt(query.get(\"cols\"), 80)\n  const rows = clampPositiveInt(query.get(\"rows\"), 24)\n\n  // Backpressure threshold — when the socket has more than 256 KiB\n  // queued, drop the next data frame for THIS subscriber rather than\n  // letting the registry block on send. Other subscribers stay live.\n  const BACKPRESSURE_BYTES = 256 * 1024\n\n  const handle = registry.attachPty(\n    sessionId,\n    { cols, rows },\n    chunk => {\n      if (ws.readyState !== ws.OPEN) return\n      if (ws.bufferedAmount > BACKPRESSURE_BYTES) return // drop\n      ws.send(\n        JSON.stringify({ kind: \"data\", b64: chunk.toString(\"base64\") }),\n      )\n    },\n    evt => {\n      if (ws.readyState !== ws.OPEN) return\n      ws.send(\n        JSON.stringify({\n          kind: \"exit\",\n          exitCode: evt.exitCode,\n          ...(evt.signal != null ? { signal: evt.signal } : {}),\n        }),\n      )\n      // Close ourselves once we've emitted exit — the session can be\n      // reattached for a buffer replay but this socket is done.\n      try {\n        ws.close(1000, \"session exited\")\n      } catch {\n        // ignore\n      }\n    },\n  )\n\n  if (!handle) {\n    // Race: the session may have vanished between the upgrade and\n    // attach. Close politely.\n    try {\n      ws.close(1011, \"session not attachable\")\n    } catch {\n      // ignore\n    }\n    return\n  }\n\n  ws.on(\"message\", (raw, isBinary) => {\n    if (isBinary) {\n      // Binary frames not supported yet — wire format is JSON-only.\n      return\n    }\n    let frame: unknown\n    try {\n      frame = JSON.parse(raw.toString(\"utf8\"))\n    } catch {\n      return // malformed\n    }\n    if (!frame || typeof frame !== \"object\") return\n    const f = frame as Record<string, unknown>\n    switch (f.kind) {\n      case \"input\": {\n        // Accept either {text} (UTF-8) or {b64} (arbitrary bytes,\n        // useful for clients sending raw key sequences).\n        if (typeof f.text === \"string\") {\n          handle.write(f.text)\n        } else if (typeof f.b64 === \"string\") {\n          try {\n            handle.write(Buffer.from(f.b64, \"base64\").toString(\"utf8\"))\n          } catch {\n            // ignore malformed base64\n          }\n        }\n        break\n      }\n      case \"resize\": {\n        const c =\n          typeof f.cols === \"number\" && f.cols > 0 ? Math.floor(f.cols) : null\n        const r =\n          typeof f.rows === \"number\" && f.rows > 0 ? Math.floor(f.rows) : null\n        if (c && r) handle.resize(c, r)\n        break\n      }\n      case \"ping\":\n        // Reply with pong so client keepalive logic works. Optional.\n        try {\n          ws.send(JSON.stringify({ kind: \"pong\" }))\n        } catch {\n          // ignore\n        }\n        break\n      // Unknown kinds silently dropped; reserved for forward compat.\n    }\n  })\n\n  ws.on(\"close\", () => {\n    handle.detach()\n  })\n  ws.on(\"error\", () => {\n    handle.detach()\n  })\n}\n\nfunction clampPositiveInt(raw: string | null, fallback: number): number {\n  if (!raw) return fallback\n  const n = Number.parseInt(raw, 10)\n  return Number.isFinite(n) && n > 0 ? n : fallback\n}\n\nfunction clampInt(\n  raw: string | null,\n  fallback: number,\n  min: number,\n  max: number,\n): number {\n  if (!raw) return fallback\n  const n = Number.parseInt(raw, 10)\n  if (!Number.isFinite(n)) return fallback\n  if (n < min) return min\n  if (n > max) return max\n  return n\n}\n\n/**\n * /sessions routes — split out of the main switch so the surface\n * stays scannable. Returns `true` when it handled the request, so\n * the dispatcher knows to skip the 404 path.\n *\n *   GET    /sessions              → list of SessionDescriptor[]\n *   GET    /sessions/:id          → one SessionDescriptor\n *   GET    /sessions/:id/stream   → SSE stream {line,stream} events\n *   GET    /sessions/:id/export   → ExportAgentSessionResult (transcript as markdown or JSON)\n *   GET    /sessions/:id/events   → raw structured events.jsonl records for a session.\n *                                    Query: since=<seq> (default 0), limit=<n> (default 500,\n *                                    max 2000). Returns {sessionId, events, nextSeq, complete};\n *                                    404 {error:\"no_transcript\"} when the file doesn't exist.\n *                                    Read-only GET, no auth gate (same policy as /export).\n *   GET    /sessions/:id/wait     → block until a lifecycle event fires (long-poll;\n *                                    requires sessionEvents + eventRing wired). Query:\n *                                    event=turn-end|awaiting-input|exited|any (default any),\n *                                    since=<cursor>, timeoutMs=<n> (default 25000, cap 55000).\n *   POST   /sessions/:id/kill     → SIGTERM, returns {ok}\n *   DELETE /sessions/:id          → forget (drop from registry; only\n *                                    valid for exited/killed/error)\n *   POST   /sessions/browser      → start a browser adapter and register\n *                                    as a tracked session; body:\n *                                    { adapter, port?, camofoxPort?, label?,\n *                                      location?, baseUrl?, binPath? }\n *                                    (requires `resolveBrowserAdapter` wired)\n */\n/** Parse the `orchestrator` body field on `POST /sessions/agent` — the\n *  same flexible `boolean | object` shape the MCP `agent_start` tool's\n *  `jsonTolerant` schema accepts, including a JSON-stringified form of\n *  either (some HTTP clients serialize nested fields as strings the\n *  same way the MCP-over-stdio clients that motivated `jsonTolerant`\n *  do). Malformed values are dropped (undefined) rather than 400'd —\n *  matches this route's existing lenient body-field parsing. */\nfunction parseOrchestratorField(\n  raw: unknown,\n): boolean | { tools?: string[]; maxDepth?: number; maxChildren?: number } | undefined {\n  const value = typeof raw === \"string\" ? tryParseJson(raw) : raw\n  if (typeof value === \"boolean\") return value\n  if (value && typeof value === \"object\" && !Array.isArray(value)) {\n    const obj = value as Record<string, unknown>\n    const tools = Array.isArray(obj.tools)\n      ? obj.tools.filter((t): t is string => typeof t === \"string\")\n      : undefined\n    const maxDepth = typeof obj.maxDepth === \"number\" ? obj.maxDepth : undefined\n    const maxChildren = typeof obj.maxChildren === \"number\" ? obj.maxChildren : undefined\n    return {\n      ...(tools ? { tools } : {}),\n      ...(maxDepth !== undefined ? { maxDepth } : {}),\n      ...(maxChildren !== undefined ? { maxChildren } : {}),\n    }\n  }\n  return undefined\n}\n\n/** Parse the `mcpServers` body field — the same `AcpMcpServer[]` shape\n *  the MCP tool accepts, tolerant of a JSON-stringified array (see\n *  `parseOrchestratorField`). Entries missing a valid `name`/`transport`\n *  are dropped rather than failing the whole array. */\nfunction parseMcpServersField(raw: unknown): AcpMcpServer[] | undefined {\n  const value = typeof raw === \"string\" ? tryParseJson(raw) : raw\n  if (!Array.isArray(value)) return undefined\n  const servers: AcpMcpServer[] = []\n  for (const item of value) {\n    if (!item || typeof item !== \"object\") continue\n    const o = item as Record<string, unknown>\n    if (typeof o.name !== \"string\") continue\n    if (o.transport !== \"stdio\" && o.transport !== \"http\" && o.transport !== \"sse\") continue\n    servers.push({\n      name: o.name,\n      transport: o.transport,\n      ...(typeof o.ref === \"string\" ? { ref: o.ref } : {}),\n    })\n  }\n  return servers\n}\n\nasync function handleSessions(\n  req: IncomingMessage,\n  res: ServerResponse,\n  path: string,\n  registry: SessionsRegistry,\n  resolveAgentAdapter?: AgentAdapterResolver,\n  ptyEnabled = false,\n  resolveBrowserAdapter?: BrowserAdapterResolver,\n  listBrowserAdapters?: BrowserAdapterLister,\n  sessionEvents?: SessionEventBus,\n  eventRing?: EventRing,\n  buildOrchestratorMcp?: BuildOrchestratorMcp,\n  daemonMcpUrl?: string,\n): Promise<boolean> {\n  const json = (status: number, body: unknown): void => {\n    res.writeHead(status, { \"content-type\": \"application/json\" })\n    res.end(JSON.stringify(body))\n  }\n\n  if (path === \"/sessions\" && req.method === \"GET\") {\n    json(200, { sessions: registry.list() })\n    return true\n  }\n\n  // Long-running agent session — spawn via the cli's adapter\n  // resolver, hold across multiple turns. Body shape:\n  //   {adapter: \"claude-code\"|\"hermes\"|...,\n  //    workspaceSlug, cwd, prompt?, label?, orchestrator?, mcpServers?}\n  // Delegates to the same `spawnAgentSession` the MCP `agent_start`\n  // tool uses (session-spawn.ts) — keeps this route from re-implementing\n  // (and re-drifting from) the orchestrator/mcpServers/hermes-default\n  // logic that lives there.\n  if (path === \"/sessions/agent\" && req.method === \"POST\") {\n    if (!resolveAgentAdapter) {\n      json(501, {\n        error: \"agent_resolver_not_configured\",\n        message:\n          \"POST /sessions/agent needs the host to inject `resolveAgentAdapter` \" +\n          \"(e.g. via @agentproto/cli's resolveAdapter shim).\",\n      })\n      return true\n    }\n    const body = await readJsonBody(req)\n    if (!body || typeof body !== \"object\") {\n      json(400, { error: \"invalid_body\" })\n      return true\n    }\n    const b = body as Record<string, unknown>\n    const adapter = typeof b.adapter === \"string\" ? b.adapter : \"\"\n    if (!adapter) {\n      json(400, { error: \"missing_adapter\" })\n      return true\n    }\n    const result = await spawnAgentSession(\n      { registry, resolveAgentAdapter, buildOrchestratorMcp, daemonMcpUrl },\n      {\n        adapter,\n        ...(typeof b.cwd === \"string\" && b.cwd.length > 0 ? { cwd: b.cwd } : {}),\n        ...(typeof b.workspaceSlug === \"string\" && b.workspaceSlug.length > 0\n          ? { workspaceSlug: b.workspaceSlug }\n          : {}),\n        ...(typeof b.resumeSessionId === \"string\" && b.resumeSessionId.length > 0\n          ? { resumeSessionId: b.resumeSessionId }\n          : {}),\n        ...(typeof b.mode === \"string\" && b.mode.length > 0 ? { mode: b.mode } : {}),\n        ...(typeof b.model === \"string\" && b.model.length > 0 ? { model: b.model } : {}),\n        ...(typeof b.effort === \"string\" && b.effort.length > 0 ? { effort: b.effort } : {}),\n        ...(typeof b.prompt === \"string\" ? { prompt: b.prompt } : {}),\n        ...(typeof b.label === \"string\" ? { label: b.label } : {}),\n        ...(b.orchestrator !== undefined\n          ? (() => {\n              const parsed = parseOrchestratorField(b.orchestrator)\n              return parsed !== undefined ? { orchestrator: parsed } : {}\n            })()\n          : {}),\n        ...(b.mcpServers !== undefined\n          ? (() => {\n              const parsed = parseMcpServersField(b.mcpServers)\n              return parsed !== undefined ? { mcpServers: parsed } : {}\n            })()\n          : {}),\n      },\n    )\n    if (!result.ok) {\n      const status =\n        result.code === \"adapter_not_found\" || result.code === \"no_cwd\"\n          ? 404\n          : result.code === \"orchestrator_not_enabled\"\n            ? 501\n            : result.code === \"orchestrator_max_depth_exceeded\" ||\n                result.code === \"orchestrator_child_quota_exceeded\"\n              ? 409\n              : 500\n      json(status, {\n        error: result.code,\n        message: result.message,\n        ...result.details,\n      })\n      return true\n    }\n    json(201, result.descriptor)\n    return true\n  }\n\n  // Browser service session — start the adapter and register as a tracked\n  // session. HTTP equivalent of the MCP `start_browser` tool.\n  // Body: { adapter: string, port?: number, camofoxPort?: number, label?: string,\n  //         location?: \"local\"|\"cloud\", baseUrl?: string, binPath?: string }\n  if (path === \"/sessions/browser\" && req.method === \"POST\") {\n    if (!resolveBrowserAdapter) {\n      json(501, {\n        error: \"browser_resolver_not_configured\",\n        message:\n          \"POST /sessions/browser needs the host to inject `resolveBrowserAdapter` \" +\n          \"(e.g. via `agentproto serve`).\",\n      })\n      return true\n    }\n    const body = await readJsonBody(req)\n    if (!body || typeof body !== \"object\") {\n      json(400, { error: \"invalid_body\" })\n      return true\n    }\n    const b = body as Record<string, unknown>\n    const adapterId = typeof b.adapter === \"string\" ? b.adapter : \"\"\n    if (!adapterId) {\n      json(400, { error: \"missing_adapter\" })\n      return true\n    }\n    const rawPort = b.port\n    if (rawPort !== undefined) {\n      const p = typeof rawPort === \"number\" ? rawPort : Number(rawPort)\n      if (!Number.isInteger(p) || p < 1 || p > 65535) {\n        json(400, {\n          error: \"invalid_port\",\n          message: `port must be an integer in range 1–65535 (got ${JSON.stringify(rawPort)})`,\n        })\n        return true\n      }\n    }\n    const rawCamofoxPort = b.camofoxPort\n    if (rawCamofoxPort !== undefined) {\n      const p = typeof rawCamofoxPort === \"number\" ? rawCamofoxPort : Number(rawCamofoxPort)\n      if (!Number.isInteger(p) || p < 1 || p > 65535) {\n        json(400, {\n          error: \"invalid_camofox_port\",\n          message: `camofoxPort must be an integer in range 1–65535 (got ${JSON.stringify(rawCamofoxPort)})`,\n        })\n        return true\n      }\n    }\n    const adapter = resolveBrowserAdapter(adapterId)\n    if (!adapter) {\n      const available = listBrowserAdapters\n        ? listBrowserAdapters()\n            .map(a => a.id)\n            .join(\", \")\n        : \"camofox, bureau\"\n      json(404, {\n        error: \"adapter_not_found\",\n        adapter: adapterId,\n        message: `Browser adapter \"${adapterId}\" not found. Available: ${available}.`,\n      })\n      return true\n    }\n    const rawLocation = b.location\n    if (rawLocation !== undefined && rawLocation !== \"local\" && rawLocation !== \"cloud\") {\n      json(400, {\n        error: \"invalid_location\",\n        message: `location must be \"local\" or \"cloud\" (got ${JSON.stringify(rawLocation)})`,\n      })\n      return true\n    }\n    const location = rawLocation as \"local\" | \"cloud\" | undefined\n    const baseUrl = typeof b.baseUrl === \"string\" ? b.baseUrl : undefined\n    const binPath = typeof b.binPath === \"string\" ? b.binPath : undefined\n    try {\n      const instance = await adapter.ensure({\n        port: typeof b.port === \"number\" ? b.port : undefined,\n        camofoxPort: typeof b.camofoxPort === \"number\" ? b.camofoxPort : undefined,\n        location,\n        baseUrl,\n        binPath,\n        initialWaitMs: 6_000,\n      })\n      const desc = registry.registerBrowser({\n        adapterId: instance.id,\n        port: instance.port,\n        baseUrl: instance.baseUrl,\n        location: location ?? adapter.location,\n        pid: instance.pid,\n        wasAlreadyRunning: instance.wasAlreadyRunning,\n        status: instance.healthy ? \"running\" : \"starting\",\n        stop: instance.stop.bind(instance),\n        label: typeof b.label === \"string\" ? b.label : undefined,\n      })\n      json(201, desc)\n    } catch (err) {\n      json(500, {\n        error: \"browser_start_failed\",\n        message: err instanceof Error ? err.message : String(err),\n      })\n    }\n    return true\n  }\n\n  // Long-running PTY session — spawn argv under node-pty. Bytes flow\n  // through the registry's byte ring buffer; attach via the WebSocket\n  // upgrade at /sessions/:id/pty. Body shape:\n  //   {argv: string[], cwd?, workspaceSlug?, cols, rows, env?, name?, label?}\n  if (path === \"/sessions/terminal\" && req.method === \"POST\") {\n    if (!ptyEnabled) {\n      json(501, {\n        error: \"pty_not_configured\",\n        message:\n          \"POST /sessions/terminal needs the host to inject `spawnPty` into createGateway \" +\n          \"(node-pty optional dep — install in @agentproto/cli).\",\n      })\n      return true\n    }\n    const body = await readJsonBody(req)\n    if (!body || typeof body !== \"object\") {\n      json(400, { error: \"invalid_body\" })\n      return true\n    }\n    const b = body as Record<string, unknown>\n    const argv = Array.isArray(b.argv)\n      ? (b.argv as unknown[]).filter((v): v is string => typeof v === \"string\")\n      : []\n    if (argv.length === 0) {\n      json(400, { error: \"missing_argv\" })\n      return true\n    }\n    const cols = typeof b.cols === \"number\" && b.cols > 0 ? Math.floor(b.cols) : 80\n    const rows = typeof b.rows === \"number\" && b.rows > 0 ? Math.floor(b.rows) : 24\n    // cwd resolution mirrors /sessions/agent exactly.\n    let cwd: string | null =\n      typeof b.cwd === \"string\" && b.cwd.length > 0 ? b.cwd : null\n    let workspaceSlug =\n      typeof b.workspaceSlug === \"string\" ? b.workspaceSlug : \"\"\n    if (!cwd) {\n      try {\n        const config = await loadWorkspacesConfig()\n        const ws = workspaceSlug\n          ? findWorkspace(config, workspaceSlug)\n          : getActiveWorkspace(config)\n        if (ws) {\n          cwd = ws.path\n          workspaceSlug = ws.slug\n        }\n      } catch {\n        // fall through to process.cwd()\n      }\n    }\n    if (!cwd) {\n      cwd = process.cwd()\n      console.warn(\n        `[/sessions/terminal] no cwd resolvable for argv=${argv.join(\" \")} ` +\n          `— falling back to daemon's cwd ${cwd}`\n      )\n    }\n    if (!workspaceSlug) workspaceSlug = \"default\"\n    try {\n      const desc = registry.spawnPty({\n        argv,\n        cwd,\n        workspaceSlug,\n        cols,\n        rows,\n        ...(b.env && typeof b.env === \"object\"\n          ? { env: b.env as Record<string, string> }\n          : {}),\n        ...(typeof b.name === \"string\" ? { name: b.name } : {}),\n        ...(typeof b.label === \"string\" ? { label: b.label } : {}),\n      })\n      json(201, desc)\n    } catch (err) {\n      const msg = err instanceof Error ? err.message : String(err)\n      const status = msg.includes(\"already in use\")\n        ? 409\n        : msg.includes(\"no PTY factory\")\n          ? 501\n          : 500\n      json(status, { error: \"pty_spawn_failed\", message: msg })\n    }\n    return true\n  }\n\n  // Send a follow-up turn to a live agent session.\n  // Body: { prompt: string | ContentBlock | ContentBlock[] }\n  //   - string                → auto-wrapped to a single text block by\n  //                             the registry (legacy / convenience).\n  //   - ContentBlock          → e.g. `{type:\"image\", source:{...}}`\n  //   - ContentBlock[]        → text + image mix for multimodal turns.\n  //                             Forwarded as-is to `agentSession.send`\n  //                             so the adapter (claude-agent-acp, …)\n  //                             negotiates its own content shape.\n  //\n  // Validation is intentionally loose — we accept anything object-\n  // shaped + non-empty arrays + non-empty strings. The adapter will\n  // reject ill-formed blocks with a clear error projected into the\n  // session's ring buffer; throwing here would just duplicate that.\n  //\n  // Query: ?wait=false → fire-and-forget (return 202 after sync\n  //   validation; output streams via /sessions/:id/stream). Default\n  //   wait=true keeps the call blocking until the turn drains, which\n  //   is what curl scripts + the MCP bridge expect.\n  const promptMatch = path.match(/^\\/sessions\\/([^/]+)\\/prompt$/)\n  if (promptMatch && req.method === \"POST\") {\n    const id = promptMatch[1]\n    if (!id) return false\n    const body = await readJsonBody(req)\n    const prompt = (body as { prompt?: unknown } | null)?.prompt\n    const validPrompt =\n      (typeof prompt === \"string\" && prompt.length > 0) ||\n      (Array.isArray(prompt) &&\n        prompt.length > 0 &&\n        prompt.every(b => b !== null && typeof b === \"object\")) ||\n      (prompt !== null && typeof prompt === \"object\" && !Array.isArray(prompt))\n    if (!validPrompt) {\n      json(400, {\n        error: \"missing_prompt\",\n        message:\n          \"Body `prompt` must be a non-empty string, a content block object, or an array of content blocks.\",\n      })\n      return true\n    }\n    const reqUrl = req.url ?? \"\"\n    const queryString = reqUrl.includes(\"?\")\n      ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1)\n      : \"\"\n    const wait = new URLSearchParams(queryString).get(\"wait\")\n    const fireAndForget = wait === \"false\" || wait === \"0\"\n    try {\n      if (fireAndForget) {\n        // Awaited: enqueuePrompt only resolves once the resume attempt\n        // (if any) + admission checks pass — a dead or busy session\n        // rejects here, before the 202 goes out, instead of us\n        // reporting `queued: true` for a prompt nothing will dispatch.\n        await registry.enqueuePrompt(id, prompt)\n        json(202, { ok: true, id, queued: true })\n      } else {\n        await registry.sendPrompt(id, prompt)\n        json(200, { ok: true, id })\n      }\n    } catch (err) {\n      if (err instanceof SessionNotAliveError) {\n        json(409, { error: \"session_not_alive\", status: err.status })\n        return true\n      }\n      const msg = err instanceof Error ? err.message : String(err)\n      // Differentiate \"not found\" / \"wrong kind\" / \"busy\" — they\n      // surface as readable thrown messages from the registry.\n      const status = msg.includes(\"no session\")\n        ? 404\n        : msg.includes(\"not an agent\")\n          ? 400\n          : msg.includes(\"mid-turn\")\n            ? 409\n            : 500\n      json(status, { error: \"send_prompt_failed\", message: msg })\n    }\n    return true\n  }\n\n  if (path === \"/sessions\" && req.method === \"POST\") {\n    const body = await readJsonBody(req)\n    if (!body || typeof body !== \"object\") {\n      json(400, { error: \"invalid_body\" })\n      return true\n    }\n    const b = body as Record<string, unknown>\n    const argv = Array.isArray(b.argv)\n      ? (b.argv as unknown[]).filter((v): v is string => typeof v === \"string\")\n      : []\n    if (argv.length === 0) {\n      json(400, { error: \"missing_argv\" })\n      return true\n    }\n    try {\n      const desc = registry.spawn({\n        kind:\n          b.kind === \"terminal\" || b.kind === \"agent-cli\" || b.kind === \"command\"\n            ? b.kind\n            : \"command\",\n        workspaceSlug:\n          typeof b.workspaceSlug === \"string\" ? b.workspaceSlug : \"default\",\n        cwd: typeof b.cwd === \"string\" ? b.cwd : process.cwd(),\n        argv,\n        env:\n          b.env && typeof b.env === \"object\"\n            ? (b.env as Record<string, string>)\n            : undefined,\n        label: typeof b.label === \"string\" ? b.label : undefined,\n      })\n      json(201, desc)\n    } catch (err) {\n      json(500, {\n        error: \"spawn_failed\",\n        message: err instanceof Error ? err.message : String(err),\n      })\n    }\n    return true\n  }\n\n  // Per-id routes. The `:id` slot also accepts a session's `name`\n  // when one was set at spawn time — `findByIdOrName` resolves both\n  // and the rest of the handler operates on the canonical id.\n  const idMatch = path.match(\n    /^\\/sessions\\/([^/]+)(\\/stream|\\/kill|\\/preview|\\/export|\\/events|\\/wait)?$/,\n  )\n  if (!idMatch) return false\n  const [, rawIdOrName, suffix] = idMatch\n  if (!rawIdOrName) return false\n  const resolvedDesc = registry.findByIdOrName(rawIdOrName)\n  const id = resolvedDesc?.id ?? rawIdOrName\n\n  if (suffix === \"/export\" && req.method === \"GET\") {\n    // Transcript export — reads the adapter's native persistence layer\n    // (claude-code JSONL / hermes SQLite) and returns a rendered\n    // transcript. Query params: format (markdown|json), adapter, cwd.\n    // Read-only GET, no auth gate (same policy as /preview).\n    const reqUrl = req.url ?? \"\"\n    const qs = new URLSearchParams(\n      reqUrl.includes(\"?\") ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1) : \"\",\n    )\n    const fmt = qs.get(\"format\") === \"json\" ? \"json\" as const : \"markdown\" as const\n    const adapterOverride = qs.get(\"adapter\") ?? undefined\n    const cwdOverride = qs.get(\"cwd\") ?? undefined\n    const sourceParam = qs.get(\"source\")\n    const source =\n      sourceParam === \"native\" || sourceParam === \"daemon\" ? sourceParam : undefined\n    const result = await exportAgentSession({\n      sessionId: rawIdOrName,\n      registry,\n      format: fmt,\n      ...(adapterOverride ? { adapter: adapterOverride } : {}),\n      ...(cwdOverride ? { cwd: cwdOverride } : {}),\n      ...(source ? { source } : {}),\n    })\n    if (result.content.startsWith(\"Error:\")) {\n      const isNotFound =\n        result.content.includes(\"not found in registry\") ||\n        result.content.includes(\"not found\") ||\n        result.content.includes(\"not found\")\n      json(isNotFound ? 404 : 422, {\n        error: \"export_failed\",\n        message: result.content,\n        sessionId: rawIdOrName,\n        adapter: result.adapter,\n      })\n    } else {\n      json(200, result)\n    }\n    return true\n  }\n\n  if (suffix === \"/events\" && req.method === \"GET\") {\n    // Raw structured events.jsonl records — the same on-disk capture\n    // /export's daemon-events strategy reads, exposed directly so a web\n    // panel can render rich components instead of the collapsed\n    // markdown/JSON transcript. Read-only GET, no auth gate (same\n    // policy as /export / /preview).\n    const reqUrl = req.url ?? \"\"\n    const qs = new URLSearchParams(\n      reqUrl.includes(\"?\") ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1) : \"\",\n    )\n    const sinceRaw = qs.get(\"since\")\n    if (sinceRaw !== null && !/^\\d+$/.test(sinceRaw)) {\n      json(400, {\n        error: \"invalid_since\",\n        message: \"since must be a non-negative integer\",\n      })\n      return true\n    }\n    const since = sinceRaw !== null ? Number.parseInt(sinceRaw, 10) : 0\n    const limit = clampInt(qs.get(\"limit\"), 500, 1, 2000)\n\n    // events.jsonl is always keyed by the agentproto session id (same\n    // resolution export's daemon-events strategy relies on) — `id` above\n    // already resolved to that via findByIdOrName, falling back to the\n    // raw path segment when the registry doesn't know it.\n    const filePath = sessionEventsPath(id)\n    let fileStream: ReturnType<typeof createReadStream>\n    try {\n      fileStream = createReadStream(filePath, { encoding: \"utf8\" })\n      await new Promise<void>((resolve, reject) => {\n        fileStream.once(\"error\", reject)\n        fileStream.once(\"open\", resolve)\n      })\n    } catch (err) {\n      const code = (err as NodeJS.ErrnoException).code\n      if (code === \"ENOENT\") {\n        json(404, { error: \"no_transcript\" })\n        return true\n      }\n      throw err\n    }\n\n    const events: Record<string, unknown>[] = []\n    let truncated = false\n    const rl = createInterface({ input: fileStream, crlfDelay: Infinity })\n    for await (const line of rl) {\n      const trimmed = line.trim()\n      if (!trimmed) continue\n      let rec: Record<string, unknown>\n      try {\n        rec = JSON.parse(trimmed) as Record<string, unknown>\n      } catch {\n        continue\n      }\n      if (typeof rec.seq !== \"number\" || rec.seq <= since) continue\n      if (events.length >= limit) {\n        truncated = true\n        continue\n      }\n      events.push(rec)\n    }\n\n    const nextSeq =\n      events.length > 0 ? (events[events.length - 1]?.seq as number) : since\n    json(200, {\n      sessionId: id,\n      events,\n      nextSeq,\n      complete: !truncated,\n    })\n    return true\n  }\n\n  if (suffix === \"/preview\" && req.method === \"GET\") {\n    // Read-only snapshot of the recent ring buffer — used by the\n    // dashboard's detail pane so the user sees what the session was\n    // doing without committing to an attach. Returns BOTH lines\n    // (for agent-cli/command sessions) and recent-bytes (for PTY).\n    // Caller picks whichever is populated.\n    if (!resolvedDesc) {\n      json(404, { error: \"session_not_found\", id: rawIdOrName })\n      return true\n    }\n    const reqUrl = req.url ?? \"\"\n    const qs = new URLSearchParams(\n      reqUrl.includes(\"?\") ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1) : \"\",\n    )\n    const lineCap = clampInt(qs.get(\"lines\"), 10, 1, 200)\n    const byteCap = clampInt(qs.get(\"bytes\"), 16 * 1024, 256, 64 * 1024)\n    // No registry method exists for \"give me the recent buffer\n    // snapshot\" — readTerminalOutput is the closest. For non-PTY\n    // sessions, attach with a no-op subscriber, read backfill,\n    // detach. Cheap; the backfill is synchronous on attach.\n    const lines: string[] = []\n    if (resolvedDesc.pty !== true) {\n      const unsub = registry.attach(id, line => {\n        lines.push(line)\n      })\n      if (unsub) unsub()\n    }\n    const bufBytes = registry.readTerminalOutput(id, byteCap)\n    json(200, {\n      id: resolvedDesc.id,\n      lines: lines.slice(-lineCap),\n      bytes: bufBytes ? bufBytes.toString(\"base64\") : null,\n    })\n    return true\n  }\n\n  if (suffix === \"/wait\" && req.method === \"GET\") {\n    // Blocking long-poll — same machinery as the MCP `session_monitor`\n    // tool (monitorSessionWait). Resolves when the session fires a\n    // matching lifecycle event, or when timeoutMs elapses. Read-only GET,\n    // no auth gate (same policy as /preview / /stream).\n    if (!sessionEvents || !eventRing) {\n      json(501, {\n        error: \"wait_not_configured\",\n        message:\n          \"GET /sessions/:id/wait needs the host to wire `sessionEvents` + `eventRing` \" +\n          \"into the HTTP server (the daemon does this in createGateway).\",\n      })\n      return true\n    }\n    const reqUrl = req.url ?? \"\"\n    const qs = new URLSearchParams(\n      reqUrl.includes(\"?\") ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1) : \"\",\n    )\n    // 404 when the session is unknown AND no `since` cursor was passed —\n    // a cursor implies \"replay events I might have missed\", so we still\n    // honour it for a now-dead session. Without a cursor, waiting on a\n    // missing session would block until timeout for nothing.\n    if (!resolvedDesc && qs.get(\"since\") === null) {\n      json(404, { error: \"session_not_found\", id: rawIdOrName })\n      return true\n    }\n    const rawEvent = qs.get(\"event\")\n    const event: SessionWaitEvent =\n      rawEvent === \"turn-end\" ||\n      rawEvent === \"awaiting-input\" ||\n      rawEvent === \"exited\" ||\n      rawEvent === \"any\"\n        ? (rawEvent as SessionWaitEvent)\n        : \"any\"\n    const rawSince = qs.get(\"since\")\n    const since =\n      rawSince !== null && /^\\d+$/.test(rawSince)\n        ? Number.parseInt(rawSince, 10)\n        : undefined\n    // Cap at 55s to stay under typical HTTP client/proxy timeouts; the\n    // CLI chains multiple calls when its total --timeout exceeds this.\n    const timeoutMs = clampInt(qs.get(\"timeoutMs\"), 25_000, 1_000, 55_000)\n    const result = await monitorSessionWait({\n      registry,\n      sessionEvents,\n      eventRing,\n      sessionIds: [id],\n      event,\n      timeoutMs,\n      ...(since !== undefined ? { since } : {}),\n    })\n    json(200, result)\n    return true\n  }\n\n  if (suffix === \"/stream\" && req.method === \"GET\") {\n    if (!resolvedDesc) {\n      json(404, { error: \"session_not_found\", id: rawIdOrName })\n      return true\n    }\n    res.writeHead(200, {\n      \"content-type\": \"text/event-stream\",\n      \"cache-control\": \"no-cache\",\n      connection: \"keep-alive\",\n    })\n    // Keep-alive ping every 25s — proxies / browsers eventually\n    // close idle SSE connections; the comment line keeps the pipe\n    // warm without confusing the EventSource parser (it ignores\n    // anything starting with `:`).\n    const ping = setInterval(() => {\n      try {\n        res.write(`: keep-alive\\n\\n`)\n      } catch {\n        clearInterval(ping)\n      }\n    }, 25_000)\n    const unsub = registry.attach(id, (line, stream) => {\n      try {\n        res.write(\n          `data: ${JSON.stringify({ line, stream })}\\n\\n`\n        )\n      } catch {\n        // Client gone — cleanup happens on `close`.\n      }\n    })\n    if (!unsub) {\n      clearInterval(ping)\n      res.end()\n      return true\n    }\n    req.once(\"close\", () => {\n      unsub()\n      clearInterval(ping)\n    })\n    return true\n  }\n\n  if (suffix === \"/kill\" && req.method === \"POST\") {\n    const ok = registry.kill(id)\n    json(ok ? 200 : 404, { ok, sessionId: id })\n    return true\n  }\n\n  if (!suffix && req.method === \"GET\") {\n    if (!resolvedDesc) {\n      json(404, { error: \"session_not_found\", id: rawIdOrName })\n      return true\n    }\n    json(200, resolvedDesc)\n    return true\n  }\n\n  if (!suffix && req.method === \"DELETE\") {\n    const ok = registry.forget(id)\n    json(ok ? 200 : 404, { ok, id })\n    return true\n  }\n\n  return false\n}\n\n/**\n * /tunnels routes — create, list, get, and stop public tunnels.\n * Returns `true` when it handled the request so the dispatcher\n * skips the 404 path.\n *\n *   GET    /tunnels              → { tunnels: TunnelDescriptor[] }\n *   POST   /tunnels              → TunnelDescriptor (creates a new tunnel)\n *   GET    /tunnels/:id          → TunnelDescriptor\n *   DELETE /tunnels/:id          → { ok, tunnelId }\n */\nasync function handleTunnels(\n  req: IncomingMessage,\n  res: ServerResponse,\n  path: string,\n  registry: TunnelRegistry,\n): Promise<boolean> {\n  const json = (status: number, body: unknown): void => {\n    res.writeHead(status, { \"content-type\": \"application/json\" })\n    res.end(JSON.stringify(body))\n  }\n\n  if (path === \"/tunnels\" && req.method === \"GET\") {\n    const urlStr = req.url ?? \"\"\n    const qs = urlStr.includes(\"?\")\n      ? new URLSearchParams(urlStr.slice(urlStr.indexOf(\"?\") + 1))\n      : new URLSearchParams()\n    const onlyActive = qs.get(\"onlyActive\") === \"true\"\n    let tunnels = registry.list()\n    if (onlyActive) {\n      tunnels = tunnels.filter(\n        t => t.status === \"starting\" || t.status === \"active\",\n      )\n    }\n    json(200, { tunnels })\n    return true\n  }\n\n  if (path === \"/tunnels\" && req.method === \"POST\") {\n    const body = await readJsonBody(req)\n    if (!body || typeof body !== \"object\") {\n      json(400, { error: \"invalid_body\" })\n      return true\n    }\n    const b = body as Record<string, unknown>\n    const targetPort =\n      typeof b.targetPort === \"number\" && b.targetPort > 0\n        ? Math.floor(b.targetPort)\n        : null\n    if (!targetPort) {\n      json(400, {\n        error: \"missing_targetPort\",\n        message: \"body must include `targetPort` (integer 1-65535)\",\n      })\n      return true\n    }\n    try {\n      const desc = await registry.create({\n        targetPort,\n        // Any provider slug (built-in, legacy alias, or third-party) — the\n        // registry resolves/validates it and surfaces an unknown slug as a\n        // create_failed error below.\n        ...(typeof b.provider === \"string\" ? { provider: b.provider } : {}),\n        ...(typeof b.name === \"string\" ? { name: b.name } : {}),\n        ...(typeof b.label === \"string\" ? { label: b.label } : {}),\n        ...(typeof b.targetHost === \"string\" ? { targetHost: b.targetHost } : {}),\n        ...(b.autostart === true ? { autostart: true } : {}),\n        ...(typeof b.hostname === \"string\" ? { hostname: b.hostname } : {}),\n        ...(typeof b.tunnelId === \"string\" ? { tunnelId: b.tunnelId } : {}),\n        ...(typeof b.credentialsFile === \"string\"\n          ? { credentialsFile: b.credentialsFile }\n          : {}),\n      })\n      json(201, desc)\n    } catch (err) {\n      json(500, {\n        error: \"create_failed\",\n        message: err instanceof Error ? err.message : String(err),\n      })\n    }\n    return true\n  }\n\n  const tunnelMatch = path.match(/^\\/tunnels\\/([^/]+)$/)\n  if (!tunnelMatch) return false\n  const rawIdOrName = decodeURIComponent(tunnelMatch[1] ?? \"\")\n\n  if (req.method === \"GET\") {\n    const desc = registry.findByIdOrName(rawIdOrName)\n    if (!desc) {\n      json(404, { error: \"tunnel_not_found\", id: rawIdOrName })\n      return true\n    }\n    json(200, desc)\n    return true\n  }\n\n  if (req.method === \"DELETE\") {\n    const ok = await registry.stop(rawIdOrName)\n    if (!ok) {\n      json(404, { error: \"tunnel_not_found\", id: rawIdOrName })\n      return true\n    }\n    json(200, { ok, tunnelId: rawIdOrName })\n    return true\n  }\n\n  return false\n}\n\n/**\n * /routines routes — start, list, poll, cancel, and resolve escalations\n * for background routine runs (a flat sequential list of steps with\n * per-step `waitFor` fan-in). Returns `true` when it handled the\n * request so the dispatcher skips the 404 path.\n *\n *   POST /routines                          → start a run (RoutineRun)\n *   GET  /routines                          → { runs: RoutineRun[] }\n *   GET  /routines/:id                      → RoutineRun\n *   POST /routines/:id/cancel               → { runId, status }\n *   POST /routines/:id/escalation/resolve   → { runId, ok }\n *\n * Thin adapters over the same RoutineRunner the MCP `routine_start/\n * status/cancel/escalation_resolve/list` tools call — no duplicated\n * orchestration logic between the two transports.\n */\nasync function handleRoutines(\n  req: IncomingMessage,\n  res: ServerResponse,\n  path: string,\n  routineRunner: RoutineRunner,\n): Promise<boolean> {\n  const json = (status: number, body: unknown): void => {\n    res.writeHead(status, { \"content-type\": \"application/json\" })\n    res.end(JSON.stringify(body))\n  }\n\n  if (path === \"/routines\" && req.method === \"GET\") {\n    json(200, { runs: routineRunner.list() })\n    return true\n  }\n\n  if (path === \"/routines\" && req.method === \"POST\") {\n    const body = await readJsonBody(req)\n    if (!body || typeof body !== \"object\") {\n      json(400, { error: \"invalid_body\" })\n      return true\n    }\n    const b = body as Record<string, unknown>\n    const routineId = typeof b.routineId === \"string\" ? b.routineId : \"\"\n    if (!routineId) {\n      json(400, { error: \"missing_routineId\" })\n      return true\n    }\n    if (!Array.isArray(b.steps) || b.steps.length === 0) {\n      json(400, {\n        error: \"missing_steps\",\n        message: \"body must include a non-empty `steps` array\",\n      })\n      return true\n    }\n    try {\n      const run = await routineRunner.start({\n        routineId,\n        steps: b.steps as RoutineStep[],\n        ...(typeof b.workspaceSlug === \"string\" ? { workspaceSlug: b.workspaceSlug } : {}),\n        ...(typeof b.cwd === \"string\" ? { cwd: b.cwd } : {}),\n        ...(typeof b.notifyUrl === \"string\" ? { notifyUrl: b.notifyUrl } : {}),\n      })\n      json(201, run)\n    } catch (err) {\n      json(400, {\n        error: \"start_failed\",\n        message: err instanceof Error ? err.message : String(err),\n      })\n    }\n    return true\n  }\n\n  // /routines/:id/cancel\n  const cancelMatch = path.match(/^\\/routines\\/([^/]+)\\/cancel$/)\n  if (cancelMatch && req.method === \"POST\") {\n    const runId = decodeURIComponent(cancelMatch[1] ?? \"\")\n    if (!routineRunner.status(runId)) {\n      json(404, { error: \"run_not_found\", runId })\n      return true\n    }\n    routineRunner.cancel(runId)\n    const run = routineRunner.status(runId)\n    json(200, { runId, status: run?.status ?? \"not_found\" })\n    return true\n  }\n\n  // /routines/:id/escalation/resolve\n  const resolveMatch = path.match(/^\\/routines\\/([^/]+)\\/escalation\\/resolve$/)\n  if (resolveMatch && req.method === \"POST\") {\n    const runId = decodeURIComponent(resolveMatch[1] ?? \"\")\n    if (!routineRunner.status(runId)) {\n      json(404, { error: \"run_not_found\", runId })\n      return true\n    }\n    const body = await readJsonBody(req)\n    const b = body && typeof body === \"object\" ? (body as Record<string, unknown>) : {}\n    const stepIndex = typeof b.stepIndex === \"number\" ? b.stepIndex : undefined\n    const response = typeof b.response === \"string\" ? b.response : undefined\n    if (stepIndex === undefined || response === undefined) {\n      json(400, {\n        error: \"invalid_body\",\n        message: \"body must include `stepIndex` (number) and `response` (string)\",\n      })\n      return true\n    }\n    routineRunner.resolve(runId, stepIndex, response)\n    json(200, { runId, ok: true })\n    return true\n  }\n\n  // /routines/:id\n  const idMatch = path.match(/^\\/routines\\/([^/]+)$/)\n  if (idMatch && req.method === \"GET\") {\n    const runId = decodeURIComponent(idMatch[1] ?? \"\")\n    const run = routineRunner.status(runId)\n    if (!run) {\n      json(404, { error: \"run_not_found\", runId })\n      return true\n    }\n    json(200, run)\n    return true\n  }\n\n  return false\n}\n\n/**\n * /workflows routes — start, list, poll, cancel, and resolve escalations\n * for background workflow runs (ordered stages of steps that run\n * concurrently within a stage, gated by a barrier). Returns `true` when\n * it handled the request so the dispatcher skips the 404 path.\n *\n *   POST /workflows                          → start a run (WorkflowRun)\n *   GET  /workflows                          → { runs: WorkflowRun[] }\n *   GET  /workflows/:id                      → WorkflowRun\n *   POST /workflows/:id/cancel               → { runId, status }\n *   POST /workflows/:id/escalation/resolve   → { runId, ok }\n *\n * Thin adapters over the same WorkflowRunner the MCP `workflow_start/\n * status/cancel/escalation_resolve/list` tools call — no duplicated\n * orchestration logic between the two transports.\n */\nasync function handleWorkflows(\n  req: IncomingMessage,\n  res: ServerResponse,\n  path: string,\n  workflowRunner: WorkflowRunner,\n): Promise<boolean> {\n  const json = (status: number, body: unknown): void => {\n    res.writeHead(status, { \"content-type\": \"application/json\" })\n    res.end(JSON.stringify(body))\n  }\n\n  if (path === \"/workflows\" && req.method === \"GET\") {\n    json(200, { runs: workflowRunner.list() })\n    return true\n  }\n\n  if (path === \"/workflows\" && req.method === \"POST\") {\n    const body = await readJsonBody(req)\n    if (!body || typeof body !== \"object\") {\n      json(400, { error: \"invalid_body\" })\n      return true\n    }\n    const b = body as Record<string, unknown>\n    const workflowId = typeof b.workflowId === \"string\" ? b.workflowId : \"\"\n    if (!workflowId) {\n      json(400, { error: \"missing_workflowId\" })\n      return true\n    }\n    if (!Array.isArray(b.stages) || b.stages.length === 0) {\n      json(400, {\n        error: \"missing_stages\",\n        message: \"body must include a non-empty `stages` array\",\n      })\n      return true\n    }\n    try {\n      const run = await workflowRunner.start({\n        workflowId,\n        stages: b.stages as WorkflowStage[],\n        ...(typeof b.workspaceSlug === \"string\" ? { workspaceSlug: b.workspaceSlug } : {}),\n        ...(typeof b.cwd === \"string\" ? { cwd: b.cwd } : {}),\n        ...(typeof b.notifyUrl === \"string\" ? { notifyUrl: b.notifyUrl } : {}),\n      })\n      json(201, run)\n    } catch (err) {\n      json(400, {\n        error: \"start_failed\",\n        message: err instanceof Error ? err.message : String(err),\n      })\n    }\n    return true\n  }\n\n  // /workflows/:id/cancel\n  const cancelMatch = path.match(/^\\/workflows\\/([^/]+)\\/cancel$/)\n  if (cancelMatch && req.method === \"POST\") {\n    const runId = decodeURIComponent(cancelMatch[1] ?? \"\")\n    if (!workflowRunner.status(runId)) {\n      json(404, { error: \"run_not_found\", runId })\n      return true\n    }\n    workflowRunner.cancel(runId)\n    const run = workflowRunner.status(runId)\n    json(200, { runId, status: run?.status ?? \"not_found\" })\n    return true\n  }\n\n  // /workflows/:id/escalation/resolve\n  const resolveMatch = path.match(/^\\/workflows\\/([^/]+)\\/escalation\\/resolve$/)\n  if (resolveMatch && req.method === \"POST\") {\n    const runId = decodeURIComponent(resolveMatch[1] ?? \"\")\n    if (!workflowRunner.status(runId)) {\n      json(404, { error: \"run_not_found\", runId })\n      return true\n    }\n    const body = await readJsonBody(req)\n    const b = body && typeof body === \"object\" ? (body as Record<string, unknown>) : {}\n    const stageIndex = typeof b.stageIndex === \"number\" ? b.stageIndex : undefined\n    const stepIndex = typeof b.stepIndex === \"number\" ? b.stepIndex : undefined\n    const response = typeof b.response === \"string\" ? b.response : undefined\n    if (stageIndex === undefined || stepIndex === undefined || response === undefined) {\n      json(400, {\n        error: \"invalid_body\",\n        message:\n          \"body must include `stageIndex` (number), `stepIndex` (number), and `response` (string)\",\n      })\n      return true\n    }\n    workflowRunner.resolve(runId, stageIndex, stepIndex, response)\n    json(200, { runId, ok: true })\n    return true\n  }\n\n  // /workflows/:id\n  const idMatch = path.match(/^\\/workflows\\/([^/]+)$/)\n  if (idMatch && req.method === \"GET\") {\n    const runId = decodeURIComponent(idMatch[1] ?? \"\")\n    const run = workflowRunner.status(runId)\n    if (!run) {\n      json(404, { error: \"run_not_found\", runId })\n      return true\n    }\n    json(200, run)\n    return true\n  }\n\n  return false\n}\n\n/**\n * /policies routes — attach, list, cancel, ack, and blocking-wait for\n * completion policies. Returns `true` when it handled the request so\n * the dispatcher skips the 404 path.\n *\n *   POST /policies              → attach a policy (PolicyRunState)\n *   GET  /policies              → { policies: PolicyRunState[] }\n *   POST /policies/:id/cancel   → { policyId, status }\n *   POST /policies/:id/ack      → { policyId, status, sha?, error? }\n *   GET  /policies/:id/wait     → block until the policy resolves, then\n *                                 return the full PolicyRunState. Same\n *                                 shape the MCP `policy_status` tool\n *                                 returns. `{timedOut:true}` when\n *                                 `timeoutMs` elapses with no resolution.\n *\n * Thin adapters over the same CompletionPolicySupervisor the MCP\n * `policy_attach/status/cancel/ack/list` tools call — no duplicated\n * policy-state-machine logic between the two transports. Only mounted\n * when a supervisor is wired (the dispatcher guards on `opts.supervisor`).\n */\nasync function handlePolicies(\n  req: IncomingMessage,\n  res: ServerResponse,\n  path: string,\n  supervisor: CompletionPolicySupervisor,\n  registry?: SessionsRegistry,\n): Promise<boolean> {\n  const json = (status: number, body: unknown): void => {\n    res.writeHead(status, { \"content-type\": \"application/json\" })\n    res.end(JSON.stringify(body))\n  }\n\n  if (path === \"/policies\" && req.method === \"GET\") {\n    json(200, { policies: supervisor.list() })\n    return true\n  }\n\n  if (path === \"/policies\" && req.method === \"POST\") {\n    const body = await readJsonBody(req)\n    if (!body || typeof body !== \"object\") {\n      json(400, { error: \"invalid_body\" })\n      return true\n    }\n    const b = body as Record<string, unknown>\n    const sessionId = typeof b.sessionId === \"string\" ? b.sessionId : undefined\n    const sessionIds = Array.isArray(b.sessionIds)\n      ? b.sessionIds.filter((s): s is string => typeof s === \"string\")\n      : undefined\n    if (!sessionId && !(sessionIds && sessionIds.length > 0)) {\n      json(400, {\n        error: \"missing_sessions\",\n        message: \"body must include `sessionId` or a non-empty `sessionIds`\",\n      })\n      return true\n    }\n    const then = b.then as \"emit\" | \"commit\"\n    if (then !== \"emit\" && then !== \"commit\") {\n      json(400, { error: \"invalid_then\", message: 'body.then must be \"emit\" or \"commit\"' })\n      return true\n    }\n    if (then === \"commit\" && !b.commit) {\n      json(400, {\n        error: \"missing_commit\",\n        message: 'then:\"commit\" requires a `commit` spec',\n      })\n      return true\n    }\n    try {\n      const state = supervisor.attach({\n        ...(sessionId ? { sessionId } : {}),\n        ...(sessionIds && sessionIds.length > 0 ? { sessionIds } : {}),\n        ...(b.gate ? { gate: b.gate as AttachPolicyInput[\"gate\"] } : {}),\n        then,\n        ...(b.commit ? { commit: b.commit as AttachPolicyInput[\"commit\"] } : {}),\n        ...(b.onFail ? { onFail: b.onFail as AttachPolicyInput[\"onFail\"] } : {}),\n        ...(b.next ? { next: b.next as AttachPolicyInput[\"next\"] } : {}),\n      })\n      json(201, state)\n    } catch (err) {\n      json(400, {\n        error: \"attach_failed\",\n        message: err instanceof Error ? err.message : String(err),\n      })\n    }\n    return true\n  }\n\n  // /policies/:id/cancel\n  const cancelMatch = path.match(/^\\/policies\\/([^/]+)\\/cancel$/)\n  if (cancelMatch && req.method === \"POST\") {\n    const policyId = decodeURIComponent(cancelMatch[1] ?? \"\")\n    if (!supervisor.getStatus(policyId)) {\n      json(404, { error: \"policy_not_found\", policyId })\n      return true\n    }\n    supervisor.cancel(policyId)\n    const state = supervisor.getStatus(policyId)\n    json(200, { policyId, status: state?.status ?? \"not_found\" })\n    return true\n  }\n\n  // /policies/:id/ack\n  const ackMatch = path.match(/^\\/policies\\/([^/]+)\\/ack$/)\n  if (ackMatch && req.method === \"POST\") {\n    const policyId = decodeURIComponent(ackMatch[1] ?? \"\")\n    const body = await readJsonBody(req)\n    const b = body && typeof body === \"object\" ? (body as Record<string, unknown>) : {}\n    const approve = typeof b.approve === \"boolean\" ? b.approve : undefined\n    if (approve === undefined) {\n      json(400, { error: \"missing_approve\", message: \"body must include boolean `approve`\" })\n      return true\n    }\n    const state = await supervisor.ack(policyId, approve)\n    if (!state) {\n      json(404, { error: \"policy_not_found\", policyId })\n      return true\n    }\n    json(200, {\n      policyId: state.policyId,\n      status: state.status,\n      ...(state.commitSha ? { sha: state.commitSha } : {}),\n      ...(state.error ? { error: state.error } : {}),\n    })\n    return true\n  }\n\n  // /policies/:id/wait — block until the named completion policy\n  // transitions out of watching/queued/gating/nudging (i.e. reaches\n  // done/blocked/awaiting-ack/cancelled), then return the full\n  // PolicyRunState. Query params: timeoutMs=<n> (default 25000, cap\n  // 55000 to stay under typical HTTP client/proxy timeouts; the CLI\n  // chains multiple calls for longer budgets). Read-only GET — no auth\n  // gate, same policy as the other /sessions read routes.\n  const waitMatch = path.match(/^\\/policies\\/([^/]+)\\/wait$/)\n  if (!waitMatch) return false\n  const policyId = decodeURIComponent(waitMatch[1] ?? \"\")\n  if (!policyId) return false\n  if (req.method !== \"GET\") {\n    json(405, { error: \"method_not_allowed\", message: \"GET only\" })\n    return true\n  }\n\n  // Fast 404 when the policy doesn't exist at all — no point blocking.\n  const current = supervisor.getStatus(policyId)\n  if (!current) {\n    json(404, { error: \"policy_not_found\", policyId })\n    return true\n  }\n\n  const reqUrl = req.url ?? \"\"\n  const qs = new URLSearchParams(\n    reqUrl.includes(\"?\") ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1) : \"\",\n  )\n  const timeoutMs = clampInt(qs.get(\"timeoutMs\"), 25_000, 1_000, 55_000)\n\n  const result = await monitorPolicyWait({\n    supervisor,\n    policyId,\n    timeoutMs,\n  })\n  // monitorPolicyWait returns `{timedOut:false, state}` on resolution, or\n  // `{timedOut:true}` on timeout. Forward the full PolicyRunState for parity\n  // with policy_status — including the `awaitingQuestions` enrichment the\n  // MCP policy_status tool applies (harness-parity): cross-reference the\n  // watched sessions' live awaitingQuestion so a REST caller can tell\n  // \"stuck on a question\" from \"still legitimately running\".\n  if (\"timedOut\" in result && result.timedOut) {\n    json(200, { timedOut: true, policyId })\n    return true\n  }\n  const state = result.state\n  if (registry) {\n    const awaitingQuestions = state.sessionIds\n      .map(id => ({ sessionId: id, desc: registry.get(id) }))\n      .filter((s): s is { sessionId: string; desc: NonNullable<ReturnType<typeof registry.get>> } => !!s.desc?.awaitingInput)\n      .map(s => ({ sessionId: s.sessionId, question: s.desc.awaitingQuestion }))\n    if (awaitingQuestions.length > 0) {\n      json(200, { ...state, awaitingQuestions })\n      return true\n    }\n  }\n  json(200, state)\n  return true\n}\n\n/**\n * /cron routes:\n *   POST   /cron          → create a new cron job\n *   GET    /cron          → list all cron jobs\n *   DELETE /cron/:id      → delete a cron job\n *   POST   /cron/:id/run  → manually fire a cron job\n */\nasync function handleCron(\n  req: IncomingMessage,\n  res: ServerResponse,\n  path: string,\n  scheduler: import(\"./cron-scheduler.js\").CronScheduler,\n): Promise<boolean> {\n  const json = (status: number, body: unknown): void => {\n    res.writeHead(status, { \"content-type\": \"application/json\" })\n    res.end(JSON.stringify(body))\n  }\n\n  if (path === \"/cron\" && req.method === \"GET\") {\n    json(200, { jobs: scheduler.list() })\n    return true\n  }\n\n  if (path === \"/cron\" && req.method === \"POST\") {\n    const body = await readJsonBody(req)\n    if (!body || typeof body !== \"object\") {\n      json(400, { error: \"invalid_body\" })\n      return true\n    }\n    const b = body as Record<string, unknown>\n    const schedule = typeof b.schedule === \"string\" ? b.schedule : \"\"\n    if (!schedule) {\n      json(400, { error: \"missing_schedule\" })\n      return true\n    }\n    const action = b.action\n    if (!action || typeof action !== \"object\") {\n      json(400, { error: \"missing_action\" })\n      return true\n    }\n    try {\n      const job = scheduler.create({\n        label: typeof b.label === \"string\" ? b.label : undefined,\n        schedule,\n        recurring: typeof b.recurring === \"boolean\" ? b.recurring : true,\n        action: action as import(\"./cron-scheduler.js\").CronAction,\n      })\n      json(201, job)\n    } catch (err) {\n      json(400, {\n        error: \"create_failed\",\n        message: err instanceof Error ? err.message : String(err),\n      })\n    }\n    return true\n  }\n\n  // /cron/:id/run — manual fire\n  const runMatch = path.match(/^\\/cron\\/([^/]+)\\/run$/)\n  if (runMatch && req.method === \"POST\") {\n    const jobId = decodeURIComponent(runMatch[1] ?? \"\")\n    try {\n      const result = await scheduler.run(jobId)\n      json(200, { jobId, result })\n    } catch (err) {\n      const msg = err instanceof Error ? err.message : String(err)\n      const status = msg.includes(\"not found\") ? 404 : 500\n      json(status, { error: \"run_failed\", message: msg })\n    }\n    return true\n  }\n\n  // /cron/:id\n  const idMatch = path.match(/^\\/cron\\/([^/]+)$/)\n  if (!idMatch) return false\n  const jobId = decodeURIComponent(idMatch[1] ?? \"\")\n\n  if (req.method === \"GET\") {\n    const job = scheduler.get(jobId)\n    if (!job) {\n      json(404, { error: \"job_not_found\", jobId })\n      return true\n    }\n    json(200, job)\n    return true\n  }\n\n  if (req.method === \"DELETE\") {\n    try {\n      scheduler.delete(jobId)\n      json(200, { ok: true, jobId })\n    } catch (err) {\n      const msg = err instanceof Error ? err.message : String(err)\n      json(404, { error: \"job_not_found\", message: msg })\n    }\n    return true\n  }\n\n  return false\n}\n\nasync function readJsonBody(req: IncomingMessage): Promise<unknown> {\n  const chunks: Buffer[] = []\n  for await (const chunk of req) {\n    chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk)\n  }\n  if (chunks.length === 0) return null\n  try {\n    return JSON.parse(Buffer.concat(chunks).toString(\"utf8\"))\n  } catch {\n    return null\n  }\n}\n","/**\n * mcp-proxy — connect the daemon as an MCP *client* to every server\n * the user imported via `~/.agentproto/imported-mcps.json`, and\n * surface their tools through dedicated MCP tools on the daemon's\n * own server. The chain looks like:\n *\n *   operator (cloud Guilde)  ──MCP──▶  agentproto-daemon (this proxy)\n *                                       │\n *                                       ├──stdio──▶ chrome-devtools-mcp\n *                                       └──http───▶ goose-bridge\n *\n * v1 design choice: instead of re-registering each upstream tool\n * under a namespaced name (which requires JSON-Schema↔Zod conversion\n * for every exotic shape — recursive refs, oneOf, etc.), the proxy\n * exposes two indirection tools:\n *   - `mcp_list_imported_tools(alias?)` lets the operator discover\n *     what's available\n *   - `mcp_call_imported(alias, toolName, args)` invokes a specific\n *     tool, forwarding the JSON args verbatim\n *\n * Trade-off: agents do a 2-step (list → call) instead of seeing the\n * imports directly in their tool palette. We keep tool inputs\n * unconstrained at the MCP layer; validation is the upstream\n * server's job. v2 can re-expose namespaced tools once we ship a\n * solid JSON-Schema → Zod converter.\n *\n * Lifecycle: clients are connected lazily on the first call that\n * touches them and held open until daemon shutdown. The registry\n * notices new/removed imports by stat'ing the imports file's mtime\n * before each call — cheap, avoids forcing the HTTP routes to push.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\"\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\"\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\"\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\"\nimport {\n  loadImportedMcps,\n  IMPORTED_MCPS_PATH,\n  type ImportedMcpEntry,\n} from \"./mcp-imports.js\"\nimport type { DiscoveredMcp } from \"./mcp-discovery.js\"\n\ninterface ProxyClient {\n  entry: ImportedMcpEntry\n  /** Live MCP client. Null while a connect is in-flight or after a\n   *  connection error — the next call retries. */\n  client: Client | null\n  /** Tools list cached after the first successful fetch. Cleared on\n   *  disconnect so stale tool names don't survive a reconnect. */\n  tools: ProxyToolDescriptor[] | null\n  /** Last connection error message, kept so listAliases can surface\n   *  diagnostics to the operator without re-throwing on every list. */\n  lastError: string | null\n}\n\nexport interface ProxyToolDescriptor {\n  name: string\n  description?: string\n  /** JSON Schema as published by the upstream server. Forwarded to\n   *  the operator verbatim — they read it to figure out args. */\n  inputSchema?: unknown\n}\n\nexport interface ProxyAliasSummary {\n  alias: string\n  importId: string\n  source: DiscoveredMcp[\"source\"]\n  type: DiscoveredMcp[\"type\"]\n  /** \"connected\" | \"error\" | \"pending\" — pending = never tried yet. */\n  status: \"connected\" | \"error\" | \"pending\"\n  toolCount: number\n  lastError?: string\n}\n\nexport interface CallResult {\n  ok: true\n  result: unknown\n}\nexport interface CallError {\n  ok: false\n  error: string\n}\nexport type ProxyCallOutcome = CallResult | CallError\n\nexport class McpProxyRegistry {\n  private clients = new Map<string, ProxyClient>()\n  private lastMtimeMs = 0\n  /** Sentinel so we know whether the file has *ever* been read.\n   *  Distinguishes \"file missing on first call\" (legit empty state)\n   *  from \"we've read it before and it's gone\" (treat as empty too,\n   *  but only after closing live clients). */\n  private hasReadOnce = false\n\n  /**\n   * Reload the imports file when its mtime has advanced. Avoids\n   * repeated parsing when nothing changed — most calls are no-ops.\n   * Disconnects clients whose import was removed; connects the new\n   * set lazily (the first call that touches them).\n   */\n  async ensureCurrent(): Promise<void> {\n    let mtimeMs = 0\n    try {\n      const st = await fs.stat(IMPORTED_MCPS_PATH())\n      mtimeMs = st.mtimeMs\n    } catch {\n      // ENOENT — empty imports state. If we'd previously loaded\n      // some, close them.\n      mtimeMs = 0\n    }\n    if (this.hasReadOnce && mtimeMs === this.lastMtimeMs) return\n\n    const config = await loadImportedMcps().catch(() => ({\n      version: 1 as const,\n      imports: [] as ImportedMcpEntry[],\n    }))\n    const wantedIds = new Set(config.imports.map(e => e.id))\n\n    // Drop clients for imports the user removed.\n    for (const [id, c] of this.clients.entries()) {\n      if (!wantedIds.has(id)) {\n        await safeClose(c.client)\n        this.clients.delete(id)\n      }\n    }\n    // Add placeholders for new imports — connect lazily.\n    for (const entry of config.imports) {\n      const existing = this.clients.get(entry.id)\n      if (existing) {\n        // Snapshot may have changed (user re-imported same id with\n        // different command). Detect by comparing serialised\n        // snapshots; on mismatch, force reconnect.\n        if (\n          JSON.stringify(existing.entry.snapshot) !==\n          JSON.stringify(entry.snapshot)\n        ) {\n          await safeClose(existing.client)\n          this.clients.set(entry.id, freshPlaceholder(entry))\n        } else {\n          existing.entry = entry\n        }\n      } else {\n        this.clients.set(entry.id, freshPlaceholder(entry))\n      }\n    }\n    this.lastMtimeMs = mtimeMs\n    this.hasReadOnce = true\n  }\n\n  /**\n   * Lazy connect: the first call to `connectIfNeeded(alias)`\n   * actually opens the transport + handshakes. Subsequent calls\n   * reuse the live client.\n   */\n  private async connectIfNeeded(alias: string): Promise<ProxyClient | null> {\n    await this.ensureCurrent()\n    const handle = this.findByAlias(alias)\n    if (!handle) return null\n    if (handle.client) return handle\n    try {\n      const client = await openClient(handle.entry)\n      handle.client = client\n      handle.lastError = null\n      // Eagerly fetch tools so listTools doesn't pay the round-trip\n      // on next call. Cheap (single tools/list request).\n      const t = await client.listTools()\n      handle.tools = t.tools.map(toDescriptor)\n      return handle\n    } catch (err) {\n      handle.client = null\n      handle.tools = null\n      handle.lastError = err instanceof Error ? err.message : String(err)\n      return handle\n    }\n  }\n\n  /** Find a client handle by alias *or* import id (defensive — agents\n   *  sometimes pass the id from `mcp_imported_list`). */\n  private findByAlias(aliasOrId: string): ProxyClient | undefined {\n    for (const c of this.clients.values()) {\n      if (c.entry.alias === aliasOrId) return c\n      if (c.entry.id === aliasOrId) return c\n    }\n    return undefined\n  }\n\n  async listAliases(): Promise<ProxyAliasSummary[]> {\n    await this.ensureCurrent()\n    return Array.from(this.clients.values()).map(c => ({\n      alias: c.entry.alias,\n      importId: c.entry.id,\n      source: c.entry.snapshot.source,\n      type: c.entry.snapshot.type,\n      status: c.client\n        ? \"connected\"\n        : c.lastError\n          ? \"error\"\n          : \"pending\",\n      toolCount: c.tools?.length ?? 0,\n      ...(c.lastError ? { lastError: c.lastError } : {}),\n    }))\n  }\n\n  async listTools(\n    alias: string\n  ): Promise<{ ok: true; tools: ProxyToolDescriptor[] } | { ok: false; error: string }> {\n    const handle = await this.connectIfNeeded(alias)\n    if (!handle) return { ok: false, error: `unknown alias \"${alias}\"` }\n    if (!handle.client || !handle.tools) {\n      return {\n        ok: false,\n        error: handle.lastError ?? \"client not connected\",\n      }\n    }\n    return { ok: true, tools: handle.tools }\n  }\n\n  async callTool(\n    alias: string,\n    toolName: string,\n    args: unknown\n  ): Promise<ProxyCallOutcome> {\n    const handle = await this.connectIfNeeded(alias)\n    if (!handle) return { ok: false, error: `unknown alias \"${alias}\"` }\n    if (!handle.client) {\n      return {\n        ok: false,\n        error: handle.lastError ?? \"client not connected\",\n      }\n    }\n    try {\n      const result = await handle.client.callTool({\n        name: toolName,\n        arguments:\n          args && typeof args === \"object\"\n            ? (args as Record<string, unknown>)\n            : {},\n      })\n      return { ok: true, result }\n    } catch (err) {\n      // Mark the client as dirty — the connection may have died\n      // mid-call (process crash, http server restart). The next call\n      // re-opens via connectIfNeeded.\n      const msg = err instanceof Error ? err.message : String(err)\n      if (/closed|disconnect|EPIPE|ECONNRESET/i.test(msg)) {\n        await safeClose(handle.client)\n        handle.client = null\n        handle.tools = null\n        handle.lastError = msg\n      }\n      return { ok: false, error: msg }\n    }\n  }\n\n  async closeAll(): Promise<void> {\n    await Promise.all(\n      Array.from(this.clients.values()).map(c => safeClose(c.client))\n    )\n    this.clients.clear()\n  }\n}\n\nfunction freshPlaceholder(entry: ImportedMcpEntry): ProxyClient {\n  return { entry, client: null, tools: null, lastError: null }\n}\n\nfunction toDescriptor(tool: {\n  name: string\n  description?: string\n  inputSchema?: unknown\n}): ProxyToolDescriptor {\n  return {\n    name: tool.name,\n    ...(tool.description ? { description: tool.description } : {}),\n    ...(tool.inputSchema ? { inputSchema: tool.inputSchema } : {}),\n  }\n}\n\n/**\n * Replace `${VAR}` and `${VAR:-default}` placeholders in env values\n * with the corresponding `process.env` entry (or default), the same\n * way claude-code / cursor expand mcp-server env. When the variable\n * is unset and no default is given, the placeholder is dropped — the\n * upstream then sees the env var as absent rather than as the\n * literal `${MISSING_VAR}`, which it usually treats as \"use default\n * config\" rather than \"explicit empty token\".\n */\nfunction expandEnvPlaceholders(\n  raw: Record<string, string>\n): Record<string, string> {\n  const out: Record<string, string> = {}\n  for (const [k, v] of Object.entries(raw)) {\n    const expanded = v.replace(\n      /\\$\\{([A-Z_][A-Z0-9_]*)(?::-([^}]*))?\\}/gi,\n      (_match, name: string, fallback: string | undefined) => {\n        const fromEnv = process.env[name]\n        if (fromEnv !== undefined) return fromEnv\n        if (fallback !== undefined) return fallback\n        return \"\"\n      }\n    )\n    // Drop the var entirely if it expanded to empty — keeps the\n    // upstream from receiving an empty-string token + treating it as\n    // a real (but invalid) credential.\n    if (expanded.length === 0) continue\n    out[k] = expanded\n  }\n  return out\n}\n\nasync function safeClose(client: Client | null): Promise<void> {\n  if (!client) return\n  try {\n    await client.close()\n  } catch {\n    // best-effort\n  }\n}\n\n/**\n * Open a transport for a discovered MCP. stdio spawns the command;\n * http/sse open over the network. Returns a connected `Client` on\n * success; throws with a useful message on failure.\n */\nasync function openClient(entry: ImportedMcpEntry): Promise<Client> {\n  const snap = entry.snapshot\n  const client = new Client(\n    { name: \"agentproto-daemon-proxy\", version: \"0.1.0\" },\n    { capabilities: {} }\n  )\n  if (snap.type === \"stdio\") {\n    if (!snap.command) {\n      throw new Error(\n        `import \"${entry.alias}\" is stdio but has no command field`\n      )\n    }\n    // claude-code / cursor / vscode all support `${VAR}` placeholders\n    // in the env map (and the more permissive `${VAR:-default}`\n    // form). Our scanner stores the snapshot verbatim — expand at\n    // spawn time so live env changes work without a re-import, and\n    // tokens like REPLICATE_API_TOKEN don't end up forwarded as the\n    // literal string `${REPLICATE_API_TOKEN}`.\n    const expandedEnv = expandEnvPlaceholders(snap.env ?? {})\n    const transport = new StdioClientTransport({\n      command: snap.command,\n      args: snap.args ?? [],\n      env: { ...process.env, ...expandedEnv } as Record<string, string>,\n      // Pipe stderr so we can include it in the error message instead of\n      // surfacing the opaque \"Connection closed\" MCP error code.\n      stderr: \"pipe\",\n    })\n    const stderrBuf: string[] = []\n    transport.stderr?.on(\"data\", (chunk: Buffer | string) => {\n      stderrBuf.push(typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\"))\n      if (stderrBuf.length > 40) stderrBuf.shift()\n    })\n    try {\n      await client.connect(transport)\n    } catch (err) {\n      const stderrText = stderrBuf.join(\"\").trim()\n      const msg = err instanceof Error ? err.message : String(err)\n      throw new Error(stderrText ? `${msg}\\nstderr: ${stderrText.slice(-600)}` : msg)\n    }\n    return client\n  }\n  if (snap.type === \"http\") {\n    if (!snap.url) throw new Error(`import \"${entry.alias}\" has no url`)\n    const transport = new StreamableHTTPClientTransport(new URL(snap.url), {\n      requestInit: {\n        headers: snap.headers ?? {},\n      },\n    })\n    await client.connect(transport)\n    return client\n  }\n  if (snap.type === \"sse\") {\n    if (!snap.url) throw new Error(`import \"${entry.alias}\" has no url`)\n    const transport = new SSEClientTransport(new URL(snap.url), {\n      requestInit: {\n        headers: snap.headers ?? {},\n      },\n    })\n    await client.connect(transport)\n    return client\n  }\n  throw new Error(\n    `import \"${entry.alias}\" has unsupported transport type \"${snap.type}\"`\n  )\n}\n","/**\n * In-process pub/sub bus for session lifecycle events. Separate from\n * RuntimeEvents (global daemon bus) — session events are scoped to\n * individual sessions and fire at turn-level granularity.\n *\n * Consumers: EventRing (session_events_poll cursor), WebhookNotifier\n * (fire-and-forget HTTP), RoutineRunner (state machine fan-in),\n * and session_monitor MCP tool (long-poll multiplexed).\n */\n\nimport { EventEmitter } from \"node:events\"\n\nexport type SessionEventType =\n  | \"session:turn-end\"\n  | \"session:awaiting-input\"\n  | \"session:exited\"\n  | \"session:command-done\"\n  | \"policy:passed\"\n  | \"policy:failed\"\n  | \"policy:commit-ready\"\n  | \"policy:committed\"\n  | \"cron:fired\"\n  | \"cron:succeeded\"\n  | \"cron:failed\"\n\n/**\n * Structured detail on why a session is awaiting input, when derivable.\n * `source: \"structured\"` — a driver-reported ACP-style prompt (e.g. a tool\n * permission request with real options). `source: \"heuristic\"` — a\n * best-effort guess from the tail of the transcript (trailing \"?\" plus\n * an optional enumerated option list) for drivers that don't report\n * structured prompts. Absent entirely when neither could be determined —\n * callers still have the plain `awaitingInput` boolean in that case.\n */\nexport interface SessionAwaitingQuestion {\n  text: string\n  options?: string[]\n  source: \"structured\" | \"heuristic\"\n}\n\nexport interface SessionTurnEndEvent {\n  type: \"session:turn-end\"\n  sessionId: string\n  awaitingInput: boolean\n  label?: string\n  ts: string\n  question?: SessionAwaitingQuestion\n  /**\n   * The adapter's stream `turn-end` reason, when the driver reports one\n   * (e.g. `\"completed\"`, `\"cancelled\"`, `\"max_turns\"`, or\n   * `\"watchdog-timeout\"` when the ACP client's turn-idle watchdog fired\n   * because the adapter went silent — see\n   * `@agentproto/acp/client`'s `AcpClientOptions.turnIdleTimeoutMs`).\n   * Absent for drivers that don't report a reason.\n   */\n  reason?: string\n}\n\nexport interface SessionAwaitingInputEvent {\n  type: \"session:awaiting-input\"\n  sessionId: string\n  label?: string\n  ts: string\n  question?: SessionAwaitingQuestion\n}\n\nexport interface SessionExitedEvent {\n  type: \"session:exited\"\n  sessionId: string\n  exitCode?: number\n  status: \"exited\" | \"killed\" | \"error\"\n  label?: string\n  ts: string\n}\n\n/** Emitted when command_execute finishes. commandId matches the id\n *  returned by the command_execute MCP tool. */\nexport interface SessionCommandDoneEvent {\n  type: \"session:command-done\"\n  sessionId: string\n  commandId: string\n  exitCode: number\n  ts: string\n}\n\n/** Emitted by the supervisor when a completion policy's gate passes. */\nexport interface PolicyPassedEvent {\n  type: \"policy:passed\"\n  policyId: string\n  sessionId: string\n  ts: string\n}\n\n/** Emitted by the supervisor when a completion policy's gate fails. */\nexport interface PolicyFailedEvent {\n  type: \"policy:failed\"\n  policyId: string\n  sessionId: string\n  exitCode?: number\n  ts: string\n}\n\n/**\n * Emitted by the supervisor (WP5) when a `then:\"commit\"` policy's gate passes\n * but `requireHumanAck` is set: the commit is staged-and-ready but NOT yet\n * executed. Carries the exact paths + message that `policy_ack(approve:true)`\n * will commit. The policy sits in `awaiting-ack` until acked.\n */\nexport interface PolicyCommitReadyEvent {\n  type: \"policy:commit-ready\"\n  policyId: string\n  sessionId: string\n  paths: string[]\n  message: string\n  ts: string\n}\n\n/** Emitted by the supervisor (WP5) when a `then:\"commit\"` policy has actually\n *  committed — either directly (requireHumanAck:false) or after an approving\n *  `policy_ack`. Carries the resulting commit sha. */\nexport interface PolicyCommittedEvent {\n  type: \"policy:committed\"\n  policyId: string\n  sessionId: string\n  sha: string\n  paths: string[]\n  message: string\n  ts: string\n}\n\n/** Emitted by CronScheduler when a job fires (before the action runs). */\nexport interface CronFiredEvent {\n  type: \"cron:fired\"\n  jobId: string\n  label?: string\n  ts: string\n}\n\n/** Emitted by CronScheduler when a job action completes successfully. */\nexport interface CronSucceededEvent {\n  type: \"cron:succeeded\"\n  jobId: string\n  label?: string\n  summary: string\n  ts: string\n}\n\n/** Emitted by CronScheduler when a job action fails. */\nexport interface CronFailedEvent {\n  type: \"cron:failed\"\n  jobId: string\n  label?: string\n  error: string\n  ts: string\n}\n\nexport type SessionEvent =\n  | SessionTurnEndEvent\n  | SessionAwaitingInputEvent\n  | SessionExitedEvent\n  | SessionCommandDoneEvent\n  | PolicyPassedEvent\n  | PolicyFailedEvent\n  | PolicyCommitReadyEvent\n  | PolicyCommittedEvent\n  | CronFiredEvent\n  | CronSucceededEvent\n  | CronFailedEvent\n\nexport interface SessionEventBus {\n  emit(ev: SessionEvent): void\n  /** Subscribe to a specific event type. Returns an unsubscribe fn. */\n  on<E extends SessionEventType>(\n    type: E,\n    handler: (ev: Extract<SessionEvent, { type: E }>) => void,\n  ): () => void\n  /** Subscribe to all event types. Returns an unsubscribe fn. */\n  onAny(handler: (ev: SessionEvent) => void): () => void\n}\n\nexport function createSessionEventBus(): SessionEventBus {\n  const ee = new EventEmitter()\n  ee.setMaxListeners(100)\n\n  return {\n    emit(ev) {\n      ee.emit(\"event\", ev)\n    },\n    on(type, handler) {\n      const wrapped = (ev: SessionEvent) => {\n        if (ev.type === type) handler(ev as Extract<SessionEvent, { type: typeof type }>)\n      }\n      ee.on(\"event\", wrapped)\n      return () => ee.off(\"event\", wrapped)\n    },\n    onAny(handler) {\n      ee.on(\"event\", handler)\n      return () => ee.off(\"event\", handler)\n    },\n  }\n}\n","/**\n * Cursor-based ring buffer for session events. Bridges the in-process\n * SessionEventBus (push) to the session_events_poll MCP tool (pull).\n *\n * Capacity default: 1 000 events. Oldest entry dropped on overflow —\n * callers that lag beyond the cap see a gap in their cursor but never\n * a block. `since()` returns `nextCursor = totalEmitted` so a fresh\n * call with that value always starts just past the current tail.\n */\n\nimport type { SessionEvent, SessionEventBus, SessionEventType } from \"./session-event-bus.js\"\n\nconst DEFAULT_CAP = 1_000\n\nexport interface EventRingSnapshot {\n  events: SessionEvent[]\n  nextCursor: number\n}\n\nexport interface EventRingQueryOpts {\n  sessionIds?: string[]\n  types?: SessionEventType[]\n  /** Default 50. */\n  limit?: number\n}\n\nexport interface EventRing {\n  /**\n   * Return events whose ring-index >= `cursor`. Pass 0 to get all\n   * retained events; pass the previously returned `nextCursor` for an\n   * incremental read. The returned `nextCursor` is always equal to\n   * `totalEmitted` — use it as the next `cursor` argument.\n   *\n   * Negative or below-base cursors are clamped to the oldest retained\n   * event (no error, just a potential replay of a partial window).\n   */\n  since(cursor: number, opts?: EventRingQueryOpts): EventRingSnapshot\n  /** Wire the ring to a SessionEventBus. Returns an unsubscribe fn. */\n  wire(bus: SessionEventBus): () => void\n}\n\nexport function createEventRing(cap = DEFAULT_CAP): EventRing {\n  /** Circular store — oldest entry at index 0, newest at the tail. */\n  const ring: SessionEvent[] = []\n  /** Total events ever pushed. ring[0] has absolute index base = totalEmitted - ring.length. */\n  let totalEmitted = 0\n\n  return {\n    since(cursor, opts = {}) {\n      const limit = opts.limit ?? 50\n      // Absolute index of ring[0]\n      const base = totalEmitted - ring.length\n      // Clamp cursor into the valid window\n      const clampedStart = Math.max(0, cursor - base)\n      let slice = ring.slice(clampedStart)\n\n      if (opts.sessionIds && opts.sessionIds.length > 0) {\n        const ids = new Set(opts.sessionIds)\n        slice = slice.filter(e => {\n          const sid = \"sessionId\" in e ? ((e as unknown) as Record<string, unknown>)[\"sessionId\"] : undefined\n          return typeof sid === \"string\" && ids.has(sid)\n        })\n      }\n      if (opts.types && opts.types.length > 0) {\n        const types = new Set<string>(opts.types)\n        slice = slice.filter(e => types.has(e.type))\n      }\n\n      return {\n        events: slice.slice(0, limit),\n        nextCursor: totalEmitted,\n      }\n    },\n\n    wire(bus) {\n      return bus.onAny(ev => {\n        ring.push(ev)\n        totalEmitted++\n        if (ring.length > cap) ring.shift()\n      })\n    },\n  }\n}\n","/**\n * Fire-and-forget webhook notifier for session lifecycle events.\n *\n * Each session can register its own `notifyUrl` (via `agent_start`).\n * A global URL can be set via `AGENTPROTO_NOTIFY_URL` env var or\n * `~/.agentproto/notify.json` (env wins). Both are POSTed when an event\n * fires — the union of per-session + global URLs, deduplicated.\n *\n * Retry policy: one retry after 2 s on network error. No retry on 4xx/5xx.\n * Timeout: 10 s per attempt. All errors are swallowed — the notifier never\n * throws into the session's hot path.\n */\n\nimport { readFileSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport type { SessionEvent, SessionAwaitingQuestion } from \"./session-event-bus.js\"\n\nexport interface WebhookNotifier {\n  /** Register a per-session URL (called from agent_start). */\n  register(sessionId: string, url: string): void\n  unregister(sessionId: string): void\n  /** Handler to wire into SessionEventBus.onAny. Fire-and-forget. */\n  onSessionEvent(ev: SessionEvent): void\n}\n\ninterface NotifyPayload {\n  sessionId: string\n  label?: string\n  event: string\n  awaitingInput: boolean\n  ts: string\n  exitCode?: number\n  status?: string\n  question?: SessionAwaitingQuestion\n}\n\nexport function createWebhookNotifier(opts?: {\n  /** Pre-resolved global URL — overridden at call time by env var or file. */\n  globalUrl?: string\n}): WebhookNotifier {\n  const perSession = new Map<string, string>()\n\n  const resolveGlobalUrl = (): string | undefined => {\n    if (process.env.AGENTPROTO_NOTIFY_URL) return process.env.AGENTPROTO_NOTIFY_URL\n    try {\n      const path = join(homedir(), \".agentproto\", \"notify.json\")\n      const parsed = JSON.parse(readFileSync(path, \"utf8\")) as unknown\n      if (parsed && typeof parsed === \"object\" && \"url\" in parsed) {\n        const { url } = parsed as { url: unknown }\n        if (typeof url === \"string\" && url) return url\n      }\n    } catch {\n      // file absent or malformed — not an error\n    }\n    return opts?.globalUrl\n  }\n\n  const post = async (url: string, payload: NotifyPayload): Promise<void> => {\n    const body = JSON.stringify(payload)\n    const headers = { \"Content-Type\": \"application/json\" }\n    try {\n      const resp = await fetch(url, {\n        method: \"POST\",\n        headers,\n        body,\n        signal: AbortSignal.timeout(10_000),\n      })\n      if (resp.ok) return\n      // 4xx/5xx — no retry\n    } catch {\n      // Network error — one retry after 2 s\n      await new Promise<void>(res => setTimeout(res, 2_000))\n      try {\n        await fetch(url, {\n          method: \"POST\",\n          headers,\n          body,\n          signal: AbortSignal.timeout(10_000),\n        })\n      } catch {\n        // Give up silently\n      }\n    }\n  }\n\n  return {\n    register(sessionId, url) {\n      perSession.set(sessionId, url)\n    },\n    unregister(sessionId) {\n      perSession.delete(sessionId)\n    },\n    onSessionEvent(ev) {\n      // Only fire on meaningful lifecycle events (not command-done, which\n      // goes through the command-tools layer)\n      if (\n        ev.type !== \"session:turn-end\" &&\n        ev.type !== \"session:awaiting-input\" &&\n        ev.type !== \"session:exited\"\n      ) {\n        return\n      }\n\n      const targets = new Set<string>()\n      const sessionUrl = perSession.get(ev.sessionId)\n      if (sessionUrl) targets.add(sessionUrl)\n      const globalUrl = resolveGlobalUrl()\n      if (globalUrl) targets.add(globalUrl)\n      if (targets.size === 0) return\n\n      const payload: NotifyPayload = {\n        sessionId: ev.sessionId,\n        label: ev.label,\n        event: ev.type.replace(\"session:\", \"\"),\n        awaitingInput:\n          ev.type === \"session:awaiting-input\" ||\n          (ev.type === \"session:turn-end\" && ev.awaitingInput),\n        ts: ev.ts,\n      }\n      if (ev.type === \"session:exited\") {\n        payload.exitCode = ev.exitCode\n        payload.status = ev.status\n      }\n      if ((ev.type === \"session:turn-end\" || ev.type === \"session:awaiting-input\") && ev.question) {\n        payload.question = ev.question\n      }\n\n      for (const url of targets) {\n        void post(url, payload)\n      }\n    },\n  }\n}\n","/**\n * In-process routine runner — executes a sequence of RoutineStep[]\n * by reacting to SessionEventBus events instead of polling.\n *\n * State machine per run:\n *   idle → running → (per step) → done | failed | cancelled\n *\n * Fan-in: a step with `waitFor: string[]` waits for ALL listed\n * sessions to fire turn-end/exited before executing its own prompt.\n *\n * Awaiting-input policy:\n *   auto-allow → send the configured prompt and continue\n *   escalate   → POST webhook, wait for external `resolve()` call\n *   fail       → mark step/run as failed\n *\n * Persistence: runs are serialised to ~/.agentproto/routine-runs.json\n * (write-tmp + rename atomic swap) on every state mutation so they\n * survive daemon restarts. On load, any run with status \"running\" or\n * \"awaiting-input\" is immediately marked \"failed\" with reason\n * \"interrupted by daemon restart\" — these runs have no live sessions\n * to resume, so marking them failed is the only safe choice (an\n * in-flight run cannot be replayed without re-executing its steps,\n * which could trigger unintended side-effects).\n *\n * Persistence opt-in: persistence is DISABLED by default (persist defaults to\n * false when no persistPath is supplied) so that unit tests calling\n * createRoutineRunner() without a persistPath never touch ~/.agentproto/.\n * Pass persist:true (or supply a persistPath) to enable durable storage — the\n * production createGateway() call does both.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { homedir } from \"node:os\"\nimport { join, dirname } from \"node:path\"\nimport { mkdirSync, readFileSync, existsSync, writeFileSync, renameSync } from \"node:fs\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { SessionEventBus } from \"./session-event-bus.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\nimport type { WebhookNotifier } from \"./webhook-notifier.js\"\n\n// ── Public types ─────────────────────────────────────────────────────\n\nexport type RoutinePolicy =\n  | { awaiting: \"auto-allow\"; prompt: string }\n  | { awaiting: \"escalate\"; webhookUrl?: string; timeoutMs?: number }\n  | { awaiting: \"fail\" }\n\nexport interface RoutineStep {\n  label: string\n  /** Prompt to send to the agent. Omit to just wait without prompting. */\n  prompt?: string\n  /** Adapter slug for spawning a NEW session. Omit to reuse the current\n   *  run's last session. */\n  adapter?: string\n  /** Fan-in: wait for ALL these session ids to finish before executing. */\n  waitFor?: string[]\n  policy?: RoutinePolicy\n}\n\nexport type RoutineRunStatus =\n  | \"idle\"\n  | \"running\"\n  | \"awaiting-input\"\n  | \"done\"\n  | \"failed\"\n  | \"cancelled\"\n\nexport interface RoutineStepState {\n  index: number\n  label: string\n  status: \"pending\" | \"running\" | \"done\" | \"failed\" | \"skipped\"\n  sessionId?: string\n  startedAt?: string\n  endedAt?: string\n  error?: string\n}\n\nexport interface RoutineRun {\n  runId: string\n  routineId: string\n  status: RoutineRunStatus\n  startedAt: string\n  endedAt?: string\n  steps: RoutineStepState[]\n  notifyUrl?: string\n  error?: string\n  result?: { sessionIds: string[] }\n}\n\nexport interface RoutineRunner {\n  /**\n   * Start a routine. Returns immediately with the run descriptor\n   * (status \"running\"). Steps execute in the background; subscribe\n   * to the webhook or poll `status(runId)` for completion.\n   */\n  start(input: {\n    routineId: string\n    steps: RoutineStep[]\n    workspaceSlug?: string\n    cwd?: string\n    notifyUrl?: string\n  }): Promise<RoutineRun>\n\n  status(runId: string): RoutineRun | undefined\n  list(): RoutineRun[]\n\n  /**\n   * Provide an external answer to a step stuck in \"escalate\" awaiting-input.\n   * The step's escalate timeout is cleared and the response is sent as the\n   * next prompt.\n   */\n  resolve(runId: string, stepIndex: number, response: string): void\n\n  cancel(runId: string): void\n}\n\n// ── Internal state per run ───────────────────────────────────────────\n\ninterface RunState {\n  run: RoutineRun\n  cancelled: boolean\n  /** cwd passed to start() — used as the CWD for all spawned sessions. */\n  cwd?: string\n  /** workspaceSlug passed to start() — forwarded to spawnAgent. */\n  workspaceSlug?: string\n  /** Filled by resolve() when a step is in \"escalate\" mode. */\n  pendingResolve?: { stepIndex: number; resolver: (response: string) => void }\n}\n\n// ── Factory ──────────────────────────────────────────────────────────\n\nconst DEFAULT_PERSIST_PATH = (): string =>\n  join(homedir(), \".agentproto\", \"routine-runs.json\")\n\n// ── Persistence helpers ──────────────────────────────────────────────\n\nfunction loadRuns(persistPath: string): Map<string, RunState> {\n  const result = new Map<string, RunState>()\n  if (!existsSync(persistPath)) return result\n  let raw: string\n  try {\n    raw = readFileSync(persistPath, \"utf8\")\n  } catch {\n    return result\n  }\n  let parsed: unknown\n  try {\n    parsed = JSON.parse(raw)\n  } catch {\n    // Malformed file — start empty (documented: not an error)\n    return result\n  }\n  if (!Array.isArray(parsed)) return result\n  for (const item of parsed) {\n    if (!item || typeof item !== \"object\" || typeof (item as RoutineRun).runId !== \"string\") continue\n    // item passes only a minimal shape check (runId: string); remaining fields\n    // are trusted as-written. Malformed entries are skipped above — this matches\n    // the \"malformed = ignored\" recovery policy used by tunnel-registry and\n    // supervisor for the same class of loader.\n    const run = item as RoutineRun\n    // Any run that was mid-flight cannot be resumed: mark it failed.\n    // Reason: the in-process state machine and its live sessions are gone;\n    // replaying steps would trigger unintended side-effects, so the safest\n    // invariant is \"interrupted = failed\". Callers can re-start a new run.\n    if (run.status === \"running\" || run.status === \"awaiting-input\") {\n      run.status = \"failed\"\n      run.error = \"interrupted by daemon restart\"\n      run.endedAt = run.endedAt ?? new Date().toISOString()\n    }\n    result.set(run.runId, { run, cancelled: false })\n  }\n  return result\n}\n\nfunction saveRuns(runs: Map<string, RunState>, persistPath: string): void {\n  try {\n    mkdirSync(dirname(persistPath), { recursive: true })\n    const payload = JSON.stringify(\n      Array.from(runs.values()).map(s => s.run),\n      null,\n      2,\n    ) + \"\\n\"\n    const tmp = `${persistPath}.tmp.${process.pid}`\n    writeFileSync(tmp, payload, \"utf8\")\n    renameSync(tmp, persistPath)\n  } catch {\n    // Best-effort — a write failure must not crash the daemon.\n  }\n}\n\nexport function createRoutineRunner(opts: {\n  registry: SessionsRegistry\n  sessionEvents: SessionEventBus\n  resolveAgentAdapter: AgentAdapterResolver\n  webhookNotifier?: WebhookNotifier\n  /** Absolute path for the persistence file. Defaults to ~/.agentproto/routine-runs.json */\n  persistPath?: string\n  /**\n   * Enable filesystem persistence. Defaults to `true` when `persistPath` is\n   * explicitly supplied, `false` otherwise. This mirrors the supervisor pattern\n   * so that unit tests calling createRoutineRunner() without a persistPath never\n   * write to ~/.agentproto/ — only the production createGateway() call (which\n   * passes persist:true) opts in to durable storage.\n   */\n  persist?: boolean\n}): RoutineRunner {\n  const { registry, sessionEvents, resolveAgentAdapter, webhookNotifier } = opts\n  const persistPath = opts.persistPath ?? DEFAULT_PERSIST_PATH()\n  const shouldPersist = opts.persist ?? (opts.persistPath !== undefined)\n\n  // Default false: tests (no opts.persist, no opts.persistPath)\n  // don't touch ~/.agentproto. Set opts.persist:true in production\n  // (createGateway does this), or supply a persistPath (which also opts in).\n\n  // Load persisted runs on init only when persistence is enabled;\n  // interrupted runs are marked failed.\n  const runs = shouldPersist ? loadRuns(persistPath) : new Map<string, RunState>()\n\n  /** Flush the in-memory run map to disk atomically. Call on every mutation. */\n  const persist = (): void => {\n    if (shouldPersist) saveRuns(runs, persistPath)\n  }\n\n  // ── Helpers ────────────────────────────────────────────────────────\n\n  /** Wait for a session to emit turn-end, awaiting-input, or exited.\n   *\n   * Subscribes synchronously so the caller can create this promise BEFORE\n   * sending a prompt — preventing a race where a fast session fires turn-end\n   * between sendPrompt() resolving and the subscription being set up.\n   *\n   * Belt-and-suspenders: after subscribing, checks whether the session is\n   * already in a terminal state (exited/killed/error or awaitingInput) and\n   * resolves immediately if so, covering the gap between session spawn and\n   * this function being called.\n   */\n  const waitTurnEnd = (sessionId: string): Promise<void> =>\n    new Promise(resolve => {\n      const unsubs: Array<() => void> = []\n      const done = (): void => {\n        for (const u of unsubs) u()\n        resolve()\n      }\n      unsubs.push(\n        sessionEvents.on(\"session:turn-end\", ev => {\n          if (ev.sessionId === sessionId) done()\n        }),\n      )\n      unsubs.push(\n        sessionEvents.on(\"session:awaiting-input\", ev => {\n          if (ev.sessionId === sessionId) done()\n        }),\n      )\n      unsubs.push(\n        sessionEvents.on(\"session:exited\", ev => {\n          if (ev.sessionId === sessionId) done()\n        }),\n      )\n      // Belt-and-suspenders: resolve immediately if the session is already done.\n      // Covers the window between session spawn and this subscription being set up.\n      const desc = registry.get(sessionId)\n      const isTerminal =\n        desc?.status === \"exited\" ||\n        desc?.status === \"killed\" ||\n        desc?.status === \"error\" ||\n        desc?.awaitingInput === true\n      if (isTerminal) done()\n    })\n\n  /** Spawn a new agent session for the given step. */\n  const spawnSession = async (\n    step: RoutineStep,\n    state: RunState,\n  ): Promise<string | null> => {\n    if (!step.adapter) return null\n    const resolved = await resolveAgentAdapter(step.adapter)\n    if (!resolved) return null\n    const lastSessionId = state.run.result?.sessionIds.at(-1)\n    // state.cwd wins (explicit caller intent); fall back to last session's cwd;\n    // last resort: daemon's process.cwd().\n    const cwd =\n      state.cwd ??\n      (lastSessionId ? registry.get(lastSessionId)?.cwd : undefined) ??\n      process.cwd()\n    try {\n      const agentSession = await resolved.startSession({ cwd })\n      const desc = registry.spawnAgent({\n        workspaceSlug: state.workspaceSlug ?? \"default\",\n        cwd,\n        agentSession,\n        adapterSlug: step.adapter,\n        label: `routine:${state.run.routineId}:${step.label}`,\n        ...(resolved.commandPreview ? { commandPreview: resolved.commandPreview } : {}),\n      })\n      state.run.result ??= { sessionIds: [] }\n      state.run.result.sessionIds.push(desc.id)\n      return desc.id\n    } catch {\n      return null\n    }\n  }\n\n  // ── Step executor ──────────────────────────────────────────────────\n\n  const executeStep = async (\n    stepDef: RoutineStep,\n    stepState: RoutineStepState,\n    state: RunState,\n  ): Promise<void> => {\n    stepState.status = \"running\"\n    stepState.startedAt = new Date().toISOString()\n    persist()\n\n    try {\n      // Fan-in: wait for all listed sessions\n      if (stepDef.waitFor?.length) {\n        await Promise.all(stepDef.waitFor.map(id => waitTurnEnd(id)))\n      }\n\n      if (state.cancelled) {\n        stepState.status = \"skipped\"\n        return\n      }\n\n      // Spawn / reuse session\n      let sessionId: string | null = null\n      if (stepDef.adapter) {\n        sessionId = await spawnSession(stepDef, state)\n        if (sessionId) stepState.sessionId = sessionId\n      } else if (state.run.result?.sessionIds.length) {\n        sessionId = state.run.result.sessionIds.at(-1) ?? null\n        if (sessionId) stepState.sessionId = sessionId\n      }\n\n      if (state.cancelled) {\n        stepState.status = \"skipped\"\n        return\n      }\n\n      // Subscribe to turn-end BEFORE sending the prompt so a fast session\n      // cannot fire the event in the window between sendPrompt() resolving\n      // and a later waitTurnEnd() call setting up its listeners.\n      if (sessionId) {\n        const turnEnded = waitTurnEnd(sessionId)\n        if (stepDef.prompt) {\n          await registry.sendPrompt(sessionId, stepDef.prompt)\n        }\n        await turnEnded\n      }\n\n      if (state.cancelled) {\n        stepState.status = \"skipped\"\n        return\n      }\n\n      // Check awaiting-input\n      const desc = sessionId ? registry.get(sessionId) : undefined\n      if (desc && (desc as { awaitingInput?: boolean }).awaitingInput) {\n        const policy = stepDef.policy ?? { awaiting: \"fail\" }\n        if (policy.awaiting === \"auto-allow\") {\n          const turnEnded = waitTurnEnd(sessionId!)\n          await registry.sendPrompt(sessionId!, policy.prompt)\n          await turnEnded\n        } else if (policy.awaiting === \"escalate\") {\n          const escalateUrl = policy.webhookUrl ?? state.run.notifyUrl\n          if (escalateUrl) {\n            void fetch(escalateUrl, {\n              method: \"POST\",\n              headers: { \"Content-Type\": \"application/json\" },\n              body: JSON.stringify({\n                type: \"routine:awaiting-input\",\n                runId: state.run.runId,\n                routineId: state.run.routineId,\n                stepIndex: stepState.index,\n                stepLabel: stepDef.label,\n              }),\n              signal: AbortSignal.timeout(10_000),\n            }).catch(() => undefined)\n          }\n          state.run.status = \"awaiting-input\"\n          persist()\n          // Wait for external resolve()\n          const response = await new Promise<string>((res, rej) => {\n            const timeoutMs = policy.timeoutMs ?? 300_000\n            const timer = setTimeout(() => {\n              state.pendingResolve = undefined\n              rej(new Error(\"escalate timeout\"))\n            }, timeoutMs)\n            state.pendingResolve = {\n              stepIndex: stepState.index,\n              resolver: (r: string) => {\n                clearTimeout(timer)\n                state.pendingResolve = undefined\n                res(r)\n              },\n            }\n          })\n          state.run.status = \"running\"\n          persist()\n          if (sessionId) {\n            const turnEnded = waitTurnEnd(sessionId)\n            await registry.sendPrompt(sessionId, response)\n            await turnEnded\n          }\n        } else {\n          // policy.awaiting === \"fail\"\n          throw new Error(\"step failed: session awaiting input\")\n        }\n      }\n\n      stepState.status = \"done\"\n      stepState.endedAt = new Date().toISOString()\n      persist()\n    } catch (err) {\n      stepState.status = \"failed\"\n      stepState.endedAt = new Date().toISOString()\n      stepState.error = err instanceof Error ? err.message : String(err)\n      persist()\n      throw err\n    }\n  }\n\n  // ── Run executor ───────────────────────────────────────────────────\n\n  const executeRun = async (state: RunState, steps: RoutineStep[]): Promise<void> => {\n    try {\n      for (let i = 0; i < steps.length; i++) {\n        if (state.cancelled) break\n        const stepState = state.run.steps[i]!\n        await executeStep(steps[i]!, stepState, state)\n        if (stepState.status === \"failed\") {\n          state.run.status = \"failed\"\n          state.run.error = stepState.error\n          state.run.endedAt = new Date().toISOString()\n          persist()\n          return\n        }\n      }\n      if (state.cancelled) {\n        state.run.status = \"cancelled\"\n      } else {\n        state.run.status = \"done\"\n      }\n      state.run.endedAt = new Date().toISOString()\n      persist()\n\n      // Fire webhook if requested\n      if (state.run.notifyUrl) {\n        void fetch(state.run.notifyUrl, {\n          method: \"POST\",\n          headers: { \"Content-Type\": \"application/json\" },\n          body: JSON.stringify({\n            type: state.cancelled ? \"routine:cancelled\" : \"routine:done\",\n            runId: state.run.runId,\n            result: state.run.result,\n          }),\n          signal: AbortSignal.timeout(10_000),\n        }).catch(() => undefined)\n      }\n    } catch {\n      state.run.status = \"failed\"\n      state.run.endedAt = new Date().toISOString()\n      persist()\n    }\n  }\n\n  // ── Public interface ───────────────────────────────────────────────\n\n  return {\n    start: async (input) => {\n      const runId = `run_${randomUUID()}`\n      const run: RoutineRun = {\n        runId,\n        routineId: input.routineId,\n        status: \"running\",\n        startedAt: new Date().toISOString(),\n        steps: input.steps.map((s, i) => ({\n          index: i,\n          label: s.label,\n          status: \"pending\",\n        })),\n        ...(input.notifyUrl ? { notifyUrl: input.notifyUrl } : {}),\n      }\n      const state: RunState = {\n        run,\n        cancelled: false,\n        ...(input.cwd !== undefined ? { cwd: input.cwd } : {}),\n        ...(input.workspaceSlug !== undefined ? { workspaceSlug: input.workspaceSlug } : {}),\n      }\n      runs.set(runId, state)\n      persist()\n      // Fire-and-forget: run steps in background\n      void executeRun(state, input.steps)\n      return run\n    },\n\n    status: (runId) => runs.get(runId)?.run,\n\n    list: () => Array.from(runs.values()).map(s => s.run),\n\n    resolve: (runId, stepIndex, response) => {\n      const state = runs.get(runId)\n      if (!state) return\n      const pr = state.pendingResolve\n      if (pr && pr.stepIndex === stepIndex) {\n        pr.resolver(response)\n      }\n    },\n\n    cancel: (runId) => {\n      const state = runs.get(runId)\n      if (!state) return\n      state.cancelled = true\n      // If the run is already terminal, leave it; otherwise mark cancelled\n      if (state.run.status === \"running\" || state.run.status === \"awaiting-input\") {\n        state.run.status = \"cancelled\"\n        state.run.endedAt = new Date().toISOString()\n        persist()\n      }\n    },\n  }\n}\n","/**\n * SessionsRegistryAgentHost — implements AgentSessionHost against the\n * runtime's in-process SessionsRegistry + SessionEventBus.\n *\n * This is a near-direct lift of the `spawnSession`/`waitTurnEnd` logic\n * that previously lived inside WorkflowRunner. The logic doesn't change;\n * it moves behind the AgentSessionHost interface so WorkflowRunner can\n * delegate to the workflow-runtime's step-walker.\n */\n\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { SessionEventBus } from \"./session-event-bus.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\nimport type { AgentSessionHost, AgentStep } from \"@agentproto/workflow-runtime\"\nimport { exportAgentSession } from \"./transcript-export.js\"\n\nexport class SessionsRegistryAgentHost implements AgentSessionHost {\n  private readonly sessionsByLabel = new Map<string, string>()\n\n  constructor(\n    private readonly registry: SessionsRegistry,\n    private readonly sessionEvents: SessionEventBus,\n    private readonly resolveAgentAdapter: AgentAdapterResolver,\n    private readonly opts?: {\n      workspaceSlug?: string\n      cwd?: string\n      /** Optional webhook URL for escalation notifications. */\n      notifyUrl?: string\n    },\n  ) {}\n\n  async spawn(\n    adapter: string,\n    opts: { cwd?: string; workspaceSlug?: string; stepId?: string },\n  ): Promise<string> {\n    const resolved = await this.resolveAgentAdapter(adapter)\n    if (!resolved) throw new Error(`adapter '${adapter}' not found`)\n    const workspaceSlug = opts.workspaceSlug ?? this.opts?.workspaceSlug ?? \"default\"\n    const cwd = opts.cwd ?? this.opts?.cwd ?? process.cwd()\n    const agentSession = await resolved.startSession({ cwd })\n    const desc = this.registry.spawnAgent({\n      workspaceSlug,\n      cwd,\n      agentSession,\n      adapterSlug: adapter,\n      label: `agent-step:${adapter}`,\n      ...(resolved.commandPreview ? { commandPreview: resolved.commandPreview } : {}),\n    })\n    if (opts.stepId) {\n      this.sessionsByLabel.set(opts.stepId, desc.id)\n    }\n    return desc.id\n  }\n\n  async sendPromptAndWait(sessionId: string, prompt: string): Promise<void> {\n    const turnEnded = this.waitTurnEnd(sessionId)\n    await this.registry.sendPrompt(sessionId, prompt)\n    await turnEnded\n  }\n\n  resolveByLabel(stepId: string): string | undefined {\n    return this.sessionsByLabel.get(stepId)\n  }\n\n  async onAwaitingInput(\n    sessionId: string,\n    policy: NonNullable<AgentStep[\"policy\"]>,\n  ): Promise<void> {\n    const desc = this.registry.get(sessionId)\n    if (!desc?.awaitingInput) return\n\n    if (policy.awaiting === \"auto-allow\") {\n      const turnEnded = this.waitTurnEnd(sessionId)\n      await this.registry.sendPrompt(sessionId, policy.prompt)\n      await turnEnded\n    } else if (policy.awaiting === \"escalate\") {\n      const escalateUrl = policy.webhookUrl ?? this.opts?.notifyUrl\n      if (escalateUrl) {\n        void fetch(escalateUrl, {\n          method: \"POST\",\n          headers: { \"Content-Type\": \"application/json\" },\n          body: JSON.stringify({\n            type: \"workflow:awaiting-input\",\n            sessionId,\n          }),\n          signal: AbortSignal.timeout(10_000),\n        }).catch(() => undefined)\n      }\n      // Escalate: throw so the caller knows this step is awaiting external input.\n      throw new Error(`step escalated: session ${sessionId} awaiting input`)\n    } else {\n      throw new Error(`step failed: session ${sessionId} awaiting input`)\n    }\n  }\n\n  async readFinalMessage(sessionId: string): Promise<string> {\n    const result = await exportAgentSession({\n      sessionId,\n      registry: this.registry,\n      format: \"json\",\n    })\n    // exportAgentSession returns a non-JSON `content` (\"Error: …\") when the\n    // session can't be exported; degrade to \"\" (→ the interpreter re-prompts)\n    // rather than throwing a raw SyntaxError out of the workflow.\n    let raw: unknown\n    try {\n      raw = JSON.parse(result.content)\n    } catch {\n      return \"\"\n    }\n    if (typeof raw !== \"object\" || raw === null) return \"\"\n    if (!(\"messages\" in raw)) return \"\"\n    const msgList = raw.messages\n    if (!Array.isArray(msgList)) return \"\"\n    for (let i = msgList.length - 1; i >= 0; i--) {\n      const m = msgList[i]\n      if (typeof m !== \"object\" || m === null) continue\n      if (!(\"role\" in m)) continue\n      if (m.role !== \"assistant\") continue\n      if (!(\"text\" in m)) continue\n      const text = m.text\n      if (typeof text === \"string\" && text.trim()) {\n        return text\n      }\n    }\n    return \"\"\n  }\n\n  async readCostUsd(sessionId: string): Promise<number> {\n    const desc = this.registry.get(sessionId)\n    return desc?.costUsd ?? 0\n  }\n\n  // ── Internal helpers ──────────────────────────────────────────────────\n\n  private waitTurnEnd(sessionId: string): Promise<void> {\n    return new Promise<void>((resolve, reject) => {\n      const unsubs: Array<() => void> = []\n      const done = (): void => {\n        for (const u of unsubs) u()\n        resolve()\n      }\n      const fail = (reason: string): void => {\n        for (const u of unsubs) u()\n        reject(new Error(reason))\n      }\n      unsubs.push(\n        this.sessionEvents.on(\"session:turn-end\", (ev) => {\n          if (ev.sessionId === sessionId) done()\n        }),\n      )\n      unsubs.push(\n        this.sessionEvents.on(\"session:awaiting-input\", (ev) => {\n          if (ev.sessionId === sessionId) done()\n        }),\n      )\n      unsubs.push(\n        this.sessionEvents.on(\"session:exited\", (ev) => {\n          if (ev.sessionId !== sessionId) return\n          // Reject on terminal-error/killed so step failures propagate to\n          // the workflow run as `status: \"failed\"`. Plain \"exited\" (clean\n          // exit code 0 path) resolves normally.\n          if (ev.status === \"killed\" || ev.status === \"error\") {\n            fail(`session ${sessionId} ended with status '${ev.status}'`)\n          } else {\n            done()\n          }\n        }),\n      )\n      // Eagerly settle if the session is already in a terminal state.\n      const desc = this.registry.get(sessionId)\n      if (desc?.status === \"exited\" || desc?.awaitingInput === true) {\n        done()\n      } else if (desc?.status === \"killed\" || desc?.status === \"error\") {\n        fail(`session ${sessionId} ended with status '${desc.status}'`)\n      }\n    })\n  }\n}\n","import { homedir } from \"node:os\"\nimport { join, dirname } from \"node:path\"\nimport { mkdirSync, readFileSync, existsSync, writeFileSync, renameSync } from \"node:fs\"\nimport type { StepCache, StepCacheEntry } from \"@agentproto/workflow-runtime\"\n\nconst DEFAULT_CACHE_DIR = (): string => join(homedir(), \".agentproto\", \"workflow-cache\")\n\n/** Filesystem-safe file stem for a caller-supplied cacheKey. */\nfunction sanitize(cacheKey: string): string {\n  const cleaned = cacheKey.replace(/[^a-zA-Z0-9._-]/g, \"_\")\n  return cleaned.length > 0 ? cleaned : \"default\"\n}\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n  return typeof v === \"object\" && v !== null && !Array.isArray(v)\n}\nfunction isEntry(v: unknown): v is StepCacheEntry {\n  return isRecord(v) && typeof v.resolvedInputHash === \"string\" && \"output\" in v\n}\n\n/** A journal-file StepCache scoped to one cacheKey. Best-effort: read/parse\n *  failures degrade to \"no cache\" (a miss), never throw into the run. */\nexport function createFileStepCache(cacheKey: string, opts?: { dir?: string }): StepCache {\n  const dir = opts?.dir ?? DEFAULT_CACHE_DIR()\n  const path = join(dir, `${sanitize(cacheKey)}.json`)\n\n  const readAll = (): Record<string, StepCacheEntry> => {\n    if (!existsSync(path)) return {}\n    let parsed: unknown\n    try {\n      parsed = JSON.parse(readFileSync(path, \"utf8\"))\n    } catch {\n      return {}\n    }\n    if (!isRecord(parsed)) return {}\n    const out: Record<string, StepCacheEntry> = {}\n    for (const [k, v] of Object.entries(parsed)) if (isEntry(v)) out[k] = v\n    return out\n  }\n\n  return {\n    get: async (key) => readAll()[key],\n    set: async (key, entry) => {\n      const all = readAll()\n      all[key] = entry\n      try {\n        mkdirSync(dirname(path), { recursive: true })\n        const tmp = `${path}.tmp.${process.pid}`\n        writeFileSync(tmp, JSON.stringify(all, null, 2) + \"\\n\", \"utf8\")\n        renameSync(tmp, path)\n      } catch {\n        // best-effort — a cache write failure must not crash the run\n      }\n    },\n  }\n}\n","/**\n * In-process workflow runner — executes an ordered list of WorkflowStage[],\n * each stage containing one or more parallel WorkflowStep[], with an\n * explicit barrier between stages.\n *\n * As of the engine-unification refactor, the internals delegate to\n * `runWorkflow` from @agentproto/workflow-runtime via a translation layer:\n * each stage becomes a `ParallelStep` with one `AgentStep` branch per step;\n * stages are chained as a flat `steps[]`. The public API —\n * `WorkflowRunner.start()` / `status()` / `cancel()` — is preserved\n * unchanged.\n *\n * Persistence: runs are serialised to ~/.agentproto/workflow-runs.json\n * (write-tmp + rename atomic swap) on every state mutation, same pattern\n * as routine-runner.ts. On load, any run with status \"running\" or\n * \"awaiting-input\" is immediately marked \"failed\" with reason\n * \"interrupted by daemon restart\".\n *\n * Persistence opt-in: disabled by default (persist defaults to false when\n * no persistPath is supplied) so unit tests never touch ~/.agentproto/.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { homedir } from \"node:os\"\nimport { join, dirname } from \"node:path\"\nimport { mkdirSync, readFileSync, existsSync, writeFileSync, renameSync } from \"node:fs\"\nimport { runWorkflow } from \"@agentproto/workflow-runtime\"\nimport type { RuntimeWorkflow } from \"@agentproto/workflow-runtime\"\nimport type { StepCache } from \"@agentproto/workflow-runtime\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { SessionEventBus } from \"./session-event-bus.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\nimport type { WebhookNotifier } from \"./webhook-notifier.js\"\nimport type { RoutinePolicy, RoutineStepState } from \"./routine-runner.js\"\nimport { SessionsRegistryAgentHost } from \"./sessions-registry-agent-host.js\"\nimport { createFileStepCache } from \"./workflow-step-cache.js\"\n\n// ── Public types ─────────────────────────────────────────────────────\n\nexport interface WorkflowStep {\n  label: string\n  /** Prompt to send to the agent. Omit to just spawn/reuse and wait. */\n  prompt?: string\n  /** Adapter slug for spawning a NEW session. Omit to reuse a prior session. */\n  adapter?: string\n  /** Reuse the session spawned by an earlier step (any prior stage),\n   *  identified by that step's `label`. Ignored if `adapter` is set. */\n  sessionRef?: string\n  policy?: RoutinePolicy\n  /** Cache this step's output under the run's `cacheKey` — opt-in, for idempotent steps. */\n  cacheable?: boolean\n}\n\nexport interface WorkflowStage {\n  /** Optional label for this stage (surfaced in status output). */\n  label?: string\n  steps: WorkflowStep[]\n}\n\nexport type WorkflowRunStatus =\n  | \"idle\"\n  | \"running\"\n  | \"awaiting-input\"\n  | \"done\"\n  | \"failed\"\n  | \"cancelled\"\n\nexport interface WorkflowStageState {\n  index: number\n  label?: string\n  status: \"pending\" | \"running\" | \"done\" | \"failed\" | \"skipped\"\n  steps: RoutineStepState[]\n}\n\nexport interface WorkflowRun {\n  runId: string\n  workflowId: string\n  status: WorkflowRunStatus\n  startedAt: string\n  endedAt?: string\n  stages: WorkflowStageState[]\n  notifyUrl?: string\n  error?: string\n  result?: { sessionIds: string[] }\n}\n\nexport interface WorkflowRunner {\n  start(input: {\n    workflowId: string\n    stages: WorkflowStage[]\n    workspaceSlug?: string\n    cwd?: string\n    notifyUrl?: string\n    /** Enable journal caching for this run; cacheable steps replay unchanged outputs. */\n    cacheKey?: string\n  }): Promise<WorkflowRun>\n\n  status(runId: string): WorkflowRun | undefined\n  list(): WorkflowRun[]\n\n  resolve(runId: string, stageIndex: number, stepIndex: number, response: string): void\n\n  cancel(runId: string): void\n}\n\n// ── Internal state per run ───────────────────────────────────────────\n\ninterface RunState {\n  run: WorkflowRun\n  cancelled: boolean\n  cwd?: string\n  workspaceSlug?: string\n  abort: AbortController\n  /** Original stages — retained so sessionRef lookups can resolve step labels. */\n  stages: WorkflowStage[]\n  /**\n   * Reserved for a future durable suspend/resume of an escalated step. NOT set\n   * by the current engine: an `escalate` policy fails the step fast\n   * (`SessionsRegistryAgentHost.onAwaitingInput` throws) instead of suspending\n   * on a resolver, so `resolve()` is a no-op today. Kept as a documented stub\n   * rather than removed, to avoid a breaking change for the `http-server` /\n   * `orchestration-tools` callers pending the durable-suspend follow-up.\n   */\n  pendingResolve?: { stageIndex: number; stepIndex: number; resolver: (response: string) => void }\n}\n\n// ── Translation: WorkflowStage[] → RuntimeWorkflow ──────────────────\n\nfunction translateStages(\n  stages: WorkflowStage[],\n  workflowId: string,\n): RuntimeWorkflow {\n  const steps = stages.map((stage, si): RuntimeWorkflow[\"steps\"][number] => {\n    const branches = stage.steps.map((step) => ({\n      id: step.label,\n      steps: [\n        {\n          kind: \"agent\" as const,\n          id: step.label,\n          ...(step.adapter !== undefined ? { adapter: step.adapter } : {}),\n          ...(step.sessionRef !== undefined ? { sessionRef: step.sessionRef } : {}),\n          ...(step.cacheable ? { cacheable: true } : {}),\n          prompt: () => step.prompt ?? \"\",\n          policy: step.policy ?? { awaiting: \"fail\" as const },\n        },\n      ],\n    }))\n    return {\n      kind: \"parallel\" as const,\n      id: `stage-${si}`,\n      branches,\n    }\n  })\n\n  return {\n    id: workflowId,\n    steps,\n  }\n}\n\n// ── Factory ──────────────────────────────────────────────────────────\n\nconst DEFAULT_PERSIST_PATH = (): string =>\n  join(homedir(), \".agentproto\", \"workflow-runs.json\")\n\n// ── Persistence helpers (mirrors routine-runner.ts exactly) ──────────\n\nfunction loadRuns(persistPath: string): Map<string, RunState> {\n  const result = new Map<string, RunState>()\n  if (!existsSync(persistPath)) return result\n  let raw: string\n  try {\n    raw = readFileSync(persistPath, \"utf8\")\n  } catch {\n    return result\n  }\n  let parsed: unknown\n  try {\n    parsed = JSON.parse(raw)\n  } catch {\n    return result\n  }\n  if (!Array.isArray(parsed)) return result\n  for (const item of parsed) {\n    if (!item || typeof item !== \"object\" || typeof (item as WorkflowRun).runId !== \"string\") continue\n    const run = item as WorkflowRun\n    if (run.status === \"running\" || run.status === \"awaiting-input\") {\n      run.status = \"failed\"\n      run.error = \"interrupted by daemon restart\"\n      run.endedAt = run.endedAt ?? new Date().toISOString()\n    }\n    result.set(run.runId, { run, cancelled: false, abort: new AbortController(), stages: [] })\n  }\n  return result\n}\n\nfunction saveRuns(runs: Map<string, RunState>, persistPath: string): void {\n  try {\n    mkdirSync(dirname(persistPath), { recursive: true })\n    const payload = JSON.stringify(\n      Array.from(runs.values()).map(s => s.run),\n      null,\n      2,\n    ) + \"\\n\"\n    const tmp = `${persistPath}.tmp.${process.pid}`\n    writeFileSync(tmp, payload, \"utf8\")\n    renameSync(tmp, persistPath)\n  } catch {\n    // Best-effort — a write failure must not crash the daemon.\n  }\n}\n\nfunction fireNotifyUrl(run: WorkflowRun): void {\n  if (!run.notifyUrl) return\n  void fetch(run.notifyUrl, {\n    method: \"POST\",\n    headers: { \"Content-Type\": \"application/json\" },\n    body: JSON.stringify({\n      type: run.status === \"cancelled\" ? \"workflow:cancelled\" : run.status === \"done\" ? \"workflow:done\" : \"workflow:failed\",\n      runId: run.runId,\n      result: run.result,\n    }),\n    signal: AbortSignal.timeout(10_000),\n  }).catch(() => undefined)\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nfunction resolveStepSessionId(\n  step: WorkflowStep,\n  agents: SessionsRegistryAgentHost,\n): string | undefined {\n  if (step.adapter) {\n    return agents.resolveByLabel(step.label)\n  }\n  if (step.sessionRef) {\n    return agents.resolveByLabel(step.sessionRef)\n  }\n  return undefined\n}\n\nfunction fillStepStates(\n  stages: WorkflowStageState[],\n  defs: WorkflowStage[],\n  agents: SessionsRegistryAgentHost,\n): string[] {\n  const sessionIds: string[] = []\n  for (let si = 0; si < stages.length; si++) {\n    const stage = stages[si]!\n    const def = defs[si]\n    if (!def) continue\n    for (let i = 0; i < stage.steps.length; i++) {\n      const stepState = stage.steps[i]!\n      const stepDef = def.steps[i]\n      if (!stepDef) continue\n      stepState.sessionId = resolveStepSessionId(stepDef, agents)\n      if (stepState.sessionId) sessionIds.push(stepState.sessionId)\n    }\n  }\n  return sessionIds\n}\n\n// ── Background execution ─────────────────────────────────────────────\n\nasync function executeRunWorkflow(\n  state: RunState,\n  runtimeWf: RuntimeWorkflow,\n  agents: SessionsRegistryAgentHost,\n  signal: AbortSignal,\n  cache?: StepCache,\n  cacheKey?: string,\n): Promise<void> {\n  try {\n    await runWorkflow({\n      workflow: runtimeWf,\n      agents,\n      signal,\n      cwd: state.cwd,\n      workspaceSlug: state.workspaceSlug,\n      ...(cache ? { cache, cacheKey } : {}),\n    })\n\n    // Success — mark all stages/steps done.\n    for (const stage of state.run.stages) {\n      stage.status = \"done\"\n      for (const step of stage.steps) {\n        step.status = \"done\"\n        step.endedAt = new Date().toISOString()\n      }\n    }\n    state.run.status = \"done\"\n    state.run.endedAt = new Date().toISOString()\n\n    const sessionIds = fillStepStates(state.run.stages, state.stages, agents)\n    if (sessionIds.length > 0) state.run.result = { sessionIds }\n  } catch (err) {\n    if (signal.aborted) {\n      state.run.status = \"cancelled\"\n      state.run.endedAt = new Date().toISOString()\n    } else {\n      const errMsg = err instanceof Error ? err.message : String(err)\n      state.run.status = \"failed\"\n      state.run.error = errMsg\n      state.run.endedAt = new Date().toISOString()\n\n      // Mark stage 0 as failed (common case) and the rest as pending.\n      for (let i = 0; i < state.run.stages.length; i++) {\n        const stage = state.run.stages[i]!\n        if (i === 0) {\n          stage.status = \"failed\"\n          for (const step of stage.steps) {\n            step.status = \"failed\"\n            step.endedAt = new Date().toISOString()\n            step.error = errMsg\n          }\n        }\n        // else: remaining stages stay \"pending\"\n      }\n    }\n  }\n\n  fireNotifyUrl(state.run)\n}\n\nexport function createWorkflowRunner(opts: {\n  registry: SessionsRegistry\n  sessionEvents: SessionEventBus\n  resolveAgentAdapter: AgentAdapterResolver\n  webhookNotifier?: WebhookNotifier\n  /** Absolute path for the persistence file. Defaults to ~/.agentproto/workflow-runs.json */\n  persistPath?: string\n  /** Enable filesystem persistence. Defaults to `true` when `persistPath` is\n   *  explicitly supplied, `false` otherwise — mirrors routine-runner.ts. */\n  persist?: boolean\n}): WorkflowRunner {\n  const { registry, sessionEvents, resolveAgentAdapter } = opts\n  const persistPath = opts.persistPath ?? DEFAULT_PERSIST_PATH()\n  const shouldPersist = opts.persist ?? (opts.persistPath !== undefined)\n\n  const runs = shouldPersist ? loadRuns(persistPath) : new Map<string, RunState>()\n\n  const persist = (): void => {\n    if (shouldPersist) saveRuns(runs, persistPath)\n  }\n\n  // ── Public interface ───────────────────────────────────────────────\n\n  return {\n    start: async (input) => {\n      const runId = `wfrun_${randomUUID()}`\n      const run: WorkflowRun = {\n        runId,\n        workflowId: input.workflowId,\n        status: \"running\",\n        startedAt: new Date().toISOString(),\n        stages: input.stages.map((stage, si) => ({\n          index: si,\n          ...(stage.label !== undefined ? { label: stage.label } : {}),\n          status: \"pending\" as const,\n          steps: stage.steps.map((s, i) => ({\n            index: i,\n            label: s.label,\n            status: \"pending\" as const,\n          })),\n        })),\n        ...(input.notifyUrl ? { notifyUrl: input.notifyUrl } : {}),\n      }\n      const abort = new AbortController()\n      const state: RunState = {\n        run,\n        cancelled: false,\n        abort,\n        stages: input.stages,\n        ...(input.cwd !== undefined ? { cwd: input.cwd } : {}),\n        ...(input.workspaceSlug !== undefined ? { workspaceSlug: input.workspaceSlug } : {}),\n      }\n      runs.set(runId, state)\n      persist()\n\n      // Translate stages → RuntimeWorkflow and launch.\n      const workflow = translateStages(input.stages, input.workflowId)\n      const agents = new SessionsRegistryAgentHost(\n        registry,\n        sessionEvents,\n        resolveAgentAdapter,\n        {\n          workspaceSlug: input.workspaceSlug,\n          cwd: input.cwd,\n          notifyUrl: input.notifyUrl,\n        },\n      )\n\n      const cache = input.cacheKey ? createFileStepCache(input.cacheKey) : undefined\n\n      void executeRunWorkflow(state, workflow, agents, abort.signal, cache, input.cacheKey).then(() => {\n        persist()\n      })\n\n      return run\n    },\n\n    status: (runId) => runs.get(runId)?.run,\n\n    list: () => Array.from(runs.values()).map(s => s.run),\n\n    // No-op today: `pendingResolve` is never set (escalate fails fast — see\n    // RunState.pendingResolve). Retained for the durable suspend/resume\n    // follow-up so the interface stays stable for existing callers.\n    resolve: (runId, stageIndex, stepIndex, response) => {\n      const state = runs.get(runId)\n      if (!state) return\n      const pr = state.pendingResolve\n      if (pr && pr.stageIndex === stageIndex && pr.stepIndex === stepIndex) {\n        pr.resolver(response)\n      }\n    },\n\n    cancel: (runId) => {\n      const state = runs.get(runId)\n      if (!state) return\n      state.cancelled = true\n      state.abort.abort()\n      if (state.run.status === \"running\" || state.run.status === \"awaiting-input\") {\n        state.run.status = \"cancelled\"\n        state.run.endedAt = new Date().toISOString()\n        persist()\n      }\n    },\n  }\n}","/**\n * Deferred/lazy MCP tool loading (harness-parity item 3).\n *\n * Motivation: a root `/mcp` session sees every tool the daemon registers —\n * today that's 60+ tools across families (agent_*, session_*, policy_*,\n * routine_*, workflow_*, terminal_*, command_*, file_*, directory_*,\n * browser_*, tunnel_*, mcp_*, inbound_watcher_*) — all with full schemas,\n * loaded upfront, whether or not the session ever touches most of them.\n *\n * NB: imported third-party MCP servers (`mcp_import`) do NOT have this\n * problem — they're already proxied behind `mcp_imported_tool_list` /\n * `mcp_imported_call` (session-tools.ts), a search-then-call pattern that\n * never mounts an upstream server's tools directly. This module addresses\n * the daemon's OWN gateway tools, the part of the surface still eager.\n *\n * ## Why this does NOT use the SDK's enable()/disable()\n *\n * `@modelcontextprotocol/sdk` 1.29.0's `server.tool(...)` returns a\n * `RegisteredTool` with `.enable()`/`.disable()`, `tools/list` filters on\n * `.enabled`, and the server auto-advertises `tools: { listChanged: true }`\n * — a real, SDK-supported dynamic-registration mechanism. An earlier draft\n * of this module used exactly that: register tools disabled, `.enable()`\n * them from `tool_search`.\n *\n * It does not work here. `http-server.ts` documents (and a live daemon\n * run confirmed): \"MCP transport: stateless mode for v1 — each request is\n * independent\" — a FRESH `McpServer` is built via `mcpServerFactory()` for\n * EVERY request, including `tools/call`. An `.enable()` mutation made\n * during a `tool_search` call lives only on that call's own throwaway\n * server instance; the very next `tools/call` for the newly-\"enabled\"\n * tool gets a brand-new instance where it's disabled again, and fails\n * with `Tool X disabled`. Confirmed by running exactly that sequence\n * against a live gateway — the mutation never survives past the request\n * that made it, so a real orchestrator would search successfully, read\n * a schema, then have the follow-up call rejected. Worse than doing\n * nothing: it looks like it works, right up until the second call.\n *\n * ## What this does instead\n *\n * Every tool stays fully registered AND enabled (`tools/call` always\n * works for any tool name, deferred or not — the daemon is stateless\n * regardless, so there is no session-scoped \"have they earned the right\n * to call this\" state to enforce even if it were desirable). \"Deferred\"\n * only means: excluded from the `tools/list` response, so a session\n * doesn't pay the schema-loading token tax for tools it never asked\n * about. The `tools/list` handler is overridden directly on the\n * underlying low-level `Server` (`mcpServer.server.setRequestHandler` —\n * the SDK's own documented escape hatch: \"For advanced usage ... use the\n * underlying Server instance\") to return only the `alwaysOn` set plus\n * `tool_search` itself; this is a pure per-request read, so it's\n * naturally correct under statelessness — there's no history to lose.\n * `tool_search` matches a keyword (or `select:name1,name2` for exact\n * names) against a catalog of every OTHER registered tool and returns\n * full JSON Schema for the hits directly in its own result text — the\n * one channel that reliably survives the stateless boundary, since it's\n * read from the SAME call that produced it.\n *\n * Opt-in and backward-compatible by construction: nothing calls this\n * unless a host explicitly wires `deferredTools` into `createGateway` —\n * see `index.ts`. Every existing daemon keeps registering (and exposing)\n * everything eagerly, exactly as before.\n *\n * Both SDK registration entry points are intercepted — `server.tool(...)`\n * AND `server.registerTool(...)` (the config-object overload; e.g.\n * mcp-apps-adapter.ts's `agentproto_sessions` panel tool uses the latter,\n * and would silently skip the catalog if only one were patched).\n *\n * Tools registered on the server BEFORE it's wrapped — e.g. `self_inspect`,\n * added inside `@agentproto/mcp-server`'s `createMcpServer()` — are\n * automatically excluded from `tools/list` too: the override only lists\n * names present in `registry` (built from tools that passed through the\n * proxy), so anything registered earlier is simply absent from that set,\n * with no extra bookkeeping needed. They stay fully callable, same as\n * every other tool here — the override only ever touches what `tools/list`\n * shows.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { ListToolsRequestSchema } from \"@modelcontextprotocol/sdk/types.js\"\nimport { z } from \"zod\"\n\ninterface CatalogEntry {\n  description?: string\n  inputSchema?: unknown\n}\n\nexport interface DeferredToolGatewayOptions {\n  /** Tool names that stay in `tools/list` from the first connection — the\n   *  always-on hot loop. Everything else registered through the wrapped\n   *  server is fully callable (statelessness makes gating calls pointless\n   *  — see module docs) but excluded from `tools/list` until\n   *  `tool_search`ed. */\n  alwaysOn: ReadonlySet<string>\n}\n\n/** Best-effort JSON Schema for a tool's Zod input object — `undefined`\n *  when the tool takes no arguments, or on any conversion failure (a\n *  malformed/incompatible schema shouldn't break the response, just omit\n *  that one tool's schema). */\nfunction toJsonSchema(inputSchema: unknown): unknown {\n  if (!inputSchema) return undefined\n  try {\n    return z.toJSONSchema(inputSchema as Parameters<typeof z.toJSONSchema>[0])\n  } catch {\n    return undefined\n  }\n}\n\nconst TOOL_SEARCH_NAME = \"tool_search\"\n\nexport function withDeferredTools(\n  server: McpServer,\n  opts: DeferredToolGatewayOptions,\n): McpServer {\n  const alwaysOn = new Set([...opts.alwaysOn, TOOL_SEARCH_NAME])\n  // Every tool that passes through the proxy, always-on or not — the\n  // `tools/list` override reads the always-on subset of this; `tool_search`\n  // reads everything else.\n  const registry = new Map<string, CatalogEntry>()\n\n  type RawRegisteredTool = { description?: string; inputSchema?: unknown }\n\n  /** Shared by both SDK registration entry points (`tool()` AND\n   *  `registerTool()` — mcp-apps-adapter.ts uses the latter; missing\n   *  either one would silently let those tools skip the catalog). */\n  const intercept =\n    (fn: (...a: unknown[]) => RawRegisteredTool) =>\n    (name: string, ...rest: unknown[]): RawRegisteredTool => {\n      const registered = fn(name, ...rest)\n      registry.set(name, { description: registered.description, inputSchema: registered.inputSchema })\n      return registered\n    }\n\n  const proxied = new Proxy(server, {\n    get(target, prop, receiver) {\n      if (prop === \"tool\") {\n        return intercept(target.tool.bind(target) as (...a: unknown[]) => RawRegisteredTool)\n      }\n      if (prop === \"registerTool\") {\n        return intercept(target.registerTool.bind(target) as (...a: unknown[]) => RawRegisteredTool)\n      }\n      const value = Reflect.get(target, prop, receiver)\n      return typeof value === \"function\" ? value.bind(target) : value\n    },\n  })\n\n  // Registered THROUGH the proxy (not directly on `server`) so it lands in\n  // `registry` and is naturally part of the always-on set via the union\n  // above. This call also triggers the SDK's one-time `tools/list`\n  // handler setup (McpServer.setToolRequestHandlers, lazily run on the\n  // first tool registration) — the override below must come AFTER this,\n  // replacing that default handler rather than racing to set it first\n  // (setting it first would make the SDK's own lazy init throw when the\n  // very next real tool registers: \"A request handler for tools/list\n  // already exists\").\n  proxied.tool(\n    TOOL_SEARCH_NAME,\n    \"Look up full schemas for tools hidden from `tools/list` (kept out to \" +\n      \"save context — every tool is still fully callable once you know its \" +\n      \"shape, this just saves you from loading all of them upfront). Match \" +\n      \"by keyword (against tool name + description) or `select:name1,name2` \" +\n      \"for exact names when you already know what you want. Schemas are \" +\n      \"returned directly in this call's result — call the tool by name \" +\n      \"right away, no need to re-fetch `tools/list` first.\",\n    {\n      query: z\n        .string()\n        .min(1)\n        .describe(\n          \"Space-separated keyword(s) to match, or `select:<name1>,<name2>` \" +\n            \"for exact tool names when you already know what you want.\",\n        ),\n      maxResults: z\n        .number()\n        .int()\n        .min(1)\n        .max(20)\n        .optional()\n        .describe(\"Cap on matches returned. Default 5.\"),\n    },\n    async input => {\n      const max = input.maxResults ?? 5\n      const candidates = Array.from(registry.entries()).filter(([name]) => !alwaysOn.has(name))\n      let hits: Array<[string, CatalogEntry]>\n\n      if (input.query.startsWith(\"select:\")) {\n        const names = new Set(\n          input.query\n            .slice(\"select:\".length)\n            .split(\",\")\n            .map(s => s.trim())\n            .filter(Boolean),\n        )\n        hits = candidates.filter(([name]) => names.has(name))\n      } else {\n        const terms = input.query.toLowerCase().split(/\\s+/).filter(Boolean)\n        hits = candidates\n          .map(([name, entry]): [string, CatalogEntry, number] => {\n            const haystack = `${name} ${entry.description ?? \"\"}`.toLowerCase()\n            return [name, entry, terms.filter(t => haystack.includes(t)).length]\n          })\n          .filter(([, , score]) => score > 0)\n          .sort((a, b) => b[2] - a[2])\n          .slice(0, max)\n          .map(([name, entry]) => [name, entry])\n      }\n\n      const tools = hits.map(([name, entry]) => ({\n        name,\n        description: entry.description,\n        inputSchema: toJsonSchema(entry.inputSchema),\n      }))\n      return {\n        content: [\n          {\n            type: \"text\",\n            text: JSON.stringify(\n              {\n                tools,\n                ...(tools.length === 0\n                  ? { note: \"No matching deferred tool. Names are case-sensitive; try a broader keyword.\" }\n                  : {}),\n              },\n              null,\n              2,\n            ),\n          },\n        ],\n      }\n    },\n  )\n\n  // Pure per-request read over `registry` — safe under statelessness since\n  // there's no cross-request history to reflect, just \"what's registered\n  // right now, filtered to alwaysOn\". Overrides the SDK's own default\n  // tools/list handler (installed by the `proxied.tool()` call above);\n  // `Server.setRequestHandler` documents itself as a replace, not an\n  // add — see @modelcontextprotocol/sdk shared/protocol.js.\n  server.server.setRequestHandler(ListToolsRequestSchema, () => ({\n    tools: Array.from(registry.entries())\n      .filter(([name]) => alwaysOn.has(name))\n      .map(([name, entry]) => ({\n        name,\n        description: entry.description,\n        inputSchema: toJsonSchema(entry.inputSchema) ?? { type: \"object\" as const, properties: {} },\n      })),\n  }))\n\n  return proxied\n}\n","/**\n * Completion-policy supervisor — WP1 + WP2 + WP3 + WP4 + WP5 + WP6 + WP7.\n *\n * WP7 (judge-gate): a gate may be a judge AGENT instead of a shell command —\n * `gate: { judge: { adapter, model?, prompt, timeoutMs? } }`. When the trigger\n * fires the supervisor spawns a short-lived agent (resolveAgentAdapter →\n * spawnAgent), prompts it with the rubric (+ a minimal context tail of the\n * watched session output), waits for its turn-end on the bus, reads the final\n * reply and parses the LAST `VERDICT: PASS|FAIL` line (case-insensitive). PASS\n * = gate pass (then-action), FAIL = gate fail (existing nudge/escalate path).\n * Fail-safe: no resolver / spawn fail / timeout (default 120s) / unparseable\n * verdict → FAIL (+ reason on state.error). The judge session is ALWAYS killed\n * when the gate settles. The judge runs while the policy holds its `gating`\n * slot, so it is accounted for in the WP6 concurrency cap. Persistence: a judge\n * gate left in `gating` at crash is re-armed to `watching` like any active\n * policy and simply re-runs the judge — no in-flight judge is persisted.\n *\n *\n * State machine per attached policy:\n *   watching → gating → acting → done\n *                    ↘ nudging (retries < maxRetries) → watching  (gate failed, nudge sent)\n *                    ↘ blocked                                     (gate failed, retries exhausted)\n *                    ↘ awaiting-ack → done       (then:\"commit\" + requireHumanAck, ack approve)\n *                                  ↘ cancelled    (ack reject)\n *   watching → cancelled  (watched session exited before turn-end)\n *\n * Trigger: session:turn-end on the watched session(s).\n * Gate: optional shell command via the same allowlist + cwd-anchor as\n *       command_execute. exit 0 = pass.\n * Action (then:\"emit\"): emits policy:passed / policy:failed on the bus\n *       (readable via session_events_poll).\n *\n * WP5 (then:\"commit\"): on a GREEN gate, prepare a host-side git commit in the\n * watched session's cwd — `git add -- <explicit paths>` then `git commit -m\n * <message>` via the same allowlisted runCommand path (argv array, shell:false).\n * GUARDRAILS: never `git add -A`/glob, never `git push`, never `--force`, never\n * a branch the policy didn't ask for (commits the cwd's current branch), message\n * passed as argv (no shell injection), empty paths → error (no commit). A `--`\n * separator precedes the paths so a path can never be parsed as a git flag.\n * \"nothing to commit\" is treated as SUCCESS (idempotent re-commit after a\n * restart). `requireHumanAck` defaults to TRUE: the gate-green transition goes\n * to `awaiting-ack` and emits `policy:commit-ready` (paths + message) instead of\n * committing; the commit runs only on `policy_ack(approve:true)` →\n * `policy:committed` (+ sha) → done; `approve:false` → cancelled. With\n * `requireHumanAck:false` the commit runs directly at the green gate.\n * onFail (WP2): when gate fails, re-prompts the session(s) (sendPrompt) up to\n *       maxRetries times, then transitions to blocked + emits policy:failed.\n *\n * WP3: persists PolicyRunState + input to ~/.agentproto/policies.json (or an\n * injected persistPath). Debounced async write on every transition; sync flush\n * at shutdown(). On boot, active policies (watching/gating/nudging/acting) are\n * re-armed to \"watching\" and re-subscribed to the bus. Terminal states (done/\n * blocked/cancelled) are kept for history. Session absent at reload → cancelled.\n *\n * WP6 (DAG + concurrency cap):\n *   - CHAINING: a policy may declare `next` — a recursive AttachPolicyInput.\n *     When the policy reaches `done` (emit-passed or commit-committed), the\n *     supervisor automatically attaches `next` as a fresh completion policy on\n *     the session(s) named in its own spec (chaining policies over EXISTING\n *     sessions — this WP does NOT spawn new sessions). The child's policyId is\n *     recorded on the parent as `nextPolicyId`. Chaining is idempotent (a parent\n *     already carrying a `nextPolicyId` never re-chains, so a re-armed/re-acked\n *     parent after a restart won't double-attach). `next` persists as part of the\n *     parent's `input`, so the whole chain survives a restart.\n *   - CONCURRENCY CAP: a daemon-wide cap (`concurrencyCap`, default 8) on how\n *     many policies may be in `gating`/`acting` at once. When a trigger fires\n *     and the cap is already saturated, the policy parks in `queued` (a FIFO\n *     gate queue) instead of gating. As each active policy settles (done /\n *     blocked / awaiting-ack / back-to-watching after a nudge), the queue is\n *     pumped and the oldest queued policy proceeds to gate. Queued policies hold\n *     NO slot, so a chained DAG can't deadlock behind the cap. The queued state\n *     persists and is re-armed to `watching` on reload (then re-evaluated).\n *\n * WP4 (fan-in): a policy may watch a GROUP of sessions (`sessionIds`). The gate\n * runs ONCE, only after EVERY member of the group has finished its turn. Members\n * are tracked in an idempotent `pending` set: a member is removed on its first\n * `session:turn-end`; a repeated turn-end for an already-removed member is a\n * no-op (no double-count). When the set empties → gating.\n *\n * A member that emits `session:exited` is treated as \"this member is done\": it\n * is removed from the pending set exactly like a turn-end (a dead session will\n * never emit one), so a partially-crashed group can still complete. If every\n * member exits, the set empties and the gate runs once. The one exception is the\n * degenerate group of size 1 (the legacy single-`sessionId` form): a lone\n * watched session that exits has nothing left to gate on, so the policy is\n * cancelled — preserving the original single-session contract.\n *\n * Back-compat: the legacy `sessionId` (single) form is a group of one. `state.\n * sessionId` is retained as the group's representative (group[0]) and is the id\n * carried on policy:passed / policy:failed events.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { basename, dirname } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { resolve } from \"node:path\"\nimport {\n  mkdirSync,\n  writeFileSync,\n  readFileSync,\n  promises as fsp,\n} from \"node:fs\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { SessionEventBus } from \"./session-event-bus.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\nimport {\n  runCommand as defaultRunCommand,\n  loadAllowlist,\n  makeCwdAnchor,\n} from \"./command-tools.js\"\nimport type { RunCommandInput, ExecuteResult } from \"./command-tools.js\"\n\n// ── Public types ─────────────────────────────────────────────────────\n\nexport interface ShellGateSpec {\n  command: string\n  args?: string[]\n  /** Working directory for the gate command. Defaults to the watched\n   *  session's own cwd (trusted as-is — it was already an explicit,\n   *  vetted choice made at `agent_start` time). When given explicitly,\n   *  anchored to that session's cwd (not the daemon's boot workspace)\n   *  so a stray/injected value can't escape it. */\n  cwd?: string\n  timeoutMs?: number\n}\n\n/**\n * Judge-agent gate (WP7). Instead of a shell command, the gate spawns a\n * short-lived LLM agent (via the daemon's `resolveAgentAdapter`), prompts it\n * with `prompt` (+ a minimal context tail of the watched session output, if\n * readable), waits for its turn to end, reads the final reply and parses a\n * verdict line (`VERDICT: PASS` / `VERDICT: FAIL`, last occurrence,\n * case-insensitive). PASS = gate pass (exit 0 equivalent), FAIL = gate fail\n * (→ the existing nudge/escalate path). Fail-safe: a judge timeout OR an\n * unparseable reply is treated as FAIL. The judge session is always killed\n * when the gate settles (success or failure).\n */\nexport interface JudgeGateSpec {\n  judge: {\n    /** Agent CLI adapter slug used to spawn the judge (e.g. \"claude-code\"). */\n    adapter: string\n    /** Optional model identifier forwarded to the adapter. */\n    model?: string\n    /** The rubric / instructions for the judge. The supervisor appends a\n     *  fixed instruction to end the reply with `VERDICT: PASS` or\n     *  `VERDICT: FAIL`. */\n    prompt: string\n    /** Max wall-clock for the judge turn before it is killed + FAIL.\n     *  Default 120_000ms. */\n    timeoutMs?: number\n  }\n}\n\n/** A gate is either a shell command (exit 0 = pass) or a judge agent. */\nexport type GateSpec = ShellGateSpec | JudgeGateSpec\n\n/** Narrow a gate spec to the judge variant. */\nfunction isJudgeGate(gate: GateSpec): gate is JudgeGateSpec {\n  return typeof (gate as JudgeGateSpec).judge === \"object\"\n}\n\nexport interface OnFailSpec {\n  /**\n   * Message sent to the watched session via sendPrompt when the gate fails.\n   * Use the placeholder {code} to embed the actual exit code.\n   * Default: \"Le gate a échoué (exit {code}). Corrige et termine jusqu'à ce qu'il passe.\"\n   */\n  nudge?: string\n  /**\n   * Maximum number of consecutive gate failures before transitioning to\n   * blocked. Must be >= 1. Default: 2.\n   */\n  maxRetries?: number\n}\n\nexport interface CommitSpec {\n  /**\n   * Explicit, literal paths to stage — workspace/cwd-relative. NEVER a glob,\n   * NEVER `-A`/`--all`. Staged via `git add -- <paths>` (the `--` guards each\n   * path from being parsed as a flag). An empty array is rejected at attach.\n   */\n  paths: string[]\n  /** Commit message. Passed as a single `-m` argv value — no shell. */\n  message: string\n  /**\n   * Human-in-the-loop gate before the commit actually runs. Default TRUE:\n   * the green gate transitions to `awaiting-ack` + emits `policy:commit-ready`\n   * and waits for `policy_ack`. Set false to commit directly at the green gate.\n   */\n  requireHumanAck?: boolean\n}\n\nexport interface AttachPolicyInput {\n  /**\n   * Session id whose turn-end triggers the policy (single-session / legacy\n   * form). Equivalent to `sessionIds: [sessionId]`. Provide this OR\n   * `sessionIds`; if both are given, `sessionIds` wins.\n   */\n  sessionId?: string\n  /**\n   * Fan-in group (WP4): the gate runs once, only after EVERY listed session\n   * has finished its turn (turn-end or exit). Supersedes `sessionId` when\n   * present and non-empty. A single-element array behaves like `sessionId`.\n   */\n  sessionIds?: string[]\n  /**\n   * Optional gate. Absent → always pass immediately. Either a shell gate\n   * (exit 0 = pass) or a judge-agent gate (WP7: `{ judge: {...} }`).\n   */\n  gate?: GateSpec\n  /**\n   * Action on a GREEN gate. \"emit\" (WP1) emits policy:passed. \"commit\" (WP5)\n   * stages explicit paths and commits on the host — see `commit`.\n   */\n  then: \"emit\" | \"commit\"\n  /** Required when then === \"commit\". Ignored otherwise. */\n  commit?: CommitSpec\n  /**\n   * What to do when the gate fails (WP2). Absent → immediately blocked\n   * (WP1 behaviour). Present → re-prompt the session up to maxRetries\n   * times before blocking; the session must still be running to nudge.\n   */\n  onFail?: OnFailSpec\n  /**\n   * DAG chaining (WP6). When this policy reaches `done`, the supervisor\n   * automatically attaches `next` as a fresh completion policy. `next` is a\n   * full AttachPolicyInput (recursive — it may declare its own `next`), and it\n   * carries the session(s) it watches in its own spec. Chaining only attaches\n   * policies onto already-running sessions; it never spawns new sessions.\n   */\n  next?: AttachPolicyInput\n}\n\nexport type PolicyRunStatus =\n  | \"watching\"\n  | \"queued\"\n  | \"gating\"\n  | \"acting\"\n  | \"nudging\"\n  | \"awaiting-ack\"\n  | \"done\"\n  | \"blocked\"\n  | \"cancelled\"\n\nexport interface PolicyRunState {\n  policyId: string\n  /** Representative session id (the fan-in group's first member, group[0]).\n   *  Carried on policy:passed / policy:failed events. */\n  sessionId: string\n  /** The full fan-in group being watched. Always present; a length-1 group is\n   *  the legacy single-session form. */\n  sessionIds: string[]\n  /** Sessions in the group that have NOT yet finished their turn. The gate\n   *  fires once this set empties. Idempotent: a member is removed on its first\n   *  turn-end/exit; repeats are no-ops. Reset to the full group on each nudge. */\n  pending: string[]\n  status: PolicyRunStatus\n  /** Number of nudges sent so far (incremented after each nudge round). */\n  retries: number\n  startedAt: string\n  endedAt?: string\n  lastGate?: { exitCode: number; at: string }\n  /**\n   * The exact commit prepared at the green gate (WP5). Set when entering\n   * `awaiting-ack` (or just before a direct commit) so that an ack arriving\n   * after a daemon restart commits the same paths/message in the same cwd,\n   * independent of whether the watched session still exists.\n   */\n  commitPlan?: { paths: string[]; message: string; cwd: string }\n  /** The resulting commit sha once `then:\"commit\"` has committed. */\n  commitSha?: string\n  /**\n   * DAG chaining (WP6): the policyId of the child policy attached when this\n   * policy reached `done`. Set exactly once (idempotent chaining guard).\n   */\n  nextPolicyId?: string\n  error?: string\n}\n\nexport interface CompletionPolicySupervisor {\n  /**\n   * Attach a completion policy to an already-running session.\n   * Returns immediately with the initial (watching) state.\n   * The state machine runs in the background.\n   */\n  attach(input: AttachPolicyInput): PolicyRunState\n  getStatus(policyId: string): PolicyRunState | undefined\n  cancel(policyId: string): void\n  /**\n   * Human acknowledgement for a `then:\"commit\"` policy parked in\n   * `awaiting-ack` (WP5). `approve:true` runs the prepared commit (→ done,\n   * emits policy:committed); `approve:false` cancels it (no commit). No-op on\n   * any other state. Returns the (possibly updated) state.\n   */\n  ack(policyId: string, approve: boolean): Promise<PolicyRunState | undefined>\n  list(): PolicyRunState[]\n  /**\n   * Subscribe to policy settlements — fired whenever a policy transitions\n   * into a terminal state (done / blocked / cancelled) OR into awaiting-ack.\n   * Used by the `/policies/:id/wait` long-poll to block until a policy\n   * resolves without reimplementing the state machine's event surface.\n   * Returns an unsubscribe fn. The callback receives the policyId; read\n   * the full state via `getStatus(policyId)`.\n   */\n  onSettle(cb: (policyId: string) => void): () => void\n  /**\n   * Sync flush of the policy snapshot to disk. Call from the daemon\n   * stop() path — mirrors sessions.shutdown().\n   */\n  shutdown(): void\n}\n\n// ── Internal ─────────────────────────────────────────────────────────\n\ninterface RunEntry {\n  input: AttachPolicyInput\n  /** Resolved fan-in group (deduped, order-preserved). group[0] is the repr. */\n  group: string[]\n  /** Live idempotent set of sessions still awaited. Mirrored to state.pending. */\n  pending: Set<string>\n  state: PolicyRunState\n  unsubscribes: Array<() => void>\n  cancelled: boolean\n  /** Per-entry gate runner, set by armEntry; invoked by the concurrency-cap\n   *  queue pump (WP6) when a slot frees. */\n  runGate?: () => Promise<void>\n}\n\n/**\n * Resolve the watched group from an attach input. `sessionIds` (when present\n * and non-empty) wins over the legacy `sessionId`. Deduped, order-preserved.\n * Throws if neither yields a session id.\n */\nfunction resolveGroup(input: AttachPolicyInput): string[] {\n  const raw =\n    input.sessionIds && input.sessionIds.length > 0\n      ? input.sessionIds\n      : input.sessionId\n        ? [input.sessionId]\n        : []\n  const group = Array.from(new Set(raw))\n  if (group.length === 0) {\n    throw new Error(\"policy_attach requires sessionId or a non-empty sessionIds\")\n  }\n  return group\n}\n\n/** Persisted envelope written to policies.json. */\ninterface PolicySnapshot {\n  savedAt: string\n  policies: Array<{ input: AttachPolicyInput; state: PolicyRunState }>\n}\n\nconst DEFAULT_NUDGE_TEMPLATE =\n  \"Le gate a échoué (exit {code}). Corrige et termine jusqu'à ce qu'il passe.\"\nconst DEFAULT_MAX_RETRIES = 2\n/** Judge-gate (WP7) wall-clock default before timeout → kill + FAIL. */\nconst DEFAULT_JUDGE_TIMEOUT_MS = 120_000\n/** Fixed instruction appended to the judge prompt so its verdict is parseable. */\nconst JUDGE_VERDICT_INSTRUCTION =\n  \"\\n\\nWhen you are done, end your reply with a single line containing exactly \" +\n  \"`VERDICT: PASS` (if the criteria are met) or `VERDICT: FAIL` (if not). \" +\n  \"Do not write anything after that line.\"\n/** Strip ANSI escape sequences (mirrors session-tools.stripAnsi). */\n// eslint-disable-next-line no-control-regex\nconst ANSI_RE = /\\x1b\\[[0-9;?]*[A-Za-z]/g\nfunction stripAnsi(s: string): string {\n  return s.replace(ANSI_RE, \"\")\n}\n/**\n * Parse the judge verdict from its final reply. Scans for `VERDICT: PASS|FAIL`\n * (case-insensitive) and returns the LAST occurrence. Returns null when no\n * verdict line is present → caller treats as FAIL (fail-safe).\n */\nfunction parseVerdict(text: string): \"PASS\" | \"FAIL\" | null {\n  const re = /VERDICT:\\s*(PASS|FAIL)/gi\n  let last: \"PASS\" | \"FAIL\" | null = null\n  let m: RegExpExecArray | null\n  while ((m = re.exec(text)) !== null) {\n    last = m[1]!.toUpperCase() as \"PASS\" | \"FAIL\"\n  }\n  return last\n}\nconst PERSIST_DEBOUNCE_MS = 1_500\n/** Daemon-wide default cap on policies concurrently in gating/acting (WP6). */\nconst DEFAULT_CONCURRENCY_CAP = 8\n\nexport const POLICIES_FILE_PATH = (): string =>\n  resolve(homedir(), \".agentproto\", \"policies.json\")\n\n// ── Factory ──────────────────────────────────────────────────────────\n\nexport function createCompletionPolicySupervisor(opts: {\n  registry: SessionsRegistry\n  sessionEvents: SessionEventBus\n  workspace: string\n  /** Override the persist path — used in tests to avoid touching ~/.agentproto. */\n  persistPath?: string\n  /** Disable persistence entirely (e.g. for unit tests that don't need it). */\n  persist?: boolean\n  /**\n   * Inject the command runner — used by tests to mock git (gate + commit) so\n   * no real subprocess/commit runs. Defaults to the host runCommand.\n   */\n  runCommand?: (input: RunCommandInput) => Promise<ExecuteResult>\n  /**\n   * Daemon-wide cap on policies concurrently in gating/acting (WP6). Excess\n   * triggered policies queue (FIFO) until a slot frees. Default 8. Values < 1\n   * are clamped to 1.\n   */\n  concurrencyCap?: number\n  /**\n   * Adapter resolver used to spawn a judge agent for a judge-gate (WP7).\n   * Same resolver the daemon passes to `agent_start`. When absent, a\n   * judge-gate fails fail-safe (FAIL) with a clear reason — shell gates are\n   * unaffected.\n   */\n  resolveAgentAdapter?: AgentAdapterResolver\n}): CompletionPolicySupervisor {\n  const { registry, sessionEvents, workspace, resolveAgentAdapter } = opts\n  const exec = opts.runCommand ?? defaultRunCommand\n  const persistPath = opts.persistPath ?? POLICIES_FILE_PATH()\n  const cap = Math.max(1, opts.concurrencyCap ?? DEFAULT_CONCURRENCY_CAP)\n  /** FIFO queue of entries whose trigger fired while the cap was saturated. */\n  const gateQueue: RunEntry[] = []\n  // Default false: WP1/WP2 tests (no opts.persist, no opts.persistPath)\n  // don't touch ~/.agentproto. Set opts.persist:true in production\n  // (createGateway) or supply persistPath to implicitly enable it.\n  const persist = opts.persist ?? (opts.persistPath !== undefined)\n  const runs = new Map<string, RunEntry>()\n  let persistTimer: ReturnType<typeof setTimeout> | null = null\n  let shutdownDone = false\n\n  // ── settlement listeners (for /policies/:id/wait long-poll) ──────\n\n  /**\n   * Listeners fired whenever a policy reaches a terminal state (done /\n   * blocked / cancelled) or parks in awaiting-ack. The HTTP long-poll\n   * `GET /policies/:id/wait` subscribes here to block until a policy\n   * resolves, mirroring the MCP `policy_status` semantics but as a\n   * blocking call. Some transitions (cancel(), ack(false), single-session\n   * exit) emit no SessionEventBus event, so this hook is the single\n   * reliable signal — see `notifySettled`.\n   */\n  const settleListeners = new Set<(policyId: string) => void>()\n  const notifySettled = (policyId: string): void => {\n    for (const cb of settleListeners) {\n      try {\n        cb(policyId)\n      } catch (err) {\n        console.warn(\n          `[supervisor] onSettle listener threw: ${err instanceof Error ? err.message : String(err)}`,\n        )\n      }\n    }\n  }\n\n  // ── persistence helpers ──────────────────────────────────────────\n\n  const buildSnapshot = (): PolicySnapshot => ({\n    savedAt: new Date().toISOString(),\n    policies: Array.from(runs.values()).map(e => ({\n      input: e.input,\n      state: e.state,\n    })),\n  })\n\n  const schedulePersist = (): void => {\n    if (!persist) return\n    if (persistTimer) clearTimeout(persistTimer)\n    persistTimer = setTimeout(() => {\n      void (async () => {\n        try {\n          const snap = buildSnapshot()\n          await fsp.mkdir(dirname(persistPath), { recursive: true })\n          await fsp.writeFile(\n            persistPath,\n            JSON.stringify(snap, null, 2) + \"\\n\",\n          )\n        } catch (err) {\n          console.warn(\n            `[supervisor] persist failed: ${err instanceof Error ? err.message : String(err)}`,\n          )\n        }\n      })()\n    }, PERSIST_DEBOUNCE_MS)\n  }\n\n  // ── concurrency cap (WP6) ────────────────────────────────────────\n\n  /** Policies currently holding a slot — i.e. in gating or acting. */\n  const countActive = (): number => {\n    let n = 0\n    for (const e of runs.values()) {\n      if (e.state.status === \"gating\" || e.state.status === \"acting\") n++\n    }\n    return n\n  }\n\n  /**\n   * Release-time pump: while there is a free slot, dequeue the oldest queued\n   * entry and run its gate. A dequeued entry is flipped back to `watching` so\n   * its runGate() guard passes; runGate() then synchronously sets `gating`\n   * (before its first await), so the loop's next countActive() sees the slot\n   * taken — no over-admission. Cancelled / no-longer-queued entries are skipped.\n   */\n  const pumpQueue = (): void => {\n    while (gateQueue.length > 0 && countActive() < cap) {\n      const entry = gateQueue.shift()!\n      if (entry.cancelled || entry.state.status !== \"queued\") continue\n      entry.state.status = \"watching\"\n      schedulePersist()\n      void entry.runGate?.()\n    }\n  }\n\n  // ── DAG chaining (WP6) ───────────────────────────────────────────\n\n  /**\n   * When `entry` reaches `done`, attach its `next` policy (if any) onto the\n   * session(s) named in the `next` spec. Idempotent: a parent that already\n   * carries a `nextPolicyId` never re-chains, so a re-armed or re-acked parent\n   * after a restart won't double-attach the child.\n   */\n  const maybeChain = (entry: RunEntry): void => {\n    const next = entry.input.next\n    if (!next) return\n    if (entry.state.nextPolicyId) return\n    try {\n      const child = attachPolicy(next)\n      entry.state.nextPolicyId = child.policyId\n      schedulePersist()\n    } catch (err) {\n      entry.state.error = `next chain failed: ${err instanceof Error ? err.message : String(err)}`\n      schedulePersist()\n    }\n  }\n\n  // ── commit action (WP5) ──────────────────────────────────────────\n\n  /**\n   * Stage explicit paths and commit on the host. Fixed argv, shell:false:\n   *   git add -- <paths...>      (the `--` guards paths from flag-parsing)\n   *   git commit -m <message>    (message is one argv value, never a shell str)\n   *   git rev-parse HEAD         (read back the sha)\n   * No `-A`, no glob, no push, no --force, no branch switch — the commit lands\n   * on whatever branch the cwd is already on. \"nothing to commit\" → success.\n   */\n  async function performCommit(plan: {\n    paths: string[]\n    message: string\n    cwd: string\n  }): Promise<{ sha: string } | { error: string }> {\n    if (plan.paths.length === 0) {\n      return { error: \"commit requires a non-empty paths[]\" }\n    }\n    // Defensive: argv-only, but still refuse blatantly unsafe path entries.\n    if (plan.paths.some(p => typeof p !== \"string\" || p.length === 0)) {\n      return { error: \"commit paths must be non-empty strings\" }\n    }\n\n    const allowlist = await loadAllowlist(workspace)\n    if (!allowlist.has(\"git\")) {\n      return { error: \"commit command 'git' not in allowlist\" }\n    }\n\n    const add = await exec({\n      command: \"git\",\n      args: [\"add\", \"--\", ...plan.paths],\n      cwd: plan.cwd,\n      timeoutMs: 60_000,\n    })\n    if (add.exitCode !== 0) {\n      return { error: `git add failed (exit ${add.exitCode}): ${add.stderr.trim()}` }\n    }\n\n    const commit = await exec({\n      command: \"git\",\n      args: [\"commit\", \"-m\", plan.message],\n      cwd: plan.cwd,\n      timeoutMs: 60_000,\n    })\n    // \"nothing to commit\" is success — a re-armed policy after a crash may find\n    // the tree already committed (design §5.4).\n    const out = `${commit.stdout}\\n${commit.stderr}`\n    const nothingToCommit = /nothing to commit|no changes added|nothing added to commit/i.test(out)\n    if (commit.exitCode !== 0 && !nothingToCommit) {\n      return { error: `git commit failed (exit ${commit.exitCode}): ${commit.stderr.trim()}` }\n    }\n\n    const head = await exec({\n      command: \"git\",\n      args: [\"rev-parse\", \"HEAD\"],\n      cwd: plan.cwd,\n      timeoutMs: 30_000,\n    })\n    if (head.exitCode !== 0) {\n      return { error: `git rev-parse HEAD failed (exit ${head.exitCode}): ${head.stderr.trim()}` }\n    }\n    return { sha: head.stdout.trim() }\n  }\n\n  /**\n   * Run the prepared commit for `entry` and settle its state. Does NOT touch\n   * bus subscriptions (callers handle that). Used by both the direct-commit\n   * path and the ack-approve path.\n   */\n  async function finishCommit(entry: RunEntry): Promise<void> {\n    const state = entry.state\n    const repr = entry.group[0]!\n    const plan = state.commitPlan\n    if (!plan) {\n      state.status = \"blocked\"\n      state.error = \"no commit plan\"\n      state.endedAt = new Date().toISOString()\n      sessionEvents.emit({\n        type: \"policy:failed\",\n        policyId: state.policyId,\n        sessionId: repr,\n        ts: new Date().toISOString(),\n      })\n      schedulePersist()\n      notifySettled(state.policyId)\n      return\n    }\n\n    const result = await performCommit(plan)\n    if (\"error\" in result) {\n      state.status = \"blocked\"\n      state.error = result.error\n      state.endedAt = new Date().toISOString()\n      sessionEvents.emit({\n        type: \"policy:failed\",\n        policyId: state.policyId,\n        sessionId: repr,\n        ts: new Date().toISOString(),\n      })\n      schedulePersist()\n      notifySettled(state.policyId)\n      pumpQueue() // WP6: release the slot this commit held\n      return\n    }\n\n    state.commitSha = result.sha\n    state.status = \"done\"\n    state.endedAt = new Date().toISOString()\n    sessionEvents.emit({\n      type: \"policy:committed\",\n      policyId: state.policyId,\n      sessionId: repr,\n      sha: result.sha,\n      paths: plan.paths,\n      message: plan.message,\n      ts: new Date().toISOString(),\n    })\n    schedulePersist()\n    maybeChain(entry) // WP6: attach `next` now that this policy is done\n    pumpQueue() // WP6: release the slot this commit held\n    notifySettled(state.policyId)\n  }\n\n  // ── arm logic (shared by attach() and reload) ────────────────────\n\n  /**\n   * Set up bus subscriptions for a run entry. Called both when\n   * attaching a fresh policy and when re-arming after reload.\n   * The caller is responsible for inserting the entry into `runs`.\n   */\n  function armEntry(entry: RunEntry): void {\n    const { input, state, unsubscribes } = entry\n    const group = entry.group\n    // Representative session id used for cwd resolution and event payloads.\n    // group is guaranteed non-empty by resolveGroup.\n    const repr = group[0]!\n\n    // Keep the serializable mirror (state.pending) in sync with the live set.\n    const syncPending = () => {\n      state.pending = Array.from(entry.pending)\n    }\n\n    let settled = false\n    const cleanup = () => {\n      if (settled) return\n      settled = true\n      for (const u of unsubscribes) u()\n      unsubscribes.length = 0\n    }\n\n    const emitFailed = (exitCode: number | undefined, error?: string) => {\n      if (error) state.error = error\n      state.status = \"blocked\"\n      state.endedAt = new Date().toISOString()\n      sessionEvents.emit({\n        type: \"policy:failed\",\n        policyId: state.policyId,\n        sessionId: repr,\n        ...(exitCode !== undefined ? { exitCode } : {}),\n        ts: new Date().toISOString(),\n      })\n      schedulePersist()\n      cleanup()\n      pumpQueue() // WP6: release the slot (if any) this run held\n      notifySettled(state.policyId)\n    }\n\n    const act = async (passed: boolean, exitCode: number) => {\n      if (entry.cancelled) return\n      state.status = \"acting\"\n      schedulePersist()\n\n      if (passed) {\n        // WP5: commit action. Prepare the plan in the watched session's cwd.\n        if (input.then === \"commit\") {\n          const commit = input.commit!\n          // The watched session's own cwd is already a vetted, explicit\n          // choice made at agent_start time — trust it as-is rather than\n          // re-anchoring it to the daemon's own boot workspace, which\n          // would reject any session spawned in a sibling worktree.\n          const cwd = registry.get(repr)?.cwd ?? workspace\n          state.commitPlan = {\n            paths: commit.paths,\n            message: commit.message,\n            cwd,\n          }\n          const requireAck = commit.requireHumanAck !== false // default true\n          if (requireAck) {\n            // Don't commit yet — park in awaiting-ack and surface the plan.\n            state.status = \"awaiting-ack\"\n            schedulePersist()\n            sessionEvents.emit({\n              type: \"policy:commit-ready\",\n              policyId: state.policyId,\n              sessionId: repr,\n              paths: commit.paths,\n              message: commit.message,\n              ts: new Date().toISOString(),\n            })\n            // Stop watching the bus; policy_ack drives the rest. The entry\n            // stays in `runs` so ack() can find it.\n            cleanup()\n            pumpQueue() // WP6: parked awaiting ack — release the slot\n            notifySettled(state.policyId)\n            return\n          }\n          // Unattended commit — run it directly at the green gate.\n          // finishCommit handles maybeChain + pumpQueue on settle.\n          await finishCommit(entry)\n          cleanup()\n          return\n        }\n\n        // then === \"emit\" (WP1)\n        sessionEvents.emit({\n          type: \"policy:passed\",\n          policyId: state.policyId,\n          sessionId: repr,\n          ts: new Date().toISOString(),\n        })\n        state.status = \"done\"\n        state.endedAt = new Date().toISOString()\n        schedulePersist()\n        cleanup()\n        maybeChain(entry) // WP6: attach `next` now that this policy is done\n        pumpQueue() // WP6: release the slot this run held\n        notifySettled(state.policyId)\n        return\n      }\n\n      // Gate failed — attempt bounded nudge if configured (WP2).\n      if (input.onFail !== undefined) {\n        const maxRetries = input.onFail.maxRetries ?? DEFAULT_MAX_RETRIES\n        if (state.retries < maxRetries) {\n          // Nudge every still-running member of the group (fan-in: WP4).\n          const running = group.filter(\n            id => registry.get(id)?.status === \"running\",\n          )\n          if (running.length > 0) {\n            const template = input.onFail.nudge ?? DEFAULT_NUDGE_TEMPLATE\n            const nudgeMsg = template.replace(\"{code}\", String(exitCode))\n            state.status = \"nudging\"\n            schedulePersist()\n            try {\n              for (const id of running) {\n                await registry.sendPrompt(id, nudgeMsg)\n              }\n            } catch {\n              emitFailed(exitCode, \"nudge prompt delivery failed\")\n              return\n            }\n            state.retries++\n            // Reset the fan-in set to the full group and return to watching —\n            // bus subscriptions remain active; the gate fires again only once\n            // every member has finished another turn.\n            entry.pending = new Set(group)\n            syncPending()\n            state.status = \"watching\"\n            schedulePersist()\n            pumpQueue() // WP6: nudged back to watching — release the slot\n            return\n          }\n        }\n      }\n\n      // No nudge configured, no running member, or retries exhausted → block\n      emitFailed(exitCode)\n    }\n\n    /**\n     * Read the recent ring-buffer tail of a session (best-effort) — used to\n     * give the judge a minimal context of the watched session's output. Mirrors\n     * agent_output: attach captures the backfill synchronously, then\n     * unsubscribe. Returns \"\" when the session/attach is unavailable.\n     */\n    const readTail = (sessionId: string, lastN: number): string => {\n      const lines: string[] = []\n      let unsub: (() => void) | null = null\n      try {\n        unsub = registry.attach(sessionId, line => {\n          lines.push(line)\n        })\n      } catch {\n        return \"\"\n      }\n      if (unsub) unsub()\n      return lines.slice(-lastN).map(stripAnsi).join(\"\\n\").trim()\n    }\n\n    /**\n     * WP7: run a judge-agent gate. Spawns a short-lived agent via\n     * resolveAgentAdapter, prompts it with the rubric (+ a minimal context tail),\n     * waits for its turn-end (or a timeout), parses VERDICT: PASS/FAIL from the\n     * final reply, and ALWAYS kills the judge session before returning.\n     * Fail-safe: no resolver / spawn failure / timeout / unparseable → FAIL.\n     * The judge runs while this policy holds its `gating` slot, so it is already\n     * accounted for in the WP6 concurrency cap.\n     */\n    const runJudge = async (\n      spec: JudgeGateSpec[\"judge\"],\n    ): Promise<{ passed: boolean; exitCode: number; reason?: string }> => {\n      if (!resolveAgentAdapter) {\n        return { passed: false, exitCode: 1, reason: \"judge gate not enabled (no adapter resolver)\" }\n      }\n      let resolved\n      try {\n        resolved = await resolveAgentAdapter(spec.adapter)\n      } catch (err) {\n        return { passed: false, exitCode: 1, reason: `judge adapter resolve failed: ${err instanceof Error ? err.message : String(err)}` }\n      }\n      if (!resolved) {\n        return { passed: false, exitCode: 1, reason: `judge adapter '${spec.adapter}' not found` }\n      }\n\n      // Same trust rationale as the commit-plan cwd above: the watched\n      // session's own cwd was already vetted at spawn time.\n      const cwd = registry.get(repr)?.cwd ?? workspace\n      const timeoutMs = spec.timeoutMs ?? DEFAULT_JUDGE_TIMEOUT_MS\n\n      // Minimal context: the tail of each watched session's output, if readable.\n      const contextBlocks = group\n        .map(id => {\n          const tail = readTail(id, 60)\n          return tail ? `--- output of session ${id} ---\\n${tail}` : \"\"\n        })\n        .filter(Boolean)\n      const context = contextBlocks.length > 0\n        ? `\\n\\nContext — recent output of the watched session(s):\\n${contextBlocks.join(\"\\n\\n\")}`\n        : \"\"\n      const fullPrompt = `${spec.prompt}${context}${JUDGE_VERDICT_INSTRUCTION}`\n\n      // Spawn the judge agent.\n      let judgeId: string\n      try {\n        const agentSession = await resolved.startSession({\n          cwd,\n          ...(spec.model ? { model: spec.model } : {}),\n        })\n        const desc = registry.spawnAgent({\n          workspaceSlug: \"default\",\n          cwd,\n          agentSession,\n          adapterSlug: spec.adapter,\n          label: `judge:${state.policyId}`,\n          ...(resolved.commandPreview ? { commandPreview: resolved.commandPreview } : {}),\n        })\n        judgeId = desc.id\n      } catch (err) {\n        return { passed: false, exitCode: 1, reason: `judge spawn failed: ${err instanceof Error ? err.message : String(err)}` }\n      }\n\n      try {\n        // Subscribe to the judge's turn-end BEFORE prompting so we never miss it.\n        const ended = new Promise<\"ended\" | \"timeout\">(resolveEnd => {\n          const unsubs: Array<() => void> = []\n          let done = false\n          const finish = (r: \"ended\" | \"timeout\") => {\n            if (done) return\n            done = true\n            clearTimeout(timer)\n            for (const u of unsubs) u()\n            resolveEnd(r)\n          }\n          const timer = setTimeout(() => finish(\"timeout\"), timeoutMs)\n          const onEnd = (ev: { sessionId: string }) => {\n            if (ev.sessionId === judgeId) finish(\"ended\")\n          }\n          unsubs.push(sessionEvents.on(\"session:turn-end\", onEnd))\n          unsubs.push(sessionEvents.on(\"session:awaiting-input\", onEnd))\n          unsubs.push(sessionEvents.on(\"session:exited\", onEnd))\n        })\n\n        try {\n          await registry.sendPrompt(judgeId, fullPrompt)\n        } catch (err) {\n          return { passed: false, exitCode: 1, reason: `judge prompt failed: ${err instanceof Error ? err.message : String(err)}` }\n        }\n\n        const outcome = await ended\n        if (outcome === \"timeout\") {\n          return { passed: false, exitCode: 1, reason: `judge timed out after ${timeoutMs}ms` }\n        }\n\n        const reply = readTail(judgeId, 200)\n        const verdict = parseVerdict(reply)\n        if (verdict === null) {\n          return { passed: false, exitCode: 1, reason: \"judge reply had no parseable VERDICT line\" }\n        }\n        return verdict === \"PASS\"\n          ? { passed: true, exitCode: 0 }\n          : { passed: false, exitCode: 1, reason: \"judge verdict: FAIL\" }\n      } finally {\n        // Always kill the judge session — success or failure.\n        try {\n          registry.kill(judgeId)\n        } catch {\n          // best-effort\n        }\n      }\n    }\n\n    const runGate = async () => {\n      if (entry.cancelled || state.status !== \"watching\") return\n      state.status = \"gating\"\n      schedulePersist()\n\n      if (!input.gate) {\n        await act(true, 0)\n        return\n      }\n\n      // WP7: judge-agent gate.\n      if (isJudgeGate(input.gate)) {\n        const { passed, exitCode, reason } = await runJudge(input.gate.judge)\n        state.lastGate = { exitCode, at: new Date().toISOString() }\n        if (!passed && reason) state.error = reason\n        schedulePersist()\n        await act(passed, exitCode)\n        return\n      }\n\n      try {\n        const allowlist = await loadAllowlist(workspace)\n        const baseName = basename(input.gate.command)\n        if (!allowlist.has(baseName)) {\n          emitFailed(-1, `gate command '${baseName}' not in allowlist`)\n          return\n        }\n\n        // The watched session's own cwd is already a vetted, explicit\n        // choice made at agent_start time (arbitrary absolute path or a\n        // registered workspaceSlug) — trust it as-is rather than\n        // re-anchoring it to the daemon's own boot workspace, which\n        // would reject every session spawned in a sibling worktree. An\n        // explicit `gate.cwd` override IS untrusted input, though — it\n        // still gets anchored, but against the session's own cwd rather\n        // than the daemon's, so it can't escape that session's tree.\n        const sessionCwd = registry.get(repr)?.cwd ?? workspace\n        const resolvedCwd = input.gate.cwd\n          ? makeCwdAnchor(sessionCwd)(input.gate.cwd)\n          : sessionCwd\n\n        const result = await exec({\n          command: input.gate.command,\n          args: input.gate.args ?? [],\n          cwd: resolvedCwd,\n          timeoutMs: input.gate.timeoutMs ?? 60_000,\n        })\n\n        state.lastGate = {\n          exitCode: result.exitCode,\n          at: new Date().toISOString(),\n        }\n        schedulePersist()\n        await act(result.exitCode === 0, result.exitCode)\n      } catch (err) {\n        emitFailed(-1, err instanceof Error ? err.message : String(err))\n      }\n    }\n    entry.runGate = runGate\n\n    /**\n     * WP6: gate-entry through the daemon-wide concurrency cap. If a slot is\n     * free, run the gate now; otherwise park in `queued` (FIFO) and let\n     * pumpQueue() admit this entry when a slot frees. Holds no slot while queued.\n     */\n    const requestGate = () => {\n      if (entry.cancelled || state.status !== \"watching\") return\n      if (countActive() >= cap) {\n        state.status = \"queued\"\n        if (!gateQueue.includes(entry)) gateQueue.push(entry)\n        schedulePersist()\n        return\n      }\n      void runGate()\n    }\n\n    /** Remove a member from the pending set (idempotent); gate once empty. */\n    const markMemberDone = (sessionId: string) => {\n      if (state.status !== \"watching\") return\n      if (!entry.pending.has(sessionId)) return // idempotent — no double-count\n      entry.pending.delete(sessionId)\n      syncPending()\n      schedulePersist()\n      if (entry.pending.size === 0) requestGate()\n    }\n\n    // Fan-in: a member's first turn-end removes it from the pending set; the\n    // gate runs once the set empties.\n    unsubscribes.push(\n      sessionEvents.on(\"session:turn-end\", ev => {\n        if (!group.includes(ev.sessionId)) return\n        markMemberDone(ev.sessionId)\n      }),\n    )\n\n    // Member exit handling:\n    //  - group of 1 (legacy single-session form): a lone watched session that\n    //    exits before turn-end has nothing to gate on → cancel (unchanged).\n    //  - fan-in group (>1): the exited member is treated as \"done\" and removed\n    //    from the pending set, exactly like a turn-end. If every member exits,\n    //    the set empties and the gate runs once.\n    unsubscribes.push(\n      sessionEvents.on(\"session:exited\", ev => {\n        if (!group.includes(ev.sessionId)) return\n        if (group.length === 1) {\n          if (\n            state.status === \"watching\" ||\n            state.status === \"gating\" ||\n            state.status === \"nudging\"\n          ) {\n            entry.cancelled = true\n            state.status = \"cancelled\"\n            state.endedAt = new Date().toISOString()\n            schedulePersist()\n            cleanup()\n            notifySettled(state.policyId)\n          }\n          return\n        }\n        markMemberDone(ev.sessionId)\n      }),\n    )\n\n    // If the pending set was already empty at arm time (e.g. re-armed after a\n    // reload where every still-awaited member had exited), gate immediately.\n    if (!entry.cancelled && state.status === \"watching\" && entry.pending.size === 0) {\n      requestGate()\n    }\n  }\n\n  // ── boot-time reload ─────────────────────────────────────────────\n\n  if (persist) {\n    let raw: string\n    try {\n      raw = readFileSync(persistPath, \"utf8\")\n    } catch {\n      raw = \"\"\n    }\n    if (raw) {\n      let parsed: PolicySnapshot | null = null\n      try {\n        parsed = JSON.parse(raw) as PolicySnapshot\n      } catch {\n        // corrupt file — ignore\n      }\n      if (parsed?.policies) {\n        for (const { input, state } of parsed.policies) {\n          const isTerminal =\n            state.status === \"done\" ||\n            state.status === \"blocked\" ||\n            state.status === \"cancelled\"\n\n          // Reconstruct the fan-in group + pending set defensively (older\n          // snapshots predate sessionIds/pending and carry only sessionId).\n          const group =\n            state.sessionIds && state.sessionIds.length > 0\n              ? Array.from(new Set(state.sessionIds))\n              : resolveGroup(input)\n          const persistedPending =\n            state.pending && state.pending.length >= 0\n              ? state.pending\n              : [...group]\n\n          // WP5: a commit parked awaiting human ack stays awaiting-ack across a\n          // restart — re-armed neither to watching nor to a terminal state. No\n          // bus subscription (it's past gating); policy_ack drives it. The\n          // commitPlan persisted with it carries the exact paths/message/cwd.\n          if (state.status === \"awaiting-ack\") {\n            runs.set(state.policyId, {\n              input,\n              group,\n              pending: new Set(persistedPending),\n              state: { ...state, sessionIds: group },\n              unsubscribes: [],\n              cancelled: false,\n            })\n            continue\n          }\n\n          if (isTerminal) {\n            // Keep for history, no re-arm needed.\n            const entry: RunEntry = {\n              input,\n              group,\n              pending: new Set(persistedPending),\n              state,\n              unsubscribes: [],\n              cancelled: true,\n            }\n            runs.set(state.policyId, entry)\n            continue\n          }\n\n          // Active state at crash time. A member still counts as alive only if\n          // the registry still reports it running/starting.\n          const isAlive = (id: string): boolean => {\n            const s = registry.get(id)\n            return !!s && (s.status === \"running\" || s.status === \"starting\")\n          }\n          const aliveGroup = group.filter(isAlive)\n\n          if (aliveGroup.length === 0) {\n            // No member survived the restart — cancel instead of hanging.\n            const cancelledState: PolicyRunState = {\n              ...state,\n              sessionIds: group,\n              pending: [],\n              status: \"cancelled\",\n              endedAt: state.endedAt ?? new Date().toISOString(),\n              error: \"session absent at reload\",\n            }\n            runs.set(state.policyId, {\n              input,\n              group,\n              pending: new Set(),\n              state: cancelledState,\n              unsubscribes: [],\n              cancelled: true,\n            })\n            continue\n          }\n\n          // Re-arm to watching. Re-subscribe only to members still awaited AND\n          // still alive: a pending member that died while the daemon was down\n          // counts as \"done\" (same rule as a live exit), so it drops out of the\n          // pending set rather than wedging the fan-in forever.\n          const rearmedPending = persistedPending.filter(\n            id => group.includes(id) && isAlive(id),\n          )\n          const rearmedState: PolicyRunState = {\n            ...state,\n            sessionIds: group,\n            pending: rearmedPending,\n            status: \"watching\",\n          }\n          const entry: RunEntry = {\n            input,\n            group,\n            pending: new Set(rearmedPending),\n            state: rearmedState,\n            unsubscribes: [],\n            cancelled: false,\n          }\n          runs.set(state.policyId, entry)\n          armEntry(entry)\n        }\n      }\n    }\n  }\n\n  // ── attach core (shared by public attach() + WP6 chaining) ───────\n\n  /**\n   * Validate + register + arm a fresh policy. Used both by the public\n   * `attach()` and by `maybeChain()` when a parent policy reaches `done`.\n   * Hoisted (function declaration) so maybeChain can reference it.\n   */\n  function attachPolicy(input: AttachPolicyInput): PolicyRunState {\n    const group = resolveGroup(input)\n    if (input.gate && isJudgeGate(input.gate)) {\n      const j = input.gate.judge\n      if (typeof j.adapter !== \"string\" || j.adapter.length === 0) {\n        throw new Error(\"judge gate requires a non-empty adapter\")\n      }\n      if (typeof j.prompt !== \"string\" || j.prompt.length === 0) {\n        throw new Error(\"judge gate requires a non-empty prompt\")\n      }\n    }\n    if (input.then === \"commit\") {\n      if (!input.commit) {\n        throw new Error('then:\"commit\" requires a commit spec')\n      }\n      if (!Array.isArray(input.commit.paths) || input.commit.paths.length === 0) {\n        throw new Error('then:\"commit\" requires a non-empty paths[]')\n      }\n      if (input.commit.paths.some(p => typeof p !== \"string\" || p.length === 0)) {\n        throw new Error(\"commit paths must be non-empty strings\")\n      }\n      if (typeof input.commit.message !== \"string\" || input.commit.message.length === 0) {\n        throw new Error('then:\"commit\" requires a non-empty message')\n      }\n    }\n    const policyId = `policy_${randomUUID().slice(0, 8)}`\n    const state: PolicyRunState = {\n      policyId,\n      sessionId: group[0]!,\n      sessionIds: group,\n      pending: [...group],\n      status: \"watching\",\n      retries: 0,\n      startedAt: new Date().toISOString(),\n    }\n    const entry: RunEntry = {\n      input,\n      group,\n      pending: new Set(group),\n      state,\n      unsubscribes: [],\n      cancelled: false,\n    }\n    runs.set(policyId, entry)\n    schedulePersist()\n    armEntry(entry)\n    return state\n  }\n\n  // ── public interface ─────────────────────────────────────────────\n\n  return {\n    attach(input) {\n      return attachPolicy(input)\n    },\n\n    getStatus(policyId) {\n      return runs.get(policyId)?.state\n    },\n\n    cancel(policyId) {\n      const entry = runs.get(policyId)\n      if (!entry) return\n      entry.cancelled = true\n      if (\n        entry.state.status === \"watching\" ||\n        entry.state.status === \"queued\" ||\n        entry.state.status === \"gating\" ||\n        entry.state.status === \"nudging\"\n      ) {\n        const wasActive =\n          entry.state.status === \"gating\" || entry.state.status === \"queued\"\n        entry.state.status = \"cancelled\"\n        entry.state.endedAt = new Date().toISOString()\n        for (const u of entry.unsubscribes) u()\n        entry.unsubscribes.length = 0\n        // WP6: drop from the gate queue and release any held slot.\n        const qi = gateQueue.indexOf(entry)\n        if (qi >= 0) gateQueue.splice(qi, 1)\n        schedulePersist()\n        if (wasActive) pumpQueue()\n        notifySettled(policyId)\n      }\n    },\n\n    async ack(policyId, approve) {\n      const entry = runs.get(policyId)\n      if (!entry) return undefined\n      // Only meaningful while parked awaiting a human ack.\n      if (entry.state.status !== \"awaiting-ack\") return entry.state\n\n      if (!approve) {\n        entry.cancelled = true\n        entry.state.status = \"cancelled\"\n        entry.state.endedAt = new Date().toISOString()\n        schedulePersist()\n        notifySettled(policyId)\n        return entry.state\n      }\n\n      await finishCommit(entry)\n      notifySettled(policyId)\n      return entry.state\n    },\n\n    list() {\n      return Array.from(runs.values()).map(e => e.state)\n    },\n\n    onSettle(cb) {\n      settleListeners.add(cb)\n      return () => {\n        settleListeners.delete(cb)\n      }\n    },\n\n    shutdown() {\n      if (shutdownDone) return\n      shutdownDone = true\n      if (persistTimer) {\n        clearTimeout(persistTimer)\n        persistTimer = null\n      }\n      if (!persist) return\n      try {\n        const snap = buildSnapshot()\n        mkdirSync(dirname(persistPath), { recursive: true })\n        writeFileSync(persistPath, JSON.stringify(snap, null, 2) + \"\\n\")\n      } catch {\n        // best-effort\n      }\n    },\n  }\n}\n","/**\n * InboundWatcher — polls agentpush `poll_inbound` on a timer and\n * spawns one agent per contact_ref that has unread inbound messages.\n *\n * Flow per tick:\n *   mcp_imported_call(alias, \"poll_inbound\", {source, since:cursor})\n *   → group events by contact_ref\n *   → spawn one agent per contact with prompt from promptTemplate\n *   → advance + persist cursor to ~/.agentproto/agentpush-cursors.json\n *\n * Cursor key = \"${alias}:${source}\" — stable across daemon restarts so\n * cursor resume actually works (a random watcherId would break it).\n *\n * Prompt template variables: {{source}}, {{contact_ref}},\n *   {{messages_json}}, {{count}}.\n *\n * The mcpServersForChild array is forwarded to the spawned agent's\n * startSession + spawnAgent so the child can call dispatch_request\n * directly on the mounted agentpush MCP server.\n *\n * State is in-memory; cursors persist to disk (debounced async write\n * + sync flush at shutdown), matching the supervisor.ts pattern.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { resolve, dirname } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { mkdirSync, writeFileSync, readFileSync, promises as fsp } from \"node:fs\"\nimport type { McpProxyRegistry } from \"./mcp-proxy.js\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface WatcherStartInput {\n  /** Imported MCP alias (e.g. \"agentpush\"). */\n  alias: string\n  /** Contact ref / channel to watch — forwarded as `source` to poll_inbound. */\n  source: string\n  /** Agent adapter slug (e.g. \"claude-code\"). */\n  adapter: string\n  /**\n   * Prompt template with placeholders:\n   *   {{source}}        — the watched source\n   *   {{contact_ref}}   — the sender's contact_ref\n   *   {{messages_json}} — JSON array of the new events\n   *   {{count}}         — number of new messages\n   */\n  promptTemplate: string\n  /** Poll interval in ms. Default 5 000. */\n  pollIntervalMs?: number\n  /** Working directory for spawned agents. Default process.cwd(). */\n  cwd?: string\n  /** Optional label suffix on spawned sessions. */\n  label?: string\n  /**\n   * MCP servers to mount in the child agent at spawn time.\n   * Pass agentpush here so the child can call dispatch_request.\n   */\n  mcpServersForChild?: Array<{\n    name: string\n    transport: \"stdio\" | \"http\" | \"sse\"\n    ref?: string\n  }>\n}\n\nexport interface WatcherDescriptor {\n  watcherId: string\n  alias: string\n  source: string\n  adapter: string\n  pollIntervalMs: number\n  status: \"running\" | \"stopped\"\n  /** Next `since` value for poll_inbound (exclusive lower bound). */\n  cursor: number\n  lastPollAt?: string\n  lastFireAt?: string\n  /** Total agent sessions spawned since the watcher started. */\n  spawned: number\n}\n\nexport interface InboundWatcher {\n  start(input: WatcherStartInput): WatcherDescriptor\n  /** Returns false when watcherId is unknown. */\n  stop(watcherId: string): boolean\n  list(): WatcherDescriptor[]\n  /** Stops all watchers and flushes cursor state to disk synchronously. */\n  shutdown(): void\n}\n\n// ── Internal ─────────────────────────────────────────────────────────\n\ninterface InboundEvent {\n  timestamp?: number\n  contact_ref?: string\n  [key: string]: unknown\n}\n\ninterface WatcherState {\n  readonly watcherId: string\n  readonly input: {\n    alias: string\n    source: string\n    adapter: string\n    promptTemplate: string\n    pollIntervalMs: number\n    cwd: string\n    label?: string\n    mcpServersForChild?: WatcherStartInput[\"mcpServersForChild\"]\n  }\n  status: \"running\" | \"stopped\"\n  cursor: number\n  /** True while a poll tick is still in-flight — prevents overlap. */\n  inFlight: boolean\n  lastPollAt?: string\n  lastFireAt?: string\n  spawned: number\n  timer: ReturnType<typeof setInterval> | null\n}\n\nexport const CURSORS_FILE_PATH = (): string =>\n  resolve(homedir(), \".agentproto\", \"agentpush-cursors.json\")\n\nconst PERSIST_DEBOUNCE_MS = 1_500\n\n// ── Factory ───────────────────────────────────────────────────────────\n\nexport function createInboundWatcher(opts: {\n  mcpProxy: McpProxyRegistry\n  registry: SessionsRegistry\n  resolveAgentAdapter: AgentAdapterResolver\n  /** Override persist path (tests). Implies persist:true unless set explicitly. */\n  persistPath?: string\n  /** Disable disk persistence entirely (unit tests). Default false. */\n  persist?: boolean\n}): InboundWatcher {\n  const { mcpProxy, registry, resolveAgentAdapter } = opts\n  const persistPath = opts.persistPath ?? CURSORS_FILE_PATH()\n  const persist = opts.persist ?? opts.persistPath !== undefined\n  const watchers = new Map<string, WatcherState>()\n  let persistTimer: ReturnType<typeof setTimeout> | null = null\n\n  // ── Cursor persistence (mirrors supervisor.ts pattern) ────────────\n\n  const loadCursors = (): Record<string, number> => {\n    try {\n      const raw = readFileSync(persistPath, \"utf8\")\n      return JSON.parse(raw) as Record<string, number>\n    } catch {\n      return {}\n    }\n  }\n\n  // Cursor key uses alias + source — stable identity that survives\n  // daemon restarts (unlike watcherId which is a new UUID per start()).\n  const buildSnapshot = (): Record<string, number> => {\n    const out: Record<string, number> = {}\n    for (const state of watchers.values()) {\n      out[`${state.input.alias}:${state.input.source}`] = state.cursor\n    }\n    return out\n  }\n\n  // Merge current in-memory snapshot with the existing file so cursors\n  // for alias:source pairs that are NOT active in this session are never\n  // erased on shutdown. Current in-memory values win on conflict.\n  const mergedSnapshot = (): Record<string, number> => ({\n    ...loadCursors(),\n    ...buildSnapshot(),\n  })\n\n  const schedulePersist = (): void => {\n    if (!persist) return\n    if (persistTimer) clearTimeout(persistTimer)\n    persistTimer = setTimeout(() => {\n      void (async () => {\n        try {\n          const snap = mergedSnapshot()\n          await fsp.mkdir(dirname(persistPath), { recursive: true })\n          await fsp.writeFile(persistPath, JSON.stringify(snap, null, 2) + \"\\n\")\n        } catch (err) {\n          console.warn(\n            `[inbound-watcher] persist failed: ${err instanceof Error ? err.message : String(err)}`,\n          )\n        }\n      })()\n    }, PERSIST_DEBOUNCE_MS)\n  }\n\n  const flushSync = (): void => {\n    if (!persist) return\n    try {\n      const snap = mergedSnapshot()\n      mkdirSync(dirname(persistPath), { recursive: true })\n      writeFileSync(persistPath, JSON.stringify(snap, null, 2) + \"\\n\")\n    } catch {\n      // best-effort — never throw in shutdown path\n    }\n  }\n\n  // ── Helpers ───────────────────────────────────────────────────────\n\n  const renderPrompt = (\n    template: string,\n    vars: {\n      source: string\n      contact_ref: string\n      messages_json: string\n      count: number\n    },\n  ): string =>\n    template\n      .replaceAll(\"{{source}}\", vars.source)\n      .replaceAll(\"{{contact_ref}}\", vars.contact_ref)\n      .replaceAll(\"{{messages_json}}\", vars.messages_json)\n      .replaceAll(\"{{count}}\", String(vars.count))\n\n  // ── Agent spawn ───────────────────────────────────────────────────\n\n  const spawnForContact = async (\n    state: WatcherState,\n    contactRef: string,\n    events: InboundEvent[],\n    resolved: NonNullable<Awaited<ReturnType<AgentAdapterResolver>>>,\n  ): Promise<void> => {\n    const prompt = renderPrompt(state.input.promptTemplate, {\n      source: state.input.source,\n      contact_ref: contactRef,\n      messages_json: JSON.stringify(events),\n      count: events.length,\n    })\n\n    const mcpServers = state.input.mcpServersForChild\n\n    try {\n      const agentSession = await resolved.startSession({\n        cwd: state.input.cwd,\n        ...(mcpServers ? { mcpServers } : {}),\n      })\n\n      const labelParts = [\"inbound\", state.watcherId, contactRef]\n      if (state.input.label) labelParts.push(state.input.label)\n\n      registry.spawnAgent({\n        workspaceSlug: \"default\",\n        cwd: state.input.cwd,\n        agentSession,\n        adapterSlug: state.input.adapter,\n        initialPrompt: prompt,\n        label: labelParts.join(\":\"),\n        ...(mcpServers ? { mcpServers } : {}),\n        ...(resolved.commandPreview\n          ? { commandPreview: resolved.commandPreview }\n          : {}),\n      })\n\n      state.spawned++\n      state.lastFireAt = new Date().toISOString()\n    } catch (err) {\n      console.warn(\n        `[inbound-watcher:${state.watcherId}] spawn failed: ${err instanceof Error ? err.message : String(err)}`,\n      )\n    }\n  }\n\n  // ── Poll ──────────────────────────────────────────────────────────\n\n  const doPoll = async (state: WatcherState): Promise<void> => {\n    if (state.status !== \"running\") return\n    // Anti-race: skip this tick if the previous one hasn't finished yet.\n    if (state.inFlight) return\n    state.inFlight = true\n    state.lastPollAt = new Date().toISOString()\n\n    try {\n      const out = await mcpProxy.callTool(state.input.alias, \"poll_inbound\", {\n        source: state.input.source,\n        ...(state.cursor > 0 ? { since: state.cursor } : {}),\n      })\n\n      if (!out.ok) {\n        console.warn(\n          `[inbound-watcher:${state.watcherId}] poll_inbound error: ${out.error}`,\n        )\n        return\n      }\n\n      // Unwrap MCP content envelope: { content: [{type:\"text\", text:\"...json...\"}] }\n      const raw = out.result as {\n        content?: Array<{ type: string; text?: string }>\n      }\n      const text = raw?.content?.find(c => c.type === \"text\")?.text\n      if (!text) return\n\n      let data: { events?: InboundEvent[] }\n      try {\n        data = JSON.parse(text) as { events?: InboundEvent[] }\n      } catch {\n        return\n      }\n\n      const events = data.events ?? []\n      if (events.length === 0) return\n\n      // Compute the new cursor value (max timestamp + 1). Guard against\n      // NaN/non-finite values from malformed events.\n      // If NO event carries a valid timestamp, fall back to Date.now() so\n      // the cursor still advances and the same events are not re-delivered\n      // on the next tick (infinite-loop guard).\n      const maxTs = events.reduce((m, e) => {\n        const ts = typeof e.timestamp === \"number\" ? e.timestamp : -Infinity\n        return Number.isFinite(ts) ? Math.max(m, ts) : m\n      }, -Infinity)\n      const nextCursor = Number.isFinite(maxTs) && maxTs >= state.cursor\n        ? maxTs + 1\n        : Date.now()\n\n      // Resolve adapter once per tick — shared across all contact spawns\n      // so N contacts don't fan out N identical adapter-resolution calls.\n      const resolved = await resolveAgentAdapter(state.input.adapter).catch(\n        () => null,\n      )\n      if (!resolved) {\n        console.warn(\n          `[inbound-watcher:${state.watcherId}] adapter \"${state.input.adapter}\" not found — events not consumed`,\n        )\n        // Do NOT advance cursor: if the adapter is missing the events\n        // should be re-delivered on the next tick once it's installed.\n        return\n      }\n\n      // Group by contact_ref, spawn one agent per contact\n      const byContact = new Map<string, InboundEvent[]>()\n      for (const ev of events) {\n        const ref = typeof ev.contact_ref === \"string\" ? ev.contact_ref : \"unknown\"\n        const bucket = byContact.get(ref) ?? []\n        bucket.push(ev)\n        byContact.set(ref, bucket)\n      }\n\n      await Promise.all(\n        Array.from(byContact.entries()).map(([ref, evs]) =>\n          spawnForContact(state, ref, evs, resolved),\n        ),\n      )\n\n      // Advance cursor AFTER spawn attempts complete.\n      // Delivery contract: at-most-once within a session. If a spawn throws\n      // unexpectedly the event is not re-delivered. Across daemon restarts\n      // delivery is at-least-once: a tick in-flight at shutdown advances the\n      // cursor as a microtask after flushSync() returns, so the new cursor\n      // value is not persisted and those events may be re-fetched on restart.\n      state.cursor = nextCursor\n      schedulePersist()\n    } finally {\n      state.inFlight = false\n    }\n  }\n\n  // ── Public interface ──────────────────────────────────────────────\n\n  return {\n    start(input: WatcherStartInput): WatcherDescriptor {\n      const watcherId = randomUUID()\n      const pollIntervalMs = input.pollIntervalMs ?? 5_000\n      const cwd = input.cwd ?? process.cwd()\n\n      // Restore persisted cursor using the stable alias:source key so\n      // a restarted daemon picks up where it left off.\n      const savedCursors = loadCursors()\n\n      const state: WatcherState = {\n        watcherId,\n        input: {\n          alias: input.alias,\n          source: input.source,\n          adapter: input.adapter,\n          promptTemplate: input.promptTemplate,\n          pollIntervalMs,\n          cwd,\n          label: input.label,\n          mcpServersForChild: input.mcpServersForChild,\n        },\n        status: \"running\",\n        cursor: savedCursors[`${input.alias}:${input.source}`] ?? 0,\n        inFlight: false,\n        spawned: 0,\n        timer: null,\n      }\n\n      state.timer = setInterval(() => {\n        void doPoll(state).catch(err => {\n          console.warn(\n            `[inbound-watcher:${watcherId}] unhandled poll error: ${err instanceof Error ? err.message : String(err)}`,\n          )\n        })\n      }, pollIntervalMs)\n\n      watchers.set(watcherId, state)\n      return toDescriptor(state)\n    },\n\n    stop(watcherId: string): boolean {\n      const state = watchers.get(watcherId)\n      if (!state) return false\n      if (state.timer) clearInterval(state.timer)\n      state.timer = null\n      state.status = \"stopped\"\n      return true\n    },\n\n    list(): WatcherDescriptor[] {\n      return Array.from(watchers.values()).map(toDescriptor)\n    },\n\n    shutdown(): void {\n      for (const state of watchers.values()) {\n        if (state.timer) clearInterval(state.timer)\n        state.timer = null\n        state.status = \"stopped\"\n      }\n      if (persistTimer) {\n        clearTimeout(persistTimer)\n        persistTimer = null\n      }\n      flushSync()\n    },\n  }\n}\n\nfunction toDescriptor(state: WatcherState): WatcherDescriptor {\n  return {\n    watcherId: state.watcherId,\n    alias: state.input.alias,\n    source: state.input.source,\n    adapter: state.input.adapter,\n    pollIntervalMs: state.input.pollIntervalMs,\n    status: state.status,\n    cursor: state.cursor,\n    lastPollAt: state.lastPollAt,\n    lastFireAt: state.lastFireAt,\n    spawned: state.spawned,\n  }\n}\n","/**\n * Daemon-native cron scheduler — persisted, survives restarts,\n * fires shell-command, agent-spawn, or session-reprompt jobs on a\n * 5-field cron schedule.\n *\n * Design decisions (see PLAN.md for rationale):\n *\n * ONE TICK LOOP (not one setInterval per job): a single 20-second interval\n * scans all active jobs, fires any whose `nextRunAt` has passed, recomputes\n * `nextRunAt`, and deactivates one-shot jobs after firing. Avoids timer\n * leaks/drift as jobs accumulate.\n *\n * COMMAND ALLOWLIST: `command` action jobs go through the same\n * `loadAllowlist` / basename check that `command_execute` uses — one\n * enforcement path, not two.\n *\n * SKIPPED FIRES: if the daemon was down past a fire time, the skipped\n * executions are NOT backfilled. Recurring jobs resume from \"now\";\n * one-shot jobs that were missed while the daemon was down are fired\n * immediately on the next tick after restart.\n *\n * PERSISTENCE: `~/.agentproto/cron-jobs.json`, atomic write-tmp+rename.\n * Job DEFINITIONS (not run state) survive restarts. `nextRunAt` is\n * recomputed from now on load when a past fire time is detected.\n *\n * EVENTS: `cron:fired`, `cron:succeeded`, `cron:failed` emitted on the\n * shared SessionEventBus so outcomes are visible via session_events_poll\n * / session_monitor — no separate notification path.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { homedir } from \"node:os\"\nimport { join, dirname, basename } from \"node:path\"\nimport {\n  mkdirSync,\n  readFileSync,\n  existsSync,\n  writeFileSync,\n  renameSync,\n} from \"node:fs\"\nimport { Cron } from \"croner\"\nimport { loadAllowlist, runCommand } from \"./command-tools.js\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { SessionEventBus } from \"./session-event-bus.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\n\n// ── Public types ─────────────────────────────────────────────────────\n\nexport type CronAction =\n  | {\n      kind: \"command\"\n      command: string\n      args?: string[]\n      cwd?: string\n      timeoutMs?: number\n    }\n  | {\n      kind: \"agent\"\n      adapter: string\n      prompt: string\n      cwd?: string\n      model?: string\n    }\n  | {\n      kind: \"prompt-session\"\n      sessionId: string\n      prompt: string\n    }\n\nexport interface CronJob {\n  id: string\n  label?: string\n  /** 5-field cron expression in local time (minute hour day-of-month month day-of-week). */\n  schedule: string\n  /** When false, the job fires once then deactivates (one-shot). Default true. */\n  recurring: boolean\n  action: CronAction\n  createdAt: string\n  /** When false, the job will not fire. */\n  active: boolean\n  nextRunAt?: string\n  lastRunAt?: string\n  lastResult?: { ok: boolean; summary: string }\n}\n\nexport interface CronScheduler {\n  /**\n   * Create and persist a new cron job. Validates the schedule expression\n   * immediately — throws if it's unparseable. Returns the created job.\n   */\n  create(input: {\n    label?: string\n    schedule: string\n    recurring?: boolean\n    action: CronAction\n  }): CronJob\n\n  list(): CronJob[]\n  get(id: string): CronJob | undefined\n\n  /**\n   * Permanently remove a job. Throws if not found.\n   */\n  delete(id: string): void\n\n  /**\n   * Manually fire a job immediately, bypassing its schedule.\n   * Returns the job's lastResult once the action completes.\n   */\n  run(id: string): Promise<CronJob[\"lastResult\"]>\n\n  /** Clean up: stop the tick interval. */\n  shutdown(): void\n}\n\n// ── Internal state ───────────────────────────────────────────────────\n\ninterface JobState {\n  job: CronJob\n  /** Live croner instance — kept for nextDate() queries and released when deleted. */\n  cronInstance?: Cron\n}\n\n// ── Factory ──────────────────────────────────────────────────────────\n\nconst DEFAULT_PERSIST_PATH = (): string =>\n  join(homedir(), \".agentproto\", \"cron-jobs.json\")\n\nconst TICK_INTERVAL_MS = 20_000\n\n// ── Persistence helpers ──────────────────────────────────────────────\n\nfunction loadJobs(persistPath: string): Map<string, JobState> {\n  const result = new Map<string, JobState>()\n  if (!existsSync(persistPath)) return result\n  let raw: string\n  try {\n    raw = readFileSync(persistPath, \"utf8\")\n  } catch {\n    return result\n  }\n  let parsed: unknown\n  try {\n    parsed = JSON.parse(raw)\n  } catch {\n    // Malformed — start empty (documented: not an error).\n    return result\n  }\n  if (!Array.isArray(parsed)) return result\n  for (const item of parsed) {\n    if (\n      !item ||\n      typeof item !== \"object\" ||\n      typeof (item as CronJob).id !== \"string\" ||\n      typeof (item as CronJob).schedule !== \"string\"\n    )\n      continue\n    const job = item as CronJob\n    // Ensure required fields have defaults for forward-compat.\n    job.recurring = job.recurring ?? true\n    job.active = job.active ?? true\n    result.set(job.id, { job })\n  }\n  return result\n}\n\nfunction saveJobs(jobs: Map<string, JobState>, persistPath: string): void {\n  try {\n    mkdirSync(dirname(persistPath), { recursive: true })\n    const payload =\n      JSON.stringify(\n        Array.from(jobs.values()).map(s => s.job),\n        null,\n        2,\n      ) + \"\\n\"\n    const tmp = `${persistPath}.tmp.${process.pid}`\n    writeFileSync(tmp, payload, \"utf8\")\n    renameSync(tmp, persistPath)\n  } catch {\n    // Best-effort — a write failure must not crash the daemon.\n  }\n}\n\n// ── Croner helpers ───────────────────────────────────────────────────\n\n/**\n * Parse a 5-field cron expression and return a dormant Cron instance\n * (not scheduled — we drive ticks manually for the one-loop pattern).\n * Throws `SyntaxError` if the expression is invalid.\n */\nfunction parseCron(schedule: string): Cron {\n  // Validate by constructing a paused instance.\n  // croner throws `SyntaxError` for bad patterns.\n  return new Cron(schedule, { paused: true })\n}\n\nfunction nextFireDate(cronInstance: Cron): Date | null {\n  return cronInstance.nextRun() ?? null\n}\n\n// ── Factory function ─────────────────────────────────────────────────\n\nexport function createCronScheduler(opts: {\n  sessionEvents: SessionEventBus\n  registry: SessionsRegistry\n  resolveAgentAdapter?: AgentAdapterResolver\n  /** Workspace dir — used for the command allowlist. */\n  workspace: string\n  /** Absolute path for the persistence file. Defaults to ~/.agentproto/cron-jobs.json */\n  persistPath?: string\n  /**\n   * Enable filesystem persistence. Defaults to `true` when `persistPath` is\n   * explicitly supplied, `false` otherwise. Production code passes persist:true.\n   */\n  persist?: boolean\n}): CronScheduler {\n  const { sessionEvents, registry, resolveAgentAdapter, workspace } = opts\n  const persistPath = opts.persistPath ?? DEFAULT_PERSIST_PATH()\n  const shouldPersist = opts.persist ?? (opts.persistPath !== undefined)\n\n  const jobs = shouldPersist ? loadJobs(persistPath) : new Map<string, JobState>()\n\n  // Rehydrate cronInstance for every loaded job and recompute nextRunAt if stale.\n  for (const state of jobs.values()) {\n    if (!state.job.active) continue\n    try {\n      const inst = parseCron(state.job.schedule)\n      state.cronInstance = inst\n      // If the stored nextRunAt is in the past (daemon was down), recompute\n      // from the cron schedule — this gives the next scheduled occurrence\n      // *after now*, not an immediate fire. Skipped executions during\n      // downtime are intentionally not backfilled (documented behaviour).\n      const storedNext = state.job.nextRunAt ? new Date(state.job.nextRunAt) : null\n      if (!storedNext || storedNext <= new Date()) {\n        const next = nextFireDate(inst)\n        state.job.nextRunAt = next?.toISOString()\n      }\n    } catch {\n      // Bad stored schedule — deactivate the job so it doesn't block boot.\n      state.job.active = false\n    }\n  }\n  if (shouldPersist) saveJobs(jobs, persistPath)\n\n  const persistNow = (): void => {\n    if (shouldPersist) saveJobs(jobs, persistPath)\n  }\n\n  // ── Action executor ───────────────────────────────────────────────\n\n  const executeAction = async (job: CronJob): Promise<{ ok: boolean; summary: string }> => {\n    const action = job.action\n\n    if (action.kind === \"command\") {\n      const allowlist = await loadAllowlist(workspace)\n      const baseName = basename(action.command)\n      if (!allowlist.has(baseName)) {\n        const allowed = [...allowlist].sort().join(\", \") || \"(empty)\"\n        throw new Error(\n          `cron job '${job.id}': command '${baseName}' is not in the allowlist. ` +\n            `Add it to ${workspace}/.agentproto/allowed-commands.json. Currently allowed: ${allowed}.`,\n        )\n      }\n      const result = await runCommand({\n        command: action.command,\n        args: action.args ?? [],\n        cwd: action.cwd ?? workspace,\n        timeoutMs: action.timeoutMs ?? 60_000,\n      })\n      if (result.exitCode !== 0) {\n        throw new Error(\n          `command exited with code ${result.exitCode}: ${result.stderr.trim() || result.stdout.trim() || \"(no output)\"}`,\n        )\n      }\n      const summary = result.stdout.trim() || `exit 0 (${result.durationMs}ms)`\n      return { ok: true, summary }\n    }\n\n    if (action.kind === \"prompt-session\") {\n      const desc = registry.get(action.sessionId)\n      if (!desc) {\n        throw new Error(\n          `cron job '${job.id}': session '${action.sessionId}' not found`,\n        )\n      }\n      if (desc.processAlive === false) {\n        throw new Error(\n          `cron job '${job.id}': session '${action.sessionId}' is not alive`,\n        )\n      }\n      // Same underlying call as the agent_prompt MCP tool / POST\n      // /sessions/:id/prompt — re-prompts the existing session in place\n      // rather than spawning a new one.\n      await registry.sendPrompt(action.sessionId, action.prompt)\n      return {\n        ok: true,\n        summary: `re-prompted session ${action.sessionId}`,\n      }\n    }\n\n    // action.kind === \"agent\"\n    if (!resolveAgentAdapter) {\n      throw new Error(\n        `cron job '${job.id}': agent action requires resolveAgentAdapter to be wired`,\n      )\n    }\n    const resolved = await resolveAgentAdapter(action.adapter)\n    if (!resolved) {\n      throw new Error(\n        `cron job '${job.id}': adapter '${action.adapter}' not found`,\n      )\n    }\n    const cwd = action.cwd ?? workspace\n    const agentSession = await resolved.startSession({\n      cwd,\n      ...(action.model ? { model: action.model } : {}),\n    })\n    const desc = registry.spawnAgent({\n      workspaceSlug: \"default\",\n      cwd,\n      agentSession,\n      adapterSlug: action.adapter,\n      label: `cron:${job.id}`,\n      ...(resolved.commandPreview ? { commandPreview: resolved.commandPreview } : {}),\n    })\n    // Fire-and-forget: send the prompt and record the session id.\n    if (action.prompt) {\n      await registry.sendPrompt(desc.id, action.prompt)\n    }\n    return {\n      ok: true,\n      summary: `spawned session ${desc.id} (adapter=${action.adapter})`,\n    }\n  }\n\n  // ── Fire a job ────────────────────────────────────────────────────\n\n  const fireJob = async (state: JobState): Promise<void> => {\n    const { job } = state\n    const now = new Date().toISOString()\n    job.lastRunAt = now\n\n    sessionEvents.emit({ type: \"cron:fired\", jobId: job.id, label: job.label, ts: now })\n\n    let result: { ok: boolean; summary: string }\n    try {\n      result = await executeAction(job)\n    } catch (err) {\n      const error = err instanceof Error ? err.message : String(err)\n      result = { ok: false, summary: error }\n      sessionEvents.emit({\n        type: \"cron:failed\",\n        jobId: job.id,\n        label: job.label,\n        error,\n        ts: new Date().toISOString(),\n      })\n      job.lastResult = result\n      if (!job.recurring) {\n        job.active = false\n        job.nextRunAt = undefined\n        state.cronInstance?.stop()\n        state.cronInstance = undefined\n      } else if (state.cronInstance) {\n        const next = nextFireDate(state.cronInstance)\n        job.nextRunAt = next?.toISOString()\n      }\n      persistNow()\n      return\n    }\n\n    sessionEvents.emit({\n      type: \"cron:succeeded\",\n      jobId: job.id,\n      label: job.label,\n      summary: result.summary,\n      ts: new Date().toISOString(),\n    })\n\n    job.lastResult = result\n    if (!job.recurring) {\n      // One-shot: deactivate after firing.\n      job.active = false\n      job.nextRunAt = undefined\n      state.cronInstance?.stop()\n      state.cronInstance = undefined\n    } else if (state.cronInstance) {\n      const next = nextFireDate(state.cronInstance)\n      job.nextRunAt = next?.toISOString()\n    }\n    persistNow()\n  }\n\n  // ── Tick loop ─────────────────────────────────────────────────────\n\n  const tick = (): void => {\n    const now = new Date()\n    for (const state of jobs.values()) {\n      if (!state.job.active) continue\n      if (!state.job.nextRunAt) continue\n      const fireAt = new Date(state.job.nextRunAt)\n      if (fireAt <= now) {\n        // Fire asynchronously — tick must not block.\n        void fireJob(state).catch(() => {\n          // fireJob already handles errors internally; this catch covers\n          // the rare case where fireJob itself throws synchronously.\n        })\n      }\n    }\n  }\n\n  const tickTimer = setInterval(tick, TICK_INTERVAL_MS)\n  tickTimer.unref() // don't keep the process alive on its own\n\n  // ── Public interface ──────────────────────────────────────────────\n\n  return {\n    create({ label, schedule, recurring = true, action }) {\n      // Validate schedule — throws SyntaxError if invalid.\n      const cronInstance = parseCron(schedule)\n      const id = `cron_${randomUUID()}`\n      const next = nextFireDate(cronInstance)\n      const job: CronJob = {\n        id,\n        ...(label ? { label } : {}),\n        schedule,\n        recurring,\n        action,\n        createdAt: new Date().toISOString(),\n        active: true,\n        nextRunAt: next?.toISOString(),\n      }\n      jobs.set(id, { job, cronInstance })\n      persistNow()\n      return job\n    },\n\n    list() {\n      return Array.from(jobs.values()).map(s => s.job)\n    },\n\n    get(id) {\n      return jobs.get(id)?.job\n    },\n\n    delete(id) {\n      const state = jobs.get(id)\n      if (!state) throw new Error(`cron job not found: ${id}`)\n      state.cronInstance?.stop()\n      jobs.delete(id)\n      persistNow()\n    },\n\n    async run(id) {\n      const state = jobs.get(id)\n      if (!state) throw new Error(`cron job not found: ${id}`)\n      await fireJob(state)\n      return state.job.lastResult\n    },\n\n    shutdown() {\n      clearInterval(tickTimer)\n      for (const state of jobs.values()) {\n        state.cronInstance?.stop()\n      }\n    },\n  }\n}\n","/**\n * Orchestrator sub-gateway (ADR §4.2 / WP2) — the security primitive\n * that lets a spawned agent become a *scoped* orchestrator without\n * handing it the daemon's full toolset.\n *\n * The plain `/mcp` endpoint registers EVERY tool (command_execute,\n * fs_*, remote_*, mcp_import, terminals, driver CRUD) and bypasses auth\n * on loopback — pointing a child at it would be a privilege handout.\n * This module builds a second, scoped MCP server that registers ONLY a\n * curated orchestration allowlist, gated by an unguessable per-child\n * scope-token. The HTTP layer mounts it at `/mcp/orchestrator`\n * (`http-server.ts`); WP3 will auto-mint a token and inject the URL at\n * spawn time. WP2 only builds the primitive.\n *\n * Three pieces:\n *   - DEFAULT_ORCHESTRATOR_TOOLS — the curated allowlist.\n *   - createScopeTokenRegistry() — mint / verify / revoke scope-tokens.\n *   - createOrchestratorMcpServerFactory() — build a scoped server for\n *     a verified scope.\n */\n\nimport { randomBytes } from \"node:crypto\"\nimport { createMcpServer } from \"@agentproto/mcp-server\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport type { AcpMcpServer } from \"@agentproto/acp\"\n\nimport { registerSessionTools } from \"./session-tools.js\"\nimport { registerOrchestrationTools } from \"./orchestration-tools.js\"\nimport { withToolSubset } from \"./tool-subset.js\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { SessionEventBus } from \"./session-event-bus.js\"\nimport type { EventRing } from \"./event-ring.js\"\nimport type { CompletionPolicySupervisor } from \"./supervisor.js\"\nimport type {\n  AgentAdapterResolver,\n  AgentAdapterLister,\n} from \"./http-server.js\"\nimport type { WebhookNotifier } from \"./webhook-notifier.js\"\n\n/**\n * The curated set of tools a scoped child orchestrator may call.\n *\n * INCLUDED — the orchestration primitives:\n *   agent_start, agent_prompt, agent_output, agent_kill,\n *   session_monitor, session_events_poll  (spawn + drive + fan-in)\n *   session_list, session_tree  (observe). NB: list is NOT yet scoped\n *     to the child's own subtree — that subtree filter is WP4\n *     (parentSessionId/depth). For WP2 it is exposed daemon-wide;\n *     documented debt.\n *\n * EXCLUDED — the danger surface (each a separate trust boundary):\n *   command_execute, terminal/PTY tools (raw shell), file_* /\n *   directory_* tools, remote_* (publish the daemon to the internet),\n *   mcp_import / mcp_discovered_* / mcp_imported_* (widen the daemon's\n *   own MCP surface), and driver CRUD (create_/delete_/update_driver —\n *   these never register here because the scoped server is built with\n *   no doctype specs).\n */\nexport const DEFAULT_ORCHESTRATOR_TOOLS: readonly string[] = [\n  \"agent_start\",\n  \"agent_prompt\",\n  \"agent_output\",\n  \"agent_kill\",\n  \"session_monitor\",\n  \"session_events_poll\",\n  \"session_list\",\n  \"session_tree\",\n  \"policy_attach\",\n  \"policy_status\",\n  \"policy_list\",\n  \"policy_cancel\",\n]\n\n/**\n * Recursion guardrail defaults (ADR §4.5 / WP4).\n *   DEFAULT_MAX_DEPTH  — how deep the orchestrator tree may grow by\n *                        default (root spawns at depth 0; a session\n *                        spawned by a depth-d orchestrator is d+1, so\n *                        depth 3 means at most 4 levels: 0,1,2,3).\n *   HARD_MAX_DEPTH     — an unconditional ceiling the schema bound +\n *                        mint both clamp to, so no caller can lift the\n *                        cap past this even with an explicit request.\n *   DEFAULT_MAX_CHILDREN — per-orchestrator alive-child quota.\n */\nexport const DEFAULT_MAX_DEPTH = 3\nexport const HARD_MAX_DEPTH = 8\nexport const DEFAULT_MAX_CHILDREN = 8\n\nexport interface OrchestratorScope {\n  /** The opaque scope-token handed to (and presented by) the child. */\n  token: string\n  /** The effective tool allowlist for this scope (⊆ the default and,\n   *  for a recursively-spawned child, ⊆ its parent's allowlist). */\n  tools: ReadonlySet<string>\n  /**\n   * Session id of the orchestrator that OWNS this token — i.e. the\n   * child session that presents it back on `/mcp/orchestrator`. The\n   * token is minted *before* the child session exists (the injector\n   * needs the URL to compose the spawn), so this is bound late, after\n   * `spawnAgent` returns the id, via `bindOwner`. Until bound, spawns\n   * through this scope are attributed to no parent and its subtree is\n   * empty (safe degradation). (ADR §4.5 / WP4) */\n  ownerSessionId?: string\n  /** Recursion depth of the owning orchestrator session. A spawn made\n   *  *through* this scope produces a child at `depth + 1`. Root scopes\n   *  (minted for a direct `/mcp` spawn) are depth 0. */\n  depth: number\n  /** Max recursion depth reachable through this scope. A spawn whose\n   *  child depth (`depth + 1`) would exceed this is rejected. Clamped\n   *  to `HARD_MAX_DEPTH`. */\n  maxDepth: number\n  /** Max concurrently-alive children the owning orchestrator may spawn\n   *  before further spawns are rejected. */\n  maxChildren: number\n}\n\n/**\n * Narrow a caller-requested tool list to ⊆ a ceiling subset.\n *\n * The `ceiling` is the maximum a caller may end up with — the global\n * `DEFAULT_ORCHESTRATOR_TOOLS` for a root scope, or the *parent's*\n * effective tools for a recursively-spawned child (non-re-grant: a\n * child can never widen beyond what its parent holds — ADR §4.5 #5).\n * The `{ tools: [...] }` form can only REMOVE from the ceiling, never\n * add: any name outside it is dropped. Omitting `requested` yields the\n * full ceiling. Omitting `ceiling` defaults to the global default.\n */\nexport function narrowOrchestratorTools(\n  requested?: readonly string[],\n  ceiling?: ReadonlySet<string>,\n): Set<string> {\n  const cap = ceiling ?? new Set(DEFAULT_ORCHESTRATOR_TOOLS)\n  if (!requested) return new Set(cap)\n  return new Set(requested.filter(t => cap.has(t)))\n}\n\nexport interface MintScopeOptions {\n  /** Caller-requested allowlist — narrowed ⊆ `ceiling` (or the default\n   *  when no ceiling is given). */\n  tools?: readonly string[]\n  /** Upper bound on the minted tools (the parent's effective tools for\n   *  a recursive child). Omit for a root scope (defaults to the global\n   *  default subset). */\n  ceiling?: ReadonlySet<string>\n  /** Depth of the owning orchestrator (default 0). */\n  depth?: number\n  /** Max depth reachable through this scope (default DEFAULT_MAX_DEPTH,\n   *  clamped to HARD_MAX_DEPTH). */\n  maxDepth?: number\n  /** Per-orchestrator alive-child quota (default DEFAULT_MAX_CHILDREN). */\n  maxChildren?: number\n}\n\nexport interface ScopeTokenRegistry {\n  /** Mint a fresh scope-token. See `MintScopeOptions`. */\n  mint(opts?: MintScopeOptions): OrchestratorScope\n  /** Resolve a presented token to its scope, or null when unknown. */\n  verify(token: string | null | undefined): OrchestratorScope | null\n  /** Late-bind the owning child session id onto a minted scope (the\n   *  token is minted before the child exists). No-op when the token is\n   *  unknown. Mutates the live scope object so `verify` reflects it. */\n  bindOwner(token: string, sessionId: string): void\n  /** Drop a token (e.g. when the child session ends). */\n  revoke(token: string): void\n}\n\n/**\n * In-memory registry of live scope-tokens. Tokens are random 256-bit\n * hex (unguessable, never persisted) — see ADR §5.3. Single-user-host\n * trust assumption mirrors the loopback auth bypass on `/mcp`.\n */\nexport function createScopeTokenRegistry(): ScopeTokenRegistry {\n  const scopes = new Map<string, OrchestratorScope>()\n  return {\n    mint(opts) {\n      const token = randomBytes(32).toString(\"hex\")\n      const scope: OrchestratorScope = {\n        token,\n        tools: narrowOrchestratorTools(opts?.tools, opts?.ceiling),\n        depth: opts?.depth ?? 0,\n        maxDepth: Math.min(opts?.maxDepth ?? DEFAULT_MAX_DEPTH, HARD_MAX_DEPTH),\n        maxChildren: opts?.maxChildren ?? DEFAULT_MAX_CHILDREN,\n      }\n      scopes.set(token, scope)\n      return scope\n    },\n    verify(token) {\n      if (!token) return null\n      return scopes.get(token) ?? null\n    },\n    bindOwner(token, sessionId) {\n      const scope = scopes.get(token)\n      if (scope) scope.ownerSessionId = sessionId\n    },\n    revoke(token) {\n      scopes.delete(token)\n    },\n  }\n}\n\nexport interface OrchestratorGatewayDeps {\n  workspace: string\n  name?: string\n  version?: string\n  registry: SessionsRegistry\n  sessionEvents: SessionEventBus\n  eventRing: EventRing\n  supervisor?: CompletionPolicySupervisor\n  resolveAgentAdapter?: AgentAdapterResolver\n  listAgentAdapters?: AgentAdapterLister\n  /** Orchestrator injector (WP3/WP4). When wired, a child orchestrator\n   *  driving the scoped server can itself spawn sub-orchestrators\n   *  (`orchestrator: true` on its `agent_start`) — the new\n   *  token inherits depth+1 and is bounded by the caller's tools\n   *  (non-re-grant). Omitted → recursion injection is unavailable on\n   *  the scoped surface (a child can still spawn plain sub-agents). */\n  orchestratorInjector?: OrchestratorInjector\n  /** Optional webhook notifier — same singleton as the root /mcp server.\n   *  When provided, per-session notifyUrl values from agent_start\n   *  are registered on spawn and unregistered on exit, so child\n   *  orchestrators spawning through this scoped gateway also fire webhooks. */\n  webhookNotifier?: WebhookNotifier\n  /** Forwarded to `registerSessionTools` — the daemon's own plain `/mcp`\n   *  gateway URL, defaulted onto `hermes` `agent_start` spawns issued\n   *  through this scoped sub-gateway that pass no `mcpServers`. See\n   *  `RegisterAgentToolsOptions.daemonMcpUrl`. */\n  daemonMcpUrl?: string\n}\n\nexport type OrchestratorMcpServerFactory = (\n  scope: OrchestratorScope,\n) => Promise<McpServer>\n\n/**\n * Build a factory that produces a scoped MCP server for a verified\n * scope. The server is created with NO doctype specs and NO workspace\n * (so no CRUD verbs, no `self_inspect`, no driver tools leak in), then\n * the orchestration passes run against a `withToolSubset` wrapper so\n * only `scope.tools` survive. Critically, `mcpProxy` and the PTY\n * factory are never wired here — import + terminal tools stay unwired\n * AND are excluded from the subset (defense in depth).\n */\nexport function createOrchestratorMcpServerFactory(\n  deps: OrchestratorGatewayDeps,\n): OrchestratorMcpServerFactory {\n  return async (scope: OrchestratorScope): Promise<McpServer> => {\n    const { server } = await createMcpServer({\n      specs: [],\n      name: `${deps.name ?? \"agentproto-runtime\"}-orchestrator`,\n      version: deps.version ?? \"0.1.0-alpha\",\n    })\n    registerSessionTools(server, {\n      registry: deps.registry,\n      toolSubset: scope.tools,\n      // The verified scope IS the calling orchestrator's identity:\n      // spawns through this server are attributed to `scope.ownerSessionId`\n      // at `scope.depth + 1`, depth/quota guards fire against it, and\n      // list/kill are filtered to its subtree (WP4).\n      callerScope: scope,\n      ...(deps.orchestratorInjector\n        ? { buildOrchestratorMcp: deps.orchestratorInjector }\n        : {}),\n      ...(deps.resolveAgentAdapter\n        ? { resolveAgentAdapter: deps.resolveAgentAdapter }\n        : {}),\n      ...(deps.listAgentAdapters\n        ? { listAgentAdapters: deps.listAgentAdapters }\n        : {}),\n      ...(deps.webhookNotifier\n        ? { webhookNotifier: deps.webhookNotifier }\n        : {}),\n      daemonMcpUrl: deps.daemonMcpUrl,\n    })\n    registerOrchestrationTools(server, {\n      registry: deps.registry,\n      sessionEvents: deps.sessionEvents,\n      eventRing: deps.eventRing,\n      toolSubset: scope.tools,\n      // WP6: pass the caller's scope so supervisor tools can enforce\n      // subtree-scoped access (attach only to own sub-agents; list/cancel\n      // only policies on own sub-agents; commit refused).\n      callerScope: scope,\n      ...(deps.supervisor ? { supervisor: deps.supervisor } : {}),\n    })\n    return server\n  }\n}\n\n/**\n * The auto-injection assembly (ADR §4.4 / WP3) — turns the \"make this\n * child an orchestrator\" intent into the concrete `mcpServers` entry\n * the ACP `session/new` call mounts, plus the token lifecycle.\n *\n * One call (`inject`) does three things:\n *   1. mint a scope-token (narrowed ⊆ default when `tools` is given);\n *   2. build the `mcpServers` entry pointing the child at the daemon's\n *      own scoped sub-gateway (`/mcp/orchestrator?scope=<token>`);\n *   3. hand back `bindLifecycle(sessionId)` so the caller can revoke\n *      the token the moment that child session exits — no token leaks\n *      past the life of the session it was minted for.\n *\n * Assembled in `createGateway` (not the CLI resolver) because it needs\n * the gateway's scope-token registry, the session-event bus, and the\n * HTTP listener's port — all of which live there.\n */\nexport interface OrchestratorInjection {\n  /** The `mcpServers` entry to merge into the child's `session/new`. */\n  entry: AcpMcpServer\n  /** The minted scope — `token` gates the endpoint, `tools` is the\n   *  effective (narrowed) allowlist. */\n  scope: OrchestratorScope\n  /**\n   * Revoke the scope-token once `sessionId` exits. Subscribes to the\n   * session-event bus for that one session's `session:exited` and\n   * self-unsubscribes on fire. Returns an unsubscribe in case the\n   * caller wants to drop the binding early (rarely needed).\n   */\n  bindLifecycle(sessionId: string): () => void\n}\n\nexport interface OrchestratorInjectorDeps {\n  scopeTokens: ScopeTokenRegistry\n  sessionEvents: SessionEventBus\n  /** Port the daemon's HTTP listener (and thus `/mcp/orchestrator`)\n   *  binds. The child reaches it over loopback. */\n  port: number\n  /** Loopback host for the injected `ref`. Always loopback — the child\n   *  is co-located on the host. Default `127.0.0.1`. */\n  host?: string\n  /** `name` advertised on the injected `mcpServers` entry. The child\n   *  sees its orchestration tools namespaced under this. Default\n   *  `agentproto`. */\n  entryName?: string\n}\n\nexport type OrchestratorInjector = (opts?: {\n  tools?: readonly string[]\n  /** The calling orchestrator's scope, when this spawn arrives via the\n   *  scoped sub-gateway (recursive spawn). The minted child token then\n   *  inherits `depth = caller.depth + 1`, its tools are bounded by the\n   *  caller's tools (non-re-grant — ADR §4.5 #5), and its depth/child\n   *  limits never exceed the caller's. Omit for a root spawn (direct\n   *  `/mcp`) → depth 0, full default subset, default limits. */\n  caller?: OrchestratorScope\n  /** Override the max depth reachable through the minted scope (clamped\n   *  to the caller's, then to HARD_MAX_DEPTH). Root-only knob. */\n  maxDepth?: number\n  /** Override the per-orchestrator child quota for the minted scope\n   *  (clamped to the caller's). Root-only knob. */\n  maxChildren?: number\n}) => OrchestratorInjection\n\n/**\n * Build the orchestrator injector. Closed over the gateway's\n * scope-token registry + session-event bus + HTTP port. Returns a\n * function that the `agent_start` handler calls when its\n * `orchestrator` field is set.\n */\nexport function createOrchestratorInjector(\n  deps: OrchestratorInjectorDeps,\n): OrchestratorInjector {\n  const host = deps.host ?? \"127.0.0.1\"\n  const name = deps.entryName ?? \"agentproto\"\n  return (opts) => {\n    const caller = opts?.caller\n    // A recursive child lands one level below its caller; a root spawn\n    // (no caller) is depth 0. Limits never escalate past the caller's.\n    const depth = caller ? caller.depth + 1 : 0\n    const maxDepth = caller\n      ? Math.min(opts?.maxDepth ?? caller.maxDepth, caller.maxDepth)\n      : (opts?.maxDepth ?? DEFAULT_MAX_DEPTH)\n    const maxChildren = caller\n      ? Math.min(opts?.maxChildren ?? caller.maxChildren, caller.maxChildren)\n      : (opts?.maxChildren ?? DEFAULT_MAX_CHILDREN)\n    const scope = deps.scopeTokens.mint({\n      ...(opts?.tools ? { tools: opts.tools } : {}),\n      // Non-re-grant: bound the child's tools by the caller's effective\n      // tools (not just the global default) — a child can never widen\n      // beyond what its parent holds.\n      ...(caller ? { ceiling: caller.tools } : {}),\n      depth,\n      maxDepth,\n      maxChildren,\n    })\n    const entry: AcpMcpServer = {\n      name,\n      transport: \"http\",\n      ref: `http://${host}:${deps.port}/mcp/orchestrator?scope=${scope.token}`,\n    }\n    const bindLifecycle = (sessionId: string): (() => void) => {\n      // Late-bind the owner: the token was minted before this child\n      // session existed; now that we have its id, attribute the scope to\n      // it so its own spawns inherit `parentSessionId = sessionId` and\n      // its subtree filters resolve.\n      deps.scopeTokens.bindOwner(scope.token, sessionId)\n      const off = deps.sessionEvents.on(\"session:exited\", ev => {\n        if (ev.sessionId !== sessionId) return\n        deps.scopeTokens.revoke(scope.token)\n        off()\n      })\n      return off\n    }\n    return { entry, scope, bindLifecycle }\n  }\n}\n","/**\n * Browser family on top of `@agentproto/adapter-kit` — Phase 3 (lightest\n * adoption: no creds, no wizard, no catalog file).\n *\n * Provides the kit-compatible types (`BrowserAdapterHandle`) and the\n * `makeBrowserAdapterLister` factory that wraps the existing injected\n * `listBrowserAdapters` / `resolveBrowserAdapter` functions in a standard\n * `AdapterLister<BrowserAdapterInfo>`.\n *\n * The resulting lister is passed as the `lister` option to\n * `registerBrowserTools`, which uses it to produce the same\n * `{ id, name, description, defaultPort }[]` JSON the legacy path emits\n * (output shape is unchanged — only the internal flow changes).\n *\n * Kit invariants honoured:\n *   - `check()` is NEVER called by the lister (OQ-5).\n *   - `BrowserAdapterInfo` carries no cred values (Appendix B).\n *   - `requiresSetup = false` → status is always \"ready\" without a ledger.\n */\n\nimport {\n  makeAdapterLister,\n  type AdapterHandle,\n  type AdapterLister,\n} from \"@agentproto/adapter-kit\"\nimport type {\n  BrowserAdapterInfo,\n  BrowserAdapterLister,\n  BrowserAdapterResolver,\n} from \"./browser-tools.js\"\n\n// ── Handle ────────────────────────────────────────────────────────────────────\n\n/**\n * Kit-compatible handle for a single in-process browser adapter.\n * `requiresSetup` is always `false` — browser adapters need no creds or\n * setup wizard, so the kit classifies them as \"ready\" on first resolution.\n */\nexport interface BrowserAdapterHandle extends AdapterHandle {\n  readonly requiresSetup: false\n  readonly defaultPort: number\n}\n\nfunction makeBrowserHandle(\n  entry: { id: string; name: string; description: string; defaultPort: number },\n  resolve?: BrowserAdapterResolver,\n): BrowserAdapterHandle {\n  return {\n    slug: entry.id,\n    name: entry.name,\n    version: \"built-in\",\n    description: entry.description,\n    requiresSetup: false,\n    defaultPort: entry.defaultPort,\n    // check() is available for on-demand health probes but is never called\n    // by the lister (kit invariant OQ-5). Returns true when the adapter\n    // is present in the injected resolver map, false otherwise.\n    check: async () => (resolve ? resolve(entry.id) != null : true),\n  }\n}\n\n// ── Noop ledger ───────────────────────────────────────────────────────────────\n\n// Browser adapters have requiresSetup=false, so the ledger result is\n// irrelevant to status classification. A lightweight noop avoids any\n// filesystem side-effects.\nconst noopLedger = {\n  exists: async (_slug: string): Promise<boolean> => false,\n  write: async (): Promise<void> => {},\n  read: async (_slug: string) => null,\n}\n\n// ── Lister factory ────────────────────────────────────────────────────────────\n\n/**\n * Build a kit-compatible `AdapterLister<BrowserAdapterInfo>` from the\n * existing injected browser adapter functions. The returned lister uses an\n * empty catalog and `discoverExtras` to surface the injected adapters, then\n * maps each resolved handle's fields into a `BrowserAdapterInfo` descriptor.\n *\n * The caller should pass the result as the `lister` option to\n * `registerBrowserTools`, which extracts `AdapterEntry.info` to preserve the\n * existing tool response shape.\n */\nexport function makeBrowserAdapterLister(opts: {\n  listBrowserAdapters: BrowserAdapterLister\n  resolveBrowserAdapter?: BrowserAdapterResolver\n}): AdapterLister<BrowserAdapterInfo> {\n  const { listBrowserAdapters, resolveBrowserAdapter } = opts\n\n  return makeAdapterLister<BrowserAdapterHandle, BrowserAdapterInfo>({\n    // Empty catalog — all adapters are discovered via discoverExtras below.\n    catalog: [],\n    // Resolver is never called with an empty catalog; noop is safe.\n    resolver: async () => null,\n    ledger: noopLedger,\n    toInfo: (handle): BrowserAdapterInfo => ({\n      id: handle.slug,\n      name: handle.name,\n      description: handle.description,\n      defaultPort: handle.defaultPort,\n    }),\n    // Surface every injected adapter as a discovered extra. The kit will\n    // call entryFor() on each, which reads ledger (returns false) and\n    // computes status as \"ready\" because requiresSetup=false.\n    discoverExtras: async () => {\n      const entries = listBrowserAdapters()\n      return entries.map(entry => makeBrowserHandle(entry, resolveBrowserAdapter))\n    },\n  })\n}\n","/**\n * Quick Cloudflare Tunnel provider — zero-credential variant.\n *\n * Spawns `cloudflared tunnel --config <ours>` against an isolated\n * config file we write per-tunnel into the workspace, parses the\n * assigned `*.trycloudflare.com` URL out of cloudflared's stderr.\n * No CF account, no API token, no DNS records. Trade-off: URL is\n * ephemeral (different each run) and there's no Cloudflare Access\n * gating — auth happens at the upstream (gateway bearer token, or\n * whatever the tunneled service does for itself).\n *\n * ## Why we don't use `--url`\n *\n * `cloudflared --url http://...` synthesises an inline ingress block\n * but ALSO merges anything from `~/.cloudflared/config.yml`. If a user\n * has prior named-tunnel config there, hostname-specific rules can\n * shadow the inline rule and every request falls through to the\n * built-in `http_status:404` catch-all (the symptom: cloudflared logs\n * `ingressRule=2 originService=http_status:404` for every request,\n * origin never sees traffic). Writing our own config and passing it\n * via `--config` is hermetic — `~/.cloudflared/config.yml` is ignored\n * entirely, so the URL-forward rule always wins.\n *\n * Use this for: ad-hoc demos, \"let me try this from another machine\n * for 10 minutes\", iterating on the remote-MCP UX before committing\n * to a domain.\n *\n * For: persistent URLs / SSO gating, use the named-CF provider (TBD).\n *\n * ## cloudflared discovery\n *\n * Detected on PATH at start time. Missing → throw with a pointer to\n * the install instructions. We deliberately don't bundle binaries —\n * keeps the OSS package free of platform-specific blobs and defers the\n * \"which version\" maintenance tax.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport { execFile } from \"node:child_process\"\nimport { mkdir, writeFile, rm } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport { randomBytes } from \"node:crypto\"\n\nimport type {\n  ProviderStartOptions,\n  ProviderStartResult,\n  RemoteProvider,\n  TunnelProviderHandle,\n} from \"./types.js\"\n\nconst execFileAsync = promisify(execFile)\n\nconst URL_REGEX = /https:\\/\\/[a-z0-9-]+\\.trycloudflare\\.com/i\n\nconst STARTUP_TIMEOUT_MS = 30_000\n\n/** Adapter-kit slug for the quick provider (catalog key). */\nexport const CLOUDFLARE_QUICK_SLUG = \"cloudflare-quick\"\n\n/** Quick tunnels need no credentials and offer no stability guarantees. */\nexport const QUICK_CAPABILITIES = {\n  stableUrl: false,\n  autostart: false,\n  customDomain: false,\n  requiresAuth: false,\n  hasApi: false,\n} as const\n\nexport function quickTunnelProvider(): RemoteProvider & TunnelProviderHandle {\n  let child: ChildProcess | null = null\n  let configPath: string | null = null\n\n  return {\n    id: \"quick\",\n    // ── adapter-kit handle surface ──────────────────────────────────\n    slug: CLOUDFLARE_QUICK_SLUG,\n    name: \"Cloudflare Quick Tunnel\",\n    // In-process provider — no npm package version to report.\n    version: \"builtin\",\n    description:\n      \"Zero-credential Cloudflare tunnel. Ephemeral *.trycloudflare.com URL, fresh each run.\",\n    requiresSetup: false,\n    capabilities: { ...QUICK_CAPABILITIES },\n    async check(): Promise<boolean> {\n      return cloudflaredOnPath()\n    },\n    async start(opts: ProviderStartOptions): Promise<ProviderStartResult> {\n      await assertCloudflaredOnPath()\n      const targetUrl = `http://${opts.target.host}:${opts.target.port}`\n\n      // Per-tunnel sentinel config — the only reason it exists is to\n      // override `~/.cloudflared/config.yml` so its ingress rules can't\n      // shadow our inline `--url` rule. We deliberately do NOT include\n      // an `ingress:` block here: quick-tunnel mode treats `--url` as\n      // the routing source of truth, and a stray top-level `ingress:`\n      // would fight it. Random suffix avoids collisions when dev\n      // restarts overlap.\n      const id = randomBytes(4).toString(\"hex\")\n      const dir = join(opts.workspace, \".agentproto\")\n      await mkdir(dir, { recursive: true })\n      configPath = join(dir, `cloudflared-${id}.yml`)\n      const configBody = [\n        `# generated by agentproto-runtime — sentinel only`,\n        `# overrides ~/.cloudflared/config.yml so its ingress rules`,\n        `# don't shadow the inline --url rule. Safe to delete when the`,\n        `# tunnel is down.`,\n        `no-autoupdate: true`,\n        `loglevel: debug`,\n        ``,\n      ].join(\"\\n\")\n      await writeFile(configPath, configBody, \"utf8\")\n      const proc = spawn(\n        \"cloudflared\",\n        [\"tunnel\", \"--config\", configPath, \"--url\", targetUrl],\n        { stdio: [\"ignore\", \"pipe\", \"pipe\"], shell: false },\n      )\n      child = proc\n\n      const url = await new Promise<string>((resolve, reject) => {\n        let settled = false\n        const timer = setTimeout(() => {\n          if (settled) return\n          settled = true\n          try {\n            proc.kill(\"SIGTERM\")\n          } catch {\n            /* noop */\n          }\n          reject(\n            new Error(\n              `cloudflared did not emit a public URL within ${STARTUP_TIMEOUT_MS / 1000}s`,\n            ),\n          )\n        }, STARTUP_TIMEOUT_MS)\n\n        const onData = (chunk: Buffer) => {\n          const text = chunk.toString(\"utf8\")\n          for (const line of text.split(/\\r?\\n/)) {\n            if (line.length > 0) opts.onLog?.(`[cloudflared] ${line}`)\n          }\n          if (settled) return\n          const match = text.match(URL_REGEX)\n          if (match) {\n            settled = true\n            clearTimeout(timer)\n            resolve(match[0])\n          }\n        }\n        // cloudflared writes the URL to stderr (it reserves stdout for\n        // proxied traffic / structured output in some modes). Watch\n        // both for safety.\n        proc.stderr?.on(\"data\", onData)\n        proc.stdout?.on(\"data\", onData)\n\n        proc.once(\"error\", err => {\n          if (settled) return\n          settled = true\n          clearTimeout(timer)\n          reject(err)\n        })\n        proc.once(\"exit\", (code, signal) => {\n          if (settled) return\n          settled = true\n          clearTimeout(timer)\n          reject(\n            new Error(\n              `cloudflared exited before emitting a URL (code=${code}, signal=${signal})`,\n            ),\n          )\n        })\n      })\n\n      // Detach the resolver listener (we already captured the URL); leave\n      // the log-forwarder attached so the gateway's RuntimeEvents stream\n      // sees ongoing tunnel chatter.\n      proc.once(\"exit\", (code, signal) => {\n        opts.onLog?.(\n          `[cloudflared] exited (code=${code ?? \"?\"} signal=${signal ?? \"-\"})`,\n        )\n      })\n\n      return { publicUrl: url, pid: proc.pid ?? null }\n    },\n\n    async stop(): Promise<void> {\n      const proc = child\n      const cfg = configPath\n      child = null\n      configPath = null\n      // Best-effort cleanup of the sentinel config — losing it means a\n      // stale `.agentproto/cloudflared-<id>.yml` file, no functional\n      // impact. We do this even if the proc never started.\n      if (cfg) {\n        try {\n          await rm(cfg, { force: true })\n        } catch {\n          /* noop */\n        }\n      }\n      if (!proc || proc.exitCode !== null) return\n      proc.kill(\"SIGTERM\")\n      // Hard-kill backstop after 3s if cloudflared ignores SIGTERM.\n      const timer = setTimeout(() => {\n        try {\n          proc.kill(\"SIGKILL\")\n        } catch {\n          /* noop */\n        }\n      }, 3_000)\n      timer.unref()\n      await new Promise<void>(resolve => {\n        if (proc.exitCode !== null) {\n          clearTimeout(timer)\n          resolve()\n          return\n        }\n        proc.once(\"exit\", () => {\n          clearTimeout(timer)\n          resolve()\n        })\n      })\n    },\n  }\n}\n\n/**\n * Non-throwing variant for the adapter-kit `check()` health probe — true\n * when `cloudflared` is reachable on PATH. NOT called during listing (the\n * kit derives status from resolvability + creds, per OQ-5); reserved for\n * on-demand health checks.\n */\nasync function cloudflaredOnPath(): Promise<boolean> {\n  try {\n    await execFileAsync(\"cloudflared\", [\"--version\"], { timeout: 3_000 })\n    return true\n  } catch {\n    return false\n  }\n}\n\nasync function assertCloudflaredOnPath(): Promise<void> {\n  try {\n    await execFileAsync(\"cloudflared\", [\"--version\"], { timeout: 3_000 })\n  } catch {\n    throw new Error(\n      \"cloudflared not found on PATH. Install it first:\\n\" +\n        \"  macOS:    brew install cloudflared\\n\" +\n        \"  Linux:    https://pkg.cloudflare.com/index.html\\n\" +\n        \"  Windows:  winget install --id Cloudflare.cloudflared\\n\" +\n        \"Or download a prebuilt binary from https://github.com/cloudflare/cloudflared/releases.\",\n    )\n  }\n}\n","/**\n * RemoteController — owns the gateway's \"publish to the internet\" state.\n *\n * One singleton per gateway. Holds:\n *   - the current tunnel provider's child process (cloudflared, …)\n *   - the bearer token gating /mcp once the tunnel is up\n *   - persisted state in `<workspace>/.agentproto/remote.json`\n *\n * The controller is the *only* component that mutates auth at runtime.\n * The HTTP server reads auth via a getter (see `AuthSource` in\n * http-server.ts), so flipping `enable() / disable()` here takes effect\n * on the next request — no restart, no race.\n *\n * ## Provider model\n *\n * Each provider implements `RemoteProvider` (start / stop / status).\n * v1 ships only `quick` (Cloudflare Quick Tunnel — no API key, no DNS,\n * ephemeral `*.trycloudflare.com` URL). Named CF Tunnel and Tailscale\n * land as additional implementations.\n *\n * ## Token model\n *\n * On enable we generate a 32-byte random bearer token, return it once\n * to the caller, and persist only its sha256 hash to disk. Same model\n * as a Stripe API key — losing the plaintext means rotating, not\n * recovering. This keeps `.agentproto/remote.json` safe to commit by\n * accident (it leaks the URL, not the credential).\n *\n * ## Security note\n *\n * The CF API token (when used by named-tunnel provider) is *never*\n * accepted as MCP tool input. The controller reads it from\n * `~/.config/agentproto/cloudflare.json` or `$CLOUDFLARE_API_TOKEN`.\n * Otherwise a remote agent could exfiltrate it through `remote_enable`.\n */\n\nimport { randomBytes, createHash } from \"node:crypto\"\nimport { mkdir, writeFile, readFile, chmod, rm } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nimport type { AuthOptions } from \"./http-server.js\"\nimport { quickTunnelProvider } from \"./remote-providers/quick.js\"\nimport type {\n  ProviderStartOptions,\n  ProviderStartResult,\n  RemoteProvider,\n} from \"./remote-providers/types.js\"\n\nexport type { ProviderStartOptions, ProviderStartResult, RemoteProvider }\n\nexport interface RemoteState {\n  provider: \"quick\"\n  publicUrl: string\n  bearerTokenHash: string\n  createdAt: string\n  /** PID of the supervised tunnel child process, if any. */\n  pid: number | null\n  /** Local target the tunnel forwards to (host + port). */\n  target: { host: string; port: number }\n  /**\n   * Whether the tunnel exposes the gateway itself (true) or some other\n   * local service (false). Bearer auth + loopback bypass only matter\n   * for the gateway path; arbitrary-target tunnels are pure passthrough\n   * and the daemon does not gate them.\n   */\n  exposesGateway: boolean\n}\n\nexport interface EnableInput {\n  provider?: \"quick\"\n  /**\n   * Local port to expose. Defaults to the gateway's own port — i.e.\n   * \"publish this MCP server.\" Pass any other port to expose a\n   * different local service (Supabase 54371, a Vite dev server, …)\n   * without spinning up a separate tunnel manager.\n   */\n  targetPort?: number\n  /**\n   * Host the tunnel forwards to. Defaults to `127.0.0.1`. Setting it\n   * to `localhost` resolves through DNS (IPv6 first on most systems);\n   * keep `127.0.0.1` unless the target is explicitly IPv6-bound.\n   */\n  targetHost?: string\n}\n\nexport interface EnableResult {\n  publicUrl: string\n  /**\n   * Bearer token issued by this gateway. Only meaningful when the\n   * tunnel exposes the gateway itself (default). For arbitrary-target\n   * tunnels (`targetPort != gateway.port`) the daemon does not gate\n   * the proxied service, and this is omitted.\n   */\n  bearerToken?: string\n  /**\n   * `<publicUrl>/mcp`. Only emitted when exposing the gateway.\n   */\n  mcpEndpoint?: string\n  /**\n   * Paste-ready `.mcp.json` snippet. Only emitted when exposing the\n   * gateway.\n   */\n  mcpConfigSnippet?: string\n  provider: \"quick\"\n  target: { host: string; port: number }\n  exposesGateway: boolean\n}\n\nexport interface RemoteStatus {\n  enabled: boolean\n  provider?: \"quick\"\n  publicUrl?: string\n  pid?: number | null\n  createdAt?: string\n  target?: { host: string; port: number }\n  exposesGateway?: boolean\n  /** Last error from the provider, if any (since last enable). */\n  lastError?: string\n}\n\nexport interface RemoteControllerOptions {\n  workspace: string\n  port: number\n  /** Hook for surfacing provider logs through RuntimeEvents. */\n  onLog?: (line: string) => void\n}\n\nconst STATE_FILE_REL = \".agentproto/remote.json\"\n\nexport class RemoteController {\n  private state: RemoteState | null = null\n  private bearerToken: string | null = null\n  private provider: RemoteProvider | null = null\n  private lastError: string | undefined\n  private readonly opts: RemoteControllerOptions\n\n  constructor(opts: RemoteControllerOptions) {\n    this.opts = opts\n  }\n\n  /**\n   * Auth getter handed to startHttpServer. The HTTP server calls this\n   * on every request so flipping enable/disable is effective without\n   * a restart.\n   */\n  readonly readAuth = (): AuthOptions => {\n    if (this.bearerToken === null) return { mode: \"none\" }\n    return { mode: \"bearer\", token: this.bearerToken }\n  }\n\n  status(): RemoteStatus {\n    if (!this.state) {\n      return { enabled: false, lastError: this.lastError }\n    }\n    return {\n      enabled: true,\n      provider: this.state.provider,\n      publicUrl: this.state.publicUrl,\n      pid: this.state.pid,\n      createdAt: this.state.createdAt,\n      target: this.state.target,\n      exposesGateway: this.state.exposesGateway,\n      lastError: this.lastError,\n    }\n  }\n\n  async enable(input: EnableInput): Promise<EnableResult> {\n    if (this.state) {\n      // Idempotent: returning the existing config would leak the\n      // bearer token (we only have the hash). Force teardown first so\n      // re-enable always rotates the token. Surface this in the docs.\n      throw new Error(\n        \"remote tunnel already active — call remote_disable first to rotate\",\n      )\n    }\n    const providerId = input.provider ?? \"quick\"\n    const provider = pickProvider(providerId)\n    this.lastError = undefined\n\n    const target = {\n      host: input.targetHost ?? \"127.0.0.1\",\n      port: input.targetPort ?? this.opts.port,\n    }\n    const exposesGateway =\n      target.host === \"127.0.0.1\" && target.port === this.opts.port\n\n    let started: ProviderStartResult\n    try {\n      started = await provider.start({\n        target,\n        workspace: this.opts.workspace,\n        onLog: line => {\n          this.opts.onLog?.(line)\n        },\n      })\n    } catch (err) {\n      this.lastError = errToMessage(err)\n      throw err\n    }\n\n    // Bearer auth + token issuance only matter when the tunnel exposes\n    // *this* gateway. For arbitrary-target tunnels (e.g. Supabase on\n    // 54371) the daemon is just provisioning a public passthrough; the\n    // proxied service does its own authn.\n    let bearerToken: string | null = null\n    let bearerTokenHash = \"\"\n    if (exposesGateway) {\n      bearerToken = randomBytes(32).toString(\"base64url\")\n      bearerTokenHash = sha256(bearerToken)\n    }\n\n    const state: RemoteState = {\n      provider: providerId,\n      publicUrl: started.publicUrl,\n      bearerTokenHash,\n      createdAt: new Date().toISOString(),\n      pid: started.pid,\n      target,\n      exposesGateway,\n    }\n\n    this.state = state\n    this.bearerToken = bearerToken\n    this.provider = provider\n\n    await persistState(this.opts.workspace, state)\n\n    const result: EnableResult = {\n      provider: providerId,\n      publicUrl: started.publicUrl,\n      target,\n      exposesGateway,\n    }\n    if (exposesGateway && bearerToken) {\n      const mcpEndpoint = `${started.publicUrl}/mcp`\n      result.bearerToken = bearerToken\n      result.mcpEndpoint = mcpEndpoint\n      result.mcpConfigSnippet = buildMcpConfigSnippet(mcpEndpoint, bearerToken)\n    }\n    return result\n  }\n\n  async disable(): Promise<{ disabled: boolean }> {\n    if (!this.state) return { disabled: false }\n    const provider = this.provider\n    this.state = null\n    this.bearerToken = null\n    this.provider = null\n    if (provider) {\n      try {\n        await provider.stop()\n      } catch (err) {\n        this.lastError = errToMessage(err)\n      }\n    }\n    await clearState(this.opts.workspace)\n    return { disabled: true }\n  }\n\n  /**\n   * Stop the provider on gateway shutdown. Does NOT clear persisted\n   * state — that survives across restarts so the user can `remote_status`\n   * after rebooting and see \"stale state, run remote_enable to refresh\".\n   * (Stale-recovery semantics land in v2; today we just leave the file.)\n   */\n  async shutdown(): Promise<void> {\n    if (this.provider) {\n      try {\n        await this.provider.stop()\n      } catch {\n        /* swallow — gateway is shutting down anyway */\n      }\n    }\n  }\n}\n\n// ── helpers ────────────────────────────────────────────────────────────\n\nfunction pickProvider(id: \"quick\"): RemoteProvider {\n  if (id === \"quick\") return quickTunnelProvider()\n  // Exhaustive guard — adding \"named-cf\" / \"tailscale\" later forces this\n  // switch to be updated, otherwise TS will yell.\n  const _exhaustive: never = id\n  throw new Error(`unknown remote provider: ${String(_exhaustive)}`)\n}\n\nfunction sha256(input: string): string {\n  return createHash(\"sha256\").update(input).digest(\"hex\")\n}\n\nfunction errToMessage(err: unknown): string {\n  return err instanceof Error ? err.message : String(err)\n}\n\nasync function persistState(workspace: string, state: RemoteState): Promise<void> {\n  const dir = join(workspace, \".agentproto\")\n  await mkdir(dir, { recursive: true })\n  const file = join(dir, \"remote.json\")\n  await writeFile(file, JSON.stringify(state, null, 2) + \"\\n\", \"utf8\")\n  // mode 0600 — even though we only persist the hash, the URL itself\n  // is sensitive (knowing it lets an attacker brute-force the token).\n  try {\n    await chmod(file, 0o600)\n  } catch {\n    /* best-effort on platforms where chmod is a noop */\n  }\n}\n\nasync function clearState(workspace: string): Promise<void> {\n  const file = join(workspace, \".agentproto/remote.json\")\n  if (!existsSync(file)) return\n  await rm(file, { force: true })\n}\n\n/**\n * Best-effort load of persisted state on boot. We don't restore the\n * bearer token from this — the hash is one-way — so a rebooted gateway\n * that finds a stale `remote.json` will surface it via `remote_status`\n * and require a fresh `remote_enable` to mint a new token.\n *\n * Exposed mostly for diagnostics; not used by the controller today.\n */\nexport async function loadPersistedState(\n  workspace: string,\n): Promise<RemoteState | null> {\n  const file = join(workspace, STATE_FILE_REL)\n  if (!existsSync(file)) return null\n  try {\n    const raw = await readFile(file, \"utf8\")\n    return JSON.parse(raw) as RemoteState\n  } catch {\n    return null\n  }\n}\n\nfunction buildMcpConfigSnippet(endpoint: string, token: string): string {\n  return JSON.stringify(\n    {\n      mcpServers: {\n        \"agentproto-remote\": {\n          transport: \"http\",\n          url: endpoint,\n          headers: { Authorization: `Bearer ${token}` },\n        },\n      },\n    },\n    null,\n    2,\n  )\n}\n","/**\n * MCP tools that drive RemoteController — the gateway's \"publish to\n * the internet\" surface.\n *\n * Three tools, mirroring the controller's lifecycle:\n *\n *   remote_enable   — bring up a tunnel, mint bearer token, return the\n *                     public /mcp URL + a paste-ready .mcp.json snippet\n *   remote_disable  — tear down tunnel, revoke token, drop bearer auth\n *   remote_status   — read-only — provider, URL, pid, lastError\n *\n * Why this lives on the MCP surface (not a separate CLI):\n *   - The user already has an MCP client connected (that's how they\n *     started talking to the gateway in the first place). One tool call\n *     replaces an entire CLI install + auth dance.\n *   - The bearer token comes back as part of the MCP response, so it\n *     doesn't have to land on the user's clipboard.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\n\nimport type { RemoteController } from \"./remote-controller.js\"\n\nexport interface RegisterRemoteToolsOptions {\n  controller: RemoteController\n}\n\nfunction text(value: string | object): {\n  content: Array<{ type: \"text\"; text: string }>\n} {\n  return {\n    content: [\n      {\n        type: \"text\",\n        text: typeof value === \"string\" ? value : JSON.stringify(value, null, 2),\n      },\n    ],\n  }\n}\n\nexport function registerRemoteTools(\n  server: McpServer,\n  opts: RegisterRemoteToolsOptions,\n): void {\n  const { controller } = opts\n\n  server.tool(\n    \"remote_enable\",\n    \"Publish a local port to the internet via Cloudflare. By default exposes \" +\n      \"this gateway and gates it with a bearer token (returned ONCE in the \" +\n      \"response — store it; only its hash is persisted). Pass `targetPort` to \" +\n      \"tunnel a different local service (Supabase, dev server, …); in that mode \" +\n      \"the daemon does not gate the proxied traffic — the upstream service \" +\n      \"handles its own auth. Returns the public URL plus a paste-ready \" +\n      \"`.mcp.json` snippet (gateway mode only). Re-running while a tunnel is \" +\n      \"already up errors; call `remote_disable` first to rotate.\",\n    {\n      provider: z\n        .enum([\"quick\"])\n        .optional()\n        .describe(\n          \"Tunnel backend. `quick` = Cloudflare Quick Tunnel (no API key, ephemeral *.trycloudflare.com URL). Defaults to `quick`. Named-CF / Tailscale providers TBD.\",\n        ),\n      targetPort: z\n        .number()\n        .int()\n        .min(1)\n        .max(65535)\n        .optional()\n        .describe(\n          \"Local port to expose. Defaults to this gateway's own port (= publish the MCP server). Pass another port to tunnel a different local service (e.g. 54371 for Supabase) — in that mode bearer auth is OFF since the upstream handles its own gating.\",\n        ),\n      targetHost: z\n        .string()\n        .optional()\n        .describe(\n          \"Host the tunnel forwards to. Defaults to `127.0.0.1`. Use `localhost` only if the target is explicitly IPv6-bound; cloudflared resolves DNS and IPv6-first lookups can break IPv4-only origins.\",\n        ),\n    },\n    async ({ provider, targetPort, targetHost }) => {\n      const result = await controller.enable({ provider, targetPort, targetHost })\n      return text(result)\n    },\n  )\n\n  server.tool(\n    \"remote_disable\",\n    \"Tear down the active remote tunnel and drop bearer auth back to \" +\n      \"loopback-only. Idempotent — calling when no tunnel is active is a no-op.\",\n    {},\n    async () => {\n      const result = await controller.disable()\n      return text(result)\n    },\n  )\n\n  server.tool(\n    \"remote_status\",\n    \"Report whether a remote tunnel is active. When active: provider, \" +\n      \"public URL, supervised PID, createdAt. The bearer token itself is \" +\n      \"never returned by status — it was shown once at enable.\",\n    {},\n    async () => {\n      return text(controller.status())\n    },\n  )\n}\n","/**\n * Named Cloudflare Tunnel provider — persistent-URL variant.\n *\n * Unlike the quick provider (ephemeral `*.trycloudflare.com`, fresh each\n * run), this runs a *named* cloudflared tunnel bound to a stable hostname\n * you control (e.g. `guilde-local.example.com`). The URL never changes —\n * which is what makes a tunnel survivable across restarts and safe to bake\n * into a client config (MCP server URL, webhook, …).\n *\n * ## BYO (bring-your-own) model\n *\n * This provider does NOT create the tunnel or its DNS record — it *runs* a\n * tunnel you've already provisioned once via the cloudflared CLI:\n *\n *   cloudflared tunnel create <name>            # → tunnel id + creds json\n *   cloudflared tunnel route dns <id> <host>    # → CNAME host → tunnel\n *\n * After that one-time setup, agentproto owns the lifecycle: it writes a\n * hermetic `--config` (tunnel id + credentials-file + a single ingress\n * rule `hostname → http://localhost:<port>`) and spawns\n * `cloudflared tunnel --config <ours> run <id>`. Because we pass our own\n * config, `~/.cloudflared/config.yml` is ignored entirely (same hermetic\n * reasoning as the quick provider) so the ingress rule always wins.\n *\n * Managed mode (provider auto-runs `create` + `route dns` via a CF API\n * token) is a future addition; BYO covers the common case without storing\n * an account-wide token.\n *\n * ## Why publicUrl is deterministic\n *\n * The hostname is known up front, so — unlike quick — we don't parse a URL\n * out of cloudflared's stderr. We instead wait for the connection-ready\n * marker (`Registered tunnel connection`) before reporting `active`, so a\n * tunnel that can't reach the edge surfaces as a start failure rather than\n * a dead \"active\" entry.\n *\n * ## credentials-file discovery\n *\n * If `credentialsFile` is omitted we default to\n * `~/.cloudflared/<tunnelId>.json` — exactly where `cloudflared tunnel\n * create` writes it. Pass an explicit path only if you relocated it.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport { execFile } from \"node:child_process\"\nimport { mkdir, writeFile, rm, access } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { randomBytes } from \"node:crypto\"\n\nimport type {\n  ProviderStartOptions,\n  ProviderStartResult,\n  RemoteProvider,\n  TunnelProviderHandle,\n} from \"./types.js\"\n\nconst execFileAsync = promisify(execFile)\n\n/** Cloudflared logs this once each edge connection is registered. */\nconst READY_REGEX = /Registered tunnel connection/i\n\nconst STARTUP_TIMEOUT_MS = 30_000\n\n/** Adapter-kit slug for the named provider (catalog key). */\nexport const CLOUDFLARE_NAMED_SLUG = \"cloudflare-named\"\n\n/** Named tunnels are stable, autostart-able, and require BYO credentials. */\nexport const NAMED_CAPABILITIES = {\n  stableUrl: true,\n  autostart: true,\n  customDomain: true,\n  requiresAuth: true,\n  hasApi: false,\n} as const\n\n/** Creds fields the named provider accepts via `setup_tunnel_provider`. */\nexport const NAMED_SETUP_FIELDS = [\n  {\n    name: \"hostname\",\n    description: \"Cloudflare tunnel hostname (e.g. agent.example.com)\",\n    required: true,\n    sensitive: true,\n  },\n  {\n    name: \"tunnelId\",\n    description:\n      \"Cloudflare tunnel UUID (e.g. 11111111-2222-3333-4444-555555555555)\",\n    required: true,\n    sensitive: true,\n  },\n  {\n    name: \"credentialsFile\",\n    description: \"Optional path to cloudflared credentials JSON file\",\n    required: false,\n    sensitive: true,\n  },\n] as const\n\nexport interface NamedTunnelConfig {\n  /** Stable public hostname routed to this tunnel (e.g. app.example.com). */\n  hostname: string\n  /** Cloudflare tunnel id or name (the `run` target). */\n  tunnelId: string\n  /**\n   * Path to the tunnel credentials JSON. Defaults to\n   * `~/.cloudflared/<tunnelId>.json`.\n   */\n  credentialsFile?: string\n}\n\nexport function namedTunnelProvider(\n  cfg: NamedTunnelConfig,\n): RemoteProvider & TunnelProviderHandle {\n  let child: ChildProcess | null = null\n  let configPath: string | null = null\n\n  const credentialsFile =\n    cfg.credentialsFile ??\n    join(homedir(), \".cloudflared\", `${cfg.tunnelId}.json`)\n\n  return {\n    id: \"named\",\n    // ── adapter-kit handle surface ──────────────────────────────────\n    slug: CLOUDFLARE_NAMED_SLUG,\n    name: \"Cloudflare Named Tunnel\",\n    // In-process provider — no npm package version to report.\n    version: \"builtin\",\n    description:\n      \"Persistent Cloudflare tunnel bound to a stable hostname you control (BYO credentials).\",\n    requiresSetup: true,\n    capabilities: { ...NAMED_CAPABILITIES },\n    setupFields: NAMED_SETUP_FIELDS,\n    async check(): Promise<boolean> {\n      // Reachable = cloudflared on PATH AND the tunnel credentials file\n      // exists. NOT called during listing (kit derives status from creds\n      // existence); reserved for on-demand health probes.\n      const [bin, creds] = await Promise.all([\n        cloudflaredOnPath(),\n        fileExists(credentialsFile),\n      ])\n      return bin && creds\n    },\n    async start(opts: ProviderStartOptions): Promise<ProviderStartResult> {\n      await assertCloudflaredOnPath()\n      await assertCredentialsExist(credentialsFile)\n\n      const targetUrl = `http://${opts.target.host}:${opts.target.port}`\n\n      // Hermetic per-run config. A named tunnel needs a real `ingress:`\n      // block (the quick provider deliberately omits it because `--url`\n      // is its routing source of truth; here `run <id>` has no `--url`,\n      // so ingress IS the routing). Random suffix avoids collisions when\n      // restarts overlap.\n      const id = randomBytes(4).toString(\"hex\")\n      const dir = join(opts.workspace, \".agentproto\")\n      await mkdir(dir, { recursive: true })\n      configPath = join(dir, `cloudflared-named-${id}.yml`)\n      const configBody = [\n        `# generated by agentproto-runtime — named tunnel run config`,\n        `# hermetic: overrides ~/.cloudflared/config.yml. Safe to delete`,\n        `# when the tunnel is down.`,\n        `tunnel: ${cfg.tunnelId}`,\n        `credentials-file: ${credentialsFile}`,\n        `no-autoupdate: true`,\n        ``,\n        `ingress:`,\n        `  - hostname: ${cfg.hostname}`,\n        `    service: ${targetUrl}`,\n        `  - service: http_status:404`,\n        ``,\n      ].join(\"\\n\")\n      await writeFile(configPath, configBody, \"utf8\")\n\n      const proc = spawn(\n        \"cloudflared\",\n        [\"tunnel\", \"--config\", configPath, \"run\", cfg.tunnelId],\n        { stdio: [\"ignore\", \"pipe\", \"pipe\"], shell: false },\n      )\n      child = proc\n\n      await new Promise<void>((resolve, reject) => {\n        let settled = false\n        const timer = setTimeout(() => {\n          if (settled) return\n          settled = true\n          try {\n            proc.kill(\"SIGTERM\")\n          } catch {\n            /* noop */\n          }\n          reject(\n            new Error(\n              `cloudflared did not register a tunnel connection within ${STARTUP_TIMEOUT_MS / 1000}s`,\n            ),\n          )\n        }, STARTUP_TIMEOUT_MS)\n\n        const onData = (chunk: Buffer) => {\n          const text = chunk.toString(\"utf8\")\n          for (const line of text.split(/\\r?\\n/)) {\n            if (line.length > 0) opts.onLog?.(`[cloudflared] ${line}`)\n          }\n          if (settled) return\n          if (READY_REGEX.test(text)) {\n            settled = true\n            clearTimeout(timer)\n            resolve()\n          }\n        }\n        proc.stderr?.on(\"data\", onData)\n        proc.stdout?.on(\"data\", onData)\n\n        proc.once(\"error\", err => {\n          if (settled) return\n          settled = true\n          clearTimeout(timer)\n          reject(err)\n        })\n        proc.once(\"exit\", (code, signal) => {\n          if (settled) return\n          settled = true\n          clearTimeout(timer)\n          reject(\n            new Error(\n              `cloudflared exited before connecting (code=${code}, signal=${signal})`,\n            ),\n          )\n        })\n      })\n\n      proc.once(\"exit\", (code, signal) => {\n        opts.onLog?.(\n          `[cloudflared] exited (code=${code ?? \"?\"} signal=${signal ?? \"-\"})`,\n        )\n      })\n\n      return { publicUrl: `https://${cfg.hostname}`, pid: proc.pid ?? null }\n    },\n\n    async stop(): Promise<void> {\n      const proc = child\n      const cfg2 = configPath\n      child = null\n      configPath = null\n      if (cfg2) {\n        try {\n          await rm(cfg2, { force: true })\n        } catch {\n          /* noop */\n        }\n      }\n      if (!proc || proc.exitCode !== null) return\n      proc.kill(\"SIGTERM\")\n      const timer = setTimeout(() => {\n        try {\n          proc.kill(\"SIGKILL\")\n        } catch {\n          /* noop */\n        }\n      }, 3_000)\n      timer.unref()\n      await new Promise<void>(resolve => {\n        if (proc.exitCode !== null) {\n          clearTimeout(timer)\n          resolve()\n          return\n        }\n        proc.once(\"exit\", () => {\n          clearTimeout(timer)\n          resolve()\n        })\n      })\n    },\n  }\n}\n\n/** Non-throwing PATH probe for the adapter-kit `check()` health surface. */\nasync function cloudflaredOnPath(): Promise<boolean> {\n  try {\n    await execFileAsync(\"cloudflared\", [\"--version\"], { timeout: 3_000 })\n    return true\n  } catch {\n    return false\n  }\n}\n\n/** Non-throwing existence check (no value read — purely a boolean probe). */\nasync function fileExists(path: string): Promise<boolean> {\n  try {\n    await access(path)\n    return true\n  } catch {\n    return false\n  }\n}\n\nasync function assertCloudflaredOnPath(): Promise<void> {\n  try {\n    await execFileAsync(\"cloudflared\", [\"--version\"], { timeout: 3_000 })\n  } catch {\n    throw new Error(\n      \"cloudflared not found on PATH. Install it first:\\n\" +\n        \"  macOS:    brew install cloudflared\\n\" +\n        \"  Linux:    https://pkg.cloudflare.com/index.html\\n\" +\n        \"  Windows:  winget install --id Cloudflare.cloudflared\\n\" +\n        \"Or download a prebuilt binary from https://github.com/cloudflare/cloudflared/releases.\",\n    )\n  }\n}\n\nasync function assertCredentialsExist(path: string): Promise<void> {\n  try {\n    await access(path)\n  } catch {\n    throw new Error(\n      `named tunnel credentials not found at ${path}.\\n` +\n        \"Provision the tunnel once, then retry:\\n\" +\n        \"  cloudflared tunnel create <name>\\n\" +\n        \"  cloudflared tunnel route dns <id-or-name> <hostname>\\n\" +\n        \"Or pass an explicit credentialsFile if you relocated the JSON.\",\n    )\n  }\n}\n","/**\n * Ngrok tunnel provider — static-domain variant.\n *\n * Spawns `ngrok http <port>` (with optional `--domain=<domain>` when a\n * reserved domain is configured), authenticates via the stored authtoken,\n * and extracts the public URL from the local ngrok agent API\n * (`http://127.0.0.1:4040/api/tunnels`) with a fallback to parsing stdout\n * JSON lines.\n *\n * ## Creds model\n *\n * Ngrok needs an authtoken (free tier ok). An optional reserved domain\n * (`--domain`) enables stable URLs (paid plan). Both are stored via the\n * adapter-kit creds store under the tunnel family.\n *\n * ## local agent API (port 4040)\n *\n * Ngrok exposes `http://127.0.0.1:4040/api/tunnels` while running — the\n * canonical source of the public URL. We poll this after spawn (with a\n * short grace period) before falling back to stdout JSON-line parsing.\n *\n * ## Why we don't use `@ngrok/ngrok` npm package\n *\n * The npm package embeds the ngrok binary and manages its own lifecycle,\n * which fights with our explicit spawn/stop model. The binary-on-PATH\n * approach mirrors the cloudflared providers and keeps the dependency\n * surface small.\n *\n * ## ngrok discovery\n *\n * Detected on PATH at check/start time. Missing → `check()` returns false\n * and `start()` throws with install instructions. We deliberately don't\n * bundle binaries.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport { execFile } from \"node:child_process\"\n\nimport type {\n  ProviderStartOptions,\n  ProviderStartResult,\n  RemoteProvider,\n  TunnelProviderHandle,\n} from \"./types.js\"\n\nconst execFileAsync = promisify(execFile)\n\n/** JSON line from ngrok's `--log-format=json` stdout: `{\"url\":\"...\",...}`. */\nconst URL_JSON_REGEX = /\"url\"\\s*:\\s*\"(https:\\/\\/[^\"]+)\"/i\n\n/** Ngrok local agent API base. */\nconst AGENT_API = \"http://127.0.0.1:4040\"\n\nconst STARTUP_TIMEOUT_MS = 30_000\nconst API_POLL_INTERVAL_MS = 500\nconst API_GRACE_MS = 2_000\n\n/** Adapter-kit slug for the ngrok provider (catalog key). */\nexport const NGROK_SLUG = \"ngrok\"\n\n/**\n * Ngrok capabilities. `stableUrl` is true only when a reserved domain is\n * configured; without one the URL is fixed in format but not guaranteed\n * across restarts without a paid plan.\n */\nexport const NGROK_CAPABILITIES = {\n  stableUrl: false, // overridden at instance level when domain is set\n  autostart: true,\n  customDomain: true,\n  requiresAuth: true,\n  hasApi: true,\n} as const\n\n/** Creds fields the ngrok provider accepts via `setup_tunnel_provider`. */\nexport const NGROK_SETUP_FIELDS = [\n  {\n    name: \"authToken\",\n    description:\n      \"Ngrok authtoken (from dashboard.ngrok.com/get-started/your-authtoken)\",\n    required: true,\n    sensitive: true,\n  },\n  {\n    name: \"domain\",\n    description: \"Optional reserved ngrok static domain (requires paid plan)\",\n    required: false,\n    sensitive: true,\n  },\n] as const\n\n/** Structured credentials for the ngrok provider. */\nexport interface TunnelNgrokCreds {\n  /** Ngrok authtoken from dashboard.ngrok.com/get-started/your-authtoken. */\n  authToken: string\n  /** Optional reserved static domain (requires ngrok paid plan). */\n  domain?: string\n}\n\n/** Factory options for building an ngrok tunnel provider. */\nexport interface NgrokProviderOpts {\n  /** Ngrok authtoken. Pass undefined for descriptor-only handles. */\n  authToken?: string\n  /** Optional reserved static domain. */\n  domain?: string\n  /**\n   * Binary presence probe. Default: real `ngrok version` PATH check.\n   * Injectable so tests can control binary-presence deterministically\n   * without a global `node:child_process` mock.\n   */\n  probeBinary?: () => Promise<boolean>\n}\n\n/**\n * Factory: build an ngrok tunnel provider.\n *\n * When called with no config (descriptor-only, for listing), `start()` and\n * `check()` will fail gracefully — the adapter-kit lister never calls those\n * methods; it only inspects handle metadata.\n */\nexport function ngrokTunnelProvider(\n  opts?: NgrokProviderOpts,\n): RemoteProvider & TunnelProviderHandle {\n  let child: ChildProcess | null = null\n\n  const authToken = opts?.authToken ?? null\n  const domain = opts?.domain ?? null\n  const hasDomain = domain != null && domain.length > 0\n  const probeBinary = opts?.probeBinary ?? ngrokOnPath\n\n  return {\n    id: \"ngrok\",\n    // ── adapter-kit handle surface ──────────────────────────────────\n    slug: NGROK_SLUG,\n    name: \"Ngrok Tunnel\",\n    version: \"builtin\",\n    description:\n      \"Ngrok tunnel with optional static domain support. Requires a free authtoken.\",\n    requiresSetup: true,\n    setupFields: NGROK_SETUP_FIELDS,\n    capabilities: {\n      ...NGROK_CAPABILITIES,\n      stableUrl: hasDomain,\n    },\n    async check(): Promise<boolean> {\n      // Reachable = ngrok binary on PATH AND an authtoken is available.\n      const [bin] = await Promise.all([probeBinary()])\n      return bin && authToken != null\n    },\n    async start(opts: ProviderStartOptions): Promise<ProviderStartResult> {\n      await assertNgrokOnPath(probeBinary)\n      if (!authToken) {\n        throw new Error(\n          \"ngrok authtoken not configured. Run setup first:\\n\" +\n            \"  agentproto tunnel setup ngrok\\n\" +\n            \"Or set NGROK_AUTHTOKEN in your environment.\",\n        )\n      }\n\n      const args = [\n        \"http\",\n        String(opts.target.port),\n        \"--log=stdout\",\n        \"--log-format=json\",\n      ]\n      if (hasDomain) args.push(`--domain=${domain}`)\n\n      const proc = spawn(\"ngrok\", args, {\n        stdio: [\"ignore\", \"pipe\", \"pipe\"],\n        env: { ...process.env, NGROK_AUTHTOKEN: authToken },\n        shell: false,\n      })\n      child = proc\n\n      // Forward logs.\n      const forwardLogs = (chunk: Buffer) => {\n        const text = chunk.toString(\"utf8\")\n        for (const line of text.split(/\\r?\\n/)) {\n          if (line.length > 0) opts.onLog?.(`[ngrok] ${line}`)\n        }\n      }\n      proc.stderr?.on(\"data\", forwardLogs)\n      proc.stdout?.on(\"data\", forwardLogs)\n\n      const url = await new Promise<string>((resolve, reject) => {\n        let settled = false\n        const timer = setTimeout(() => {\n          if (settled) return\n          settled = true\n          try {\n            proc.kill(\"SIGTERM\")\n          } catch {\n            /* noop */\n          }\n          reject(\n            new Error(\n              `ngrok did not emit a public URL within ${STARTUP_TIMEOUT_MS / 1000}s`,\n            ),\n          )\n        }, STARTUP_TIMEOUT_MS)\n\n        // Strategy 1: poll the local agent API (preferred — canonical).\n        let apiPollHandle: ReturnType<typeof setInterval> | null = null\n        const startApiPoll = () => {\n          apiPollHandle = setInterval(async () => {\n            if (settled) return\n            try {\n              const res = await fetch(`${AGENT_API}/api/tunnels`)\n              if (!res.ok) return\n              const data = (await res.json()) as {\n                tunnels?: { public_url?: string }[]\n              }\n              const pubUrl = data.tunnels?.[0]?.public_url\n              if (pubUrl) {\n                settled = true\n                clearTimeout(timer)\n                if (apiPollHandle) clearInterval(apiPollHandle)\n                resolve(pubUrl)\n              }\n            } catch {\n              // API not ready yet — keep polling.\n            }\n          }, API_POLL_INTERVAL_MS)\n          if (apiPollHandle.unref) apiPollHandle.unref()\n        }\n\n        // Strategy 2: fallback — parse JSON lines from stdout.\n        const onStdout = (chunk: Buffer) => {\n          if (settled) return\n          const text = chunk.toString(\"utf8\")\n          // Try the regex first (fast path).\n          const reMatch = text.match(URL_JSON_REGEX)\n          if (reMatch) {\n            settled = true\n            clearTimeout(timer)\n            if (apiPollHandle) clearInterval(apiPollHandle)\n            resolve(reMatch[1]!)\n            return\n          }\n          // Try line-by-line JSON parse.\n          for (const line of text.split(/\\r?\\n/)) {\n            if (line.length === 0) continue\n            try {\n              const parsed = JSON.parse(line) as { url?: string }\n              if (parsed.url) {\n                settled = true\n                clearTimeout(timer)\n                if (apiPollHandle) clearInterval(apiPollHandle)\n                resolve(parsed.url)\n                return\n              }\n            } catch {\n              // Not a JSON line — keep waiting.\n            }\n          }\n        }\n\n        // Start API polling after a short grace period (ngrok takes ~1-2s\n        // to start the agent API).\n        setTimeout(startApiPoll, API_GRACE_MS)\n\n        // Also listen on stdout for JSON-line fallback.\n        proc.stdout?.on(\"data\", onStdout)\n\n        proc.once(\"error\", err => {\n          if (settled) return\n          settled = true\n          clearTimeout(timer)\n          if (apiPollHandle) clearInterval(apiPollHandle)\n          reject(err)\n        })\n        proc.once(\"exit\", (code, signal) => {\n          if (settled) return\n          settled = true\n          clearTimeout(timer)\n          if (apiPollHandle) clearInterval(apiPollHandle)\n          reject(\n            new Error(\n              `ngrok exited before emitting a URL (code=${code}, signal=${signal})`,\n            ),\n          )\n        })\n      })\n\n      proc.once(\"exit\", (code, signal) => {\n        opts.onLog?.(\n          `[ngrok] exited (code=${code ?? \"?\"} signal=${signal ?? \"-\"})`,\n        )\n      })\n\n      return { publicUrl: url, pid: proc.pid ?? null }\n    },\n\n    async stop(): Promise<void> {\n      const proc = child\n      child = null\n      if (!proc || proc.exitCode !== null) return\n      proc.kill(\"SIGTERM\")\n      const timer = setTimeout(() => {\n        try {\n          proc.kill(\"SIGKILL\")\n        } catch {\n          /* noop */\n        }\n      }, 3_000)\n      timer.unref()\n      await new Promise<void>(resolve => {\n        if (proc.exitCode !== null) {\n          clearTimeout(timer)\n          resolve()\n          return\n        }\n        proc.once(\"exit\", () => {\n          clearTimeout(timer)\n          resolve()\n        })\n      })\n    },\n  }\n}\n\n// ── helpers ────────────────────────────────────────────────────────────\n\n/** Non-throwing PATH probe for the adapter-kit `check()` health surface. */\nasync function ngrokOnPath(): Promise<boolean> {\n  try {\n    await execFileAsync(\"ngrok\", [\"version\"], { timeout: 3_000 })\n    return true\n  } catch {\n    return false\n  }\n}\n\nasync function assertNgrokOnPath(probe?: () => Promise<boolean>): Promise<void> {\n  const ok = await (probe ?? ngrokOnPath)()\n  if (!ok) {\n    throw new Error(\n      \"ngrok not found on PATH. Install it first:\\n\" +\n        \"  macOS:    brew install ngrok/ngrok/ngrok\\n\" +\n        \"  Linux:    https://ngrok.com/download\\n\" +\n        \"  Windows:  winget install ngrok\\n\" +\n        \"Or download a prebuilt binary from https://ngrok.com/download.\",\n    )\n  }\n}","/**\n * Slug-keyed tunnel provider registry — the single source of truth that both\n * halves of the tunnel family consult:\n *\n *   - the adapter-kit listing path (`list_tunnel_adapters` / `setup_tunnel_provider`)\n *   - the lifecycle path (`TunnelRegistry`: create / restore / start / stop)\n *\n * Before this module those two halves spoke different languages — the\n * lifecycle engine only knew the short discriminators `\"quick\"`/`\"named\"` and\n * had no ngrok case at all, while the adapter half spoke slugs. They never\n * reconciled, so ngrok was listable-but-not-creatable. Routing everything\n * through one registry collapses that: a built-in OR a third-party\n * `@agentproto/adapter-<slug>` / `@<scope>/agentproto-adapter-<slug>` provider\n * resolves the same way and works end to end.\n */\n\nimport { discoverAdapterPackages } from \"@agentproto/adapter-kit\"\n\nimport {\n  quickTunnelProvider,\n  CLOUDFLARE_QUICK_SLUG,\n} from \"./quick.js\"\nimport {\n  namedTunnelProvider,\n  CLOUDFLARE_NAMED_SLUG,\n} from \"./named.js\"\nimport { ngrokTunnelProvider, NGROK_SLUG } from \"./ngrok.js\"\nimport type {\n  RemoteProvider,\n  TunnelProviderHandle,\n  TunnelProviderCapabilities,\n} from \"./types.js\"\n\n/** A resolved provider — the lifecycle + adapter-kit handle surface combined. */\nexport type TunnelProvider = RemoteProvider & TunnelProviderHandle\n\n/** Per-slug credentials, as stored by the creds store / setup tool. */\nexport type TunnelCreds = Record<string, string>\n\n/**\n * Factory for a tunnel provider. Built-ins and third-party packages both\n * expose this shape: given the slug's stored creds (or null for a\n * descriptor-only handle used in listing), return a ready provider.\n */\nexport type TunnelProviderFactory = (creds?: TunnelCreds | null) => TunnelProvider\n\n/**\n * Built-in providers keyed by canonical slug. This replaces BOTH the old\n * `pickProvider()` switch (lifecycle) and the `makeTunnelResolver()` switch\n * (listing) — one map, two consumers.\n */\nexport const BUILTIN_TUNNEL_PROVIDERS: Record<string, TunnelProviderFactory> = {\n  [CLOUDFLARE_QUICK_SLUG]: () => quickTunnelProvider(),\n  [CLOUDFLARE_NAMED_SLUG]: (creds) =>\n    namedTunnelProvider({\n      hostname: creds?.hostname ?? \"\",\n      tunnelId: creds?.tunnelId ?? \"\",\n      ...(creds?.credentialsFile\n        ? { credentialsFile: creds.credentialsFile }\n        : {}),\n    }),\n  [NGROK_SLUG]: (creds) =>\n    ngrokTunnelProvider(\n      creds?.authToken\n        ? {\n            authToken: creds.authToken,\n            ...(creds.domain ? { domain: creds.domain } : {}),\n          }\n        : undefined,\n    ),\n}\n\n/** The canonical built-in slugs, in catalog order. */\nexport const BUILTIN_TUNNEL_SLUGS = [\n  CLOUDFLARE_QUICK_SLUG,\n  CLOUDFLARE_NAMED_SLUG,\n  NGROK_SLUG,\n] as const\n\n/**\n * Legacy short discriminators → canonical slugs. Persisted `tunnels.json`\n * descriptors and existing automations create tunnels with `\"quick\"` /\n * `\"named\"`; we normalize those to slugs everywhere so old state restores and\n * old callers keep working.\n */\nexport const LEGACY_PROVIDER_ALIAS: Record<string, string> = {\n  quick: CLOUDFLARE_QUICK_SLUG,\n  named: CLOUDFLARE_NAMED_SLUG,\n}\n\n/** Map a raw provider string (slug OR legacy short name) to a canonical slug. */\nexport function normalizeProviderSlug(raw: string): string {\n  return LEGACY_PROVIDER_ALIAS[raw] ?? raw\n}\n\n/**\n * Capabilities for a BUILT-IN provider slug (or legacy short name), read\n * synchronously from a descriptor-only handle. Returns null for third-party\n * slugs (their capabilities need an async import — `resolveTunnelProvider`).\n * Used by the lifecycle engine to decide autostart eligibility by data\n * (`stableUrl`) rather than a hardcoded slug literal.\n */\nexport function builtinProviderCapabilities(\n  raw: string,\n): TunnelProviderCapabilities | null {\n  const factory = BUILTIN_TUNNEL_PROVIDERS[normalizeProviderSlug(raw)]\n  return factory ? factory(null).capabilities : null\n}\n\nconst slugToCamel = (slug: string): string =>\n  slug.replace(/-([a-z0-9])/g, (_, c: string) => c.toUpperCase())\n\n/** Duck-type a value as a tunnel provider handle (no secrets touched). */\nfunction isTunnelProvider(x: unknown): x is TunnelProvider {\n  if (!x || typeof x !== \"object\") return false\n  const h = x as Record<string, unknown>\n  const caps = h.capabilities\n  return (\n    typeof h.start === \"function\" &&\n    typeof h.stop === \"function\" &&\n    typeof caps === \"object\" &&\n    caps !== null &&\n    \"stableUrl\" in (caps as Record<string, unknown>)\n  )\n}\n\n/**\n * Import a third-party tunnel provider package and build its handle. The\n * package may export either a factory `(creds) => handle` or a ready static\n * handle, under `<camelSlug>TunnelProvider`, `<camelSlug>`, `default`, or\n * `handle`. Returns null on any failure (not importable / wrong shape) —\n * partial discovery beats failing the whole listing on one bad package.\n */\nasync function importThirdPartyProvider(\n  packageName: string,\n  slug: string,\n  creds: TunnelCreds | null,\n): Promise<TunnelProvider | null> {\n  let mod: Record<string, unknown>\n  try {\n    mod = (await import(packageName)) as Record<string, unknown>\n  } catch {\n    return null\n  }\n  const camel = slugToCamel(slug)\n  const candidate =\n    mod[`${camel}TunnelProvider`] ??\n    mod[camel] ??\n    mod.default ??\n    mod.handle\n  const built =\n    typeof candidate === \"function\"\n      ? (candidate as TunnelProviderFactory)(creds)\n      : candidate\n  return isTunnelProvider(built) ? built : null\n}\n\nexport interface ResolveTunnelProviderOpts {\n  /** Stored creds for the slug (descriptor-only listing passes null). */\n  creds?: TunnelCreds | null\n}\n\n/**\n * Resolve a slug (or legacy short name) to a concrete provider. Built-ins\n * first (no import), then a third-party package discovered on disk across\n * both naming conventions. Returns null when the slug is unknown / not\n * installed — the kit's \"supported but unavailable\" signal.\n */\nexport async function resolveTunnelProvider(\n  raw: string,\n  opts?: ResolveTunnelProviderOpts,\n): Promise<TunnelProvider | null> {\n  const slug = normalizeProviderSlug(raw)\n  const builtin = BUILTIN_TUNNEL_PROVIDERS[slug]\n  if (builtin) return builtin(opts?.creds ?? null)\n\n  const pkgs = await discoverAdapterPackages()\n  const match = pkgs.find((p) => p.slug === slug)\n  if (!match) return null\n  return importThirdPartyProvider(match.packageName, slug, opts?.creds ?? null)\n}\n\n/**\n * Discover installed third-party tunnel providers NOT already in the catalog\n * (built-ins) — the `discoverExtras` source for the kit's lister so\n * locally-installed custom providers appear in `list_tunnel_adapters`.\n */\nexport async function discoverTunnelHandles(\n  catalogSlugs: Set<string>,\n): Promise<TunnelProvider[]> {\n  const pkgs = await discoverAdapterPackages()\n  const out: TunnelProvider[] = []\n  for (const pkg of pkgs) {\n    if (catalogSlugs.has(pkg.slug)) continue\n    if (BUILTIN_TUNNEL_PROVIDERS[pkg.slug]) continue\n    const handle = await importThirdPartyProvider(pkg.packageName, pkg.slug, null)\n    if (handle) out.push(handle)\n  }\n  return out.sort((a, b) => a.slug.localeCompare(b.slug))\n}\n","/**\n * TunnelRegistry — multi-tunnel public-URL manager.\n *\n * Manages a named set of cloudflared (or future provider) tunnels,\n * each forwarding a local port to a public URL. Independent from\n * RemoteController which handles the single \"expose this gateway\"\n * use-case with bearer-token gating. This registry is for the general\n * \"create a public endpoint for any local port\" surface.\n *\n * Lifecycle:\n *   create(input) → spawns provider, waits for URL, stores descriptor\n *   list()        → TunnelDescriptor[]\n *   get(id)       → TunnelDescriptor | undefined\n *   stop(id)      → SIGTERM provider, mark stopped\n *   shutdown()    → stop all active tunnels (called on daemon exit)\n *\n * Persistence: `~/.agentproto/tunnels.json` — descriptors survive\n * daemon restarts; active entries are marked \"stopped\" on next boot\n * since their child processes are gone (same GHOST pattern as\n * sessions.ts).\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { mkdirSync, readFileSync, writeFileSync, existsSync } from \"node:fs\"\nimport { mkdir } from \"node:fs/promises\"\nimport { dirname, join, resolve } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { CLOUDFLARE_NAMED_SLUG } from \"./remote-providers/named.js\"\nimport {\n  resolveTunnelProvider,\n  normalizeProviderSlug,\n  builtinProviderCapabilities,\n  type TunnelCreds,\n} from \"./remote-providers/registry.js\"\nimport type { RemoteProvider } from \"./remote-providers/types.js\"\n\nexport type TunnelStatus = \"starting\" | \"active\" | \"stopped\" | \"error\"\n\n/**\n * Provider identifier — an open set of slugs (built-in `cloudflare-quick` /\n * `cloudflare-named` / `ngrok`, legacy short names `quick` / `named`, or any\n * third-party `@scope/agentproto-adapter-<slug>`). Normalized to a canonical\n * slug only at resolve time, so persisted descriptors keep their original\n * value and need no migration.\n */\nexport type TunnelProvider = string\n\nexport interface TunnelDescriptor {\n  id: string\n  /** Optional user-friendly slug. Accepts id-or-name in stop/status calls. */\n  name?: string\n  /** Free-text label surfaced in list / CLI table. */\n  label?: string\n  provider: TunnelProvider\n  targetHost: string\n  targetPort: number\n  publicUrl: string\n  status: TunnelStatus\n  pid: number | null\n  createdAt: string\n  stoppedAt?: string\n  lastError?: string\n  /**\n   * When true, the tunnel is relaunched on daemon boot (see\n   * `restoreOnBoot`). Only meaningful for `named` tunnels — a relaunched\n   * `quick` tunnel gets a fresh random URL, so autostart for it merely\n   * keeps *a* tunnel up, not a stable URL.\n   */\n  autostart?: boolean\n  // ── named-provider fields (unset for quick) ──────────────────────\n  /** Stable public hostname routed to this tunnel. */\n  hostname?: string\n  /** Cloudflare tunnel id or name (the `run` target). */\n  tunnelId?: string\n  /** Path to the tunnel credentials JSON (defaults under ~/.cloudflared). */\n  credentialsFile?: string\n}\n\ninterface TunnelEntry {\n  desc: TunnelDescriptor\n  provider: RemoteProvider\n}\n\nexport interface CreateTunnelInput {\n  targetPort: number\n  provider?: TunnelProvider\n  name?: string\n  label?: string\n  targetHost?: string\n  /** Relaunch this tunnel on daemon boot. See `TunnelDescriptor.autostart`. */\n  autostart?: boolean\n  // ── required when provider === \"named\" ───────────────────────────\n  /** Stable public hostname (e.g. app.example.com). */\n  hostname?: string\n  /** Cloudflare tunnel id or name to `run`. */\n  tunnelId?: string\n  /** Path to the credentials JSON (defaults to ~/.cloudflared/<tunnelId>.json). */\n  credentialsFile?: string\n}\n\nexport interface TunnelRegistryOptions {\n  /** Absolute path for persistence file. Defaults to ~/.agentproto/tunnels.json */\n  persistPath?: string\n  /** Absolute path to workspace — used as scratch dir for provider config files. */\n  workspace?: string\n  /** Hook for surfacing provider log lines. */\n  onLog?: (line: string) => void\n  /**\n   * Read stored credentials for a provider slug. Lets the lifecycle build a\n   * provider that keeps its secrets in the creds store (e.g. ngrok's authtoken,\n   * or any third-party provider) rather than on the descriptor. Injected by the\n   * daemon (index.ts); descriptor-carried config (named's hostname/tunnelId)\n   * still takes precedence.\n   */\n  readCreds?: (slug: string) => Promise<TunnelCreds | null>\n}\n\nconst TUNNELS_FILE_PATH = (): string =>\n  resolve(homedir(), \".agentproto\", \"tunnels.json\")\n\nconst HISTORY_CAP = 50\n\ninterface PersistedTunnels {\n  savedAt: string\n  tunnels: TunnelDescriptor[]\n}\n\nexport class TunnelRegistry {\n  private readonly tunnels = new Map<string, TunnelEntry>()\n  private readonly persistPath: string\n  private readonly workspace: string\n  private readonly onLog: ((line: string) => void) | undefined\n  private readonly readCreds:\n    | ((slug: string) => Promise<TunnelCreds | null>)\n    | undefined\n  private persistTimer: ReturnType<typeof setTimeout> | null = null\n\n  constructor(opts: TunnelRegistryOptions = {}) {\n    this.persistPath = opts.persistPath ?? TUNNELS_FILE_PATH()\n    this.workspace = opts.workspace ?? homedir()\n    this.onLog = opts.onLog\n    this.readCreds = opts.readCreds\n\n    this.loadFromDisk()\n  }\n\n  async create(input: CreateTunnelInput): Promise<TunnelDescriptor> {\n    const id = randomUUID()\n    const provider = input.provider ?? \"quick\"\n    const targetHost = input.targetHost ?? \"127.0.0.1\"\n\n    // Named tunnels need a stable hostname + a tunnel id to `run`. Fail\n    // fast here rather than letting cloudflared error out cryptically.\n    if (normalizeProviderSlug(provider) === CLOUDFLARE_NAMED_SLUG) {\n      if (!input.hostname || !input.tunnelId) {\n        throw new Error(\n          'named tunnel requires both \"hostname\" and \"tunnelId\" ' +\n            \"(the cloudflared tunnel you provisioned with `cloudflared tunnel create`).\",\n        )\n      }\n    }\n\n    if (input.name) {\n      const conflict = this.findByIdOrName(input.name)\n      if (conflict && (conflict.status === \"starting\" || conflict.status === \"active\")) {\n        throw new Error(\n          `tunnel name \"${input.name}\" already in use by active tunnel ${conflict.id}`,\n        )\n      }\n    }\n\n    const desc: TunnelDescriptor = {\n      id,\n      provider,\n      targetHost,\n      targetPort: input.targetPort,\n      publicUrl: \"\",\n      status: \"starting\",\n      pid: null,\n      createdAt: new Date().toISOString(),\n      ...(input.name ? { name: input.name } : {}),\n      ...(input.label ? { label: input.label } : {}),\n      ...(input.autostart ? { autostart: true } : {}),\n      ...(input.hostname ? { hostname: input.hostname } : {}),\n      ...(input.tunnelId ? { tunnelId: input.tunnelId } : {}),\n      ...(input.credentialsFile ? { credentialsFile: input.credentialsFile } : {}),\n    }\n\n    const prov = await this.pickProviderForTest(provider, desc)\n    const entry: TunnelEntry = { desc, provider: prov }\n    this.tunnels.set(id, entry)\n    this.schedulePersist()\n\n    await this.startEntry(entry)\n    return { ...desc }\n  }\n\n  /**\n   * Drive an entry's provider through start and fold the result back into\n   * its descriptor. On failure the descriptor is marked `error` and the\n   * error re-thrown (callers that want best-effort — e.g. boot restore —\n   * catch it). Shared by `create` and `restoreOnBoot`.\n   */\n  private async startEntry(entry: TunnelEntry): Promise<void> {\n    const { desc, provider } = entry\n    desc.status = \"starting\"\n    delete desc.lastError\n    this.schedulePersist()\n\n    const workspaceDir = this.workspace\n    await mkdir(join(workspaceDir, \".agentproto\"), { recursive: true }).catch(() => {\n      // ignore if already exists or not writable\n    })\n\n    let result: { publicUrl: string; pid: number | null }\n    try {\n      result = await provider.start({\n        target: { host: desc.targetHost, port: desc.targetPort },\n        workspace: workspaceDir,\n        onLog: line => this.onLog?.(line),\n      })\n    } catch (err) {\n      desc.status = \"error\"\n      desc.lastError = err instanceof Error ? err.message : String(err)\n      this.schedulePersist()\n      throw err\n    }\n\n    desc.publicUrl = result.publicUrl\n    desc.pid = result.pid\n    desc.status = \"active\"\n    delete desc.stoppedAt\n    this.schedulePersist()\n  }\n\n  /**\n   * Relaunch every `autostart` tunnel that isn't currently running. Called\n   * once on daemon boot — `loadFromDisk` has already ghosted formerly-live\n   * entries to `stopped` and given autostart ones a real provider. Quick\n   * tunnels are skipped (a relaunch yields a fresh random URL, defeating\n   * the point); named tunnels come back on their stable hostname.\n   *\n   * Best-effort: a provider that fails to start leaves its descriptor in\n   * `error` and the others still come up.\n   */\n  async restoreOnBoot(): Promise<void> {\n    const toStart = Array.from(this.tunnels.values()).filter(\n      e => e.desc.autostart === true && e.desc.status === \"stopped\",\n    )\n    for (const entry of toStart) {\n      // Autostart eligibility is data-driven: a provider whose public URL is\n      // NOT stable across restarts (e.g. cloudflare-quick) gets a fresh URL on\n      // relaunch, defeating the point — skip it. Read by slug so it holds even\n      // for a test-injected mock that carries no capabilities. Third-party\n      // providers (caps unknown here) are attempted.\n      const caps = builtinProviderCapabilities(entry.desc.provider)\n      if (caps && caps.stableUrl === false) {\n        this.onLog?.(\n          `[tunnel] skipping autostart for ephemeral-URL tunnel ${entry.desc.name ?? entry.desc.id} ` +\n            `(URL would change on relaunch — use a stable-URL provider)`,\n        )\n        continue\n      }\n      this.onLog?.(\n        `[tunnel] autostart: relaunching ${entry.desc.name ?? entry.desc.id} → ${entry.desc.hostname ?? \"?\"}`,\n      )\n      try {\n        // loadFromDisk left a stub here; build the real provider now (async —\n        // may dynamic-import a third-party package or read creds).\n        entry.provider = await this.pickProviderForTest(entry.desc.provider, entry.desc)\n        await this.startEntry(entry)\n      } catch (err) {\n        this.onLog?.(\n          `[tunnel] autostart failed for ${entry.desc.name ?? entry.desc.id}: ` +\n            `${err instanceof Error ? err.message : String(err)}`,\n        )\n      }\n    }\n  }\n\n  list(): TunnelDescriptor[] {\n    return Array.from(this.tunnels.values()).map(e => ({ ...e.desc }))\n  }\n\n  get(id: string): TunnelDescriptor | undefined {\n    const entry = this.tunnels.get(id)\n    return entry ? { ...entry.desc } : undefined\n  }\n\n  findByIdOrName(idOrName: string): TunnelDescriptor | undefined {\n    const byId = this.tunnels.get(idOrName)\n    if (byId) return { ...byId.desc }\n    for (const entry of this.tunnels.values()) {\n      if (entry.desc.name === idOrName) return { ...entry.desc }\n    }\n    return undefined\n  }\n\n  async stop(idOrName: string): Promise<boolean> {\n    const entry = this.findEntryByIdOrName(idOrName)\n    if (!entry) return false\n    if (entry.desc.status === \"stopped\") return true\n\n    try {\n      await entry.provider.stop()\n    } catch {\n      // swallow — provider may already be dead\n    }\n\n    entry.desc.status = \"stopped\"\n    entry.desc.stoppedAt = new Date().toISOString()\n    this.schedulePersist()\n    return true\n  }\n\n  async shutdown(): Promise<void> {\n    const active = Array.from(this.tunnels.values()).filter(\n      e => e.desc.status === \"starting\" || e.desc.status === \"active\",\n    )\n    await Promise.allSettled(\n      active.map(async e => {\n        try {\n          await e.provider.stop()\n        } catch {\n          // swallow\n        }\n        e.desc.status = \"stopped\"\n        e.desc.stoppedAt = new Date().toISOString()\n      }),\n    )\n    // Flush persist timer if scheduled\n    if (this.persistTimer !== null) {\n      clearTimeout(this.persistTimer)\n      this.persistTimer = null\n      this.persistNow()\n    }\n  }\n\n  // ── test seam ─────────────────────────────────────────────────────\n  // Subclasses (tests) override this to inject a mock provider. The\n  // descriptor is passed so a real provider can be built with its\n  // hostname / tunnelId / credentials. Async because the default path may\n  // dynamic-import a third-party provider package.\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  protected async pickProviderForTest(\n    _provider: TunnelProvider,\n    desc: TunnelDescriptor,\n  ): Promise<RemoteProvider> {\n    const slug = normalizeProviderSlug(desc.provider)\n    const creds = await this.credsForDescriptor(desc)\n    const provider = await resolveTunnelProvider(slug, { creds })\n    if (!provider) {\n      throw new Error(`unknown tunnel provider: ${desc.provider}`)\n    }\n    return provider\n  }\n\n  /**\n   * Build the creds passed to a provider: stored creds (ngrok authtoken,\n   * third-party secrets) merged with descriptor-carried config (named's\n   * hostname/tunnelId/credentialsFile), descriptor taking precedence.\n   */\n  private async credsForDescriptor(\n    desc: TunnelDescriptor,\n  ): Promise<TunnelCreds> {\n    const slug = normalizeProviderSlug(desc.provider)\n    const stored = this.readCreds ? (await this.readCreds(slug)) ?? {} : {}\n    const creds: TunnelCreds = { ...stored }\n    if (desc.hostname) creds.hostname = desc.hostname\n    if (desc.tunnelId) creds.tunnelId = desc.tunnelId\n    if (desc.credentialsFile) creds.credentialsFile = desc.credentialsFile\n    return creds\n  }\n\n  // ── private ──────────────────────────────────────────────────────\n\n  private findEntryByIdOrName(idOrName: string): TunnelEntry | undefined {\n    const byId = this.tunnels.get(idOrName)\n    if (byId) return byId\n    for (const entry of this.tunnels.values()) {\n      if (entry.desc.name === idOrName) return entry\n    }\n    return undefined\n  }\n\n  private schedulePersist(): void {\n    if (this.persistTimer !== null) return\n    this.persistTimer = setTimeout(() => {\n      this.persistTimer = null\n      this.persistNow()\n    }, 1_500)\n    // Don't keep the process alive just for a persist flush.\n    if (this.persistTimer.unref) this.persistTimer.unref()\n  }\n\n  private persistNow(): void {\n    try {\n      const all = Array.from(this.tunnels.values()).map(e => e.desc)\n      // Newest first, capped to HISTORY_CAP.\n      const sliced = all.slice(-HISTORY_CAP)\n      const payload: PersistedTunnels = {\n        savedAt: new Date().toISOString(),\n        tunnels: sliced,\n      }\n      mkdirSync(dirname(this.persistPath), { recursive: true })\n      writeFileSync(this.persistPath, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\")\n    } catch {\n      // Best-effort persistence — a write failure must not crash the daemon.\n    }\n  }\n\n  private loadFromDisk(): void {\n    if (!existsSync(this.persistPath)) return\n    let raw: string\n    try {\n      raw = readFileSync(this.persistPath, \"utf8\")\n    } catch {\n      return\n    }\n    let parsed: PersistedTunnels\n    try {\n      parsed = JSON.parse(raw) as PersistedTunnels\n    } catch {\n      return\n    }\n    if (!Array.isArray(parsed.tunnels)) return\n\n    for (const desc of parsed.tunnels) {\n      if (!desc.id) continue\n      // Tunnels that were \"starting\" or \"active\" at last save are dead\n      // now — the child process is gone. Mark them stopped (GHOST pattern).\n      const ghosted: TunnelDescriptor = {\n        ...desc,\n        status:\n          desc.status === \"starting\" || desc.status === \"active\"\n            ? \"stopped\"\n            : desc.status,\n        pid: null,\n        ...((desc.status === \"starting\" || desc.status === \"active\")\n          ? { stoppedAt: new Date().toISOString() }\n          : {}),\n      }\n      // Every loaded entry starts stubbed — its child process is gone. The\n      // real provider is built lazily (async) by `restoreOnBoot` for autostart\n      // entries; non-autostart entries are kept only for history and never\n      // start, so the stub (which throws on start) is correct for them.\n      this.tunnels.set(desc.id, { desc: ghosted, provider: makeStubProvider() })\n    }\n  }\n}\n\n// ── module-level helpers ───────────────────────────────────────────\n\nfunction makeStubProvider(): RemoteProvider {\n  return {\n    id: \"stub\",\n    async start() {\n      throw new Error(\"stub provider: cannot start a ghost tunnel entry\")\n    },\n    async stop() {\n      // no-op — nothing to kill\n    },\n  }\n}\n","/**\n * MCP tools that expose the TunnelRegistry to agents connected to the\n * daemon. Lets a remote operator create, list, stop, and inspect\n * public tunnels for any local port without touching the terminal.\n *\n * Four tools:\n *   tunnel_create    spawn a public URL for a local port (cloudflared quick tunnel)\n *   tunnel_list     browse active + historical tunnels\n *   tunnel_stop      SIGTERM the tunnel provider + mark stopped\n *   tunnel_status    read-only descriptor for one tunnel\n *\n * Designed parallel to session-tools.ts — same error-shape, same style.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { TunnelRegistry } from \"./tunnel-registry.js\"\n\nexport interface RegisterTunnelToolsOptions {\n  registry: TunnelRegistry\n}\n\nfunction text(value: string | object): {\n  content: Array<{ type: \"text\"; text: string }>\n} {\n  return {\n    content: [\n      {\n        type: \"text\",\n        text: typeof value === \"string\" ? value : JSON.stringify(value, null, 2),\n      },\n    ],\n  }\n}\n\nfunction errText(\n  toolName: string,\n  err: unknown,\n): { content: Array<{ type: \"text\"; text: string }>; isError: true } {\n  return {\n    content: [\n      {\n        type: \"text\",\n        text: `${toolName}: ${err instanceof Error ? err.message : String(err)}`,\n      },\n    ],\n    isError: true,\n  }\n}\n\nexport function registerTunnelTools(\n  server: McpServer,\n  opts: RegisterTunnelToolsOptions,\n): void {\n  const { registry } = opts\n\n  // ── tunnel_create ──────────────────────────────────────────────\n  server.tool(\n    \"tunnel_create\",\n    \"Spawn a public HTTPS URL for a local port. Built-in backends: \" +\n      \"`cloudflare-quick` (default, alias `quick`) = Cloudflare Quick Tunnel, \" +\n      \"no API key, ephemeral *.trycloudflare.com URL; `cloudflare-named` \" +\n      \"(alias `named`) = a cloudflared tunnel you provisioned once \" +\n      \"(`cloudflared tunnel create` + `route dns`), bound to a STABLE \" +\n      \"hostname — pass `hostname` + `tunnelId`, set `autostart:true` to \" +\n      \"relaunch on boot; `ngrok` = ngrok tunnel (configure its authtoken via \" +\n      \"`setup_tunnel_provider` first). Any installed third-party provider \" +\n      \"(`@scope/agentproto-adapter-<slug>`) also works — see \" +\n      \"`list_tunnel_adapters` for the full set. Returns the TunnelDescriptor \" +\n      \"once ready (typically <10s). Use `tunnel_list` before opening a \" +\n      \"duplicate. Unlike `remote_enable`, this does NOT gate auth — pure \" +\n      \"passthrough; the proxied service handles its own authn.\",\n    {\n      targetPort: z\n        .number()\n        .int()\n        .min(1)\n        .max(65535)\n        .describe(\"Local port to expose publicly (e.g. 3000 for a dev server).\"),\n      provider: z\n        .string()\n        .optional()\n        .describe(\n          \"Tunnel provider slug. Built-ins: `cloudflare-quick` (default), \" +\n            \"`cloudflare-named`, `ngrok` (legacy aliases `quick`/`named` \" +\n            \"accepted). Or any installed third-party provider slug — list via \" +\n            \"`list_tunnel_adapters`. `cloudflare-named` requires `hostname` + \" +\n            \"`tunnelId`.\",\n        ),\n      name: z\n        .string()\n        .optional()\n        .describe(\n          \"Optional friendly slug (e.g. 'vite-preview'). Accepted as an \" +\n            \"alias for the tunnel id in `tunnel_stop` and `tunnel_status`.\",\n        ),\n      label: z\n        .string()\n        .optional()\n        .describe(\"Free-text label shown in `tunnel_list` output.\"),\n      targetHost: z\n        .string()\n        .optional()\n        .describe(\n          \"Host the tunnel forwards to. Defaults to `127.0.0.1`. Use \" +\n            \"`localhost` only if the target is explicitly IPv6-bound.\",\n        ),\n      autostart: z\n        .boolean()\n        .optional()\n        .describe(\n          \"Relaunch this tunnel automatically on daemon boot. Only useful \" +\n            \"for `named` tunnels (a relaunched quick tunnel gets a new URL).\",\n        ),\n      hostname: z\n        .string()\n        .optional()\n        .describe(\n          \"REQUIRED for `named`: the stable public hostname routed to the \" +\n            \"tunnel (e.g. app.example.com).\",\n        ),\n      tunnelId: z\n        .string()\n        .optional()\n        .describe(\n          \"REQUIRED for `named`: the cloudflared tunnel id or name to run \" +\n            \"(from `cloudflared tunnel create`).\",\n        ),\n      credentialsFile: z\n        .string()\n        .optional()\n        .describe(\n          \"Optional for `named`: path to the tunnel credentials JSON. \" +\n            \"Defaults to ~/.cloudflared/<tunnelId>.json.\",\n        ),\n    },\n    async input => {\n      try {\n        const desc = await registry.create({\n          targetPort: input.targetPort,\n          ...(input.provider ? { provider: input.provider } : {}),\n          ...(input.name ? { name: input.name } : {}),\n          ...(input.label ? { label: input.label } : {}),\n          ...(input.targetHost ? { targetHost: input.targetHost } : {}),\n          ...(input.autostart ? { autostart: true } : {}),\n          ...(input.hostname ? { hostname: input.hostname } : {}),\n          ...(input.tunnelId ? { tunnelId: input.tunnelId } : {}),\n          ...(input.credentialsFile ? { credentialsFile: input.credentialsFile } : {}),\n        })\n        return text(desc)\n      } catch (err) {\n        return errText(\"tunnel_create\", err)\n      }\n    },\n  )\n\n  // ── tunnel_list ───────────────────────────────────────────────\n  server.tool(\n    \"tunnel_list\",\n    \"List all tunnels tracked by the daemon — active, stopped, and errored. \" +\n      \"Each entry includes provider, target port, public URL, status, pid, \" +\n      \"and age. Use before `tunnel_create` to avoid spawning duplicates \" +\n      \"for the same port.\",\n    {\n      onlyActive: z\n        .boolean()\n        .optional()\n        .describe(\n          \"When true, return only tunnels with status `starting` or `active`. \" +\n            \"Default false (return all).\",\n        ),\n    },\n    async input => {\n      let tunnels = registry.list()\n      if (input.onlyActive) {\n        tunnels = tunnels.filter(\n          t => t.status === \"starting\" || t.status === \"active\",\n        )\n      }\n      return text({ tunnels })\n    },\n  )\n\n  // ── tunnel_stop ────────────────────────────────────────────────\n  server.tool(\n    \"tunnel_stop\",\n    \"Stop an active tunnel — SIGTERM cloudflared and mark the tunnel stopped. \" +\n      \"Accepts either the tunnel id or the friendly name set at create time. \" +\n      \"Idempotent on an already-stopped tunnel.\",\n    {\n      tunnelId: z\n        .string()\n        .min(1)\n        .describe(\n          \"Tunnel id (UUID from `tunnel_create`) or the name slug \" +\n            \"(e.g. 'vite-preview').\",\n        ),\n    },\n    async input => {\n      try {\n        const ok = await registry.stop(input.tunnelId)\n        if (!ok) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: `tunnel_stop: no tunnel \"${input.tunnelId}\" — use tunnel_list to see current ids`,\n              },\n            ],\n            isError: true,\n          }\n        }\n        return text({ ok, tunnelId: input.tunnelId })\n      } catch (err) {\n        return errText(\"tunnel_stop\", err)\n      }\n    },\n  )\n\n  // ── tunnel_status ──────────────────────────────────────────────\n  server.tool(\n    \"tunnel_status\",\n    \"Return the current descriptor for one tunnel. Accepts either the \" +\n      \"tunnel id or the friendly name set at create time.\",\n    {\n      tunnelId: z\n        .string()\n        .min(1)\n        .describe(\n          \"Tunnel id (UUID from `tunnel_create`) or the name slug.\",\n        ),\n    },\n    async input => {\n      const desc = registry.findByIdOrName(input.tunnelId)\n      if (!desc) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `tunnel_status: no tunnel \"${input.tunnelId}\" — use tunnel_list to see current ids`,\n            },\n          ],\n          isError: true,\n        }\n      }\n      return text(desc)\n    },\n  )\n}\n","/**\n * Tunnel family on top of `@agentproto/adapter-kit` — the PILOT consumer.\n *\n * This module is the entire bridge between the generic kit and the two\n * concrete Cloudflare tunnel providers. It contributes nothing the kit\n * already owns (catalog/status/creds/ledger/list/MCP-tool plumbing); it\n * only supplies the tunnel-family `TInfo` (`TunnelAdapterInfo`), the\n * static `TUNNEL_CATALOG`, and the resolver that maps a catalog slug to a\n * concrete {@link TunnelProviderHandle}.\n *\n * Kit primitives used:\n *   - `makeCredsStore`      → per-slug 0600 creds under `~/.agentproto/tunnel-creds/`\n *   - `makeSetupLedger`     → `~/.agentproto/setup/<slug>.json`\n *   - `makeAdapterResolver` → wraps the throwing `load` into null-on-miss\n *   - `makeAdapterLister`   → catalog → status-classified `AdapterEntry[]`\n *   - `makeListTool`        → registers `list_tunnel_adapters`\n *   - `makeSetupTool`       → registers `setup_tunnel_provider` (multi-field form:\n *                             hostname + tunnelId + credentialsFile?, all sensitive)\n *\n * Security: `toTunnelInfo` exposes only `capabilities` — never a cred value\n * (Appendix B). The setup tool's fields are marked SENSITIVE and the result\n * NEVER echoes any field value back.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport {\n  makeCredsStore,\n  makeSetupLedger,\n  makeAdapterResolver,\n  makeAdapterLister,\n  makeListTool,\n  makeSetupTool,\n  type AdapterCatalog,\n  type AdapterLister,\n  type CredsStore,\n  type SetupField,\n  type SetupLedger,\n} from \"@agentproto/adapter-kit\"\n\nimport { CLOUDFLARE_QUICK_SLUG } from \"./remote-providers/quick.js\"\nimport { CLOUDFLARE_NAMED_SLUG } from \"./remote-providers/named.js\"\nimport { NGROK_SLUG, type TunnelNgrokCreds } from \"./remote-providers/ngrok.js\"\nimport {\n  resolveTunnelProvider,\n  discoverTunnelHandles,\n  BUILTIN_TUNNEL_PROVIDERS,\n  BUILTIN_TUNNEL_SLUGS,\n  type TunnelCreds,\n} from \"./remote-providers/registry.js\"\nimport type {\n  TunnelProviderHandle,\n  TunnelProviderCapabilities,\n} from \"./remote-providers/types.js\"\n\n/** Creds-store / ledger family key → `~/.agentproto/tunnel-creds/`. */\nexport const TUNNEL_FAMILY = \"tunnel\"\n\n/**\n * Family descriptor (`TInfo`). Pure metadata surfaced in\n * `list_tunnel_adapters`. The kit's `AdapterEntry` already carries\n * slug/name/description/status/version, so the only tunnel-specific field\n * is the declared capability set. NEVER carries a cred value.\n */\nexport interface TunnelAdapterInfo {\n  capabilities: TunnelProviderCapabilities\n}\n\n/**\n * Structured credentials for `cloudflare-named`. Collected from the\n * multi-field setup tool (hostname + tunnelId + credentialsFile?).\n */\nexport interface TunnelNamedCreds {\n  hostname: string\n  tunnelId: string\n  credentialsFile?: string\n}\n\n/** Union of all tunnel-family credential shapes (per-slug). */\nexport type TunnelProviderCreds = TunnelNamedCreds | TunnelNgrokCreds\n\n/** Static catalog of the three providers. */\nexport const TUNNEL_CATALOG: AdapterCatalog = [\n  {\n    slug: CLOUDFLARE_QUICK_SLUG,\n    name: \"Cloudflare Quick Tunnel\",\n    description:\n      \"Zero-credential Cloudflare tunnel. Ephemeral *.trycloudflare.com URL, fresh each run.\",\n    packageName: \"@agentproto/runtime\",\n    hint: \"cloudflare · ephemeral\",\n  },\n  {\n    slug: CLOUDFLARE_NAMED_SLUG,\n    name: \"Cloudflare Named Tunnel\",\n    description:\n      \"Persistent Cloudflare tunnel bound to a stable hostname you control (BYO credentials).\",\n    packageName: \"@agentproto/runtime\",\n    hint: \"cloudflare · stable\",\n  },\n  {\n    slug: NGROK_SLUG,\n    name: \"Ngrok Tunnel\",\n    description:\n      \"Ngrok tunnel with optional static domain support. Requires a free authtoken.\",\n    packageName: \"@agentproto/runtime\",\n    hint: \"ngrok · stable\",\n  },\n]\n\n/** Extract the safe descriptor from a resolved handle. No secrets. */\nexport function toTunnelInfo(handle: TunnelProviderHandle): TunnelAdapterInfo {\n  return { capabilities: handle.capabilities }\n}\n\n/**\n * Build the tunnel-family creds store (per-slug, 0600). Stored as a plain\n * string map — the structured {@link TunnelNamedCreds}/{@link TunnelNgrokCreds}\n * shapes are typed *views* used by callers that read specific providers; the\n * generic store accepts any provider's declared fields (incl. third-party),\n * which is what makes setup pluggable.\n */\nexport function makeTunnelCredsStore(home?: string): CredsStore<TunnelCreds> {\n  return makeCredsStore<TunnelCreds>({\n    family: TUNNEL_FAMILY,\n    ...(home ? { home } : {}),\n  })\n}\n\n/**\n * Resolve a catalog slug to a concrete handle via the provider registry —\n * built-ins in-process, third-party packages dynamic-imported. Reads stored\n * creds first so `named`/`ngrok` (and any third-party provider) are built\n * configured when possible; unconfigured slugs resolve to a descriptor-only\n * handle (listing never calls `start()`/`check()` — per OQ-5). Throws on an\n * unknown slug so the kit's resolver wraps it to `null` (\"supported but not\n * installed\").\n */\nexport function makeTunnelResolver(credsStore: CredsStore<TunnelCreds>) {\n  return makeAdapterResolver<TunnelProviderHandle>({\n    load: async (slug: string): Promise<TunnelProviderHandle> => {\n      const creds = await credsStore.read(slug)\n      const handle = await resolveTunnelProvider(slug, { creds })\n      if (!handle) throw new Error(`unknown tunnel adapter slug: ${slug}`)\n      return handle\n    },\n  })\n}\n\n/** Build the family lister: catalog → status-classified entries, plus any\n *  third-party providers discovered on disk (both naming conventions). */\nexport function makeTunnelLister(opts: {\n  credsStore: CredsStore<TunnelCreds>\n  ledger: SetupLedger\n}): AdapterLister<TunnelAdapterInfo> {\n  return makeAdapterLister<TunnelProviderHandle, TunnelAdapterInfo>({\n    catalog: TUNNEL_CATALOG,\n    resolver: makeTunnelResolver(opts.credsStore),\n    ledger: opts.ledger,\n    credsStore: opts.credsStore,\n    toInfo: toTunnelInfo,\n    discoverExtras: () =>\n      discoverTunnelHandles(new Set(TUNNEL_CATALOG.map((c) => c.slug))),\n  })\n}\n\n/**\n * Resolve every provider that declares creds (built-in + third-party) and\n * union their `setupFields` for the `setup_tunnel_provider` tool. Because one\n * tool spans many providers with disjoint fields, the unioned shape is relaxed\n * to all-optional at the zod layer (`required: false`); the genuine per-provider\n * required-ness is enforced in `onSetup` against the chosen provider's handle.\n */\nasync function collectSetupSchema(): Promise<{\n  validSlugs: string[]\n  fields: SetupField[]\n}> {\n  const builtinHandles = Object.values(BUILTIN_TUNNEL_PROVIDERS).map((f) =>\n    f(null),\n  )\n  const extraHandles = await discoverTunnelHandles(new Set(BUILTIN_TUNNEL_SLUGS))\n  const setupHandles = [...builtinHandles, ...extraHandles].filter(\n    (h) => h.setupFields && h.setupFields.length > 0,\n  )\n\n  const validSlugs = setupHandles.map((h) => h.slug)\n  const fieldByName = new Map<string, SetupField>()\n  for (const h of setupHandles) {\n    for (const f of h.setupFields ?? []) {\n      // First declaration wins; relax to optional for the cross-provider tool.\n      if (!fieldByName.has(f.name)) {\n        fieldByName.set(f.name, { ...f, required: false })\n      }\n    }\n  }\n  return { validSlugs, fields: [...fieldByName.values()] }\n}\n\nexport interface RegisterTunnelAdapterToolsOptions {\n  /** Home dir override (tests). Defaults to `AGENTPROTO_HOME ?? ~/.agentproto`. */\n  home?: string\n}\n\n/**\n * Register the tunnel family's adapter-kit MCP tools on the server:\n *   - `list_tunnel_adapters`  (parameterless; status + capabilities, no creds)\n *   - `setup_tunnel_provider` (multi-field; fields are union of every\n *     configurable provider's declared `setupFields`, all SENSITIVE and never\n *     echoed). Async because the field schema is derived from resolved handles\n *     (incl. third-party providers discovered on disk).\n */\nexport async function registerTunnelAdapterTools(\n  server: McpServer,\n  opts: RegisterTunnelAdapterToolsOptions = {},\n): Promise<void> {\n  const credsStore = makeTunnelCredsStore(opts.home)\n  const ledger = makeSetupLedger(opts.home ? { home: opts.home } : {})\n\n  makeListTool<TunnelAdapterInfo>({\n    server,\n    toolName: \"list_tunnel_adapters\",\n    description:\n      \"List known tunnel providers with their status (supported/available/\" +\n      \"ready), version, and declared capabilities (stableUrl, autostart, \" +\n      \"customDomain, requiresAuth, hasApi). Credentials are never returned. \" +\n      \"Use `setup_tunnel_provider` to configure a provider that needs creds.\",\n    lister: makeTunnelLister({ credsStore, ledger }),\n  })\n\n  const { validSlugs, fields } = await collectSetupSchema()\n\n  makeSetupTool({\n    server,\n    toolName: \"setup_tunnel_provider\",\n    description:\n      \"Configure a tunnel provider that requires credentials (e.g. \" +\n      \"cloudflare-named or ngrok). Each field is SENSITIVE — stored 0600 and \" +\n      \"never echoed back in tool results. Only the fields a given provider \" +\n      \"declares are stored.\",\n    validSlugs,\n    fields,\n    onSetup: async (slug: string, fields: Record<string, string>) => {\n      // Resolve the chosen provider so its OWN setupFields drive validation —\n      // works for built-ins and third-party providers alike.\n      const handle = await resolveTunnelProvider(slug)\n      const declared = handle?.setupFields\n      if (!handle || !declared || declared.length === 0) {\n        return { ok: false, hint: `provider '${slug}' is not configurable` }\n      }\n\n      const missing = declared\n        .filter((f) => f.required === true)\n        .map((f) => f.name)\n        .filter((name) => {\n          const v = fields[name]\n          return v === undefined || v.length === 0\n        })\n      if (missing.length > 0) {\n        return {\n          ok: false,\n          hint: `missing required field(s): ${missing.join(\", \")}`,\n        }\n      }\n\n      // Persist only the provider's declared, non-empty fields.\n      const creds: TunnelCreds = {}\n      for (const f of declared) {\n        const v = fields[f.name]\n        if (v !== undefined && v.length > 0) creds[f.name] = v\n      }\n      await credsStore.write(slug, creds)\n\n      const now = new Date().toISOString()\n      await ledger.write(slug, {\n        slug,\n        completedAt: now,\n        steps: [{ id: \"creds\", completedAt: now }],\n      })\n      return { ok: true, hint: `${slug} configured — status is now ready` }\n    },\n  })\n}","/**\n * `WorkspaceFs` — minimal `readFile` / `writeFile` adapter over a\n * workspace directory. Mirrors the `McpWorkspace.filesystem` shape\n * used by `@guilde/mcp` so the daemon can be plugged in as the\n * workspace backend for a Guilde MCP server (via its\n * `loadGuildWorkspace` injection point) without re-shimming.\n *\n * All paths are workspace-relative. Absolute paths are rejected to\n * keep the surface predictable when the daemon binds to a public\n * port.\n */\n\nimport { existsSync } from \"node:fs\"\nimport { mkdir, readFile as fsReadFile, writeFile as fsWriteFile } from \"node:fs/promises\"\nimport { dirname, isAbsolute, join, normalize, relative, resolve } from \"node:path\"\n\nexport interface WorkspaceFs {\n  readFile(path: string): Promise<string>\n  writeFile(path: string, content: string | Uint8Array): Promise<void>\n  exists(path: string): Promise<boolean>\n}\n\nexport interface CreateWorkspaceFsOptions {\n  /** Absolute path to the workspace root. */\n  workspace: string\n}\n\nexport class WorkspacePathError extends Error {\n  constructor(message: string) {\n    super(message)\n    this.name = \"WorkspacePathError\"\n  }\n}\n\nexport function createWorkspaceFs(opts: CreateWorkspaceFsOptions): WorkspaceFs {\n  const root = resolve(opts.workspace)\n\n  function resolvePath(path: string): string {\n    if (typeof path !== \"string\" || path.length === 0) {\n      throw new WorkspacePathError(\"path must be a non-empty string\")\n    }\n    if (isAbsolute(path)) {\n      throw new WorkspacePathError(\n        \"absolute paths are not allowed; use a workspace-relative path\",\n      )\n    }\n    const joined = normalize(join(root, path))\n    const rel = relative(root, joined)\n    if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n      throw new WorkspacePathError(\n        `path escapes the workspace: '${path}'`,\n      )\n    }\n    return joined\n  }\n\n  return {\n    async readFile(path) {\n      const abs = resolvePath(path)\n      const buf = await fsReadFile(abs)\n      return buf.toString(\"utf8\")\n    },\n    async writeFile(path, content) {\n      const abs = resolvePath(path)\n      await mkdir(dirname(abs), { recursive: true })\n      await fsWriteFile(abs, content)\n    },\n    async exists(path) {\n      try {\n        const abs = resolvePath(path)\n        return existsSync(abs)\n      } catch {\n        return false\n      }\n    },\n  }\n}\n","/**\n * `~/.agentproto/providers.json` — the provider API-key store (mode 0600).\n *\n * Distinct from `credentials.json` (host-binding OAuth tokens for\n * `serve --connect`) and from per-adapter `setup[]` tokens. This file holds\n * the LLM/model **provider** keys (anthropic, openrouter, openai, …) that the\n * model gateways in spawned agents read from the environment.\n *\n * Why a store at all: before this, the only way to give the daemon a provider\n * key was an ambient `export FOO_API_KEY=…` in whatever shell launched\n * `serve`. That's invisible, easy to forget, and per-shell. Storing the keys\n * here (0600, same-user-only) lets `serve` inject them at boot — set once,\n * works for every daemon. Explicit env still wins (see injectProviderKeysIntoEnv).\n *\n * Keys never leave this file except into the daemon's own process env; they\n * are never logged. A browser-loaded localhost page can't read a 0600 file —\n * the same defence the runtime.json bearer token relies on.\n */\n\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\n\n/**\n * Canonical provider → environment-variable name. The spawned model gateways\n * (Mastra in mastra-agent, hermes/opencode's routers) read the provider key\n * from these env names. Aligned with the adapter manifests' `models.env`\n * maps + the common SDK conventions.\n */\nexport const PROVIDER_ENV_VARS: Readonly<Record<string, string>> = {\n  anthropic: \"ANTHROPIC_API_KEY\",\n  openrouter: \"OPENROUTER_API_KEY\",\n  openai: \"OPENAI_API_KEY\",\n  google: \"GOOGLE_GENERATIVE_AI_API_KEY\",\n  groq: \"GROQ_API_KEY\",\n  mistral: \"MISTRAL_API_KEY\",\n  // Vercel AI Gateway — a gateway provider, like openrouter, that fronts many\n  // upstream model families behind one key.\n  \"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n}\n\nexport type KnownProvider = keyof typeof PROVIDER_ENV_VARS\n\nexport interface ProviderEntry {\n  /** The provider API key (or gateway key). */\n  apiKey: string\n  /** Optional custom base URL (self-hosted / proxy). */\n  baseUrl?: string\n  /** Wall-clock ISO timestamp the key was last set. */\n  updatedAt: string\n}\n\nexport interface ProvidersFile {\n  version: 1\n  providers: Record<string, ProviderEntry>\n}\n\n/** Fresh empty file each call — never share the `providers` object, or a\n *  later `setProviderKey` mutation leaks into every other load in-process. */\nfunction emptyFile(): ProvidersFile {\n  return { version: 1, providers: {} }\n}\n\nexport function providersPath(): string {\n  return resolve(homedir(), \".agentproto\", \"providers.json\")\n}\n\n/** Resolve the env-var name for a provider (canonical map, else\n *  `<PROVIDER>_API_KEY` upper-snake fallback so new providers still work). */\nexport function providerEnvVar(provider: string): string {\n  return (\n    PROVIDER_ENV_VARS[provider] ??\n    `${provider.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_API_KEY`\n  )\n}\n\nexport async function loadProviders(): Promise<ProvidersFile> {\n  try {\n    const raw = await readFile(providersPath(), \"utf8\")\n    const parsed = JSON.parse(raw) as unknown\n    if (\n      !parsed ||\n      typeof parsed !== \"object\" ||\n      !(\"providers\" in parsed) ||\n      typeof (parsed as Record<string, unknown>).providers !== \"object\" ||\n      (parsed as Record<string, unknown>).providers === null\n    ) {\n      return emptyFile()\n    }\n    return {\n      version: 1,\n      providers: (parsed as ProvidersFile).providers,\n    }\n  } catch {\n    return emptyFile() // ENOENT / malformed → empty\n  }\n}\n\nasync function writeProviders(file: ProvidersFile): Promise<void> {\n  const dir = join(homedir(), \".agentproto\")\n  await mkdir(dir, { recursive: true })\n  // mode 0600 so other local users can't read the keys.\n  await writeFile(providersPath(), JSON.stringify(file, null, 2) + \"\\n\", {\n    encoding: \"utf8\",\n    mode: 0o600,\n  })\n}\n\n/** Set (or replace) a provider's key. Returns the env-var it maps to. */\nexport async function setProviderKey(\n  provider: string,\n  apiKey: string,\n  baseUrl?: string,\n): Promise<string> {\n  const file = await loadProviders()\n  file.providers[provider] = {\n    apiKey,\n    ...(baseUrl ? { baseUrl } : {}),\n    updatedAt: new Date().toISOString(),\n  }\n  await writeProviders(file)\n  return providerEnvVar(provider)\n}\n\n/** Remove a provider's key. Returns true if it existed. */\nexport async function removeProviderKey(provider: string): Promise<boolean> {\n  const file = await loadProviders()\n  if (!(provider in file.providers)) return false\n  delete file.providers[provider]\n  await writeProviders(file)\n  return true\n}\n\n/**\n * Inject stored provider keys into a target env (default `process.env`).\n * **Explicit env always wins** — a var already set is never overwritten, so a\n * one-off `FOO_API_KEY=… serve` or a CI secret takes precedence over the\n * store. Returns the list of provider names actually injected (for a boot log\n * that names providers, never values).\n */\nexport async function injectProviderKeysIntoEnv(\n  env: NodeJS.ProcessEnv = process.env,\n): Promise<string[]> {\n  const file = await loadProviders()\n  const injected: string[] = []\n  for (const [provider, entry] of Object.entries(file.providers)) {\n    if (!entry?.apiKey) continue\n    const name = providerEnvVar(provider)\n    if (env[name]) continue // explicit env wins\n    env[name] = entry.apiKey\n    if (entry.baseUrl) env[`${provider.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_BASE_URL`] = entry.baseUrl\n    injected.push(provider)\n  }\n  return injected\n}\n","/**\n * @agentproto/runtime — long-running gateway around an agentproto\n * workspace dir.\n *\n * Composes:\n *   - `@agentproto/mcp-server` (CRUD verbs over registered specs)\n *   - HTTP transport (Streamable HTTP) on a configurable port\n *   - HEARTBEAT.md autonomy loop\n *   - Append-only conversation persistence (`conversations/<id>.md`)\n *   - Workspace filesystem adapter (compatible with the\n *     `McpWorkspace.filesystem` shape used by `@guilde/mcp`)\n *\n * Single entry point: `createGateway(opts)`. Returns a handle with\n * `url` and `stop()` — the rest of the surface lives on the HTTP\n * server.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { join, resolve } from \"node:path\"\nimport { createMcpServer } from \"@agentproto/mcp-server\"\nimport type { DoctypeSpec } from \"@agentproto/manifest\"\n\nimport { writeRuntimeMeta } from \"./agentproto-dir.js\"\nimport { registerCommandTools } from \"./command-tools.js\"\nimport { fileConversationStore } from \"./conversations.js\"\nimport { createRuntimeEvents } from \"./events.js\"\nimport { registerFsTools } from \"./fs-tools.js\"\nimport { registerSessionTools, registerExportSessionTool } from \"./session-tools.js\"\nimport {\n  registerBrowserTools,\n  type BrowserAdapterResolver,\n  type BrowserAdapterLister,\n} from \"./browser-tools.js\"\nimport { registerMcpApps } from \"./mcp-apps-adapter.js\"\nimport { makeSessionsPanelApp } from \"./sessions-panel-app.js\"\nimport {\n  makeAgentsOverviewApp,\n  registerSummarizeSessionTool,\n} from \"./agents-overview-app.js\"\nimport { makeBureauSessionsApp } from \"./bureau-sessions-app.js\"\nimport { startHeartbeat, type BuildHeartbeatAgent } from \"./heartbeat.js\"\nimport {\n  startHttpServer,\n  type AuthOptions,\n  type AgentAdapterResolver,\n  type AgentAdapterLister,\n} from \"./http-server.js\"\nimport {\n  createSessionsRegistry,\n  type SessionsRegistry,\n  type PtyFactory,\n} from \"./sessions.js\"\nimport { McpProxyRegistry } from \"./mcp-proxy.js\"\nimport { registerOrchestrationTools } from \"./orchestration-tools.js\"\nimport { createSessionEventBus } from \"./session-event-bus.js\"\nimport { createEventRing } from \"./event-ring.js\"\nimport { createWebhookNotifier } from \"./webhook-notifier.js\"\nimport { createRoutineRunner } from \"./routine-runner.js\"\nimport { createWorkflowRunner } from \"./workflow-runner.js\"\nimport { createFileStepCache } from \"./workflow-step-cache.js\"\nimport { withDeferredTools } from \"./deferred-tools.js\"\nimport { createCompletionPolicySupervisor } from \"./supervisor.js\"\nimport { createInboundWatcher } from \"./inbound-watcher.js\"\nimport { createCronScheduler } from \"./cron-scheduler.js\"\nexport type {\n  WatcherStartInput,\n  WatcherDescriptor,\n  InboundWatcher,\n} from \"./inbound-watcher.js\"\nimport {\n  createScopeTokenRegistry,\n  createOrchestratorMcpServerFactory,\n  createOrchestratorInjector,\n  type OrchestratorScope,\n} from \"./orchestrator-gateway.js\"\n\nexport type {\n  AgentAdapterResolver,\n  AgentAdapterLister,\n  AdapterListEntry,\n} from \"./http-server.js\"\nexport type { BrowserAdapterResolver, BrowserAdapterLister, BrowserAdapterInfo } from \"./browser-tools.js\"\nexport { makeBrowserAdapterLister } from \"./browser-adapters.js\"\nexport type { BrowserAdapterHandle } from \"./browser-adapters.js\"\nexport type {\n  AgentSessionLike,\n  AgentStreamEvent,\n  SessionDescriptor,\n  SessionKind,\n  SessionStatus,\n  SpawnSessionInput,\n  SpawnAgentInput,\n  SessionsRegistry,\n  RegisterBrowserInput,\n  RegisterSessionInput,\n} from \"./sessions.js\"\nexport { formatToolCall, formatToolResult } from \"./tool-presenter.js\"\nimport { RemoteController } from \"./remote-controller.js\"\nimport { registerRemoteTools } from \"./remote-tools.js\"\nimport { TunnelRegistry } from \"./tunnel-registry.js\"\nimport { registerTunnelTools } from \"./tunnel-tools.js\"\nimport {\n  registerTunnelAdapterTools,\n  makeTunnelCredsStore,\n} from \"./tunnel-adapters.js\"\nimport { createWorkspaceFs, type WorkspaceFs } from \"./workspace-fs.js\"\n\nexport type { ConversationStore, ConversationMeta, ConversationTurn } from \"./conversations.js\"\nexport type { HeartbeatRunner, BuildHeartbeatAgent, HeartbeatAgent } from \"./heartbeat.js\"\nexport type { RuntimeEvent, RuntimeEvents } from \"./events.js\"\nexport type { WorkspaceFs } from \"./workspace-fs.js\"\nexport type { TunnelDescriptor, TunnelStatus, TunnelProvider } from \"./tunnel-registry.js\"\nexport { parseDuration } from \"./heartbeat.js\"\nexport { createWorkspaceFs } from \"./workspace-fs.js\"\nexport { createFileStepCache } from \"./workflow-step-cache.js\"\nexport {\n  sweepStaleRuntimeMetas,\n  unlinkRuntimeMeta,\n  readRuntimeMeta,\n  daemonRegistryDir,\n  readDaemonRegistry,\n  sweepStaleDaemonRegistry,\n  writeDaemonRegistryEntry,\n  unlinkDaemonRegistryEntry,\n  type RuntimeMeta,\n} from \"./agentproto-dir.js\"\nexport { fileConversationStore } from \"./conversations.js\"\nexport {\n  loadProviders,\n  setProviderKey,\n  removeProviderKey,\n  injectProviderKeysIntoEnv,\n  providerEnvVar,\n  providersPath,\n  PROVIDER_ENV_VARS,\n  type ProviderEntry,\n  type ProvidersFile,\n} from \"./providers-store.js\"\nexport {\n  DEFAULT_ORCHESTRATOR_TOOLS,\n  narrowOrchestratorTools,\n  createScopeTokenRegistry,\n  createOrchestratorMcpServerFactory,\n  createOrchestratorInjector,\n  type OrchestratorScope,\n  type ScopeTokenRegistry,\n  type OrchestratorMcpServerFactory,\n  type OrchestratorGatewayDeps,\n  type OrchestratorInjector,\n  type OrchestratorInjection,\n  type OrchestratorInjectorDeps,\n} from \"./orchestrator-gateway.js\"\n\n// Blocking-wait service functions + supervisor types — shared between the\n// MCP tool surface (session_monitor / policy_status) and the REST HTTP\n// surface (GET /sessions/:id/wait, GET /policies/:id/wait).\nexport {\n  monitorSessionWait,\n  monitorPolicyWait,\n  type SessionWaitEvent,\n  type SessionWaitResult,\n} from \"./orchestration-tools.js\"\nexport type {\n  AttachPolicyInput,\n  CommitSpec,\n  CompletionPolicySupervisor,\n  GateSpec,\n  JudgeGateSpec,\n  OnFailSpec,\n  PolicyRunState,\n  PolicyRunStatus,\n  ShellGateSpec,\n} from \"./supervisor.js\"\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnySpec = DoctypeSpec<any, any>\n\nexport interface CreateGatewayOptions {\n  /** Absolute path to the workspace dir. */\n  workspace: string\n  /** AIP doctype specs to expose as MCP CRUD verbs. */\n  specs: readonly AnySpec[]\n  /** Port to bind. Default 18790. */\n  port?: number\n  /** Bind host. Default `127.0.0.1` (loopback). Set `0.0.0.0` for LAN. */\n  bind?: string\n  /** Auth mode. Default `none` (safe only on loopback). */\n  auth?: AuthOptions\n  /**\n   * Resolves a heartbeat-runnable agent from its workspace id.\n   * Required for HEARTBEAT.md to do anything; without it ticks emit\n   * `heartbeat-error` events instead of generating.\n   */\n  buildAgent?: BuildHeartbeatAgent\n  /** Server name advertised over MCP. */\n  name?: string\n  /** Server version advertised over MCP. */\n  version?: string\n  /**\n   * Run BOOT.md once at startup. Pass `false` to disable. Defaults to\n   * `true`. The boot file is plain markdown — frontmatter-free; the\n   * agent named in `defaultBootAgent` (or skipped if unset) gets the\n   * body as a single prompt and the reply is appended to a `boot-<iso>`\n   * conversation.\n   */\n  boot?: boolean\n  /** Agent id used for BOOT.md if no per-file frontmatter. */\n  defaultBootAgent?: string\n  /** Optional adapter resolver — when provided, enables\n   *  `POST /sessions/agent` (long-running agent CLIs like\n   *  claude-code / hermes via the @agentproto/cli adapter system).\n   *  Without this, /sessions still works for raw `argv` spawns. */\n  resolveAgentAdapter?: AgentAdapterResolver\n  /** Optional adapter lister — when provided, enables\n   *  `GET /adapters` HTTP route + `adapter_list` MCP tool so UIs\n   *  can discover what's installed on the host. */\n  listAgentAdapters?: AgentAdapterLister\n  /** Optional browser adapter resolver — when provided, enables the\n   *  `start_browser` MCP tool (launches Camofox / Bureau / Chromium). */\n  resolveBrowserAdapter?: BrowserAdapterResolver\n  /** Optional browser adapter lister — when provided, enables the\n   *  `browser_adapter_list` MCP tool. */\n  listBrowserAdapters?: BrowserAdapterLister\n  /** Optional PTY factory (node-pty wrapper, typically from the cli\n   *  layer's `loadNodePtyFactory()`). When provided, enables\n   *  `POST /sessions/terminal`, the `terminal_start` MCP\n   *  tool family, and the `/sessions/:id/pty` WebSocket. Without it,\n   *  those routes return 501 / the MCP tools aren't registered. */\n  spawnPty?: PtyFactory\n  /** Override the per-boot bearer token. Default: `randomUUID()`.\n   *  Tests can pin a known value; production should always let\n   *  the gateway generate fresh. The token is written into\n   *  `<workspace>/.agentproto/runtime.json` (mode 0600) and required\n   *  on mutating `/sessions/*` routes + the PTY WS upgrade. */\n  token?: string\n  /** Trusted browser origins allowed to drive mutating routes\n   *  without a bearer token. See `RuntimeHttpServerOptions.allowedOrigins`\n   *  for match semantics. Default: localhost on any port. */\n  allowedOrigins?: readonly string[]\n  /** When true, drop the localhost-wildcard defaults — only the\n   *  explicit `allowedOrigins` list is honoured. */\n  strictOrigins?: boolean\n  /**\n   * Opt-in deferred/lazy MCP tool loading (harness-parity item 3, see\n   * `deferred-tools.ts`). When set, every root-gateway tool outside\n   * `alwaysOn` registers but starts disabled — excluded from the first\n   * `tools/list` — until the always-on `tool_search` meta-tool pulls it\n   * in by keyword. Omitted (default) → every tool is eagerly enabled,\n   * identical to pre-existing behaviour. Does not affect the scoped\n   * `/mcp/orchestrator` sub-gateway, which already exposes a small\n   * curated allowlist (`DEFAULT_ORCHESTRATOR_TOOLS`).\n   */\n  deferredTools?: { alwaysOn?: readonly string[] }\n}\n\n/**\n * Default always-on set when `deferredTools` is enabled without an\n * explicit `alwaysOn` override: the core spawn/drive/observe loop most\n * sessions need immediately. Everything else (fs_*, directory_*,\n * command_*, remote_*, browser_*, terminal_*, mcp_*, routine_*,\n * workflow_*, policy_*, inbound_watcher_*, session_tree, agent_export,\n * adapter_list, ...) starts deferred.\n */\nconst DEFAULT_ALWAYS_ON_TOOLS: readonly string[] = [\n  \"agent_start\",\n  \"agent_prompt\",\n  \"agent_output\",\n  \"agent_kill\",\n  \"session_list\",\n  \"session_monitor\",\n  \"session_events_poll\",\n]\n\nexport interface GatewayHandle {\n  url: string\n  workspace: string\n  workspaceFs: WorkspaceFs\n  registered: readonly string[]\n  /** Sessions registry — exposed so MCP tools / external spawners\n   *  inside the same process can register their child processes for\n   *  visibility through /sessions and the CLI TUI. */\n  sessions: SessionsRegistry\n  /** Tunnel registry — manages public cloudflared tunnels for any\n   *  local port. Exposed so embedding hosts can open tunnels\n   *  programmatically without going through the HTTP/MCP surface. */\n  tunnels: TunnelRegistry\n  /** Per-boot bearer token required on mutating /sessions/* routes\n   *  + WS PTY upgrades. Exposed so an embedding host (e.g. the CLI\n   *  shell that hosts the gateway in-process) can pass it to child\n   *  tools without re-reading the runtime.json file. */\n  token: string\n  /** Mint a scope-token for the scoped orchestrator sub-gateway\n   *  (`/mcp/orchestrator`). The returned `token` gates that endpoint\n   *  and `tools` is the effective allowlist (⊆ the default orchestrator\n   *  subset). WP3 will call this at spawn time and inject the URL into\n   *  the child's `mcpServers`; for WP2 it's the internal primitive. */\n  mintOrchestratorScope(opts?: {\n    tools?: readonly string[]\n  }): OrchestratorScope\n  stop(): Promise<void>\n}\n\n/**\n * Spin up the gateway. Order:\n *   1. Build MCP server + load AIP-40 extensions\n *   2. Build conversation store + workspace fs adapter\n *   3. (optional) Run BOOT.md once\n *   4. Start HTTP server\n *   5. Start heartbeat ticker\n *\n * `stop()` reverses 4–5 (heartbeat first, then HTTP). The MCP server\n * is owned by the HTTP server's per-session transports and is closed\n * implicitly when those close.\n */\nexport async function createGateway(\n  opts: CreateGatewayOptions,\n): Promise<GatewayHandle> {\n  const workspace = resolve(opts.workspace)\n  if (!existsSync(workspace)) {\n    throw new Error(`runtime: workspace dir does not exist: ${workspace}`)\n  }\n  const port = opts.port ?? 18790\n  // Loopback URL for the daemon's own plain `/mcp` gateway — always\n  // 127.0.0.1 regardless of `opts.bind`, mirroring the orchestrator\n  // injector's loopback default (orchestrator-gateway.ts), since a\n  // spawned child is co-located on the same host and reaches the\n  // daemon over loopback, never the LAN-bind address.\n  const daemonMcpUrl = `http://127.0.0.1:${port}/mcp`\n\n  const events = createRuntimeEvents()\n  const conversations = fileConversationStore({ workspace })\n  const workspaceFs = createWorkspaceFs({ workspace })\n\n  // Singleton controller for \"publish to the internet\" state. Created\n  // disabled — auth stays `mode: \"none\"` until `remote_enable` is\n  // called. Tunnel logs flow through the events stream so `/events`\n  // subscribers see cloudflared chatter.\n  const remote = new RemoteController({\n    workspace,\n    port,\n    onLog: line =>\n      events.emit({\n        type: \"remote-log\",\n        at: new Date().toISOString(),\n        line,\n      }),\n  })\n\n  // Multi-tunnel registry — independent from RemoteController. Manages\n  // the general \"create a public URL for any local port\" surface\n  // (tunnel_create / tunnel_list / tunnel_stop MCP tools + /tunnels HTTP\n  // routes). Logs flow through the same events stream.\n  // Shared tunnel creds store (~/.agentproto/tunnel-creds/, 0600) — lets the\n  // registry rebuild a provider that keeps its secrets off the descriptor\n  // (ngrok authtoken, third-party creds) when restoring on boot / creating.\n  const tunnelCredsStore = makeTunnelCredsStore()\n  const tunnels = new TunnelRegistry({\n    workspace,\n    onLog: line =>\n      events.emit({\n        type: \"remote-log\",\n        at: new Date().toISOString(),\n        line,\n      }),\n    readCreds: slug => tunnelCredsStore.read(slug),\n  })\n  // Relaunch any `autostart` (named) tunnels that were live before this\n  // daemon restarted. Non-blocking — boot must not wait on cloudflared,\n  // and a failed restore leaves that one tunnel `error` without gating\n  // the rest of the gateway.\n  void tunnels.restoreOnBoot().catch(() => {\n    // restoreOnBoot already logs per-tunnel failures via onLog.\n  })\n\n  // Build a server once eagerly so we can capture `registered` for\n  // `/health`. The server is NOT used for serving — every `/mcp`\n  // request gets its own freshly-constructed pair, mirroring the\n  // SDK's official stateless pattern. See the comment on\n  // `RuntimeHttpServerOptions.mcpServerFactory` for why.\n  const { registered } = await createMcpServer({\n    specs: opts.specs,\n    workspace,\n    name: opts.name ?? \"agentproto-runtime\",\n    version: opts.version ?? \"0.1.0-alpha\",\n  })\n\n  // Event bus + ring for orchestration tools (session_events_poll / session_monitor).\n  // Declared before the sessions registry so we can pass the bus into it.\n  const sessionEvents = createSessionEventBus()\n  const eventRing = createEventRing()\n  // Wire the ring so every session:* event is buffered for session_events_poll.\n  eventRing.wire(sessionEvents)\n  // Wire the webhook notifier so per-session and global URLs are\n  // notified on turn-end / awaiting-input / exited events.\n  const webhookNotifier = createWebhookNotifier()\n  sessionEvents.onAny(ev => webhookNotifier.onSessionEvent(ev))\n  // Unregister per-session URLs on exit so the notifier map doesn't\n  // leak memory across sessions.\n  sessionEvents.on(\"session:exited\", ev => {\n    webhookNotifier.unregister(ev.sessionId)\n  })\n\n  // Sessions registry — single instance per gateway, captured by\n  // the per-request mcpServerFactory closure below + handed to\n  // startHttpServer for the /sessions HTTP routes. Declared here\n  // (above the factory) so its identifier is visible at closure-\n  // build time, even though the factory only invokes later.\n  const sessions = createSessionsRegistry({\n    sessionEvents,\n    ...(opts.spawnPty ? { spawnPty: opts.spawnPty } : {}),\n    // Resume hook: when a prompt arrives for a dead agent-cli row\n    // (typical after daemon restart), the registry calls back into\n    // the adapter resolver to re-create the AgentSession with\n    // `resumeSessionId = adapterSessionId`. ACP semantics: the\n    // upstream provider reattaches to the prior conversation.\n    // Unwired (no resolveAgentAdapter) → legacy \"not an agent\n    // session\" error, user must spawn fresh.\n    ...(opts.resolveAgentAdapter\n      ? {\n          resumeAgent: async ({\n            adapterSlug,\n            cwd,\n            resumeSessionId,\n            mcpServers,\n            onActivity,\n          }) => {\n            const adapter = await opts.resolveAgentAdapter!(adapterSlug)\n            if (!adapter) return null\n            try {\n              return await adapter.startSession({\n                cwd,\n                resumeSessionId,\n                // Re-mount the persisted spawn-time toolset on resume\n                // (orchestrator WP1) — closes the gap where re-spawn\n                // dropped mcpServers.\n                ...(mcpServers ? { mcpServers } : {}),\n                ...(onActivity ? { onActivity } : {}),\n              })\n            } catch (err) {\n              console.warn(\n                `[agentproto] resumeAgent('${adapterSlug}', ${resumeSessionId}) failed: ${\n                  err instanceof Error ? err.message : String(err)\n                }`\n              )\n              return null\n            }\n          },\n        }\n      : {}),\n  })\n\n  // Completion-policy supervisor — watches sessions and runs shell gates.\n  // Declared after `sessions` so it can resolve session cwd at gate time.\n  const supervisor = createCompletionPolicySupervisor({\n    registry: sessions,\n    sessionEvents,\n    workspace,\n    persist: true,\n    // WP6: daemon-wide cap on policies concurrently gating/acting. Excess\n    // queue (FIFO) until a slot frees. Override via AGENTPROTO_POLICY_CONCURRENCY.\n    concurrencyCap: (() => {\n      const raw = process.env.AGENTPROTO_POLICY_CONCURRENCY\n      const n = raw ? Number.parseInt(raw, 10) : NaN\n      return Number.isFinite(n) && n > 0 ? n : undefined\n    })(),\n    // WP7: judge-agent gate spawns a short-lived agent via the same resolver\n    // agent_start uses. Absent → judge gates fail-safe (FAIL).\n    ...(opts.resolveAgentAdapter\n      ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n      : {}),\n  })\n\n  // Routine runner — singleton per daemon, shared across all MCP connections.\n  // Persists run state to ~/.agentproto/routine-runs.json so runs survive\n  // daemon restarts (interrupted runs are marked \"failed\" on load).\n  // Declared after `sessions` and `supervisor` so it shares the same\n  // registry + event bus. Only wired when `resolveAgentAdapter` is\n  // available (routine steps need to spawn agent sessions).\n  const routineRunner = opts.resolveAgentAdapter\n    ? createRoutineRunner({\n        registry: sessions,\n        sessionEvents,\n        resolveAgentAdapter: opts.resolveAgentAdapter,\n        webhookNotifier,\n        persist: true,\n      })\n    : undefined\n\n  // Cron scheduler — singleton per daemon, persisted to\n  // ~/.agentproto/cron-jobs.json. Jobs survive daemon restarts;\n  // skipped fires during downtime are NOT backfilled (documented behaviour).\n  // Declared after `sessions` so it can spawn agent sessions via the registry.\n  // Agent jobs need `resolveAgentAdapter`; command jobs work without it.\n  const cronScheduler = createCronScheduler({\n    sessionEvents,\n    registry: sessions,\n    ...(opts.resolveAgentAdapter\n      ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n      : {}),\n    workspace,\n    persist: true,\n  })\n\n  // Workflow runner — sibling primitive to routineRunner (stage-barrier\n  // parallel orchestration rather than a flat sequential list). Same\n  // singleton-per-daemon, same persistence pattern, own persist file\n  // (~/.agentproto/workflow-runs.json) so the two run stores never collide.\n  const workflowRunner = opts.resolveAgentAdapter\n    ? createWorkflowRunner({\n        registry: sessions,\n        sessionEvents,\n        resolveAgentAdapter: opts.resolveAgentAdapter,\n        webhookNotifier,\n        persist: true,\n      })\n    : undefined\n\n  // Per-boot bearer token. Required on mutating /sessions/* routes\n  // and on the WS upgrade for /sessions/:id/pty. Persisted to\n  // runtime.json (mode 0600) so the same-user CLI can read it; a\n  // browser-loaded localhost page can't.\n  const token = opts.token ?? randomUUID()\n\n  // MCP proxy — single registry that holds open Client connections\n  // to every imported MCP server. The per-request mcpServerFactory\n  // captures it so each /mcp request reuses the same upstream\n  // sessions instead of re-spawning stdio children.\n  const mcpProxy = new McpProxyRegistry()\n\n  // Inbound watcher — polls an agentpush source on a timer and spawns\n  // one agent per new contact_ref. Wired when an adapter resolver is\n  // available (otherwise the watcher would have nowhere to spawn).\n  const inboundWatcher =\n    opts.resolveAgentAdapter\n      ? createInboundWatcher({\n          mcpProxy,\n          registry: sessions,\n          resolveAgentAdapter: opts.resolveAgentAdapter,\n          persist: true,\n        })\n      : undefined\n\n  // Scope-token registry (WP2) — mints/validates the per-child tokens\n  // that gate `/mcp/orchestrator` and carry each orchestrator's identity\n  // (owner session, depth, tools, limits — WP4). The injector + scoped\n  // factory below both close over it.\n  const scopeTokens = createScopeTokenRegistry()\n\n  // Orchestrator auto-injection (WP3). Closed over the scope-token\n  // registry + the session-event bus + the HTTP port: when\n  // `agent_start` is called with `orchestrator`, this mints a\n  // scoped token, builds the `mcpServers` entry pointing the child at\n  // `/mcp/orchestrator?scope=<token>` on the daemon's own loopback\n  // port, and revokes the token on the child's `session:exited`. The\n  // port is the daemon's configured listener port (`startHttpServer`\n  // binds `opts.port` directly), reachable by the co-located child\n  // over loopback.\n  // The injected entry is named \"agentproto\" (the default) so the\n  // child's orchestration tools surface under a stable namespace,\n  // independent of the daemon's advertised server name.\n  // Defined BEFORE the scoped factory so the factory can hand it to the\n  // scoped server's `agent_start` — that's what lets a child\n  // orchestrator recursively spawn its OWN sub-orchestrators (WP4),\n  // bounded by depth/quota/tools inheritance.\n  const orchestratorInjector = createOrchestratorInjector({\n    scopeTokens,\n    sessionEvents,\n    port,\n  })\n\n  // Scoped orchestrator sub-gateway (WP2). The scope-token registry\n  // mints/validates per-child tokens; the factory builds a scoped MCP\n  // server exposing only the curated orchestration subset for a verified\n  // scope. Mounted by the HTTP server at `/mcp/orchestrator` (no\n  // loopback bypass — token required). The verified scope is also the\n  // calling orchestrator's identity, so the scoped server enforces the\n  // WP4 depth/quota guards + subtree scoping against it.\n  const orchestratorMcpServerFactory = createOrchestratorMcpServerFactory({\n    workspace,\n    name: opts.name ?? \"agentproto-runtime\",\n    version: opts.version ?? \"0.1.0-alpha\",\n    registry: sessions,\n    sessionEvents,\n    eventRing,\n    supervisor,\n    orchestratorInjector,\n    webhookNotifier,\n    daemonMcpUrl,\n    ...(opts.resolveAgentAdapter\n      ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n      : {}),\n    ...(opts.listAgentAdapters\n      ? { listAgentAdapters: opts.listAgentAdapters }\n      : {}),\n  })\n\n  const mcpServerFactory = async () => {\n    const { server: rawServer } = await createMcpServer({\n      specs: opts.specs,\n      workspace,\n      name: opts.name ?? \"agentproto-runtime\",\n      version: opts.version ?? \"0.1.0-alpha\",\n    })\n    // Deferred/lazy tool loading (opt-in — see deferred-tools.ts). Wraps\n    // every subsequent `registerXTools(server, ...)` pass below so tools\n    // outside `alwaysOn` register but start disabled (hidden from the\n    // first `tools/list`) until `tool_search` pulls them in. Omitted →\n    // `server` is the raw, fully-eager gateway, today's behaviour.\n    const server = opts.deferredTools\n      ? withDeferredTools(rawServer, { alwaysOn: new Set(opts.deferredTools.alwaysOn ?? DEFAULT_ALWAYS_ON_TOOLS) })\n      : rawServer\n    // Canonical filesystem tools so remote MCP clients (cloud\n    // workspace-providers, IDEs, ad-hoc tooling) can read/write the\n    // workspace without each implementing AIP-aware glue. Names match\n    // `@modelcontextprotocol/server-filesystem` for drop-in compat.\n    registerFsTools(server, { workspace })\n    // Subprocess execution — the runtime's superpower for cloud\n    // agents. Any allowlisted CLI on the user's machine (claude, gh,\n    // pnpm, …) is reachable via `command_execute`. Allowlist lives at\n    // `.agentproto/allowed-commands.json`; default-deny.\n    registerCommandTools(server, { workspace })\n    // Remote-tunnel lifecycle. The controller is a singleton on the\n    // gateway, so registering its tools per-request is just rebinding\n    // the same closures — the underlying state lives in `remote`.\n    registerRemoteTools(server, { controller: remote })\n    // Agent-session orchestration — operators (Mastra agents in\n    // cloud Guilde, Claude Code as a sub-agent, …) drive long-running\n    // claude/hermes/aider sessions on the user's machine through\n    // these MCP tools. The registry + adapter resolver are\n    // singletons on the gateway, same closure-rebind pattern.\n    registerSessionTools(server, {\n      registry: sessions,\n      mcpProxy,\n      ptyEnabled: opts.spawnPty != null,\n      buildOrchestratorMcp: orchestratorInjector,\n      webhookNotifier,\n      daemonMcpUrl,\n      ...(opts.resolveAgentAdapter\n        ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n        : {}),\n      ...(opts.listAgentAdapters\n        ? { listAgentAdapters: opts.listAgentAdapters }\n        : {}),\n    })\n    registerBrowserTools(server, {\n      registry: sessions,\n      ...(opts.resolveBrowserAdapter\n        ? { resolveBrowserAdapter: opts.resolveBrowserAdapter }\n        : {}),\n      ...(opts.listBrowserAdapters\n        ? { listBrowserAdapters: opts.listBrowserAdapters }\n        : {}),\n    })\n    registerOrchestrationTools(server, {\n      registry: sessions,\n      sessionEvents,\n      eventRing,\n      supervisor,\n      ...(routineRunner ? { routineRunner } : {}),\n      ...(workflowRunner ? { workflowRunner } : {}),\n      ...(inboundWatcher ? { inboundWatcher } : {}),\n      cronScheduler,\n    })\n    // MCP Apps — agentproto_sessions panel via the AgnoMcpApp adapter.\n    // Tool: agentproto_sessions  Resource: ui://agentproto_sessions/view\n    const listSessionsFiltered = (filter?: \"running\" | \"all\") => {\n      let rows = sessions.list()\n      if (filter === \"running\") {\n        rows = rows.filter(s => s.status === \"running\" || s.status === \"starting\")\n      }\n      return rows\n    }\n    registerMcpApps(server, [\n      makeSessionsPanelApp({ listSessions: listSessionsFiltered }),\n      makeAgentsOverviewApp({ listSessions: listSessionsFiltered }),\n      makeBureauSessionsApp({ listSessions: listSessionsFiltered }),\n    ])\n    // Server-side per-session summariser backing the agents-overview panel.\n    // Heuristic today (no LLM in @agentproto/runtime) — see agents-overview-app.ts.\n    registerSummarizeSessionTool(server, {\n      getSession: (id) => sessions.get(id),\n      tailLines: (id, lastN) => {\n        // Same source as agent_output: attach replays the ring\n        // buffer synchronously, then we unsubscribe immediately.\n        const lines: string[] = []\n        const unsub = sessions.attach(id, (line) => { lines.push(line) })\n        if (unsub) unsub()\n        return lines.slice(-lastN)\n      },\n    })\n    // Transcript exporter — reads the adapter's native persistence\n    // (claude-code JSONL / hermes SQLite) and renders a clean markdown or\n    // JSON transcript. Co-located with the session tools; registry access\n    // mirrors the summarise_session pattern above.\n    registerExportSessionTool(server, { registry: sessions })\n    // Multi-tunnel tools — same closure-rebind pattern.\n    registerTunnelTools(server, { registry: tunnels })\n    // Tunnel adapter introspection/setup, riding on @agentproto/adapter-kit\n    // (list_tunnel_adapters + setup_tunnel_provider). Stateless wrt the\n    // gateway — creds/ledger live under ~/.agentproto.\n    await registerTunnelAdapterTools(server, {})\n    return server\n  }\n\n  // ── boot ─────────────────────────────────────────────────────────\n  if (opts.boot !== false) {\n    await runBoot(workspace, opts, conversations, events).catch((err) => {\n      events.emit({\n        type: \"heartbeat-error\",\n        at: new Date().toISOString(),\n        agent: opts.defaultBootAgent,\n        error: `BOOT.md failed: ${err instanceof Error ? err.message : String(err)}`,\n      })\n    })\n  }\n\n  const heartbeat = startHeartbeat({\n    workspace,\n    conversations,\n    events,\n    buildAgent: opts.buildAgent ?? noopBuildAgent,\n  })\n\n  const http = await startHttpServer({\n    port,\n    bind: opts.bind,\n    // Auth is read on every request via this getter. `opts.auth`\n    // (when provided) is the startup default and represents the\n    // operator's intent — bearer-only deployments stay bearer-only\n    // even when no remote tunnel is up. The controller's auth wins\n    // once a tunnel is enabled (it issues a fresh token); on disable\n    // we fall back to `opts.auth` if set, otherwise `mode: \"none\"`.\n    auth: () => {\n      const remoteAuth = remote.readAuth()\n      if (remoteAuth.mode === \"bearer\") return remoteAuth\n      return opts.auth ?? { mode: \"none\" }\n    },\n    mcpServerFactory,\n    orchestratorMcpServerFactory,\n    verifyOrchestratorScope: scopeTokens.verify,\n    conversations,\n    events,\n    heartbeat,\n    sessions,\n    mcpProxy,\n    token,\n    ptyEnabled: opts.spawnPty != null,\n    tunnels,\n    sessionEvents,\n    eventRing,\n    supervisor,\n    ...(routineRunner ? { routineRunner } : {}),\n    ...(workflowRunner ? { workflowRunner } : {}),\n    ...(opts.allowedOrigins ? { allowedOrigins: opts.allowedOrigins } : {}),\n    ...(opts.strictOrigins ? { strictOrigins: true } : {}),\n    ...(opts.resolveAgentAdapter\n      ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n      : {}),\n    // Same injector + gateway URL passed to `registerAgentTools` above —\n    // lets POST /sessions/agent mint the same scoped orchestrator\n    // sub-gateway + hermes default-mcpServers safety net the MCP\n    // `agent_start` tool gets (session-spawn.ts is the shared logic).\n    buildOrchestratorMcp: orchestratorInjector,\n    daemonMcpUrl,\n    ...(opts.listAgentAdapters\n      ? { listAgentAdapters: opts.listAgentAdapters }\n      : {}),\n    ...(opts.resolveBrowserAdapter\n      ? { resolveBrowserAdapter: opts.resolveBrowserAdapter }\n      : {}),\n    ...(opts.listBrowserAdapters\n      ? { listBrowserAdapters: opts.listBrowserAdapters }\n      : {}),\n    meta: { workspace, registered },\n    cronScheduler,\n  })\n\n  heartbeat.start()\n  events.emit({\n    type: \"boot\",\n    at: new Date().toISOString(),\n    workspace,\n    registered,\n  })\n\n  // Record a snapshot of the running config so external tooling /\n  // shell users can introspect a live gateway via\n  // `cat <workspace>/.agentproto/runtime.json`. Best-effort — failure\n  // here doesn't gate the gateway being functional.\n  void writeRuntimeMeta(workspace, {\n    workspace,\n    port,\n    bind: opts.bind ?? \"127.0.0.1\",\n    pid: process.pid,\n    startedAt: new Date().toISOString(),\n    name: opts.name ?? \"agentproto-runtime\",\n    registered,\n    token,\n  })\n\n  return {\n    url: http.url,\n    workspace,\n    workspaceFs,\n    registered,\n    sessions,\n    tunnels,\n    token,\n    mintOrchestratorScope: scopeTokens.mint,\n    async stop() {\n      heartbeat.stop()\n      // Flush inbound-watcher cursor state before sessions shut down.\n      inboundWatcher?.shutdown()\n      // Stop the cron scheduler tick loop before sessions shut down.\n      cronScheduler.shutdown()\n      // Flush completion-policy state before sessions shut down so\n      // policies referencing live sessions are persisted with their\n      // current status (not \"killed\" sessions).\n      supervisor.shutdown()\n      // Kill all live sessions before tearing down HTTP — otherwise\n      // long-running children inherit the daemon's listening socket\n      // and stay around as zombies after the parent exits.\n      sessions.shutdown()\n      // Close upstream MCP clients (their stdio children would\n      // otherwise leak the same way).\n      await mcpProxy.closeAll()\n      // Stop all active tunnels (TunnelRegistry) then the remote\n      // controller's single-gateway tunnel. Both before HTTP so\n      // cloudflared doesn't briefly proxy to a dead port.\n      await tunnels.shutdown()\n      await remote.shutdown()\n      await http.stop()\n    },\n  }\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nconst noopBuildAgent: BuildHeartbeatAgent = async () => null\n\nasync function runBoot(\n  workspace: string,\n  opts: CreateGatewayOptions,\n  conversations: import(\"./conversations.js\").ConversationStore,\n  events: import(\"./events.js\").RuntimeEvents,\n): Promise<void> {\n  const path = join(workspace, \"BOOT.md\")\n  if (!existsSync(path)) return\n  const body = (await readFile(path, \"utf8\")).trim()\n  if (!body) return\n  if (!opts.buildAgent || !opts.defaultBootAgent) return\n\n  const agent = await opts.buildAgent(opts.defaultBootAgent)\n  if (!agent) return\n\n  const conversationId = `boot-${new Date().toISOString().slice(0, 19).replace(/[:.]/g, \"-\")}`\n  await conversations.open(conversationId, { agent: opts.defaultBootAgent })\n  await conversations.appendTurn(conversationId, \"user\", body, {\n    attribution: \"boot\",\n  })\n  const reply = await agent.generate(body)\n  await conversations.appendTurn(conversationId, \"assistant\", reply.text, {\n    attribution: opts.defaultBootAgent,\n  })\n  events.emit({\n    type: \"heartbeat-fired\",\n    at: new Date().toISOString(),\n    agent: opts.defaultBootAgent,\n    conversationId,\n    prompt: body,\n    reply: reply.text,\n    durationMs: 0,\n  })\n}\n"]}