{"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/config.ts","../src/providers-store.ts","../src/spawn-defaults.ts","../src/role.ts","../src/role-pack.ts","../src/role-registry.ts","../src/mcp-credential-deps.ts","../src/sandbox-agent-session-proxy.ts","../src/session-spawn.ts","../src/agent-tools.ts","../src/mcp-discovery.ts","../src/resume-strategies.ts","../src/session-restart-core.ts","../src/mcp-imports.ts","../src/usage.ts","../src/tool-subset.ts","../src/session-tools.ts","../src/browser-tools.ts","../src/mcp-apps-adapter.ts","../src/panel-bridge.ts","../src/sessions-panel.ts","../src/sessions-panel-app.ts","../src/agents-overview-app.ts","../src/bureau-sessions-app.ts","../src/session-story-panel.ts","../src/session-story-panel-app.ts","../src/terminal-panel-app.ts","../src/heartbeat.ts","../src/command-log.ts","../src/session-observer.ts","../src/terminal-transcript-writer.ts","../src/sessions.ts","../src/orchestration-tools.ts","../src/preset-tools.ts","../src/http-server.ts","../src/langfuse-session-tracer.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/cloudflared-spawn.ts","../src/remote-providers/quick.ts","../src/remote-controller.ts","../src/remote-tools.ts","../src/pairing-tools.ts","../src/daemon-health-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/sandbox-providers/local.ts","../src/sandbox-providers/registry.ts","../src/sandbox-adapters.ts","../src/eval-reporter-tools.ts","../src/workspace-fs.ts","../src/pairing-registry.ts","../src/index.ts"],"names":["resolve","stat","readFile","join","text","mkdir","existsSync","writeFile","readdir","isAbsolute","normalize","relative","z","homedir","spawn","fs","FRONTMATTER_RE","isRecord","deps","dirname","resolveSandboxProvider","getModelProvider","loadRoleRegistry","registry","resolvePath","desc","adapters","mkdirSync","createWriteStream","usage","EventEmitter","rt","opts","readFileSync","enrichPermission","state","server","id","createReadStream","createInterface","policyId","jobId","writeFileSync","randomUUID","renameSync","DEFAULT_PERSIST_PATH","loadRuns","saveRuns","errMsg","compileWorkflow","ANSI_RE","stripAnsi","PERSIST_DEBOUNCE_MS","fsp","basename","entry","toDescriptor","cwd","randomBytes","rm","execFileAsync","promisify","execFile","STARTUP_TIMEOUT_MS","cloudflaredOnPath","assertCloudflaredOnPath","slugToCamel","discoverAdapterPackages","HISTORY_CAP","makeAdapterLister","makeListTool","fields","POLL_INTERVAL_MS","createServer","importThirdPartyProvider","makeCredsStore","makeAdapterResolver","collectSetupSchema","makeSetupLedger","makeSetupTool","fsReadFile","fsWriteFile","chmod","createMcpServer"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,EA8StC,iBAAA,CAAkB,gCAAgC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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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\"\nimport type { SessionsRegistry } from \"./sessions.js\"\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  /** Registry used to mint a `kind:\"command\"` session for every\n   *  `command_execute` call (see `SessionsRegistry.recordCommand`) so\n   *  invocations show up in `command_list`/`session_list` and their full\n   *  result is durably persisted, not just returned to the caller. */\n  registry: SessionsRegistry\n  /** Slug recorded on the minted command session's descriptor. Defaults\n   *  to \"default\", matching the fallback cron-scheduler.ts already uses\n   *  for its own agent-action spawns. */\n  workspaceSlug?: 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      // Mint a kind:\"command\" session for this completed run — synchronous,\n      // so the id is available immediately. The JSONL body write is\n      // fire-and-forget internally (recordCommand never delays or fails\n      // the caller's actual result).\n      const desc = opts.registry.recordCommand({\n        workspaceSlug: opts.workspaceSlug ?? \"default\",\n        cwd: resolvedCwd,\n        command,\n        args: args ?? [],\n        exitCode: result.exitCode,\n        signal: result.signal,\n        durationMs: result.durationMs,\n        stdout: result.stdout,\n        stderr: result.stderr,\n        ...(result.truncated ? { truncated: true } : {}),\n      })\n      return {\n        content: [\n          {\n            type: \"text\" as const,\n            text: JSON.stringify({ ...result, sessionId: desc.id }),\n          },\n        ],\n      }\n    },\n  )\n\n  server.tool(\n    \"command_log_tail\",\n    \"Read back command_execute (and cron `command` job) results. Every invocation is its own `kind:\\\"command\\\"` session — the same rows `command_list`/`session_list({kind:'command'})` return — with its full stdout/stderr/exitCode/durationMs stored at that session's own record. Pass `sessionId` (e.g. from a session descriptor's `priorCommandSessionId`) to fetch one specific invocation, or omit it to list the most recent ones for this workspace.\",\n    {\n      sessionId: z\n        .string()\n        .optional()\n        .describe(\"Fetch one specific command session's full result by id.\"),\n      lastN: z\n        .number()\n        .int()\n        .min(1)\n        .max(500)\n        .optional()\n        .describe(\"Max invocations to return when listing (ignored with `sessionId`). Default 50, max 500.\"),\n      cwd: z\n        .string()\n        .optional()\n        .describe(\n          \"Restrict the listing to invocations spawned with this cwd (workspace-relative or absolute). Ignored with `sessionId`.\",\n        ),\n    },\n    async ({ sessionId, lastN, cwd }) => {\n      if (sessionId) {\n        const entry = await opts.registry.readCommandLog(sessionId)\n        return {\n          content: [{ type: \"text\" as const, text: JSON.stringify({ entry }) }],\n        }\n      }\n      const limit = lastN ?? 50\n      const resolvedCwd = cwd !== undefined ? anchorCwd(cwd) : undefined\n      let rows = opts.registry.list().filter(d => d.kind === \"command\")\n      if (resolvedCwd !== undefined) {\n        rows = rows.filter(d => d.cwd === resolvedCwd)\n      }\n      // Newest last, matching agent_output's ring-buffer tail convention.\n      rows.sort((a, b) => (a.endedAt ?? a.startedAt).localeCompare(b.endedAt ?? b.startedAt))\n      const tail = rows.slice(-limit)\n      const entries = await Promise.all(\n        tail.map(async d => ({ sessionId: d.id, ...(await opts.registry.readCommandLog(d.id)) })),\n      )\n      return {\n        content: [\n          {\n            type: \"text\" as const,\n            text: JSON.stringify({ entries }, null, 2),\n          },\n        ],\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, readFileSync, type WriteStream } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport type { SessionObserver } from \"./session-observer.js\"\nimport type { AgentStreamEvent } from \"./sessions.js\"\nimport type { SessionUsage } from \"./usage.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\n/** Highest `seq` already durably on disk for a session, or 0 when the file\n *  is absent/empty. A fresh writer instance (e.g. after a daemon restart)\n *  opens the existing events.jsonl in append mode, so its first record must\n *  continue from this cursor rather than restarting at 1 — otherwise a\n *  restart mid-session emits duplicate seq numbers and any `since`-based\n *  reader (GET /sessions/:id/events) silently drops the post-restart tail.\n *  Records are written in ascending `seq`, so the max is on the last valid\n *  line, but a truncated/partial final line is tolerated by scanning every\n *  parseable line rather than trusting the tail. */\nfunction highestSeqOnDisk(path: string): number {\n  let raw: string\n  try {\n    raw = readFileSync(path, \"utf8\")\n  } catch {\n    // ENOENT (fresh session) or any read error — start from 0.\n    return 0\n  }\n  let max = 0\n  for (const line of raw.split(\"\\n\")) {\n    const trimmed = line.trim()\n    if (!trimmed) continue\n    try {\n      const rec = JSON.parse(trimmed) as { seq?: unknown }\n      if (typeof rec.seq === \"number\" && rec.seq > max) max = rec.seq\n    } catch {\n      // Ignore a malformed/partial line (e.g. a torn final write).\n    }\n  }\n  return max\n}\n\nexport interface TranscriptWriter extends SessionObserver {\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  /** Record a durable `usage_snapshot` recap at a turn boundary or on\n   *  session exit — the cumulative cost/token/context view resolved by\n   *  `deriveSessionUsage`. Distinct from the high-frequency `usage_update`\n   *  stream: this is the aggregable turn-boundary durable record, so a\n   *  daemon restart doesn't lose the session's accumulated usage. */\n  recordUsageSnapshot(sessionId: string, usage: SessionUsage): 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  /** Subscribe to every record as it's written for one session — the\n   *  live-push half of `GET /sessions/:id/events/stream`'s replay-then-\n   *  subscribe handoff (http-server.ts). Delivers the exact object shape\n   *  written to disk (`{seq, ts, kind, ...}`, pre-JSON.stringify), so a\n   *  consumer already reducing the poll route's `events` array can reduce\n   *  this stream with identical logic. No backfill here — history is a\n   *  file read the caller does itself; this only wires the live tap.\n   *  Notification happens synchronously, in the same call that appends the\n   *  record, so a caller that subscribes before doing its own disk read is\n   *  guaranteed to observe (via this callback) every record from that\n   *  point on, even ones the read might otherwise race. Returns an\n   *  unsubscribe fn; safe to call more than once. */\n  subscribe(sessionId: string, onRecord: (record: Record<string, unknown>) => void): () => 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  const listeners = new Map<string, Set<(record: Record<string, unknown>) => void>>()\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 eventsPath = sessionEventsPath(sessionId, baseDir)\n    // Resume the seq counter from what's already durable so a restart\n    // mid-session keeps events.jsonl monotonic in append mode.\n    const resumeSeq = highestSeqOnDisk(eventsPath)\n    const stream = createWriteStream(eventsPath, { 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: resumeSeq,\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    const full = { seq: state.seq, ts: new Date().toISOString(), ...record }\n    state.stream.write(JSON.stringify(full) + \"\\n\")\n    const subs = listeners.get(sessionId)\n    if (subs) {\n      for (const onRecord of subs) onRecord(full)\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            // Carried through so a replay can tell an ENRICHMENT of an\n            // announced call from a genuine second call. Readers merge by\n            // toolCallId either way, but a record that silently drops the\n            // distinction can't be reasoned about after the fact.\n            ...(evt.isUpdate ? { isUpdate: true } : {}),\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            // Persist cumulative token counts when the adapter reports them\n            // (claude-code over ACP, hermes via its state.db reader,\n            // mastracode via its native usage_update) so the transcript can\n            // price/aggregate a session even without a `cost` block.\n            ...(evt.tokensIn !== undefined ? { tokensIn: evt.tokensIn } : {}),\n            ...(evt.tokensOut !== undefined ? { tokensOut: evt.tokensOut } : {}),\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    recordUsageSnapshot(sessionId, usage) {\n      const state = getState(sessionId)\n      // Order after any buffered text/thought so on-disk order matches\n      // wall-clock order.\n      flushBuffers(sessionId, state)\n      writeRecord(sessionId, state, {\n        kind: \"usage_snapshot\",\n        sessionId,\n        // Omit absent fields so a missing value never reads as a measured 0.\n        ...(usage.model !== undefined ? { model: usage.model } : {}),\n        ...(usage.costUsd !== undefined ? { costUsd: usage.costUsd } : {}),\n        ...(usage.tokensIn !== undefined ? { tokensIn: usage.tokensIn } : {}),\n        ...(usage.tokensOut !== undefined ? { tokensOut: usage.tokensOut } : {}),\n        ...(usage.contextSize !== undefined ? { contextSize: usage.contextSize } : {}),\n        ...(usage.contextUsed !== undefined ? { contextUsed: usage.contextUsed } : {}),\n        source: usage.source,\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    subscribe(sessionId, onRecord) {\n      let subs = listeners.get(sessionId)\n      if (!subs) {\n        subs = new Set()\n        listeners.set(sessionId, subs)\n      }\n      subs.add(onRecord)\n      return () => {\n        const current = listeners.get(sessionId)\n        if (!current) return\n        current.delete(onRecord)\n        if (current.size === 0) listeners.delete(sessionId)\n      }\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/** Find a workspace whose path is an ancestor of (or equal to) the\n *  given directory. Returns the most specific match (longest path)\n *  when multiple workspaces nest under the same root. */\nexport function findWorkspaceByPath(\n  config: WorkspacesConfig,\n  dir: string\n): WorkspaceEntry | undefined {\n  const resolved = resolve(dir)\n  const candidates = config.workspaces\n    .filter(w => resolved.startsWith(resolve(w.path) + \"/\") || resolved === resolve(w.path))\n    .sort((a, b) => b.path.length - a.path.length)\n  return candidates[0]\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 * `~/.agentproto/config.json` — single hand-editable JSON for the\n * agentproto control plane's defaults. Sits alongside the existing\n * surface files (workspaces.json, credentials.json, sessions.json):\n *\n *   workspaces.json     which directories are workspaces + which is active\n *   credentials.json    tunnel host bearer tokens (mode 0600)\n *   sessions.json       last-known snapshot of the registry (informational)\n *   config.json         daemon defaults: port, bind, allowed origins,\n *                       tunnel host, feature toggles\n *\n * Resolution order for every daemon knob is:\n *   1. CLI flag (e.g. --port)\n *   2. Env var (where one exists, e.g. AGENTPROTO_TOKEN)\n *   3. config.json\n *   4. Hardcoded default\n *\n * This means a user can call `agentproto config set daemon.port 18791`\n * once and never re-pass `--port 18791` to `serve install` etc. CLI\n * flags still win for one-off overrides.\n *\n * Schema is intentionally narrow + extensible — unknown keys are\n * preserved on save (deep-merge), so a newer CLI writing a new\n * field won't drop one an older CLI doesn't know about. No secrets\n * here; credentials stay in credentials.json (mode 0600).\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { dirname, join } from \"node:path\"\nimport type { SpawnDefaultsConfig } from \"./spawn-defaults.js\"\n\nexport const CONFIG_VERSION = 1 as const\n\nexport interface DaemonConfig {\n  /** Absolute path to the workspace the daemon binds to at boot. */\n  workspace?: string\n  /** HTTP port. Default 18790. */\n  port?: number\n  /** Bind addr. Default 127.0.0.1. */\n  bind?: string\n  /** Trusted browser origins for mutating /sessions/* routes (in\n   *  addition to the hardcoded localhost defaults). */\n  allowedOrigins?: string[]\n  /** When true, the daemon does NOT auto-trust localhost-on-any-port.\n   *  Only origins explicitly listed in `allowedOrigins` are allowed.\n   *  Pair with a curated list (e.g. `[\"http://localhost:3000\"]`) for\n   *  hardened setups. Default false. */\n  strictOrigins?: boolean\n  /** Server label sent in tunnel hello frames. */\n  label?: string\n  /** Bearer token gating the gateway at boot (`AuthOptions` with\n   *  `mode: \"bearer\"`). Unlike `remote_enable`'s ephemeral quick-tunnel\n   *  token, this one lives in config.json and survives daemon restarts.\n   *  Set via `agentproto config set daemon.authToken <token>` (e.g.\n   *  `$(openssl rand -hex 32)`). Unset ⇒ the gateway boots with\n   *  `mode: \"none\"` — fully open on loopback, same as today. */\n  authToken?: string\n}\n\nexport interface TunnelConfig {\n  /** Cloud WS URL. When set + autoconnect=true, `agentproto serve`\n   *  bootstraps with `--connect <host>`. */\n  host?: string\n  /** apt_ daemon token to present at the tunnel upgrade. When set,\n   *  `agentproto serve` uses this BEFORE falling back to\n   *  credentials.json — handy in profiles where the token-per-host\n   *  mapping in credentials.json doesn't fit (e.g. host = tunnel URL\n   *  but credentials were minted against the api URL). */\n  token?: string\n  /** Whether `agentproto daemon start` connects the tunnel by\n   *  default. v0 only — implementer can ignore until daemon needs it. */\n  autoconnect?: boolean\n  /**\n   * Opt into end-to-end encryption of the outbound `serve --connect` tunnel\n   * (design: tunnel-e2e/v1). When true, the daemon negotiates a\n   * token-authenticated ephemeral handshake with the host and wraps the tunnel\n   * frames in an AEAD box, so even the trusted host loses plaintext visibility.\n   * The handshake authenticates both ends against the shared `tunnel.token`, so\n   * `token` MUST also be set. Fully backward-compatible: if the host doesn't\n   * advertise e2e (an older host), the daemon falls back to today's plaintext\n   * tunnel. Unset/false ⇒ plaintext, byte-identical to today. */\n  e2e?: boolean\n}\n\nexport interface FeaturesConfig {\n  /** Hint that PTY is desired — informational; the daemon still\n   *  detects node-pty's presence at runtime. */\n  pty?: boolean\n}\n\n/**\n * Policy for `agentproto worktree new` (PLAN.md §1.4 — config carries\n * policy, never state; git itself is the authority for which worktrees\n * exist). This is the fix for the sprawl the plan measured: 31 linked\n * worktrees across 6 different parent directories, because there was no\n * `worktree new` verb and therefore no convention to converge on.\n */\nexport interface WorktreesConfig {\n  /**\n   * Absolute path new worktrees are created under. Layout:\n   * `<root>/<repoName>/<slug>`. Resolution order (mirrors every other\n   * knob in this file, see the module docblock): `--root` flag >\n   * `AGENTPROTO_WORKTREES_ROOT` env > this field > the hardcoded default\n   * `~/.agentproto/worktrees`. The default is a real single root, not\n   * \"unconfigured\" — `worktree new` converges to one place with zero\n   * setup, which is the only way the sprawl actually stops (the 6 roots\n   * that exist today are 6 people each inventing a default by hand).\n   */\n  root?: string\n}\n\nexport interface PairingConfig {\n  /** Rendezvous broker WS URL (ws:// or wss://) used by `pair offer` and by\n   *  autoconnect on boot. When unset, `pair offer` requires an explicit\n   *  `--rendezvous`. Mirrors `tunnel.host`. */\n  rendezvous?: string\n  /** Whether the daemon opens standing rendezvous connections for every\n   *  persisted pairing on boot (so a paired client can reconnect anytime).\n   *  Mirrors `tunnel.autoconnect`. Default true when a rendezvous is set. */\n  autoconnect?: boolean\n}\n\n/**\n * A user-defined generic ACP agent — the config-file half of\n * `AcpAgentSpec` (the slug is the record key in `acpAgents`, so it's\n * omitted here). Any CLI that already speaks the Agent Client Protocol\n * can be wired with zero code by declaring one of these under\n * `acpAgents.<slug>` in `~/.agentproto/config.json`; the CLI's\n * `acpHandleFromSpec` mints a runnable `AgentCliHandle` from it at\n * resolve time (see `packages/cli/src/registry/acp-generic.ts`). Kept\n * in this package (not the CLI's) so `config.ts` stays the single\n * source of truth for the config surface without a cli→runtime→cli\n * import cycle — the CLI's `AcpAgentSpec` extends this shape.\n */\nexport interface AcpAgentConfigEntry {\n  /** Display name. Defaults to the slug when omitted. */\n  name?: string\n  /** One-line description surfaced in `agentproto acp ls`. */\n  description?: string\n  /** Executable to spawn, e.g. \"gemini\". */\n  bin: string\n  /** Extra argv appended after `bin`, e.g. [\"--experimental-acp\"]. */\n  bin_args?: string[]\n  /** Extra environment variables for the spawned process. */\n  env?: Record<string, string>\n  /** Flag the CLI uses to receive the working directory, if it needs\n   *  one passed explicitly (most ACP agents take cwd over the wire). */\n  cwd_flag?: string\n  /** When true, advertise resumable + native-resume continuation. */\n  resumable?: boolean\n  /** Known model ids for the agent (informational + validation hints). */\n  models?: { default?: string; allowed?: string[] }\n  /** Shown when `bin` is missing from PATH (how to install the CLI). */\n  install_hint?: string\n}\n\n/**\n * Per-environment connection bundle. A profile overrides specific\n * fields of the top-level `daemon` / `tunnel` / `features` blocks\n * when selected via `--profile <name>` (or the top-level\n * `activeProfile` setting). Missing fields fall through to the\n * top-level config, so a profile only needs to declare what's\n * different — typically just `tunnel.host` + `tunnel.token`.\n *\n * Example:\n *   {\n *     \"daemon\": { \"workspace\": \"/code\", \"port\": 18790 },\n *     \"activeProfile\": \"local\",\n *     \"profiles\": {\n *       \"local\": { \"tunnel\": { \"host\": \"ws://localhost:3200/connect\",\n *                              \"token\": \"apt_local\", \"autoconnect\": true } },\n *       \"prod\":  { \"tunnel\": { \"host\": \"wss://tunnel.guilde.work/connect\",\n *                              \"token\": \"apt_prod\",  \"autoconnect\": true },\n *                  \"daemon\": { \"port\": 18791 } }\n *     }\n *   }\n *\n * Sandbox daemons generate per-sandbox profile entries at provision\n * time so the daemon inside the sandbox boots with\n * `agentproto serve --profile sandbox-<id>` and no extra plumbing.\n */\nexport interface ProfileConfig {\n  daemon?: DaemonConfig\n  tunnel?: TunnelConfig\n  features?: FeaturesConfig\n}\n\n/**\n * A user-defined named terminal/TUI preset stored in\n * `~/.agentproto/config.json` under `terminalPresets`. Presets keep\n * local launch recipes (argv, env, cwd, name/label) out of shared\n * adapter manifests — e.g. pointing a Claude Code TUI at a local\n * LLM gateway without retyping proxy env vars every spawn.\n */\nexport interface TerminalPreset {\n  /** Command + args to spawn. When provided, `sessions terminal` can\n   *  be used without `-- <argv...>`. */\n  argv?: string[]\n  /** Extra environment variables layered on top of the daemon's\n   *  inherited process.env. Values MUST be strings. */\n  env?: Record<string, string>\n  /** Working directory for the PTY session. Relative paths are\n   *  resolved against the current working directory at CLI time. */\n  cwd?: string\n  /** Workspace slug used for cwd fallback when `cwd` is omitted. */\n  workspace?: string\n  /** Stable session name passed to the registry (`name` field). */\n  name?: string\n  /** Human-readable label surfaced in session listings. */\n  label?: string\n}\n\nexport interface AgentprotoConfig {\n  version?: number\n  daemon?: DaemonConfig\n  tunnel?: TunnelConfig\n  features?: FeaturesConfig\n  /** E2E daemon-pairing defaults (rendezvous URL + autoconnect). */\n  pairing?: PairingConfig\n  /** Where `agentproto worktree new` creates worktrees. See\n   *  {@link WorktreesConfig}. */\n  worktrees?: WorktreesConfig\n  /** Named connection profiles. See `ProfileConfig` for the merge\n   *  semantics — a profile's fields shallow-override the top-level\n   *  defaults for the selected run. */\n  profiles?: Record<string, ProfileConfig>\n  /** Profile name to use when `--profile` isn't passed. When unset,\n   *  the top-level `daemon` / `tunnel` blocks are used directly. */\n  activeProfile?: string\n  /** Default `skills` + `options` auto-applied to every `agent_start`\n   *  spawn — global and per-adapter. See `resolveSpawnDefaults` in\n   *  `spawn-defaults.ts` for the merge precedence with an explicit call.\n   *  Absent ⇒ current behaviour exactly (no regression). */\n  defaults?: SpawnDefaultsConfig\n  /** User-defined generic ACP agents, keyed by adapter slug. Each entry\n   *  is minted into a runnable handle by the CLI's `acpHandleFromSpec`\n   *  when `resolveAdapter(slug)` finds no npm adapter package. User\n   *  entries shadow the curated `ACP_CATALOG` on slug collision. */\n  acpAgents?: Record<string, AcpAgentConfigEntry>\n  /** User-defined named terminal/TUI presets. Local-only; never\n   *  packaged in shared adapter manifests or defaults. */\n  terminalPresets?: Record<string, TerminalPreset>\n  /** Unknown keys preserved across save round-trips. */\n  [unknown: string]: unknown\n}\n\nexport const CONFIG_FILE_PATH = (): string =>\n  join(homedir(), \".agentproto\", \"config.json\")\n\n/**\n * Drop any `acpAgents` entries that aren't a shape we can turn into a\n * handle. The one hard requirement is a non-empty string `bin` (the\n * executable to spawn); everything else is optional and defaulted\n * downstream. Invalid entries are removed rather than throwing so the\n * daemon still boots — one warning names the offending slug so the\n * user can fix their config. Returns `undefined` when nothing valid\n * remains, keeping the key absent (== \"no generic agents\").\n */\nfunction sanitizeAcpAgents(\n  raw: unknown,\n  target: string,\n): Record<string, AcpAgentConfigEntry> | undefined {\n  if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n    console.warn(\n      `[runtime/config] ${target}: 'acpAgents' is not an object — ignoring`,\n    )\n    return undefined\n  }\n  const out: Record<string, AcpAgentConfigEntry> = {}\n  for (const [slug, value] of Object.entries(raw as Record<string, unknown>)) {\n    if (\n      value &&\n      typeof value === \"object\" &&\n      !Array.isArray(value) &&\n      typeof (value as { bin?: unknown }).bin === \"string\" &&\n      (value as { bin: string }).bin.length > 0\n    ) {\n      out[slug] = value as AcpAgentConfigEntry\n    } else {\n      console.warn(\n        `[runtime/config] ${target}: acpAgents.${slug} is missing a string 'bin' — ignoring`,\n      )\n    }\n  }\n  return Object.keys(out).length > 0 ? out : undefined\n}\n\n/**\n * Load config.json. Returns an empty object (NOT null) when the file\n * is missing, malformed, or unreadable — callers can `cfg.daemon?.port`\n * safely without null-guards. Errors during a malformed-read are\n * logged once so the user notices the file is broken without the\n * daemon refusing to boot.\n */\nexport async function loadConfig(path?: string): Promise<AgentprotoConfig> {\n  const target = path ?? CONFIG_FILE_PATH()\n  try {\n    const raw = await fs.readFile(target, \"utf8\")\n    const parsed = JSON.parse(raw) as unknown\n    if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n      const cfg = parsed as AgentprotoConfig\n      // Sanitize `acpAgents` in the same tolerant spirit as the rest of\n      // this loader: a malformed entry is dropped (with one warning) so a\n      // single bad hand-edit can't make every generic ACP agent\n      // unresolvable. Full AIP-45 validation happens later, at\n      // `acpHandleFromSpec` time, with precise field-level messages.\n      if (cfg.acpAgents !== undefined) {\n        cfg.acpAgents = sanitizeAcpAgents(cfg.acpAgents, target)\n      }\n      return cfg\n    }\n    console.warn(\n      `[runtime/config] ${target}: top-level value is not an object — ignoring`,\n    )\n    return {}\n  } catch (err) {\n    // ENOENT is the common case; only warn on other shapes.\n    const code = (err as NodeJS.ErrnoException).code\n    if (code && code !== \"ENOENT\") {\n      console.warn(\n        `[runtime/config] failed to read ${target}: ${\n          err instanceof Error ? err.message : String(err)\n        }`,\n      )\n    }\n    return {}\n  }\n}\n\n/**\n * Write config.json atomically (tmp + rename) so a concurrent\n * `agentproto config edit` can't half-truncate the file. Writes\n * `next` AS-IS — callers are expected to pass the full desired\n * state (loaded the existing config, mutated, passed it back).\n *\n * Earlier versions deep-merged with the on-disk file, but that made\n * deletions impossible: `setConfigKey(cfg, \"x\", undefined)` would\n * remove the key from memory, then the deep-merge would silently\n * re-add it from disk. The current design trusts the caller's\n * snapshot and uses atomic rename for crash safety.\n */\nexport async function saveConfig(\n  next: AgentprotoConfig,\n  path?: string,\n): Promise<void> {\n  const target = path ?? CONFIG_FILE_PATH()\n  const payload = { ...next, version: CONFIG_VERSION }\n  const dir = dirname(target)\n  await fs.mkdir(dir, { recursive: true })\n  const tmp = `${target}.tmp`\n  await fs.writeFile(tmp, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\")\n  await fs.rename(tmp, target)\n}\n\n/**\n * Read a dot-notation key (`daemon.port`) out of a config. Returns\n * `undefined` when any segment is missing.\n */\nexport function getConfigKey(\n  cfg: AgentprotoConfig,\n  dotted: string,\n): unknown {\n  let cur: unknown = cfg\n  for (const part of dotted.split(\".\")) {\n    if (cur == null || typeof cur !== \"object\") return undefined\n    cur = (cur as Record<string, unknown>)[part]\n  }\n  return cur\n}\n\n/**\n * Set a dot-notation key in a config. Returns a new object — does\n * NOT mutate. Creates intermediate objects as needed. Setting\n * `value: undefined` is treated as a delete.\n */\nexport function setConfigKey(\n  cfg: AgentprotoConfig,\n  dotted: string,\n  value: unknown,\n): AgentprotoConfig {\n  const parts = dotted.split(\".\")\n  const out: AgentprotoConfig = { ...cfg }\n  let cur: Record<string, unknown> = out as Record<string, unknown>\n  for (let i = 0; i < parts.length - 1; i++) {\n    const k = parts[i]!\n    const next = cur[k]\n    if (next && typeof next === \"object\" && !Array.isArray(next)) {\n      cur[k] = { ...(next as Record<string, unknown>) }\n    } else {\n      cur[k] = {}\n    }\n    cur = cur[k] as Record<string, unknown>\n  }\n  const leaf = parts[parts.length - 1]!\n  if (value === undefined) {\n    delete cur[leaf]\n  } else {\n    cur[leaf] = value\n  }\n  return out\n}\n\n/**\n * Deep merge — objects are recursively combined, everything else\n * (arrays, primitives) is replaced wholesale by `b`. Mirrors what\n * `Object.assign({}, a, b)` does for shallow keys.\n */\nfunction deepMerge<A extends Record<string, unknown>, B extends Record<string, unknown>>(\n  a: A,\n  b: B,\n): A & B {\n  const out: Record<string, unknown> = { ...a }\n  for (const [k, v] of Object.entries(b)) {\n    const cur = out[k]\n    if (\n      v &&\n      typeof v === \"object\" &&\n      !Array.isArray(v) &&\n      cur &&\n      typeof cur === \"object\" &&\n      !Array.isArray(cur)\n    ) {\n      out[k] = deepMerge(\n        cur as Record<string, unknown>,\n        v as Record<string, unknown>,\n      )\n    } else {\n      out[k] = v\n    }\n  }\n  return out as A & B\n}\n","/**\n * Re-exports `@agentproto/providers-store` unchanged. Moved out of `runtime`\n * so a standalone process (e.g. `@agentproto/llm-endpoint`, which has zero\n * runtime deps) can read the provider-key store without depending on the\n * whole daemon. Kept as a same-named module (rather than deleting it) so the\n * `@agentproto/runtime/providers-store` subpath and every existing relative\n * `./providers-store.js` import in this package keep working.\n */\nexport * from \"@agentproto/providers-store\"\n","/**\n * Pure resolver for `~/.agentproto/config.json`'s `defaults` block —\n * computes the effective `skills` + `options` + `auth` for an `agent_start`\n * spawn before adapter-specific normalization. No fs, no adapter I/O, so\n * it's unit-testable in isolation from `session-spawn.ts` (which owns the\n * fs read + the adapter-manifest lookup).\n *\n * Precedence (lowest → highest): global `defaults` < `defaults.adapters.\n * <slug>` < the explicit `agent_start` call.\n *   - `options`: shallow-merged maps, later (higher-precedence) keys win.\n *   - `skills`: global ∪ per-adapter when the caller didn't pass `skills`\n *     at all; an explicit `skills` (even `[]`) REPLACES the union rather\n *     than merging into it — a deliberate exact set, mirroring how an\n *     explicit `mcpServers: []` opts out of the hermes default in\n *     `session-spawn.ts`.\n *   - `auth`: surfaces the RAW billing-auth material (requested mode, both\n *     candidate credentials, per-spawn provider pin, and the `explicit`\n *     signal) so the descriptor-aware resolver ({@link resolveAuthSpec},\n *     which also needs the adapter's provider/subscription descriptor +\n *     providers.json) can decide the final mode, env var, scrub set, and\n *     credential source. Credentials are named in config or the provider\n *     store — never read from the ambient shell env.\n */\n\nimport { getModelProvider } from \"@agentproto/model-catalog/llm\"\nimport type { CatalogProvider } from \"@agentproto/model-catalog\"\nimport { providerEnvVar } from \"./providers-store.js\"\n\n/**\n * Deterministic billing-auth config for one adapter slug (today, only\n * claude-code interprets it — see `AgentCliStartOptions.auth` in\n * `@agentproto/driver-agent-cli`). EXPLICIT credential selection, not\n * scrub-by-absence: `token`/`apiKey` are the actual secret values, named\n * here (or supplied per-spawn) rather than inherited from the launching\n * shell. Never logged; only a fingerprint (see {@link credentialFingerprint})\n * is ever surfaced back to a caller.\n */\nexport interface DefaultsAdapterAuthConfig {\n  /** `\"subscription\"` or `\"api-key\"`. Omitted ⇒ the resolver picks by\n   *  ordered preference (subscription first for adapters that support it —\n   *  see {@link resolveAuthSpec}), never a hardcoded default. */\n  mode?: \"subscription\" | \"api-key\"\n  /** The subscription bearer token for `\"subscription\"` mode — minted via\n   *  `claude setup-token` (bills the Max/Pro subscription, not API credits),\n   *  SET to the adapter's `authSubscription.setEnv`. */\n  token?: string\n  /** Explicit API key for `\"api-key\"` mode, SET to `providerEnvVar(provider)`.\n   *  Wins over the `providers.json` store key for the same provider. */\n  apiKey?: string\n  /** Per-spawn provider PIN — overrides the adapter's fixed provider and the\n   *  model-derived provider (the sharp edge for by-model routers whose config\n   *  routes a catalog-\"anthropic\" model elsewhere). A `CatalogProvider` id. */\n  provider?: CatalogProvider\n}\n\nexport interface DefaultsAdapterConfig {\n  skills?: string[]\n  options?: Record<string, boolean | number | string>\n  auth?: DefaultsAdapterAuthConfig\n}\n\n/** Shape of `config.json`'s top-level `defaults` block. */\nexport interface SpawnDefaultsConfig {\n  skills?: string[]\n  options?: Record<string, boolean | number | string>\n  adapters?: Record<string, DefaultsAdapterConfig>\n  /** Depth cutoff for the role-derived default (see `resolveRole` in\n   *  `role.ts`) applied when an `agent_start` call omits `role`:\n   *  `depth < cutoff` → supervisor, `depth >= cutoff` → executor.\n   *  Default 1 (root spawns keep today's unrestricted behaviour; any\n   *  spawn made THROUGH an orchestrator defaults to executor). Tune\n   *  this up (e.g. to a large number) to restore the old permissive\n   *  behaviour for existing deep spawns wholesale. */\n  defaultRoleDepthCutoff?: number\n  /** Trust-boundary cap on pack-carried roles (see `role-registry.ts`'s\n   *  `loadRoleRegistry`): a role pack whose `toolPolicy.delegation` is\n   *  `\"allow\"` at a level ABOVE this cap has it forced to `\"deny\"` —\n   *  the pack can still declare the intent, the daemon just refuses to\n   *  grant it. Lets an operator install third-party role packs without\n   *  trusting every one of them to self-grant delegation. Undefined\n   *  (default) ⇒ no cap, any pack-declared level may carry\n   *  `delegation: \"allow\"` (back-compat: #214 had no such knob). */\n  maxGrantableDelegation?: number\n  /** Default per-session Langfuse tracing opt-in when an `agent_start` call\n   *  omits `trace`. Default false — sessions trace only when they opt in or\n   *  this is on. See `filterSessionObserver` / `SpawnAgentInput.trace`. */\n  langfuseTracing?: boolean\n  /** Redactor slug applied to traced session content before it's sent to\n   *  Langfuse (see `@agentproto/redaction`'s registry). Default \"secrets\"\n   *  (deny-list by key + value-scan for secret shapes). */\n  traceRedactor?: string\n}\n\nexport interface ResolveSpawnDefaultsInput {\n  /** Explicit-call `skills`. Undefined ⇒ caller expressed no preference,\n   *  fall through to the config union. Provided ⇒ replaces it outright. */\n  skills?: string[]\n  /** Explicit-call AIP-45 `options` map — wins per-key over both the\n   *  global and per-adapter config defaults. */\n  options?: Record<string, boolean | number | string>\n  /** Explicit-call `agent_start.auth` override. `mode` wins over\n   *  `defaults.adapters.<slug>.auth.mode`; the credential field matching the\n   *  RESOLVED mode wins over the matching config field. Undefined ⇒ falls\n   *  through entirely to the per-adapter config default. */\n  auth?: DefaultsAdapterAuthConfig\n}\n\nexport interface ResolvedSpawnDefaults {\n  skills: string[]\n  options: Record<string, boolean | number | string>\n  /** RAW billing-auth material (config precedence applied) — fed to the\n   *  descriptor-aware {@link resolveAuthSpec}, which owns the final mode /\n   *  env / scrub / credential-source decision. Both candidate credentials\n   *  are surfaced (NOT collapsed to one), since the ordered-mode selection\n   *  needs to know which are available before it picks the mode. */\n  auth: ResolvedSpawnAuthMaterial\n}\n\nexport interface ResolvedSpawnAuthMaterial {\n  /** Operator-requested mode (per-spawn > per-adapter config), or undefined\n   *  ⇒ let the resolver pick by ordered preference. */\n  requestedMode?: \"subscription\" | \"api-key\"\n  /** True when the operator explicitly configured `auth` (per-spawn OR in\n   *  `defaults.adapters.<slug>.auth`). The ONLY way to tell \"set mode, no\n   *  key\" (fail-fast) from \"set nothing\" (ambient) — both give no credential.\n   *  DECISION 5. */\n  explicit: boolean\n  /** Subscription bearer token (per-spawn > config), if configured. */\n  subscriptionCredential?: string\n  /** Explicit API key (per-spawn > config), if configured — distinct from the\n   *  providers.json store key the resolver fetches separately. */\n  apiKeyCredential?: string\n  /** Per-spawn provider pin, if given. */\n  provider?: CatalogProvider\n}\n\nexport function resolveSpawnDefaults(\n  defaults: SpawnDefaultsConfig | undefined,\n  adapterSlug: string,\n  input: ResolveSpawnDefaultsInput,\n): ResolvedSpawnDefaults {\n  const adapterDefaults = defaults?.adapters?.[adapterSlug]\n\n  const options: Record<string, boolean | number | string> = {\n    ...defaults?.options,\n    ...adapterDefaults?.options,\n    ...input.options,\n  }\n\n  const skills =\n    input.skills !== undefined\n      ? input.skills\n      : Array.from(\n          new Set([...(defaults?.skills ?? []), ...(adapterDefaults?.skills ?? [])]),\n        )\n\n  const requestedMode = input.auth?.mode ?? adapterDefaults?.auth?.mode\n  const explicit = input.auth !== undefined || adapterDefaults?.auth !== undefined\n  const subscriptionCredential = input.auth?.token ?? adapterDefaults?.auth?.token\n  const apiKeyCredential = input.auth?.apiKey ?? adapterDefaults?.auth?.apiKey\n  const authProvider = input.auth?.provider ?? adapterDefaults?.auth?.provider\n\n  return {\n    skills,\n    options,\n    auth: {\n      explicit,\n      ...(requestedMode ? { requestedMode } : {}),\n      ...(subscriptionCredential !== undefined ? { subscriptionCredential } : {}),\n      ...(apiKeyCredential !== undefined ? { apiKeyCredential } : {}),\n      ...(authProvider ? { provider: authProvider } : {}),\n    },\n  }\n}\n\n/**\n * Public credential key-shape prefixes, longest / most-specific first (the\n * match is first-hit, so `sk-ant-oat` must precede `sk-ant-api`/`sk-ant-`,\n * `sk-or-v1-` precede `sk-or-`, and both precede the bare `sk-`). These are\n * PUBLIC key-shape knowledge — the visible leading bytes of each provider's\n * credential format — never secret; only these + the last 4 chars are ever\n * revealed. DECISION 6: the fingerprint is derived from the credential's own\n * shape, NOT from `mode`, so it stays honest across providers (a gateway\n * `sk-or-…` key run in api-key mode reads as `api-key · sk-or-…`).\n */\nconst CREDENTIAL_FINGERPRINT_PREFIXES: readonly string[] = [\n  \"sk-ant-oat\",\n  \"sk-ant-api\",\n  \"sk-ant-\",\n  \"sk-or-v1-\",\n  \"sk-or-\",\n  \"sk-proj-\",\n  \"sk-\",\n  \"gsk_\",\n  \"AIza\",\n]\n\n/**\n * Derive a SAFE, non-secret fingerprint for a resolved auth credential —\n * NEVER the raw value — for recording on the session descriptor / surfacing\n * in `agentproto sessions --watch` and `agent_sessions_list` (the\n * \"verifiability\" requirement: answer \"what was used\" without exposing the\n * secret). Format: `<mode> · <shape-prefix>…<last4>` when the shape is known\n * (e.g. `subscription · sk-ant-oat…3f9c`), else `<mode> · …<last4>`.\n *\n * The shape marker is matched from a PUBLIC key-prefix table (longest-match),\n * not derived from `mode` — see {@link CREDENTIAL_FINGERPRINT_PREFIXES}. Only\n * the matched prefix + the last 4 characters are ever surfaced, never the\n * middle (mirrors GitHub's `ghp_…abcd` style).\n */\nexport function credentialFingerprint(\n  mode: \"subscription\" | \"api-key\",\n  credential: string,\n): string {\n  const prefix = CREDENTIAL_FINGERPRINT_PREFIXES.find(p => credential.startsWith(p))\n  const last4 = credential.slice(-4)\n  return prefix ? `${mode} · ${prefix}…${last4}` : `${mode} · …${last4}`\n}\n\n/**\n * The adapter's billing-auth capability, projected from its AIP-45 manifest\n * (`provider` / `authEnforce` / `authSubscription`) by the host resolver. The\n * runtime reads THIS, never the manifest directly — keeping the LLM-catalog\n * coupling in the runtime and the driver mechanical.\n */\nexport interface AdapterAuthDescriptor {\n  /** FIXED provider for a single-provider adapter; omitted for by-model\n   *  routers (provider then derives from the requested model). */\n  provider?: CatalogProvider\n  /** Enforcement policy — `\"always\"` engages every spawn (claude-code's\n   *  #312 fail-fast); `\"when-configured\"` (default) only when `explicit`. */\n  authEnforce?: \"always\" | \"when-configured\"\n  /** Subscription (OAuth/bearer) support. Presence ⇒ the adapter supports\n   *  `\"subscription\"` mode. Mirrors the driver's `AgentCliAuthSubscription`. */\n  authSubscription?: {\n    setEnv: string\n    conflictEnv?: string[]\n    unsetEnvAdd?: string[]\n  }\n}\n\n/** The fully-resolved spec the driver applies mechanically. Structurally\n *  matches `@agentproto/driver-agent-cli`'s `ResolvedAuthSpec` (each package\n *  owns its own copy; the object flows across the boundary by shape). */\nexport interface ResolvedAuthSpec {\n  mode: \"subscription\" | \"api-key\"\n  credential?: string\n  setEnv: string\n  unsetEnv: string[]\n  explicit: boolean\n  enforce: \"always\" | \"when-configured\"\n}\n\n/** Where the resolved credential came from — the observable billing axis\n *  (DECISION 10②), never inferred. */\nexport type CredentialSource = \"explicit-config\" | \"providers-store\" | \"none\"\n\n/**\n * The OBSERVABLE echo (DECISION 9③ / 10②) — recorded on the session\n * descriptor so a verifier checks the RESOLUTION, never the model's\n * self-report. Never carries the raw credential (only its fingerprint).\n */\nexport interface AuthEcho {\n  provider: CatalogProvider\n  authMode: \"subscription\" | \"api-key\"\n  credentialSource: CredentialSource\n  setEnv: string\n  fingerprint?: string\n}\n\n/**\n * Thrown when the operator requested a billing mode the adapter can't serve —\n * today only `\"subscription\"` on an adapter with no `authSubscription`. A\n * LOUD, distinct failure (DECISION 4②), never a silent downgrade to api-key.\n */\nexport class AuthResolutionError extends Error {\n  readonly code = \"unsupported_auth_mode\"\n  constructor(message: string) {\n    super(message)\n    this.name = \"AuthResolutionError\"\n  }\n}\n\nexport interface ResolveAuthSpecInput {\n  descriptor: AdapterAuthDescriptor\n  /** `input.model ?? adapter default model` — for model-derived provider. */\n  model?: string\n  /** Per-spawn provider pin (`input.auth.provider`). */\n  requestedProvider?: CatalogProvider\n  /** Operator-requested mode; undefined ⇒ ordered preference. */\n  requestedMode?: \"subscription\" | \"api-key\"\n  /** Operator explicitly configured `auth` (DECISION 5). */\n  explicit: boolean\n  /** Subscription bearer credential, if configured. */\n  subscriptionCredential?: string\n  /** Explicit api-key credential from config, if configured. */\n  apiKeyConfigCredential?: string\n  /** api-key credential from `providers.json` (fetched by the caller). */\n  apiKeyStoreCredential?: string\n}\n\n/**\n * THE billing-auth resolver (DECISIONS 4, 6, 9, 10). Pure: given the adapter\n * descriptor + raw config material + (caller-fetched) store key, it decides\n * the provider, the mode (ordered — subscription over api-key when a\n * subscription credential is present; a requested-but-unsupported mode throws\n * `unsupported_auth_mode`), the env var to SET, the derived SCRUB set, and the\n * credential + its source. Returns the driver `spec` + the observable `echo`,\n * or `undefined` when no provider resolves (⇒ ambient, no injection — never\n * guess). NEVER falls back to a default provider/model. Fail-loud on a\n * configured-but-missing credential is deferred to the driver's mechanical\n * apply (it engages then throws `missing_auth_credential`), so the `explicit`\n * / `enforce` signals are carried through on the spec.\n */\nexport function resolveAuthSpec(\n  input: ResolveAuthSpecInput,\n): { spec: ResolvedAuthSpec; echo: AuthEcho } | undefined {\n  // 1. Provider: per-spawn pin → adapter-fixed → model-derived. None ⇒\n  //    ambient (no injection); an unknown/free-form model id lands here too.\n  const provider =\n    input.requestedProvider ??\n    input.descriptor.provider ??\n    (input.model ? getModelProvider(input.model) : undefined)\n  if (!provider) return undefined\n\n  const sub = input.descriptor.authSubscription\n  const supportsSub = sub !== undefined\n  const enforce = input.descriptor.authEnforce ?? \"when-configured\"\n  const apiKeyEnv = providerEnvVar(provider)\n\n  const subCredAvailable = input.subscriptionCredential !== undefined\n  const apiCredAvailable =\n    input.apiKeyConfigCredential !== undefined || input.apiKeyStoreCredential !== undefined\n\n  // 2/3. Mode: explicit request (validated) OR ordered preference (DECISION\n  //      10 — subscription first when supported; never silently pick api-key\n  //      while a subscription credential is present and preferred).\n  let mode: \"subscription\" | \"api-key\"\n  if (input.requestedMode) {\n    if (input.requestedMode === \"subscription\" && !supportsSub) {\n      throw new AuthResolutionError(\n        `auth mode \"subscription\" is not supported for provider \"${provider}\" ` +\n          `(this adapter declares no authSubscription) — use api-key instead.`,\n      )\n    }\n    mode = input.requestedMode\n  } else {\n    const preference: Array<\"subscription\" | \"api-key\"> = supportsSub\n      ? [\"subscription\", \"api-key\"]\n      : [\"api-key\"]\n    mode =\n      preference.find(m => (m === \"subscription\" ? subCredAvailable : apiCredAvailable)) ??\n      preference[0]!\n  }\n\n  // 4/5. setEnv + credential + source for the resolved mode.\n  let setEnv: string\n  let credential: string | undefined\n  let credentialSource: CredentialSource\n  if (mode === \"subscription\") {\n    // Guaranteed present: the explicit path validated supportsSub, and the\n    // ordered path only yields \"subscription\" when supportsSub.\n    setEnv = sub!.setEnv\n    credential = input.subscriptionCredential\n    credentialSource = credential !== undefined ? \"explicit-config\" : \"none\"\n  } else {\n    setEnv = apiKeyEnv\n    if (input.apiKeyConfigCredential !== undefined) {\n      credential = input.apiKeyConfigCredential\n      credentialSource = \"explicit-config\"\n    } else if (input.apiKeyStoreCredential !== undefined) {\n      credential = input.apiKeyStoreCredential\n      credentialSource = \"providers-store\"\n    } else {\n      credential = undefined\n      credentialSource = \"none\"\n    }\n  }\n\n  // 4. Derived scrub: every conflicting billing-credential var EXCEPT the one\n  //    being set, plus (native/subscription mode only) the adapter's gateway\n  //    hygiene. Single-credential provider (no authSubscription) → empty scrub\n  //    (the setEnv overwrite already prevents a leak).\n  const credVars = new Set<string>([apiKeyEnv])\n  if (sub) {\n    credVars.add(sub.setEnv)\n    for (const c of sub.conflictEnv ?? []) credVars.add(c)\n  }\n  credVars.delete(setEnv)\n  const unsetEnv = [...credVars]\n  if (mode === \"subscription\" && sub?.unsetEnvAdd) unsetEnv.push(...sub.unsetEnvAdd)\n\n  const spec: ResolvedAuthSpec = {\n    mode,\n    ...(credential !== undefined ? { credential } : {}),\n    setEnv,\n    unsetEnv,\n    explicit: input.explicit,\n    enforce,\n  }\n  const echo: AuthEcho = {\n    provider,\n    authMode: mode,\n    credentialSource,\n    setEnv,\n    ...(credential !== undefined\n      ? { fingerprint: credentialFingerprint(mode, credential) }\n      : {}),\n  }\n  return { spec, echo }\n}\n\n/** Manifest-declared AIP-45 option id + type, the minimum an adapter\n *  resolver needs to expose for `normalizeSkillsOption` below. Mirrors\n *  `AgentCliOption`'s `id`/`type` fields without importing\n *  `@agentproto/driver-agent-cli` into the runtime package. */\nexport interface DeclaredAdapterOption {\n  id: string\n  type: \"boolean\" | \"integer\" | \"string\" | \"enum\"\n}\n\n/**\n * Fold the resolved `skills` list into `options.skills` using whatever\n * shape the adapter's manifest declares for that option id (today, only\n * `type: \"string\"` exists for a skills-shaped option — e.g. hermes'\n * comma-joined `--skills a,b`). Adapters with no declared `skills` option\n * (e.g. claude-code, which auto-discovers from `~/.claude/skills`) are a\n * documented no-op — the effective skills list has nowhere to go, so it's\n * dropped rather than guessing a flag the manifest didn't declare.\n *\n * An `options.skills` already present (from config defaults or the\n * explicit call) is respected as-is and never overwritten here.\n */\nexport function normalizeSkillsOption(\n  skills: string[],\n  options: Record<string, boolean | number | string>,\n  declaredOptions: readonly DeclaredAdapterOption[] | undefined,\n): Record<string, boolean | number | string> {\n  if (skills.length === 0 || \"skills\" in options) return options\n  const skillsOption = declaredOptions?.find(o => o.id === \"skills\")\n  if (!skillsOption || skillsOption.type !== \"string\") return options\n  return { ...options, skills: skills.join(\",\") }\n}\n","/**\n * Spawn-time role profiles — the primitive that decides whether a\n * spawned agent may itself delegate (spawn further children).\n *\n * A role is 3 layers:\n *   - `disposition`  — a system-prompt fragment. Soft: sets the mindset.\n *   - `toolPolicy`   — whether delegation tools are injected into the\n *     child at all. HARD: enforced by the daemon at the `agent_start`\n *     injection point (`session-spawn.ts`), not by the child's own\n *     behaviour. A child cannot widen its own `toolPolicy` — not via\n *     `promptAppend`, not by requesting `orchestrator` itself.\n *   - `skills[]`     — role-specific skill set (built-ins ship empty/\n *     unset; a future pack-carried role can populate this).\n *\n * Why the asymmetry matters: a process can bring its own disposition\n * and skills (those are portable, could live in a skill/pack), but it\n * can never strip tools the daemon already injected into it. Only the\n * spawner controls that — which is exactly why `toolPolicy` must be\n * resolved and enforced here, at spawn time, rather than left to a\n * prompt instruction the model could rationalize past.\n */\n\nexport type DelegationPolicy = \"allow\" | \"deny\"\n\nexport interface RoleToolPolicy {\n  delegation: DelegationPolicy\n}\n\nexport interface RoleProfile {\n  name: string\n  disposition: string\n  toolPolicy: RoleToolPolicy\n  skills?: string[]\n  /**\n   * Privilege level in the spawn lattice. Higher = more privileged.\n   * The default spawn-gate rule (`canSpawn`) is non-escalation: a\n   * parent may spawn a child only when `child.level <= parent.level`\n   * — peers and subordinates are fine, spawning something MORE\n   * privileged than yourself is not. (Unbounded same-level recursion —\n   * e.g. supervisor spawning supervisor spawning supervisor — is a\n   * pre-existing, deliberate pattern bounded separately by\n   * `maxDepth`/`maxChildren`, not this lattice; see `spawnableRoles`\n   * below for a role that also needs to cap recursion itself.)\n   * `spawnableRoles` (below), when set, opts a role into a closed\n   * allowlist instead — level is then only used for display/ordering.\n   */\n  level: number\n  /**\n   * Closed allowlist of role names this role may spawn, by name — the\n   * opt-in \"figé pipeline\" mode. When set, `canSpawn` checks name\n   * membership instead of the level comparison. Undefined (the\n   * default, open mode) ⇒ non-escalation by `level`.\n   */\n  spawnableRoles?: string[]\n}\n\n/**\n * MCP tool names that let a child spawn or drive further children.\n * This is the minimum \"delegation surface\" gated by `toolPolicy.\n * delegation`: `agent_start` (spawn) and `agent_prompt` (drive an\n * already-spawned child). Any future Task/subagent-spawn tool belongs\n * in this list too.\n */\nexport const DELEGATION_TOOL_NAMES: readonly string[] = [\n  \"agent_start\",\n  \"agent_prompt\",\n]\n\nexport const EXECUTOR_ROLE: RoleProfile = {\n  name: \"executor\",\n  disposition:\n    \"You are the leaf. You execute the task yourself — you do not spawn \" +\n    \"or delegate to another agent, even if it seems convenient or the \" +\n    \"task looks complex. Do the work directly with the tools you have. \" +\n    \"This includes any subagent/Task tool your own CLI ships natively — \" +\n    \"it is not routed through agentproto and the daemon cannot strip it, \" +\n    \"so the rule holds regardless of what tools appear available to you.\",\n  toolPolicy: { delegation: \"deny\" },\n  skills: [],\n  // The floor of the lattice — in practice spawns nothing, since\n  // `toolPolicy.delegation: \"deny\"` already strips `agent_start` before\n  // the level comparison is ever reached. NOTE: that strip only covers\n  // the daemon's own MCP gateway (agent_start/agent_prompt) — a native\n  // subagent/Task tool bundled with the CLI itself (e.g. claude-code's\n  // Task tool) isn't an MCP tool and can't be gated here at all, which\n  // is why the disposition above spells it out explicitly.\n  level: 0,\n}\n\nexport const SUPERVISOR_ROLE: RoleProfile = {\n  name: \"supervisor\",\n  disposition:\n    \"You decompose, delegate, and verify. Prefer doing small work inline; \" +\n    \"delegate the parts that genuinely benefit from a separate agent, and \" +\n    \"check their output before relying on it. Delegate via agent_start, \" +\n    \"not your own CLI's native subagent/Task tool — a native subagent is \" +\n    \"invisible to the daemon (no session id, no tracking, no kill switch, \" +\n    \"nobody watching it but you), whereas agent_start gives the caller a \" +\n    \"session they can actually observe and supervise.\",\n  toolPolicy: { delegation: \"allow\" },\n  level: 100,\n}\n\nconst BUILTIN_ROLES: Readonly<Record<string, RoleProfile>> = {\n  [EXECUTOR_ROLE.name]: EXECUTOR_ROLE,\n  [SUPERVISOR_ROLE.name]: SUPERVISOR_ROLE,\n}\n\n/**\n * Merge a custom (pack-carried) registry with the two built-ins.\n * Built-ins ALWAYS win a name collision — a pack cannot shadow\n * `executor`/`supervisor` and can't widen the floor it's built on.\n * The single place this rule lives; every consumer below\n * (`resolveRole`, `listRoles`, `spawnableRolesFor`) merges through\n * this function so they can never disagree about a name.\n */\nexport function mergeRoleRegistry(\n  custom?: Readonly<Record<string, RoleProfile>>,\n): Record<string, RoleProfile> {\n  return { ...custom, ...BUILTIN_ROLES }\n}\n\n/**\n * Depth cutoff separating the depth-derived defaults when a spawn\n * passes no explicit `role`: `depth < cutoff` → supervisor, `depth >=\n * cutoff` → executor. Overridable via config.json's\n * `defaults.defaultRoleDepthCutoff` (see `SpawnDefaultsConfig`).\n */\nexport const DEFAULT_ROLE_DEPTH_CUTOFF = 1\n\n/**\n * Resolve a role by name, or — when `name` is omitted — derive one\n * from spawn depth against `cutoff`. Pure; no fs, no adapter I/O.\n *\n * `registry`, when given, is a custom (pack-carried) registry merged\n * with the two built-ins (built-ins win — see `mergeRoleRegistry`).\n * Omitted ⇒ built-ins only, byte-identical to #214.\n *\n * @throws when `name` is given but unrecognized (a caller typo should\n * fail loudly rather than silently fall back to a default role).\n */\nexport function resolveRole(\n  name: string | undefined,\n  depth: number,\n  cutoff: number = DEFAULT_ROLE_DEPTH_CUTOFF,\n  registry?: Readonly<Record<string, RoleProfile>>,\n): RoleProfile {\n  if (name !== undefined) {\n    const roles = registry ? mergeRoleRegistry(registry) : BUILTIN_ROLES\n    const role = roles[name]\n    if (!role) {\n      const known = Object.keys(roles).join(\", \")\n      throw new Error(`resolveRole: unknown role \"${name}\" — expected one of: ${known}.`)\n    }\n    return role\n  }\n  return depth < cutoff ? SUPERVISOR_ROLE : EXECUTOR_ROLE\n}\n\n/**\n * List every role in the merged registry (built-ins + `registry`).\n * Pure; no fs. Omit `registry` for built-ins only.\n */\nexport function listRoles(\n  registry?: Readonly<Record<string, RoleProfile>>,\n): RoleProfile[] {\n  return Object.values(mergeRoleRegistry(registry))\n}\n\n/**\n * THE single source of truth for whether `parent` may spawn `child` —\n * shared by the hard spawn gate (`session-spawn.ts`) and every\n * introspection surface (`spawnableRolesFor`, `role_list`, the \"Roles\n * you may spawn\" context line) so they can never disagree.\n *\n * A role whose OWN `toolPolicy.delegation` is `\"deny\"` can spawn\n * NOTHING, full stop — the lattice below is moot once the tools\n * themselves are stripped (this is what makes `EXECUTOR_ROLE`, in\n * practice, unable to spawn even a peer at its own floor level, and\n * what makes `composeRoleContext`/`role_list` correctly show an empty\n * spawnable set for it).\n *\n * When delegation is allowed, `parent.spawnableRoles`, if set, is a\n * closed allowlist checked by name. Otherwise (the default, open mode)\n * it's non-escalation: `child.level <= parent.level` — a role may\n * spawn a peer or a subordinate, never something more privileged than\n * itself. (Unbounded same-level recursion is a pre-existing, deliberate\n * pattern bounded separately by `maxDepth`/`maxChildren`, not this\n * lattice.)\n */\nexport function canSpawn(parent: RoleProfile, child: RoleProfile): boolean {\n  if (parent.toolPolicy.delegation === \"deny\") return false\n  if (parent.spawnableRoles) return parent.spawnableRoles.includes(child.name)\n  return child.level <= parent.level\n}\n\n/** Every role in the merged registry that `parent` may spawn, per\n *  `canSpawn`. Pure; no fs. */\nexport function spawnableRolesFor(\n  parent: RoleProfile,\n  registry?: Readonly<Record<string, RoleProfile>>,\n): RoleProfile[] {\n  return listRoles(registry).filter(child => canSpawn(parent, child))\n}\n\n/**\n * Compose the child's effective system-context text:\n *   disposition + (optional) \"Roles you may spawn: …\" line + (optional)\n *   promptAppend — in that order. `promptAppend` layers ON TOP of the\n *   disposition — it specializes, it can never replace it (and,\n *   independently, it can never re-open the tool gate `toolPolicy`\n *   enforces — see `DELEGATION_TOOL_NAMES` gating in\n *   `session-spawn.ts`).\n *\n * The spawn-line lets a delegating role KNOW its options at runtime\n * instead of guessing — omitted entirely when `spawnableRolesFor`\n * returns empty (a leaf/executor sees nothing extra).\n */\nexport function composeRoleContext(\n  role: RoleProfile,\n  promptAppend?: string,\n  registry?: Readonly<Record<string, RoleProfile>>,\n): string {\n  const spawnable = spawnableRolesFor(role, registry)\n  const spawnLine =\n    spawnable.length > 0\n      ? `Roles you may spawn: ${spawnable.map(r => r.name).join(\", \")}.`\n      : undefined\n  return [role.disposition, spawnLine, promptAppend].filter((p): p is string => !!p).join(\"\\n\\n\")\n}\n","/**\n * Pack-carried role definitions — parses a `ROLE.md` file (frontmatter +\n * markdown body) into a `RoleProfile`. Pure: takes a string, returns a\n * value or throws. No fs here — see `role-registry.ts` for the on-disk /\n * adapter-package discovery that hands this function raw file contents.\n *\n * Frontmatter is a flat `key: value` block between `---` fences, the same\n * trivial format `conversations.ts`'s `parseFrontmatter` uses (no yaml\n * dep) extended with dotted keys (`toolPolicy.delegation`) and\n * comma-separated list values (`skills: a, b, c`). The body (everything\n * after the closing fence) becomes `disposition` verbatim.\n */\n\nimport type { DelegationPolicy, RoleProfile } from \"./role.js\"\n\nconst FRONTMATTER_RE = /^---\\n([\\s\\S]*?)\\n---\\n?/\n\nfunction parseFields(raw: string): Record<string, string> {\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    if (!key) continue\n    out[key] = value\n  }\n  return out\n}\n\nfunction isDelegationPolicy(value: string | undefined): value is DelegationPolicy {\n  return value === \"allow\" || value === \"deny\"\n}\n\nfunction parseList(value: string | undefined): string[] | undefined {\n  if (value === undefined || value === \"\") return undefined\n  const stripped = value.replace(/^\\[/, \"\").replace(/\\]$/, \"\")\n  const items = stripped\n    .split(\",\")\n    .map(s => s.trim())\n    .filter(Boolean)\n  return items.length > 0 ? items : undefined\n}\n\n/**\n * Parse a `ROLE.md` document into a `RoleProfile`.\n *\n * @throws when the frontmatter fence is missing, `role` (the name) is\n * absent, `level` is missing/not a finite number, or\n * `toolPolicy.delegation` is missing/not `\"allow\"`/`\"deny\"` — a\n * malformed pack must fail loudly rather than silently install a\n * half-specified role.\n */\nexport function parseRolePack(md: string): RoleProfile {\n  const match = md.match(FRONTMATTER_RE)\n  if (!match) {\n    throw new Error(\n      \"parseRolePack: missing frontmatter — expected a '---' fenced header at the top of ROLE.md\",\n    )\n  }\n  const fields = parseFields(match[1] ?? \"\")\n  const disposition = md.slice(match[0].length).trim()\n\n  const name = fields.role\n  if (!name) {\n    throw new Error(\"parseRolePack: missing 'role' field in frontmatter\")\n  }\n\n  const level = fields.level !== undefined ? Number(fields.level) : NaN\n  if (!Number.isFinite(level)) {\n    throw new Error(\n      `parseRolePack: missing or invalid 'level' field for role \"${name}\" (expected a number)`,\n    )\n  }\n\n  const delegation = fields[\"toolPolicy.delegation\"]\n  if (!isDelegationPolicy(delegation)) {\n    throw new Error(\n      `parseRolePack: missing or invalid 'toolPolicy.delegation' field for role \"${name}\" ` +\n        '(expected \"allow\" or \"deny\")',\n    )\n  }\n\n  const skills = parseList(fields.skills)\n  const spawnableRoles = parseList(fields.spawnableRoles)\n\n  const profile: RoleProfile = {\n    name,\n    disposition,\n    toolPolicy: { delegation },\n    level,\n    ...(skills ? { skills } : {}),\n    ...(spawnableRoles ? { spawnableRoles } : {}),\n  }\n  return profile\n}\n","/**\n * On-disk + adapter-carried role pack discovery — the fs half of the\n * role registry (the pure half — merge-with-builtins, resolution,\n * `canSpawn` — lives in `role.ts`).\n *\n * Two discovery paths, mirroring how #212 discovers skill packs\n * (`packages/cli/src/commands/skill-install/pack-resolve.ts`'s\n * `listSkills`: readdir + stat + frontmatter parse) and how the tunnel\n * family discovers third-party providers\n * (`remote-providers/registry.ts`'s `discoverTunnelHandles`: dynamic\n * `import()` + duck-typed export lookup) — reusing both established\n * patterns rather than inventing a third:\n *\n *   - standalone: `<dir>/roles/<slug>/ROLE.md`, one folder per custom\n *     role, same shape as a skill pack's `skills/<slug>/SKILL.md`.\n *   - adapter-carried: any package `discoverAdapterPackages()` finds\n *     (same `@agentproto/adapter-<slug>` / `@<scope>/agentproto-\n *     adapter-<slug>` convention agent-CLI adapters use) may declare\n *     `metadata.roles: string[]` — raw ROLE.md markdown, one entry per\n *     role. Embedding content directly (rather than a second relative-\n *     path fs lookup into the package's install dir) keeps this half\n *     testable without a real node_modules fixture and avoids a second\n *     package-root resolution step.\n *\n * Partial discovery beats failing the whole registry on one broken\n * pack or adapter declaration — a malformed entry is skipped, not\n * thrown (unlike `parseRolePack` called directly, which throws).\n */\n\nimport { readdir, readFile, stat } from \"node:fs/promises\"\nimport { dirname, join } from \"node:path\"\n\nimport { discoverAdapterPackages } from \"@agentproto/provider-kit\"\n\nimport { CONFIG_FILE_PATH, loadConfig } from \"./config.js\"\nimport { parseRolePack } from \"./role-pack.js\"\nimport type { RoleProfile } from \"./role.js\"\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n  return Array.isArray(value) && value.every(v => typeof v === \"string\")\n}\n\n/**\n * A role pack whose `toolPolicy.delegation` is `\"allow\"` at a level\n * above the operator's cap is forced to `\"deny\"` — the pack can still\n * declare its intent, but the daemon refuses to grant it. Undefined\n * cap ⇒ no restriction (back-compat: #214 had no such knob).\n */\nfunction applyDelegationCap(\n  role: RoleProfile,\n  maxGrantableDelegation: number | undefined,\n): RoleProfile {\n  if (maxGrantableDelegation === undefined) return role\n  if (role.toolPolicy.delegation !== \"allow\") return role\n  if (role.level <= maxGrantableDelegation) return role\n  return { ...role, toolPolicy: { delegation: \"deny\" } }\n}\n\nasync function loadStandaloneRoles(\n  rolesDir: string,\n  out: Record<string, RoleProfile>,\n  maxGrantableDelegation: number | undefined,\n): Promise<void> {\n  let entries: string[]\n  try {\n    entries = await readdir(rolesDir)\n  } catch {\n    return\n  }\n  for (const entry of entries) {\n    const roleDir = join(rolesDir, entry)\n    try {\n      const st = await stat(roleDir)\n      if (!st.isDirectory()) continue\n    } catch {\n      continue\n    }\n    try {\n      const md = await readFile(join(roleDir, \"ROLE.md\"), \"utf8\")\n      const role = applyDelegationCap(parseRolePack(md), maxGrantableDelegation)\n      out[role.name] = role\n    } catch {\n      // Skip role packs whose ROLE.md can't be read/parsed — partial\n      // discovery beats failing the whole registry on one bad pack.\n    }\n  }\n}\n\nexport interface AdapterPackageRef {\n  slug: string\n  packageName: string\n}\n\ninterface LoadAdapterCarriedRolesDeps {\n  discover: () => Promise<readonly AdapterPackageRef[]>\n  importPackage: (specifier: string) => Promise<unknown>\n}\n\nconst slugToCamel = (slug: string): string =>\n  slug.replace(/-([a-z0-9])/g, (_m, c: string) => c.toUpperCase())\n\nasync function loadAdapterCarriedRoles(\n  out: Record<string, RoleProfile>,\n  maxGrantableDelegation: number | undefined,\n  deps: LoadAdapterCarriedRolesDeps,\n): Promise<void> {\n  const packages = await deps.discover()\n  for (const pkg of packages) {\n    let mod: unknown\n    try {\n      mod = await deps.importPackage(pkg.packageName)\n    } catch {\n      continue\n    }\n    if (!isRecord(mod)) continue\n    const camel = slugToCamel(pkg.slug)\n    const candidateRaw = mod[camel] ?? mod.default ?? mod.handle\n    const candidate = isRecord(candidateRaw) ? candidateRaw : undefined\n    const metadata = candidate && isRecord(candidate.metadata) ? candidate.metadata : undefined\n    const roleDocs = metadata?.roles\n    if (!isStringArray(roleDocs)) continue\n    for (const doc of roleDocs) {\n      try {\n        const role = applyDelegationCap(parseRolePack(doc), maxGrantableDelegation)\n        out[role.name] = role\n      } catch {\n        // Skip malformed role declarations — one adapter's bad\n        // metadata must not take down the whole registry.\n      }\n    }\n  }\n}\n\nexport interface LoadRoleRegistryOptions {\n  /** Cap on the level at which a pack may self-grant\n   *  `toolPolicy.delegation: \"allow\"` — see `applyDelegationCap`.\n   *  Undefined (default) ⇒ no cap. */\n  maxGrantableDelegation?: number\n  /** Injectable for tests — defaults to `discoverAdapterPackages` from\n   *  `@agentproto/provider-kit`. */\n  discoverAdapterPackages?: () => Promise<readonly AdapterPackageRef[]>\n  /** Injectable for tests — defaults to real dynamic `import()`. */\n  importPackage?: (specifier: string) => Promise<unknown>\n}\n\n/**\n * Load every custom (non-built-in) role reachable from `dir` — the\n * standalone `<dir>/roles/<slug>/ROLE.md` folders plus any installed\n * adapter package's `metadata.roles`. Returns a plain slug→profile map;\n * it does NOT merge in the two built-ins (`role.ts`'s\n * `mergeRoleRegistry` does that, uniformly, at every consumption site —\n * `resolveRole`, `listRoles`, `spawnableRolesFor` — so a pack can never\n * shadow `executor`/`supervisor` regardless of where the merged result\n * is used).\n */\nexport async function loadRoleRegistry(\n  dir: string,\n  opts?: LoadRoleRegistryOptions,\n): Promise<Record<string, RoleProfile>> {\n  const out: Record<string, RoleProfile> = {}\n  await loadStandaloneRoles(join(dir, \"roles\"), out, opts?.maxGrantableDelegation)\n  await loadAdapterCarriedRoles(out, opts?.maxGrantableDelegation, {\n    discover: opts?.discoverAdapterPackages ?? discoverAdapterPackages,\n    importPackage: opts?.importPackage ?? (specifier => import(specifier)),\n  })\n  return out\n}\n\n/**\n * The production default: `~/.agentproto/roles/` + adapter-carried\n * packs, capped by `config.json`'s `defaults.maxGrantableDelegation`.\n * Callers that need dependency injection (tests, or a host with its\n * own config source) should call `loadRoleRegistry` directly instead.\n */\nexport async function loadDefaultRoleRegistry(): Promise<Record<string, RoleProfile>> {\n  const config = await loadConfig()\n  return loadRoleRegistry(dirname(CONFIG_FILE_PATH()), {\n    maxGrantableDelegation: config.defaults?.maxGrantableDelegation,\n  })\n}\n","/**\n * Dependency-injection surface for MCP credential resolution.\n *\n * `packages/runtime` intentionally does NOT depend on `@agentproto/auth`;\n * the daemon bootstrap (e.g. `packages/cli`) can set a broker-backed\n * resolver here, and `session-spawn.ts` will call it when an `mcpServers`\n * entry carries `credentialRef`. Errors from the hook are treated as\n * non-fatal by the caller.\n */\n\nexport interface McpCredentialDeps {\n  /** Resolve brokered headers for an `mcpServers` entry that names a\n   *  `credentialRef`. The returned headers are merged ON TOP of the\n   *  entry's static `headers` so brokered auth wins on collision. */\n  resolveMcpCredentialHeaders?: (o: {\n    credentialRef: string\n    signal?: AbortSignal\n  }) => Promise<Record<string, string> | undefined>\n  /** Resolve a single named secret (an env-var-shaped slug — e.g. a sandbox\n   *  spec's `env.passthrough` / `env.auth.state.env` entries) to its raw\n   *  value. Distinct from `resolveMcpCredentialHeaders` above (which\n   *  resolves an MCP `credentialRef` PATH into Authorization-style\n   *  headers): this is the `SecretResolver` shape `agent_start`'s sandbox\n   *  branch (`session-spawn.ts`) passes to `@agentproto/sandbox`'s\n   *  `SandboxSecretsConfig.resolver` — so a booted sandbox's env is filled\n   *  from the same host-injected broker as every other secret, never a\n   *  bare `process.env` read at the call site. Returns null when the slug\n   *  can't be resolved (missing/unconfigured). */\n  resolveSandboxSecret?: (slug: string) => Promise<string | null>\n}\n\nlet deps: McpCredentialDeps = {}\n\nexport function setMcpCredentialDeps(d: McpCredentialDeps): void {\n  deps = d\n}\n\nexport function getMcpCredentialDeps(): McpCredentialDeps {\n  return deps\n}\n","/**\n * `AgentSessionLike` proxy over a booted sandbox's OWN agentproto daemon\n * (Option A — see the sandbox-into-agent_start plan). `session-spawn.ts`'s\n * sandbox branch boots the box, calls `host.start()` to run the box's own\n * `agent_start`, and hands the resulting session id here — the registry\n * then treats this proxy exactly like a local adapter's `AgentSessionLike`.\n *\n * `send()` drives the box daemon's session via `agent_prompt` +\n * `session_monitor` + `agent_output`, and flattens the result into the same\n * `AgentStreamEvent` shape the local adapter path yields (text-delta lines\n * plus a terminal turn-end). That shape match is load-bearing: the\n * registry's `runAgentTurn` feeds every yielded event through the SAME\n * transcript-writer + output-ring path it uses for a local session, with no\n * special-casing — so the conversation is captured durably on the HOST\n * side, independent of the (ephemeral) box. `agent_output`/`agent_export`\n * keep working after `agent_kill` / box teardown (amendment: conversation\n * survives sandbox teardown).\n *\n * Known limitation (documented, not fixed here): this flattens the box's\n * structured events into plain text lines — tool-call/usage_update\n * fidelity from the SANDBOXED adapter is lost (usage accounting, tool-call\n * visibility). Follow-up work can subscribe to the box daemon's SSE\n * `/sessions/:id/stream` instead of polling `agent_output`.\n */\n\nimport type { SandboxAgentSessionHost, SandboxLifecyclePolicy } from \"@agentproto/sandbox\"\nimport type { AgentSessionLike, AgentStreamEvent } from \"./sessions.js\"\n\n/** `session_monitor`'s max accepted long-poll window (`orchestration-tools.ts`). */\nconst MAX_POLL_MS = 49_000\n/** Pull the full ring-buffer cap each poll so a verbose turn doesn't lose\n *  lines between polls (the ring buffer itself is still capped upstream —\n *  see the module doc's known-limitation note). */\nconst MAX_OUTPUT_LINES = 500\n\nexport interface SandboxAgentSessionProxyOpts {\n  /** The booted sandbox's daemon host. `prompt`/`output`/`kill`/`waitForAny`\n   *  drive the box's OWN `agent_start` session; `stop()`/`pause()` tear the\n   *  box down (closes the daemon connection, then stops/pauses the\n   *  sandbox) — `pause` is only present when the booted sandbox supports\n   *  it (see `BootedSandbox.pause`). */\n  host: Pick<SandboxAgentSessionHost, \"prompt\" | \"output\" | \"kill\" | \"waitForAny\" | \"stop\" | \"pause\">\n  /** Session id on the BOX's own daemon (from `host.start(...)`) — NOT this\n   *  proxy's local session id (the registry mints its own on `spawnAgent`). */\n  remoteSessionId: string\n  /** PR3 AIP-36 lifecycle policy (`resolveLifecyclePolicy`) — decides\n   *  whether `close()` pauses the box (reuse-friendly) or kills it\n   *  (ephemeral, the default). Omitted ⇒ always kill, matching PR2. */\n  lifecyclePolicy?: SandboxLifecyclePolicy\n}\n\n/**\n * Best-effort extraction of the prompt text from whatever `sessions.ts`'s\n * `runAgentTurn` hands `AgentSessionLike.send()` — today always either a\n * bare string, or the ACP-style `{type:\"text\", text}` block `runAgentTurn`\n * wraps a string message into before calling `send()`.\n */\nfunction extractPromptText(message: unknown): string {\n  if (typeof message === \"string\") return message\n  if (message && typeof message === \"object\" && \"text\" in message) {\n    const text = (message as { text?: unknown }).text\n    if (typeof text === \"string\") return text\n  }\n  return JSON.stringify(message)\n}\n\n/**\n * Build an `AgentSessionLike` over a box daemon's own `agent_start` session.\n * See module docs for the event-fidelity limitation and the cancel-\n * semantics note below.\n */\nexport function createSandboxAgentSessionProxy(\n  opts: SandboxAgentSessionProxyOpts,\n): AgentSessionLike {\n  const { host, remoteSessionId, lifecyclePolicy } = opts\n  let lastPrompt: string | undefined\n  let closed = false\n\n  return {\n    sessionId: remoteSessionId,\n\n    async *send(message: unknown): AsyncIterable<AgentStreamEvent> {\n      const prompt = extractPromptText(message)\n      lastPrompt = prompt\n      await host.prompt(remoteSessionId, prompt)\n\n      // Tracks how much of the box's `agent_output` tail this turn has\n      // already yielded, as a character offset into the raw joined string\n      // — NOT a line count. `projectEvent`'s text-delta handling expects\n      // newline-delimited STREAM FRAGMENTS it coalesces itself (partial\n      // lines included); re-splitting the tail into whole lines here and\n      // yielding each separately (with the splitting newline stripped)\n      // would feed it back newline-less chunks that get glued into one\n      // mangled line instead. Yielding the raw new suffix (embedded\n      // newlines intact) lets that same coalescing logic split it\n      // correctly. Known limitation (documented in the module doc): if\n      // the box's ring buffer evicts lines from the front between polls,\n      // this offset can go stale — acceptable for the turn sizes this\n      // flattening path targets; a real fix subscribes to the box's SSE\n      // stream instead of polling a bounded tail.\n      let seenLength = 0\n      for (;;) {\n        const result = await host.waitForAny([remoteSessionId], {\n          event: \"any\",\n          timeoutMs: MAX_POLL_MS,\n        })\n        // A clean long-poll timeout carries no `event` at all — keep\n        // polling past it instead of mistaking it for a real settle\n        // (mirrors `@agentproto/worktree`'s `waitForSettled`).\n        if (result.timedOut) continue\n\n        const tail = await host.output(remoteSessionId, MAX_OUTPUT_LINES)\n        if (tail.length > seenLength) {\n          yield { kind: \"text-delta\", text: tail.slice(seenLength) }\n        }\n        seenLength = tail.length\n\n        if (result.event === \"exited\") {\n          // The box's OWN session ended out-of-band (crash, OOM, an\n          // independent kill) — not a normal turn boundary. Throwing here\n          // (rather than yielding a turn-end) lets the registry's existing\n          // `runAgentTurn` catch flip this session's status to \"error\" and\n          // emit `session:exited`, the same \"proxy detects remote exit\"\n          // behaviour a local adapter crash gets today — no new plumbing.\n          throw new Error(\n            `sandbox proxy: remote session \"${remoteSessionId}\" exited — the box's own ` +\n              \"agentproto daemon ended this session (crash, OOM, or an out-of-band kill).\",\n          )\n        }\n        yield {\n          kind: \"turn-end\",\n          reason: result.event === \"awaiting-input\" ? \"awaiting-input\" : \"completed\",\n        }\n        return\n      }\n    },\n\n    async cancel(): Promise<void> {\n      // There is no bare \"interrupt, no next prompt\" primitive on the wire\n      // — `agent_prompt` always carries a prompt. Re-deliver the last\n      // prompt with `interrupt: true`, cancelling the in-flight turn and\n      // restarting it on the same session (a documented limitation: a\n      // cancel before any prompt was sent, or a race with a fresh prompt,\n      // has nothing/the wrong thing to redeliver).\n      if (lastPrompt === undefined) return\n      await host.prompt(remoteSessionId, lastPrompt, { interrupt: true })\n    },\n\n    async close(): Promise<void> {\n      if (closed) return\n      closed = true\n      try {\n        await host.kill(remoteSessionId)\n      } finally {\n        // PAUSE (not kill) when the lifecycle policy says this box is\n        // meant to be reused later — falls back to `stop()` when the\n        // provider never exposed a `pause()` (e.g. `local`, or a policy\n        // that resolved to \"pause\" against a non-pausable provider): a\n        // teardown must never silently no-op and leak the box.\n        if (lifecyclePolicy?.teardown === \"pause\" && host.pause) {\n          await host.pause()\n        } else {\n          await host.stop()\n        }\n      }\n    },\n  }\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 { AgentSessionLike, SessionsRegistry, SessionDescriptor } from \"./sessions.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\nimport {\n  loadWorkspacesConfig,\n  findWorkspace,\n  findWorkspaceByPath,\n  getActiveWorkspace,\n} from \"./workspaces-config.js\"\nimport { loadConfig } from \"./config.js\"\nimport type { OrchestratorScope } from \"./orchestrator-gateway.js\"\nimport type { WebhookNotifier } from \"./webhook-notifier.js\"\nimport {\n  resolveSpawnDefaults,\n  normalizeSkillsOption,\n  resolveAuthSpec,\n  AuthResolutionError,\n  type SpawnDefaultsConfig,\n  type DefaultsAdapterAuthConfig,\n  type ResolvedAuthSpec,\n  type AuthEcho,\n} from \"./spawn-defaults.js\"\nimport { getProviderKey } from \"./providers-store.js\"\nimport { getModelProvider } from \"@agentproto/model-catalog/llm\"\nimport { resolveRole, composeRoleContext, canSpawn, DELEGATION_TOOL_NAMES } from \"./role.js\"\nimport type { RoleProfile } from \"./role.js\"\nimport { loadDefaultRoleRegistry } from \"./role-registry.js\"\nimport { getMcpCredentialDeps } from \"./mcp-credential-deps.js\"\nimport {\n  createSandboxAgentSessionHost,\n  resolveLifecyclePolicy,\n  type SandboxAgentSessionHost,\n  type SandboxLifecyclePolicy,\n  type SandboxSpec,\n} from \"@agentproto/sandbox\"\nimport { createSandboxAgentSessionProxy } from \"./sandbox-agent-session-proxy.js\"\nimport type { SandboxProviderResolver } from \"./sandbox-adapters.js\"\n\n/** `agent_start.sandbox`'s inline-spec form, plus the PR3 reuse field. See\n *  `SpawnAgentSessionInput.sandbox`. */\nexport type SandboxSpecInput = SandboxSpec & { reuse?: string }\n\n/**\n * Retry-safety for the process-forking half of `agent_start`.\n *\n * Why: `agent_start` is a non-idempotent, side-effecting call (it forks a\n * real adapter process) exposed over MCP's at-least-once transport. A slow\n * or dropped response followed by a caller retry — measured in production as\n * two live agents, same label/cwd, 7.7s apart, sharing one working directory\n * for ~5 minutes before a human noticed — currently spawns TWO processes\n * with no way for the caller to detect it (the tool result only ever carries\n * the LAST spawn's id).\n *\n * This is deliberately CALLER-SUPPLIED (`idempotencyKey`), not derived from\n * request content (adapter+cwd+prompt+label hash). A content hash was tried\n * and rejected: this file's own test suite exercises a legitimate orchestrator\n * fan-out where two structurally-identical `agent_start` calls (same adapter,\n * cwd, no label/prompt) under one caller scope are expected to spawn as TWO\n * distinct sessions — the second is meant to be rejected by the maxChildren\n * quota check, not silently answered with the first session's descriptor.\n * Intentional identical-looking concurrent spawns are a real, exercised\n * pattern here (see also `Workflow`'s `isolation: \"worktree\"`, which exists\n * precisely because same-cwd concurrent agents are sometimes wanted and\n * sometimes dangerous) — content alone can't tell the two apart. Only the\n * caller's own declared intent can, so idempotency is opt-in: omitting\n * `idempotencyKey` is a byte-for-byte behavioural no-op.\n *\n * Scope: guards only the actual fork + registry registration (the `try`\n * block below) — the one irreversible side effect. Pre-flight validation\n * (depth/quota/role checks) still re-runs for a deduped retry; those are\n * pure functions of current state, not side effects, so re-running them is\n * harmless. The one known gap: a retry that resolves `orchestrator: true`\n * still mints a fresh scope token via `buildOrchestratorMcp` before the\n * dedup check is reached, and that token is never bound (leaked) since the\n * retry returns the ORIGINAL session's descriptor — accepted as a narrower,\n * pre-existing-shape problem than the double-process bug this fixes.\n *\n * Window: a resolved (successful) claim is remembered for\n * `SPAWN_CLAIM_WINDOW_MS` so a same-key retry seconds later still hits it;\n * a FAILED claim is dropped immediately so a genuine post-error retry tries\n * fresh instead of replaying the same failure forever. Scoped per registry\n * instance (WeakMap) so independent daemons/tests never share a cache.\n */\nconst SPAWN_CLAIM_WINDOW_MS = 30_000\n\ninterface SpawnClaim {\n  result: Promise<SpawnAgentSessionResult>\n  /** Wall-clock time the claim settled successfully — undefined while\n   *  still in-flight. Only set for `ok: true` results; see the docblock\n   *  above for why a failure is dropped instead of cached. */\n  resolvedAt?: number\n}\n\nconst spawnClaimsByRegistry = new WeakMap<SessionsRegistry, Map<string, SpawnClaim>>()\n\nfunction claimsFor(registry: SessionsRegistry): Map<string, SpawnClaim> {\n  let claims = spawnClaimsByRegistry.get(registry)\n  if (!claims) {\n    claims = new Map()\n    spawnClaimsByRegistry.set(registry, claims)\n  }\n  return claims\n}\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  role?: string\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      // A tool ERROR must never be filtered — a failing turn is exactly when a\n      // caller reads the output, and hiding it makes the session look silently\n      // stuck. Only decorative framing and non-error [thought]/[tool]/[tool-result]\n      // chatter is dropped in clean mode.\n      if (/^\\[tool-error\\]/.test(t)) return true\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  /** Loads config.json's `defaults` block (global + per-adapter skills/\n   *  options auto-applied at every spawn — see `resolveSpawnDefaults`).\n   *  Defaults to reading the real `~/.agentproto/config.json` via\n   *  `loadConfig` when omitted; tests inject a stub to avoid touching\n   *  the real file. */\n  loadDefaultsConfig?: () => Promise<SpawnDefaultsConfig | undefined>\n  /** Loads the custom (pack-carried) role registry, merged with the\n   *  two built-ins by `resolveRole`/`canSpawn` — see `role.ts`'s\n   *  `mergeRoleRegistry`. Defaults to `loadDefaultRoleRegistry()`\n   *  (`~/.agentproto/roles/` + adapter-carried packs) when omitted;\n   *  tests inject a stub registry to avoid touching the real\n   *  filesystem. */\n  loadRoleRegistry?: () => Promise<Record<string, RoleProfile>>\n  /** Resolves an `agent_start.sandbox` slug (or an inline spec's own\n   *  `.provider`) to a concrete sandbox provider handle. Required for\n   *  `input.sandbox` — omitted ⇒ `sandbox_provider_not_found`. */\n  resolveSandboxProvider?: SandboxProviderResolver\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  /** Manifest-declared option id → value map (AIP-45 `options`), applied\n   *  at spawn time alongside `mode`. Forwarded verbatim to the driver's\n   *  `startSession({ options })` → `composeSpawn`'s option patches. */\n  options?: Record<string, boolean | number | string>\n  /** Normalized, adapter-agnostic skill ids for this session. Merged with\n   *  config.json's `defaults.skills` / `defaults.adapters.<slug>.skills`\n   *  (global < per-adapter < this field, which REPLACES the union rather\n   *  than merging into it when provided — a deliberate exact set). Folded\n   *  into `options.skills` per the resolved adapter's declared `skills`\n   *  option shape (e.g. hermes' comma-joined string); adapters with no\n   *  such option (e.g. claude-code, which auto-discovers skills) ignore\n   *  it. See `resolveSpawnDefaults` / `normalizeSkillsOption`. */\n  skills?: string[]\n  model?: string\n  effort?: string\n  /**\n   * Deterministic billing-auth mode + EXPLICIT credential for adapters that\n   * declare an env-var vocabulary for it (today: claude-code — see\n   * `AgentCliAuth.modes` in `@agentproto/driver-agent-cli`). `mode` wins over\n   * `~/.agentproto/config.json`'s `defaults.adapters.<slug>.auth.mode`\n   * (default `\"subscription\"`); the credential (`token` for `\"subscription\"`,\n   * `apiKey` for `\"api-key\"`) wins over the config field matching the\n   * RESOLVED mode — see `resolveSpawnDefaults`. Never read from the ambient\n   * shell env; never logged (only a fingerprint is recorded on the session\n   * descriptor — see `credentialFingerprint`). Adapters that don't declare\n   * the vocabulary ignore this field entirely.\n   */\n  auth?: DefaultsAdapterAuthConfig\n  mcpServers?: AcpMcpServer[]\n  orchestrator?: boolean | { tools?: string[]; maxDepth?: number; maxChildren?: number }\n  notifyUrl?: string\n  wait?: boolean\n  maxCostUsd?: number\n  /** Spawn-time role — `\"executor\"` | `\"supervisor\"` | omitted. See\n   *  `resolveRole` in `role.ts`. Omitted ⇒ derived from spawn depth\n   *  against `defaults.defaultRoleDepthCutoff` (default 1). A resolved\n   *  role with `toolPolicy.delegation === \"deny\"` is a HARD gate:\n   *  `orchestrator` is ignored outright and the hermes/default\n   *  full-gateway injection excludes `DELEGATION_TOOL_NAMES` — neither\n   *  this field's own request nor `promptAppend` can re-open it. */\n  role?: string\n  /** One-off runtime text layered ON TOP of the resolved role's\n   *  disposition (never replacing it) and prepended to `prompt`. See\n   *  `composeRoleContext`. Cannot widen `toolPolicy` — see `role` above. */\n  promptAppend?: string\n  /** Opt this session into Langfuse tracing (prompt/completion + tool spans +\n   *  tokens/cost). Effective opt-in is `trace ?? langfuseTracingDefault ?? false`\n   *  — see `SpawnAgentInput.trace` in sessions.ts. */\n  trace?: boolean\n  /** Run this session inside a sandbox instead of on the host — a provider\n   *  slug from `list_sandbox_providers` (e.g. `\"local\"`, `\"e2b\"`), or an\n   *  inline AIP-36 `SandboxSpec`, optionally carrying `reuse: \"<sandboxId>\"`\n   *  to reconnect to an existing box instead of booting fresh. When set,\n   *  this branch resolves the provider, boots (or reconnects) the box,\n   *  spawns `adapter` on the BOX's own `agent_start`, and wires a\n   *  `SandboxAgentSessionProxy` in place of the local `resolveAgentAdapter`\n   *  path — see `sandbox-agent-session-proxy.ts`. */\n  sandbox?: string | SandboxSpecInput\n  /** Start this session in permission-hold mode: every ACP permission request\n   *  is surfaced + parked in the cross-session inbox (`permissions_list` /\n   *  `permissions_respond`) instead of auto-answered. Threaded to the driver's\n   *  `startSession({ permissionHold })` and recorded on the descriptor. Ignored\n   *  for sandbox spawns (the box's own daemon owns permission handling).\n   *  Default false — unchanged auto-answer behaviour. */\n  permissionHold?: boolean\n  /** Caller-declared \"this is the same logical spawn\" token. A second\n   *  `agent_start` with the same `(adapter, cwd, idempotencyKey)` within\n   *  `SPAWN_CLAIM_WINDOW_MS` of a SUCCESSFUL spawn returns that spawn's\n   *  descriptor instead of forking a second process — the fix for a\n   *  retried call otherwise silently duplicating a live agent. Omit for\n   *  today's behaviour (every call spawns). See the docblock on\n   *  `SpawnClaim` for why this is opt-in rather than automatic. */\n  idempotencyKey?: string\n}\n\nexport type SpawnAgentSessionResult =\n  | {\n      ok: true\n      descriptor: SessionDescriptor\n      output?: string[]\n      /** Set when this result was returned to a duplicate call recognized\n       *  via `idempotencyKey` — no new process was spawned; `descriptor` is\n       *  the ORIGINAL spawn's. Absent on the original (non-duplicate) call. */\n      deduped?: boolean\n    }\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        | \"invalid_role\"\n        | \"role_spawn_denied\"\n        | \"unsupported_auth_mode\"\n        | \"agent_spawn_failed\"\n        | \"sandbox_provider_not_found\"\n        | \"sandbox_boot_failed\"\n        | \"sandbox_reconnect_failed\"\n        | \"sandbox_proxy_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    loadDefaultsConfig,\n    resolveSandboxProvider,\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\n  if (!cwd || !resolvedSlug) {\n    try {\n      const config = await loadWorkspacesConfig()\n      if (!cwd) {\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      } else if (!resolvedSlug) {\n        // cwd provided but no explicit workspaceSlug — try to match\n        // cwd against a registered workspace so the session lands in\n        // the right workspace instead of the global default.\n        const ws = findWorkspaceByPath(config, cwd)\n        if (ws) {\n          resolvedSlug = ws.slug\n        }\n      }\n    } catch {\n      // fall through to error below\n    }\n  }\n  resolvedSlug = resolvedSlug ?? \"default\"\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  // A sandboxed spawn runs `adapter` on the BOX's own `agent_start` — the\n  // host's local adapter registry has no bearing on it (the box resolves\n  // `adapter` itself), so the local resolution + not-found gate are\n  // skipped entirely for `input.sandbox`. See the sandbox branch below,\n  // which short-circuits BEFORE `resolved.startSession(...)` is ever\n  // reached.\n  const resolved = input.sandbox === undefined ? await resolveAgentAdapter(input.adapter) : null\n  if (input.sandbox === undefined && !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  // Config-level defaults (WP: session-skills-defaults) — auto-apply\n  // `defaults.skills` / `defaults.options` (global + per-adapter) unless\n  // the caller's explicit `agent_start` fields already say otherwise.\n  // Pure merge in `resolveSpawnDefaults`; adapter-shape folding (e.g.\n  // hermes' comma-joined `options.skills`) in `normalizeSkillsOption`,\n  // using the manifest's own declared option type via `resolved`.\n  // Loaded here (before the role/orchestrator decisions below) because\n  // both `defaultRoleDepthCutoff` and `skills`/`options` come from the\n  // same block.\n  const configDefaults = loadDefaultsConfig\n    ? await loadDefaultsConfig()\n    : (await loadConfig()).defaults\n  // Role REGISTRY (spawn-role-profiles extensibility): custom\n  // (pack-carried) roles merged with the two built-ins at every\n  // resolution below — see `role.ts`'s `mergeRoleRegistry`. Loaded once\n  // per spawn so the child-role resolution and the parent-role gate\n  // check (right below) agree on the exact same set.\n  const roleRegistry = deps.loadRoleRegistry\n    ? await deps.loadRoleRegistry()\n    : await loadDefaultRoleRegistry()\n  // Spawn-time role (see role.ts). Resolved BEFORE the orchestrator/\n  // hermes-default mcpServers decisions below so `toolPolicy.delegation`\n  // can gate both — the hard tool gate this whole primitive exists for.\n  let role\n  try {\n    role = resolveRole(input.role, childDepth, configDefaults?.defaultRoleDepthCutoff, roleRegistry)\n  } catch (err) {\n    return {\n      ok: false,\n      code: \"invalid_role\",\n      message: `agent_start: ${err instanceof Error ? err.message : String(err)}`,\n    }\n  }\n  // Privilege-lattice spawn gate: when this spawn arrives through the\n  // scoped orchestrator sub-gateway, `callerScope` carries the resolved\n  // role of the SPAWNING session (see `OrchestratorScope.role`). Reject\n  // BEFORE any tool injection when the caller may not spawn this role —\n  // the second line of defense (after `toolPolicy.delegation`) for a\n  // custom role that keeps delegation but must not spawn UP. A root\n  // spawn (no callerScope) has no parent to gate against, same as the\n  // existing depth/quota checks above.\n  if (callerScope) {\n    let parentRole: RoleProfile\n    try {\n      parentRole = resolveRole(\n        callerScope.role,\n        callerScope.depth,\n        configDefaults?.defaultRoleDepthCutoff,\n        roleRegistry,\n      )\n    } catch (err) {\n      return {\n        ok: false,\n        code: \"invalid_role\",\n        message: `agent_start: caller role — ${err instanceof Error ? err.message : String(err)}`,\n      }\n    }\n    if (!canSpawn(parentRole, role)) {\n      return {\n        ok: false,\n        code: \"role_spawn_denied\",\n        message:\n          `agent_start: role \"${parentRole.name}\" (level ${parentRole.level}) may not spawn ` +\n          `role \"${role.name}\" (level ${role.level}). ` +\n          (parentRole.spawnableRoles\n            ? `Allowed: ${parentRole.spawnableRoles.join(\", \") || \"(none)\"}.`\n            : `Open mode requires a level at or below ${parentRole.level} — spawning something more privileged than yourself is never allowed.`),\n        details: {\n          parentRole: parentRole.name,\n          parentLevel: parentRole.level,\n          childRole: role.name,\n          childLevel: role.level,\n        },\n      }\n    }\n  }\n  const delegationDenied = role.toolPolicy.delegation === \"deny\"\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  //\n  // HARD GATE: a role that denies delegation drops `orchestrator`\n  // outright, regardless of what the caller requested — this is the\n  // capability gate applied from outside; `promptAppend` cannot\n  // reopen it (it's never consulted here at all).\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  //\n  // HARD GATE: when the resolved role denies delegation, the injected\n  // gateway URL carries `denyTools=<DELEGATION_TOOL_NAMES>` so the\n  // daemon's `/mcp` handler strips `agent_start`/`agent_prompt` from\n  // what it registers for this one request — the child still gets the\n  // rest of the daemon's tools (fs, command_execute, …) to do real work.\n  if (!mcpServers && input.adapter === \"hermes\" && daemonMcpUrl) {\n    const ref = delegationDenied\n      ? `${daemonMcpUrl}${daemonMcpUrl.includes(\"?\") ? \"&\" : \"?\"}denyTools=${DELEGATION_TOOL_NAMES.join(\",\")}`\n      : daemonMcpUrl\n    mcpServers = [{ name: \"agentproto\", transport: \"http\", ref }]\n  }\n  let bindOrchestratorLifecycle:\n    | ((sessionId: string) => () => void)\n    | undefined\n  if (!delegationDenied && 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      // This session's OWN resolved role — becomes the \"parent role\" the\n      // gate above checks a FUTURE spawn (made through this scope)\n      // against, once this session itself calls `agent_start`.\n      role: role.name,\n    })\n    mcpServers = [...(mcpServers ?? []), injection.entry]\n    bindOrchestratorLifecycle = injection.bindLifecycle\n  }\n  const spawnDefaults = resolveSpawnDefaults(configDefaults, input.adapter, {\n    skills: input.skills,\n    options: input.options,\n    auth: input.auth,\n  })\n  // ── Billing-auth resolution (DECISIONS 4/9/10) ──────────────────\n  // The runtime decides provider → ordered mode → setEnv/scrub → credential\n  // source → fingerprint, and emits BOTH the mechanical `spec` the driver\n  // applies AND the observable `echo` recorded on the descriptor. Fail-loud\n  // on a configured-but-missing credential is the DRIVER's job (it engages\n  // then throws `missing_auth_credential`); a requested-but-unsupported mode\n  // fails LOUD right here (`unsupported_auth_mode`). No provider resolves ⇒\n  // no spec ⇒ ambient (no injection). Skipped for a sandbox spawn — the box's\n  // own daemon resolves its own credential independently.\n  let authSpec: ResolvedAuthSpec | undefined\n  let authEcho: AuthEcho | undefined\n  if (resolved && input.sandbox === undefined && resolved.authDescriptor) {\n    const authModel = input.model ?? resolved.defaultModel\n    const pinnedProvider = spawnDefaults.auth.provider\n    const resolvedProvider =\n      pinnedProvider ??\n      resolved.authDescriptor.provider ??\n      (authModel ? getModelProvider(authModel) : undefined)\n    // Consult providers.json (the EXPLICIT store — never ambient env) ONLY\n    // when the operator explicitly opted into auth for this spawn (`explicit`)\n    // AND no explicit config key was already supplied. Gating on `explicit` is\n    // the money-safety invariant: for an UNCONFIGURED spawn the store must NOT\n    // be consulted — otherwise an `always` adapter (claude-code) would flip\n    // ordered-mode to api-key off a leftover `auth provider set anthropic` key\n    // and silently bill org credits (DECISION 5/10: unconfigured `always` ⇒\n    // fail-fast, preserving #312). For `when-configured` adapters unconfigured\n    // still means ambient (boot injection already placed keys in ambient env),\n    // so gating on `explicit` is correct for every adapter.\n    const apiKeyStoreCredential =\n      resolvedProvider &&\n      spawnDefaults.auth.explicit &&\n      spawnDefaults.auth.apiKeyCredential === undefined\n        ? await getProviderKey(resolvedProvider)\n        : undefined\n    try {\n      const result = resolveAuthSpec({\n        descriptor: resolved.authDescriptor,\n        ...(authModel ? { model: authModel } : {}),\n        ...(pinnedProvider ? { requestedProvider: pinnedProvider } : {}),\n        ...(spawnDefaults.auth.requestedMode\n          ? { requestedMode: spawnDefaults.auth.requestedMode }\n          : {}),\n        explicit: spawnDefaults.auth.explicit,\n        ...(spawnDefaults.auth.subscriptionCredential !== undefined\n          ? { subscriptionCredential: spawnDefaults.auth.subscriptionCredential }\n          : {}),\n        ...(spawnDefaults.auth.apiKeyCredential !== undefined\n          ? { apiKeyConfigCredential: spawnDefaults.auth.apiKeyCredential }\n          : {}),\n        ...(apiKeyStoreCredential !== undefined ? { apiKeyStoreCredential } : {}),\n      })\n      if (result) {\n        authSpec = result.spec\n        authEcho = result.echo\n      }\n    } catch (err) {\n      if (err instanceof AuthResolutionError) {\n        return {\n          ok: false,\n          code: \"unsupported_auth_mode\",\n          message: `agent_start: ${err.message}`,\n          details: { adapter: input.adapter, provider: resolvedProvider },\n        }\n      }\n      throw err\n    }\n  }\n  const effectiveOptions = normalizeSkillsOption(\n    spawnDefaults.skills,\n    spawnDefaults.options,\n    resolved?.declaredOptions,\n  )\n  // Compose the role's disposition (+ optional promptAppend, layered on\n  // top, never replacing it) into the initial prompt — the only text\n  // channel this codebase has into a freshly-spawned child (there's no\n  // separate system-prompt field on `startSession`). No `prompt` at all\n  // ⇒ nothing to compose onto; the child still gets the tool gate above,\n  // it just doesn't see the disposition until its first turn.\n  const effectivePrompt = input.prompt\n    ? `${composeRoleContext(role, input.promptAppend, roleRegistry)}\\n\\n${input.prompt}`\n    : input.prompt\n\n  // ── retry-safety claim (see SpawnClaim docblock above) ────────────\n  // Opt-in: no idempotencyKey ⇒ no map lookup, no behavioural change.\n  let settleClaim: ((result: SpawnAgentSessionResult) => void) | undefined\n  if (input.idempotencyKey) {\n    const claims = claimsFor(registry)\n    const key = `${input.adapter}\\x1f${cwd}\\x1f${input.idempotencyKey}`\n    const now = Date.now()\n    for (const [k, claim] of claims) {\n      if (claim.resolvedAt !== undefined && now - claim.resolvedAt > SPAWN_CLAIM_WINDOW_MS) {\n        claims.delete(k)\n      }\n    }\n    const existing = claims.get(key)\n    if (existing) {\n      const result = await existing.result\n      return result.ok ? { ...result, deduped: true } : result\n    }\n    let resolveClaim!: (result: SpawnAgentSessionResult) => void\n    claims.set(key, { result: new Promise(resolve => { resolveClaim = resolve }) })\n    settleClaim = result => {\n      if (result.ok) {\n        const claim = claims.get(key)\n        if (claim) claim.resolvedAt = Date.now()\n      } else {\n        claims.delete(key)\n      }\n      resolveClaim(result)\n    }\n  }\n  const finish = (result: SpawnAgentSessionResult): SpawnAgentSessionResult => {\n    settleClaim?.(result)\n    return result\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    const resolvedMcpServers = await resolveMcpCredentialHeaders(mcpServers)\n    let liveSessionId: string | undefined\n\n    let agentSession: AgentSessionLike\n    let commandPreview: string | undefined\n    let readUsage: (() => Promise<{ costUsd?: number; tokensIn?: number; tokensOut?: number } | null>) | undefined\n    let sandboxId: string | undefined\n    let sandboxTeardown: SandboxLifecyclePolicy[\"teardown\"] | undefined\n\n    if (input.sandbox !== undefined) {\n      const booted = await bootSandboxAgentSession({\n        sandbox: input.sandbox,\n        resolveSandboxProvider,\n        adapter: input.adapter,\n        // The host's own resolved `cwd` — valid as-is for a same-machine\n        // provider (`local`); a genuinely remote box (e2b) needs its own\n        // filesystem story (AIP-36 `mounts`, out of scope here — see the\n        // plan's \"local MCP servers unreachable from sandbox\" risk, which\n        // applies equally to bare filesystem paths). Forwarding it is\n        // still strictly better than omitting it: the box's OWN\n        // `agent_start` needs SOME cwd to resolve, and a bad path fails\n        // no worse than no path at all.\n        cwd,\n        ...(resolvedMcpServers ? { mcpServers: resolvedMcpServers } : {}),\n        ...(input.model ? { model: input.model } : {}),\n        ...(input.effort ? { effort: input.effort } : {}),\n        ...(input.label ? { label: input.label } : {}),\n      })\n      if (!booted.ok) return booted\n      agentSession = booted.agentSession\n      commandPreview = booted.commandPreview\n      sandboxId = booted.sandboxId\n      sandboxTeardown = booted.sandboxTeardown\n    } else {\n      // `resolved` is guaranteed non-null here — the `input.sandbox ===\n      // undefined` branch above already returned `adapter_not_found`\n      // otherwise.\n      agentSession = await resolved!.startSession({\n        cwd,\n        ...(input.resumeSessionId ? { resumeSessionId: input.resumeSessionId } : {}),\n        ...(input.mode ? { mode: input.mode } : {}),\n        ...(Object.keys(effectiveOptions).length > 0\n          ? { options: effectiveOptions }\n          : {}),\n        ...(input.model ? { model: input.model } : {}),\n        ...(input.effort ? { effort: input.effort } : {}),\n        ...(authSpec ? { auth: authSpec } : {}),\n        ...(resolvedMcpServers ? { mcpServers: resolvedMcpServers } : {}),\n        ...(input.permissionHold ? { permissionHold: true } : {}),\n        onActivity: () => {\n          if (liveSessionId) registry.pulseActivity(liveSessionId)\n        },\n      })\n      commandPreview = resolved!.commandPreview\n      if (resolved!.readUsage) {\n        const startedSession = agentSession\n        readUsage = () => resolved!.readUsage!(startedSession.sessionId)\n      }\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 && effectivePrompt ? {} : effectivePrompt ? { initialPrompt: effectivePrompt } : {}),\n      ...(input.label ? { label: input.label } : {}),\n      ...(resolvedMcpServers ? { mcpServers: resolvedMcpServers } : {}),\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      ...(commandPreview ? { commandPreview } : {}),\n      ...(input.maxCostUsd !== undefined ? { maxCostUsd: input.maxCostUsd } : {}),\n      ...(readUsage ? { readUsage } : {}),\n      ...(input.trace !== undefined ? { trace: input.trace } : {}),\n      // Verifiability: record the OBSERVABLE echo — resolved provider, mode,\n      // credential source, the env var actually set, and a non-secret\n      // fingerprint (never the credential). DECISION 9③/10②. Recorded only\n      // when a credential actually resolved (fingerprint present); a\n      // configured-but-missing-credential spawn fails fast in the driver\n      // before a descriptor exists. Absent for sandbox spawns (the box\n      // resolves its own credential, so a host-side echo would misrepresent\n      // it — `authEcho` is already left undefined for those above).\n      ...(authEcho?.fingerprint\n        ? {\n            auth: {\n              mode: authEcho.authMode,\n              fingerprint: authEcho.fingerprint,\n              provider: authEcho.provider,\n              credentialSource: authEcho.credentialSource,\n              setEnv: authEcho.setEnv,\n            },\n          }\n        : {}),\n      ...(sandboxId ? { remote: true, sandboxId } : {}),\n      ...(sandboxTeardown ? { sandboxTeardown } : {}),\n      // Hold mode is a local-driver capability; a sandbox spawn proxies to the\n      // box's own daemon, which handles permissions there.\n      ...(input.permissionHold && input.sandbox === undefined ? { permissionHold: true } : {}),\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 && effectivePrompt) {\n      await registry.sendPrompt(desc.id, effectivePrompt)\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 finish({ ok: true, descriptor: desc, output })\n    }\n    return finish({ ok: true, descriptor: desc })\n  } catch (err) {\n    return finish({\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/**\n * Resolve brokered auth headers for any `mcpServers` entry that names a\n * `credentialRef`. The returned headers are merged ON TOP of the entry's\n * static `headers` (brokered wins on collision). Hook errors are non-fatal:\n * the entry is left unchanged and a warning is logged. Entries without a\n * `credentialRef` pass through untouched.\n */\nasync function resolveMcpCredentialHeaders(\n  mcpServers: AcpMcpServer[] | undefined,\n): Promise<AcpMcpServer[] | undefined> {\n  if (!mcpServers || mcpServers.length === 0) return mcpServers\n\n  const { resolveMcpCredentialHeaders: resolve } = getMcpCredentialDeps()\n  if (!resolve) return mcpServers\n\n  return Promise.all(\n    mcpServers.map(async (entry) => {\n      const ref = entry.credentialRef\n      if (!ref) return entry\n\n      let brokered: Record<string, string> | undefined\n      try {\n        brokered = await resolve({ credentialRef: ref })\n      } catch (err) {\n        console.warn(\n          `[agent_start] credentialRef resolution failed for \"${entry.name}\" ` +\n            `(${ref}): ${err instanceof Error ? err.message : String(err)}`,\n        )\n        return entry\n      }\n\n      if (!brokered || Object.keys(brokered).length === 0) return entry\n\n      return {\n        ...entry,\n        headers: { ...entry.headers, ...brokered },\n      }\n    }),\n  )\n}\n\ntype SandboxBootResult =\n  | {\n      ok: true\n      agentSession: AgentSessionLike\n      commandPreview: string\n      sandboxId: string\n      sandboxTeardown: SandboxLifecyclePolicy[\"teardown\"]\n    }\n  | {\n      ok: false\n      code: \"sandbox_provider_not_found\" | \"sandbox_boot_failed\" | \"sandbox_reconnect_failed\" | \"sandbox_proxy_failed\"\n      message: string\n    }\n\n/**\n * Rebuild `mcpServers` entries as the box daemon's own `agent_start` expects\n * them (`StartAgentArgs.mcpServers: McpServerMount[]`). A plain field-by-\n * field object literal (rather than forwarding `AcpMcpServer` values as-is)\n * because `McpServerMount` carries an index signature `AcpMcpServer` lacks —\n * and deliberately drops `credentialRef`: by the time a spawn reaches here,\n * `resolveMcpCredentialHeaders` has already resolved it into `headers` on\n * the HOST side, so the box would only re-attempt (and fail/warn on) a\n * broker it doesn't have.\n */\nfunction toMcpServerMounts(entries: readonly AcpMcpServer[]): Array<{\n  name: string\n  transport: \"stdio\" | \"http\" | \"sse\"\n  ref?: string\n  headers?: Record<string, string>\n}> {\n  return entries.map(e => ({\n    name: e.name,\n    transport: e.transport,\n    ...(e.ref !== undefined ? { ref: e.ref } : {}),\n    ...(e.headers !== undefined ? { headers: e.headers } : {}),\n  }))\n}\n\n/**\n * Resolve `opts.sandbox`, boot the box, spawn `adapter` on the box's OWN\n * `agent_start`, and wrap the result in a `SandboxAgentSessionProxy`. Called\n * from inside `spawnAgentSession`'s try block, AFTER the role/depth/quota\n * gates above have already run — a rejected spawn never boots a box.\n *\n * Every failure mode returns its own discriminated `code` rather than\n * throwing into the generic `agent_spawn_failed` catch, so callers can\n * distinguish \"no such provider\" from \"the box never came up\" from \"the\n * box's own agent_start rejected the adapter\".\n */\nasync function bootSandboxAgentSession(opts: {\n  sandbox: string | SandboxSpecInput\n  resolveSandboxProvider?: SandboxProviderResolver\n  adapter: string\n  cwd: string\n  mcpServers?: AcpMcpServer[]\n  model?: string\n  effort?: string\n  label?: string\n}): Promise<SandboxBootResult> {\n  const providerSlug = typeof opts.sandbox === \"string\" ? opts.sandbox : opts.sandbox.provider\n  if (!opts.resolveSandboxProvider) {\n    return {\n      ok: false,\n      code: \"sandbox_provider_not_found\",\n      message:\n        `agent_start: sandbox provider \"${providerSlug}\" not found — the daemon has no ` +\n        \"sandbox provider resolver wired (createGateway needs `resolveSandboxProvider`).\",\n    }\n  }\n  const handle = await opts.resolveSandboxProvider(providerSlug)\n  if (!handle) {\n    return {\n      ok: false,\n      code: \"sandbox_provider_not_found\",\n      message:\n        `agent_start: sandbox provider \"${providerSlug}\" not found. Check ` +\n        \"`list_sandbox_providers`, then `setup_sandbox_provider` if it needs credentials.\",\n    }\n  }\n  const spec: SandboxSpec =\n    typeof opts.sandbox === \"string\" ? { provider: opts.sandbox, config: {} } : opts.sandbox\n  // Reuse target (PR3) — `agent_start.sandbox.reuse`. Undefined ⇒ boot a\n  // fresh box, exactly as PR2. Also feeds `resolveLifecyclePolicy` below:\n  // a reused box defaults to PAUSE (not kill) on close, since it would be\n  // pointless to reconnect to a box that's about to be killed anyway.\n  const reuseSandboxId = typeof opts.sandbox === \"object\" ? opts.sandbox.reuse : undefined\n  const lifecyclePolicy = resolveLifecyclePolicy(spec, reuseSandboxId !== undefined)\n\n  // AIP-36 `env.passthrough` / `env.auth.state.env` — the only env-var\n  // slugs a spec actually declares today (see PLAN §4 AMENDMENT: no\n  // provider-required-secrets surface exists on `SandboxProviderHandle`\n  // yet, so this is the full slug set).\n  const passthrough = spec.env?.passthrough ?? []\n  const authEnv = spec.env?.auth?.state?.env ?? []\n  const slugs = Array.from(new Set([...passthrough, ...authEnv]))\n\n  let host: SandboxAgentSessionHost\n  try {\n    host = await createSandboxAgentSessionHost({\n      provider: handle.provider,\n      spec,\n      ...(reuseSandboxId !== undefined ? { sandboxId: reuseSandboxId } : {}),\n      // AMENDMENT — do NOT default to `process.env`: always pass an\n      // explicit resolver backed by the host's own secrets broker\n      // (`mcp-credential-deps.ts`'s `resolveSandboxSecret`, the same DI\n      // seam `resolveMcpCredentialHeaders` above uses), never the bare\n      // `defaultProcessEnvResolver` fallback `@agentproto/sandbox` would\n      // otherwise apply when `resolver` is omitted.\n      secrets: { slugs, resolver: resolveSandboxSecret },\n    })\n  } catch (err) {\n    return reuseSandboxId !== undefined\n      ? {\n          ok: false,\n          code: \"sandbox_reconnect_failed\",\n          message:\n            `agent_start: sandbox reconnect failed (provider \"${providerSlug}\", sandbox ` +\n            `\"${reuseSandboxId}\") — ${err instanceof Error ? err.message : String(err)}`,\n        }\n      : {\n          ok: false,\n          code: \"sandbox_boot_failed\",\n          message:\n            `agent_start: sandbox boot failed (provider \"${providerSlug}\") — ` +\n            `${err instanceof Error ? err.message : String(err)}`,\n        }\n  }\n\n  let remoteSessionId: string\n  try {\n    const remoteDesc = await host.start({\n      adapter: opts.adapter,\n      cwd: opts.cwd,\n      ...(opts.mcpServers ? { mcpServers: toMcpServerMounts(opts.mcpServers) } : {}),\n      ...(opts.model ? { model: opts.model } : {}),\n      ...(opts.effort ? { effort: opts.effort } : {}),\n      ...(opts.label ? { label: opts.label } : {}),\n    })\n    remoteSessionId = remoteDesc.id\n  } catch (err) {\n    await host.stop().catch(() => undefined)\n    return {\n      ok: false,\n      code: \"sandbox_proxy_failed\",\n      message:\n        `agent_start: the sandbox's own agent_start failed for adapter \"${opts.adapter}\" — ` +\n        `${err instanceof Error ? err.message : String(err)}`,\n    }\n  }\n\n  return {\n    ok: true,\n    agentSession: createSandboxAgentSessionProxy({ host, remoteSessionId, lifecyclePolicy }),\n    commandPreview: `sandbox:${providerSlug} → ${opts.adapter}`,\n    sandboxId: host.sandboxId,\n    sandboxTeardown: lifecyclePolicy.teardown,\n  }\n}\n\n/**\n * `SandboxSecretsConfig.resolver` — resolves an AIP-36 env slug through the\n * host's secrets broker (`mcp-credential-deps.ts`), never `process.env`\n * directly. Returns null (not a thrown error) on any failure or when no\n * broker is wired — `@agentproto/sandbox`'s own `resolveSandboxSecretsEnv`\n * is what turns a null into the loud \"missing secret\" failure, so a\n * provider that genuinely needs the slug still fails the boot instead of\n * silently running with an empty value.\n */\nasync function resolveSandboxSecret(slug: string): Promise<string | null> {\n  const { resolveSandboxSecret: resolve } = getMcpCredentialDeps()\n  if (!resolve) return null\n  try {\n    return await resolve(slug)\n  } catch (err) {\n    console.warn(\n      `[agent_start] sandbox secret resolution failed for \"${slug}\": ` +\n        `${err instanceof Error ? err.message : String(err)}`,\n    )\n    return null\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\"\nimport { listRoles, spawnableRolesFor } from \"./role.js\"\nimport type { RoleProfile } from \"./role.js\"\nimport { loadDefaultRoleRegistry } from \"./role-registry.js\"\nimport { SandboxSpecSchema } from \"@agentproto/sandbox\"\nimport type { SandboxProviderResolver } from \"./sandbox-adapters.js\"\n\n/** `SandboxSpecSchema` plus the PR3 reuse field — `{ provider, reuse: \"<sandboxId>\" }`\n *  reconnects to an existing box (via `SandboxProvider.connect`) instead of\n *  booting a fresh one. Built from the same shape (rather than `.extend()`)\n *  so it stays a plain `.strict()` object independent of that schema's own\n *  extend semantics. */\nconst sandboxSpecWithReuseSchema = z\n  .object({\n    ...SandboxSpecSchema.shape,\n    reuse: z\n      .string()\n      .min(1)\n      .optional()\n      .describe(\n        \"Existing sandbox id (a prior session's `sandboxId`) to reconnect to instead of \" +\n          \"booting a new box. Requires the provider to support reconnect (e.g. e2b); \" +\n          \"omit to boot fresh (default).\"\n      ),\n  })\n  .strict()\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\n// ── session-id argument aliasing ──────────────────────────────────────────\n// `agent_start` returns the session as `{ \"id\": \"sess_…\" }`, but the drive\n// tools (`agent_prompt` / `agent_output` / `agent_kill`) historically took\n// `sessionId`. Passing the natural `{ id }` shape back therefore failed with a\n// Zod error, forcing a failed call per tool to learn the field name. These\n// tools now accept EITHER field (additive, back-compat): `sessionId` stays the\n// documented primary; `id` is a first-class alias so an agent can pipe\n// `agent_start`'s return straight through.\nconst sessionIdField = z\n  .string()\n  .optional()\n  .describe(\n    \"Session id (as returned by agent_start). Accepts either `sessionId` or \" +\n      \"its alias `id` — pass whichever you have.\",\n  )\nconst sessionIdAliasField = z\n  .string()\n  .optional()\n  .describe(\"Alias for `sessionId` — the `id` field returned by agent_start.\")\n\n/** Coalesce the `sessionId` / `id` alias pair. */\nfunction resolveSessionIdArg(input: {\n  sessionId?: string\n  id?: string\n}): string | undefined {\n  return input.sessionId ?? input.id\n}\n\n/** Uniform error when neither `sessionId` nor `id` was supplied. */\nfunction missingSessionIdError(tool: string): {\n  content: { type: \"text\"; text: string }[]\n  isError: true\n} {\n  return {\n    content: [\n      {\n        type: \"text\",\n        text: `${tool}: missing session id — pass \\`sessionId\\` (or its alias \\`id\\`).`,\n      },\n    ],\n    isError: true,\n  }\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  /** Loads the custom (pack-carried) role registry — forwarded to\n   *  `spawnAgentSession` (gates `agent_start`) and used directly by\n   *  `role_list` (the introspection-only mirror of the same data), so\n   *  the two can never disagree. Defaults to `loadDefaultRoleRegistry()`\n   *  (`~/.agentproto/roles/` + adapter-carried packs) when omitted;\n   *  tests inject a stub registry to avoid touching the real\n   *  filesystem. */\n  loadRoleRegistry?: () => Promise<Record<string, RoleProfile>>\n  /** Resolves an `agent_start.sandbox` slug (or an inline spec's own\n   *  `.provider`) to a concrete sandbox provider handle — forwarded to\n   *  `spawnAgentSession`. Omitted → `sandbox` is rejected with\n   *  `sandbox_provider_not_found`. */\n  resolveSandboxProvider?: SandboxProviderResolver\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    loadRoleRegistry,\n    resolveSandboxProvider,\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      idempotencyKey: z\n        .string()\n        .min(1)\n        .optional()\n        .describe(\n          \"Caller-declared 'this is the same logical spawn' token. A retried \" +\n            \"agent_start call (e.g. after a slow/lost response) that repeats the \" +\n            \"same `idempotencyKey` for the same `adapter`+`cwd` within ~30s of a \" +\n            \"successful spawn gets that SAME session's descriptor back instead of \" +\n            \"forking a second process — set `deduped: true` on the response so \" +\n            \"you can tell. Omit to spawn unconditionally (today's behaviour, and \" +\n            \"still required for deliberate concurrent spawns into the same cwd — \" +\n            \"this field can't distinguish a retry from an intentional duplicate \" +\n            \"spawn, only your own declared key can). Recommended for any caller \" +\n            \"that might retry a spawn it can't otherwise confirm succeeded.\"\n        ),\n      permissionHold: mcpBool\n        .optional()\n        .describe(\n          \"Start the session in permission-hold mode: every ACP permission \" +\n            \"request the agent raises (Write, Bash, …) is SURFACED and HELD in \" +\n            \"the cross-session inbox (`permissions_list` / `permissions_respond`) \" +\n            \"instead of auto-answered, and the agent blocks until a human/\" +\n            \"orchestrator approves or denies it. Default false = today's \" +\n            \"auto-answer behaviour. ACP adapters only; others ignore it.\"\n        ),\n      options: jsonTolerant(\n        z.record(z.string(), z.union([z.boolean(), z.number(), z.string()]))\n      )\n        .optional()\n        .describe(\n          \"Manifest-declared option id → value map (AIP-45 `options`), applied at \" +\n            \"spawn time alongside `mode` — e.g. hermes' `skills` (string, prepended \" +\n            \"before the subcommand) or a boolean flag appended when true. Each value \" +\n            \"is validated against the option's declared `type`/`enum`/`min`/`max`; \" +\n            \"unknown ids reject. Adapters that don't declare a given option id reject it.\"\n        ),\n      skills: jsonTolerant(z.array(z.string()))\n        .optional()\n        .describe(\n          \"Normalized, adapter-agnostic skill ids for this session (e.g. \" +\n            \"['agentproto']). Merges with `~/.agentproto/config.json`'s \" +\n            \"`defaults.skills` / `defaults.adapters.<slug>.skills` (global < \" +\n            \"per-adapter < this field, which REPLACES rather than unions the \" +\n            \"config defaults when provided — a deliberate exact set). Folded \" +\n            \"into `options.skills` using the resolved adapter's declared \" +\n            \"shape (e.g. hermes' comma-joined `--skills a,b`); adapters with \" +\n            \"no declared `skills` option (e.g. claude-code, which auto-\" +\n            \"discovers from `~/.claude/skills`) ignore this — no-op.\"\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      auth: jsonTolerant(\n        z.object({\n          mode: z.enum([\"subscription\", \"api-key\"]).optional(),\n          token: z.string().optional(),\n          apiKey: z.string().optional(),\n        })\n      )\n        .optional()\n        .describe(\n          \"Deterministic billing-auth mode + EXPLICIT credential for adapters that \" +\n            \"declare it (today: claude-code). EXPLICIT credential selection, not \" +\n            \"scrub-by-absence: `mode` picks 'subscription' (default) or 'api-key'; \" +\n            \"`token`/`apiKey` (matching the resolved mode) is the secret VALUE, merged \" +\n            \"against `~/.agentproto/config.json`'s `defaults.adapters.claude-code.auth` \" +\n            \"(this field's `mode` wins; the credential for the resolved mode wins over \" +\n            \"the matching config field). For claude-code, 'subscription' SETS \" +\n            \"CLAUDE_CODE_OAUTH_TOKEN to \" +\n            \"`token` (a bearer token minted via `claude setup-token` — bills the Max/Pro \" +\n            \"subscription, not API credits) and DELETES ANTHROPIC_API_KEY + the cloud-\" +\n            \"provider redirect toggles + ANTHROPIC_BASE_URL. 'api-key' SETS \" +\n            \"ANTHROPIC_API_KEY to `apiKey` and DELETES ANTHROPIC_AUTH_TOKEN — the \" +\n            \"deliberate 'bill the API' choice. FAILS FAST (refuses the spawn, no \" +\n            \"fallback) when the resolved mode has no credential configured anywhere. \" +\n            \"The secret is never logged or echoed back — only a fingerprint appears on \" +\n            \"the session descriptor / `agent_sessions_list`. Adapters that don't declare \" +\n            \"this vocabulary ignore this field entirely.\"\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            headers: z\n              .record(z.string(), z.string())\n              .optional()\n              .describe(\n                \"Static HTTP headers sent with every request to an `http` or `sse` \" +\n                  \"MCP server (e.g. a fixed auth token). Ignored for `stdio` transports.\"\n              ),\n            credentialRef: z\n              .string()\n              .optional()\n              .describe(\n                \"Brokered credential path resolved at spawn time into additional \" +\n                  \"`headers` (typically `Authorization`). The actual secret never lives \" +\n                  \"in env or config; brokered headers win on collision with `headers`.\"\n              ),\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      role: z\n        .string()\n        .optional()\n        .describe(\n          \"Spawn-time role gating whether this child may itself delegate \" +\n            \"(spawn/drive further children) and, if it can, which roles IT \" +\n            \"may in turn spawn. Built-ins: 'executor' = leaf, cannot \" +\n            \"delegate — `orchestrator` is ignored and `agent_start`/\" +\n            \"`agent_prompt` are stripped from its default toolset, \" +\n            \"regardless of `promptAppend`. 'supervisor' = may delegate \" +\n            \"(today's default behaviour). Custom roles installed as role \" +\n            \"packs (see `role_list`) resolve the same way. A spawn made \" +\n            \"THROUGH an orchestrator is additionally gated by the \" +\n            \"privilege lattice: the calling role may only spawn a role \" +\n            \"allowlisted in its `spawnableRoles`, or — open mode, the \" +\n            \"default — at or below its own `level` (never something MORE \" +\n            \"privileged than itself). Omit `role` to \" +\n            \"derive from spawn depth (root spawns default to supervisor; \" +\n            \"spawns made through an orchestrator default to executor — see \" +\n            \"`defaultRoleDepthCutoff` in config.json's `defaults` block).\"\n        ),\n      promptAppend: z\n        .string()\n        .optional()\n        .describe(\n          \"One-off runtime text layered ON TOP of the resolved role's \" +\n            \"disposition and prepended to `prompt` — it specializes the \" +\n            \"disposition, it cannot replace it, and it cannot re-open the \" +\n            \"tool gate (an executor asked to 'delegate anyway' via this \" +\n            \"field still has no delegation tools).\"\n        ),\n      trace: z\n        .boolean()\n        .optional()\n        .describe(\n          \"Emit Langfuse observability traces for this session (prompt/completion + \" +\n            \"tool spans + tokens/cost). Off by default; requires langfuse eval-reporter \" +\n            \"creds configured.\"\n        ),\n      sandbox: jsonTolerant(\n        z.union([\n          z\n            .string()\n            .min(1)\n            .describe(\"Sandbox provider slug from `list_sandbox_providers` (e.g. 'local', 'e2b').\"),\n          sandboxSpecWithReuseSchema.describe(\n            \"Inline AIP-36 SandboxDefinition — boots this exact spec instead of a catalog slug. \" +\n              \"Set `reuse` to reconnect to an existing sandbox id instead of booting fresh.\"\n          ),\n        ])\n      )\n        .optional()\n        .describe(\n          \"Run this session inside a sandbox instead of on the host — pass a provider \" +\n            \"slug (see `list_sandbox_providers`) or an inline AIP-36 SandboxDefinition \" +\n            \"object. The daemon boots the sandbox, spawns `adapter` on the box's OWN \" +\n            \"agentproto daemon, and proxies the conversation back onto this session — \" +\n            \"`agent_prompt`/`agent_output`/`agent_kill` behave exactly as they do for a \" +\n            \"local spawn, and the transcript stays readable here even after the box is \" +\n            \"torn down. Omit to run locally (default). Pass an inline spec with `reuse: \" +\n            \"\\\"<sandboxId>\\\"` (from a prior session's `sandboxId`) to reconnect to an \" +\n            \"existing box instead — by default such a box is PAUSED (not killed) on \" +\n            \"session close so it stays reusable; set `lifecycle.destroy_on` to always kill it.\"\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          loadRoleRegistry,\n          resolveSandboxProvider,\n        },\n        input,\n      )\n      if (result.ok) {\n        const body = {\n          ...result.descriptor,\n          ...(result.output ? { output: result.output } : {}),\n          ...(result.deduped ? { deduped: true } : {}),\n        }\n        return {\n          content: [{ type: \"text\", text: JSON.stringify(body, null, 2) }],\n        }\n      }\n      // The orchestrator guardrail errors + the role-spawn gate have\n      // always been reported as a structured JSON blob (error/message/\n      // +details); every other failure is a plain-text message.\n      // Preserved verbatim here so the MCP tool's output shape doesn't\n      // change under this refactor.\n      const text =\n        result.code === \"orchestrator_max_depth_exceeded\" ||\n        result.code === \"orchestrator_child_quota_exceeded\" ||\n        result.code === \"role_spawn_denied\"\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. By default, \" +\n      \"a session mid-turn rejects the new prompt — pass `interrupt: true` to \" +\n      \"cancel the in-flight turn and redirect the SAME session onto this \" +\n      \"prompt instead, without losing its context (unlike `agent_kill`, \" +\n      \"which ends the session entirely). `interrupt` is a no-op on an \" +\n      \"already-idle session.\",\n    {\n      sessionId: sessionIdField,\n      id: sessionIdAliasField,\n      prompt: z.string().min(1).describe(\"The next user turn (plain text).\"),\n      interrupt: z\n        .boolean()\n        .optional()\n        .describe(\n          \"When true and the session is mid-turn, cancel the in-flight \" +\n            \"turn and deliver this prompt on the same session instead of \" +\n            \"rejecting. No-op when the session is already idle. Default false \" +\n            \"(mid-turn rejects, as today).\"\n        ),\n    },\n    async input => {\n      const sessionId = resolveSessionIdArg(input)\n      if (!sessionId) return missingSessionIdError(\"agent_prompt\")\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        // (and not `interrupt`ed) surfaces here as a real tool error\n        // instead of a lying `{queued: true}` for a prompt that goes\n        // nowhere. The caller polls agent_output for the turn's actual\n        // progress/completion.\n        await registry.enqueuePrompt(sessionId, input.prompt, {\n          interrupt: input.interrupt,\n        })\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify(\n                { ok: true, 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: sessionIdField,\n      id: sessionIdAliasField,\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 sessionId = resolveSessionIdArg(input)\n      if (!sessionId) return missingSessionIdError(\"agent_output\")\n      const desc = registry.get(sessionId)\n      if (!desc) {\n        return {\n          content: [\n            { type: \"text\", text: `agent_output: no session \"${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(sessionId, (line, _stream) => {\n        lines.push(line)\n      })\n      if (unsub) unsub()\n      const tail = lines.slice(-limit)\n      let output = input.clean ? cleanAgentLines(tail) : tail\n      // Resilience: a tool-busy turn emits `[tool]`/`[tool-result]` lines but\n      // little or no assistant text, and clean mode strips those — so an agent\n      // working hard (reading, writing files, installing) surfaces as an EMPTY\n      // `lines`, which reads as \"idle/stuck\" to a polling orchestrator. When\n      // clean output is empty but the ring HAS content, fall back to the\n      // ANSI-stripped raw tail so the session's activity is always visible and\n      // polling agent_output is a reliable liveness/progress signal.\n      let activityFallback = false\n      if (input.clean && output.length === 0 && tail.length > 0) {\n        output = tail\n          .map(stripAnsi)\n          .map(l => l.trimEnd())\n          .filter(l => l.trim().length > 0)\n          .slice(-limit)\n        activityFallback = output.length > 0\n      }\n      return {\n        content: [\n          {\n            type: \"text\",\n            text: JSON.stringify(\n              {\n                sessionId,\n                status: desc.status,\n                lastOutputAt: desc.lastOutputAt,\n                // Distinct liveness heartbeat: advances on ANY adapter-process\n                // activity (streamed thinking/text deltas, tool traffic), even\n                // across a stretch where the coalesced ring emits no new LINE\n                // and `lastOutputAt` looks frozen. A monitor compares the two —\n                // `lastActivityAt` moving while `lastOutputAt` is stale means\n                // \"alive and working\", not \"stalled\". See SessionDescriptor.\n                ...(desc.lastActivityAt ? { lastActivityAt: desc.lastActivityAt } : {}),\n                // processAlive is a live OS query stamped by registry.get().\n                ...(desc.processAlive !== undefined ? { processAlive: desc.processAlive } : {}),\n                // Surfaced so a caller can distinguish \"idle\" from \"mid tool\n                // call\" without guessing from empty output.\n                ...(desc.blockedOn ? { blockedOn: desc.blockedOn } : {}),\n                ...(activityFallback ? { activityFallback: true } : {}),\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: sessionIdField,\n      id: sessionIdAliasField,\n    },\n    async input => {\n      const sessionId = resolveSessionIdArg(input)\n      if (!sessionId) return missingSessionIdError(\"agent_kill\")\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(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 \"${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,\n                  },\n                  null,\n                  2,\n                ),\n              },\n            ],\n            isError: true,\n          }\n        }\n      }\n      const ok = registry.kill(sessionId)\n      return {\n        content: [\n          {\n            type: \"text\",\n            text: JSON.stringify({ ok, 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  // ── role_list ─────────────────────────────────────────────────\n  server.tool(\n    \"role_list\",\n    \"Enumerate every spawn-time role known to the daemon — the two \" +\n      \"built-ins (executor, supervisor) plus any custom role installed as \" +\n      \"a role pack. Read-only: pure visibility into the same registry \" +\n      \"`agent_start`'s `role` field and privilege-lattice spawn gate use — \" +\n      \"this tool never itself grants or denies a spawn. Use before \" +\n      \"`agent_start` with `orchestrator` to discover which roles this \" +\n      \"session may in turn spawn.\",\n    {},\n    async () => {\n      try {\n        const registry = loadRoleRegistry ? await loadRoleRegistry() : await loadDefaultRoleRegistry()\n        const roles = listRoles(registry).map(role => ({\n          name: role.name,\n          level: role.level,\n          delegation: role.toolPolicy.delegation,\n          spawnable: spawnableRolesFor(role, registry).map(child => child.name),\n        }))\n        return {\n          content: [{ type: \"text\", text: JSON.stringify({ roles }, null, 2) }],\n        }\n      } catch (err) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: `role_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\n        .string()\n        .optional()\n        .describe(\n          \"agentproto session id (sess_xxx), adapter-native id, or session name. \" +\n            \"Accepts either `sessionId` or its alias `id`.\",\n        ),\n      id: sessionIdAliasField,\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 sessionId = resolveSessionIdArg(input)\n      if (!sessionId) return missingSessionIdError(\"agent_export\")\n      const result = await doExport({\n        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 resume id of a\n   *  session in the given workspace. Returns the id or null when nothing\n   *  eligible.\n   *\n   *  When `expectedId` is set the session's own conversation id is known\n   *  (agent-cli descriptors carry it as `adapterSessionId`; for\n   *  claude-code it IS the on-disk `.jsonl` uuid — see acp-host.ts) and\n   *  the probe MUST bind to exactly that transcript: it confirms\n   *  `<expectedId>` exists and returns it, else null. It never falls\n   *  through to a mtime guess in that case — resuming *some other*\n   *  session that merely shares the cwd is a silent cross-session\n   *  correctness bug, strictly worse than not resuming at all.\n   *\n   *  Only when `expectedId` is absent (e.g. a raw PTY claude session that\n   *  never had an ACP session id) does the probe fall back to\n   *  most-recently-modified, filtered to files at-or-after `prevStartedAt`\n   *  (avoids resuming an unrelated prior conversation).\n   *\n   *  Skip when the adapter doesn't persist sessions externally. */\n  fsProbe?(\n    cwd: string,\n    prevStartedAt: string,\n    expectedId?: string,\n  ): 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).\n *\n * When `expectedId` is supplied the caller already knows this session's\n * own conversation id, so the probe binds to exactly `<expectedId>.jsonl`\n * (returning the id iff that file exists) rather than guessing. This is\n * the fix for a silent cross-session resume: the old mtime-latest path\n * would, when several claude sessions share a cwd, hand back a DIFFERENT\n * (often concurrent, still-active) session's transcript — dropping the\n * caller into unrelated work with no error. Only when `expectedId` is\n * absent do we fall back to the UUID of the most-recently modified\n * `.jsonl`, filtered to files at-or-after `prevStartedAt`.\n */\nfunction probeMtimeLatestJsonl(\n  storeRel: string,\n): (\n  cwd: string,\n  prevStartedAt: string,\n  expectedId?: string,\n) => Promise<string | null> {\n  return async (cwd, prevStartedAt, expectedId) => {\n    const encoded = cwd.replace(/\\//g, \"-\")\n    const dir = resolve(homedir(), storeRel, encoded)\n    // Ground truth beats heuristic: resume the session we were actually\n    // asked to, never whichever transcript happens to be newest.\n    if (expectedId) {\n      try {\n        await fs.stat(join(dir, `${expectedId}.jsonl`))\n        return expectedId\n      } catch {\n        return null\n      }\n    }\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  // Pass the session's own conversation id (agent-cli sets it as\n  // `adapterSessionId`; for claude-code it equals the on-disk `.jsonl`\n  // uuid — acp-host.ts pins them equal) so the probe binds to THIS\n  // session's transcript instead of the newest one in the cwd. Without\n  // it, a restart of a session that shares a cwd with a concurrent one\n  // could silently resume the wrong conversation.\n  const id = await strategy.fsProbe(\n    prev.cwd,\n    prev.startedAt,\n    prev.adapterSessionId,\n  )\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 * Shared agent-session restart core — the \"agent\" branch of\n * `decideRestartStrategy` (resume-strategies.ts), factored out so both\n * the `session_restart` MCP tool (session-tools.ts) and the cron\n * scheduler's `prompt-session` action (cron-scheduler.ts) resume a dead\n * session via the exact same path. PTY strategies stay inline in\n * session-tools.ts — cron `prompt-session` jobs only ever target\n * agent-cli sessions.\n *\n * Lives in its own module (not resume-strategies.ts) because\n * resume-strategies.ts is deliberately duck-typed against a minimal\n * shape to avoid a value-level import of sessions.ts (see its own\n * top-of-file comment). This module needs the real `SessionsRegistry`\n * / `AgentAdapterResolver` types, so it can't share that constraint.\n *\n * Billing-auth resolution (money bug fix): a restarted session used to\n * respawn with NO auth resolution at all, so a session pinned to\n * `subscription` billing silently came back on whatever the daemon's\n * ambient env happened to hold (e.g. a leaked `ANTHROPIC_API_KEY`) —\n * bills org credits under a Max/Pro-pinned session with no signal\n * anywhere. This module now re-runs the SAME resolver\n * `session-spawn.ts` uses (`resolveAuthSpec`, fed by\n * `resolveSpawnDefaults`), sourcing the requested MODE from the prior\n * descriptor's `auth.mode` (the secret itself is never persisted there,\n * by design — see `SessionDescriptor.auth`) and re-resolving the actual\n * credential from `~/.agentproto/config.json` / providers.json, same\n * merge order as a fresh spawn. The logic is duplicated rather than\n * shared with `session-spawn.ts` because that file is out of scope for\n * this fix (see its own callers) — both call sites must stay in sync by\n * inspection, same as they already do for `decideRestartStrategy`.\n */\n\nimport type { SessionDescriptor, SessionsRegistry, SessionAuthEcho } from \"./sessions.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\nimport {\n  decideRestartStrategy,\n  augmentWithFsResume,\n  describeResumePath,\n} from \"./resume-strategies.js\"\nimport {\n  resolveSpawnDefaults,\n  resolveAuthSpec,\n  type SpawnDefaultsConfig,\n  type DefaultsAdapterAuthConfig,\n  type ResolvedAuthSpec,\n  type AuthEcho,\n} from \"./spawn-defaults.js\"\nimport { getProviderKey } from \"./providers-store.js\"\nimport { getModelProvider } from \"@agentproto/model-catalog/llm\"\nimport { loadConfig } from \"./config.js\"\n\nexport interface RestartAgentSessionResult {\n  desc: SessionDescriptor\n  resumedFrom: string\n  resumeVia: string\n  resumeFallback?: boolean\n}\n\nexport interface RestartAgentSessionOptions {\n  /**\n   * Skip `decideRestartStrategy`'s PTY-native preference (e.g. claude-code's\n   * `claude --resume <id>`, chosen whenever a native resume id is found —\n   * see resume-strategies.ts) and always resume at the ACP level via\n   * `prev.adapterSessionId` instead. A PTY-resumed session is a raw\n   * terminal — it has no `sendPrompt`, only `writeTerminalInput` — so\n   * any caller that needs to keep sending structured prompts to the\n   * resumed session (the cron scheduler's `prompt-session` action) MUST\n   * set this; there's nothing \"less correct\" about ACP resume for\n   * claude-code specifically, it's simply the strategy that yields an\n   * agent-cli session instead of a PTY one.\n   */\n  forceAgentResume?: boolean\n  /** Loads config.json's `defaults` block — same seam as\n   *  `SpawnAgentSessionDeps.loadDefaultsConfig` in session-spawn.ts.\n   *  Defaults to reading the real `~/.agentproto/config.json` via\n   *  `loadConfig` when omitted; tests inject a stub to avoid touching\n   *  the real file. */\n  loadDefaultsConfig?: () => Promise<SpawnDefaultsConfig | undefined>\n}\n\n/**\n * Resume an agent-cli session's conversation via provider-native or\n * ACP-level resume (never PTY — throws for `pty-native`/`pty-plain`/\n * `unsupported` strategies, unless `forceAgentResume` is set). Falls\n * back to a fresh spawn (no continuity) if the adapter rejects the\n * resume id with a \"not found\" error — same behaviour `session_restart`\n * has always had for a prior session that died before its first turn.\n */\nexport async function restartAgentSession(\n  registry: SessionsRegistry,\n  resolveAgentAdapter: AgentAdapterResolver,\n  prev: SessionDescriptor,\n  opts: RestartAgentSessionOptions = {},\n): Promise<RestartAgentSessionResult> {\n  // `forceAgentResume` never consults `augmented` (see the `resumeVia`\n  // comment below) — skip the FS probe entirely rather than pay for I/O\n  // whose result is discarded.\n  const augmented = opts.forceAgentResume ? prev : await augmentWithFsResume(prev)\n  const strategy = opts.forceAgentResume\n    ? ({ kind: \"agent\", resumeSessionId: prev.adapterSessionId } as const)\n    : decideRestartStrategy(augmented)\n\n  if (strategy.kind !== \"agent\") {\n    throw new Error(\n      `restartAgentSession: session '${prev.id}' resolved to a '${strategy.kind}' ` +\n        \"restart strategy — only agent-adapter sessions are resumable this way.\",\n    )\n  }\n\n  const adapterSlug = prev.adapterSlug\n  if (!adapterSlug) {\n    throw new Error(\n      \"restartAgentSession: internal error — agent resume strategy without adapterSlug\",\n    )\n  }\n\n  const resolved = await resolveAgentAdapter(adapterSlug)\n  if (!resolved) {\n    throw new Error(`restartAgentSession: adapter '${adapterSlug}' not found.`)\n  }\n\n  let cwd = prev.cwd\n  if (!cwd) console.warn(`[restartAgentSession] no cwd on prior descriptor ${prev.id} — falling back to daemon's cwd ${process.cwd()}`)\n  cwd ??= process.cwd()\n\n  // ── Billing-auth re-resolution ───────────────────────────────────\n  // Mirrors session-spawn.ts's resolution exactly (same resolver, same\n  // config precedence), except the requested MODE comes from the prior\n  // descriptor's echo rather than a fresh `agent_start.auth` call — the\n  // credential itself is never on the descriptor (only the fingerprint\n  // is), so it's re-resolved from config/providers.json here, not\n  // copied. No prior `auth` echo (adapter with no `authDescriptor`, or\n  // a session that never got one) ⇒ `explicitAuthInput` stays\n  // undefined, which resolves exactly like a fresh spawn with no\n  // explicit `auth` — falls through to `defaults.adapters.<slug>.auth`,\n  // never inventing a mode. `resolveAuthSpec` throws\n  // `AuthResolutionError` (unsupported mode) and the driver's\n  // `startSession` throws `missing_auth_credential` (engaged mode, no\n  // credential) — both propagate uncaught, exactly the fail-loud\n  // contract `agent_start` already has. Never logged/echoed here beyond\n  // the fingerprint already carried on `AuthEcho`.\n  let authSpec: ResolvedAuthSpec | undefined\n  let authEcho: AuthEcho | undefined\n  if (resolved.authDescriptor) {\n    const configDefaults = opts.loadDefaultsConfig\n      ? await opts.loadDefaultsConfig()\n      : (await loadConfig()).defaults\n    const explicitAuthInput: DefaultsAdapterAuthConfig | undefined = prev.auth\n      ? { mode: prev.auth.mode }\n      : undefined\n    const spawnDefaults = resolveSpawnDefaults(configDefaults, adapterSlug, {\n      auth: explicitAuthInput,\n    })\n    const authModel = prev.model ?? resolved.defaultModel\n    const pinnedProvider = spawnDefaults.auth.provider\n    const resolvedProvider =\n      pinnedProvider ??\n      resolved.authDescriptor.provider ??\n      (authModel ? getModelProvider(authModel) : undefined)\n    // Same money-safety gate as session-spawn.ts: the providers.json store\n    // is only consulted when the resolved auth is EXPLICIT (never for an\n    // unconfigured `always`-enforcing adapter, which must fail-fast instead\n    // of silently picking up a leftover store key).\n    const apiKeyStoreCredential =\n      resolvedProvider &&\n      spawnDefaults.auth.explicit &&\n      spawnDefaults.auth.apiKeyCredential === undefined\n        ? await getProviderKey(resolvedProvider)\n        : undefined\n    const result = resolveAuthSpec({\n      descriptor: resolved.authDescriptor,\n      ...(authModel ? { model: authModel } : {}),\n      ...(pinnedProvider ? { requestedProvider: pinnedProvider } : {}),\n      ...(spawnDefaults.auth.requestedMode\n        ? { requestedMode: spawnDefaults.auth.requestedMode }\n        : {}),\n      explicit: spawnDefaults.auth.explicit,\n      ...(spawnDefaults.auth.subscriptionCredential !== undefined\n        ? { subscriptionCredential: spawnDefaults.auth.subscriptionCredential }\n        : {}),\n      ...(spawnDefaults.auth.apiKeyCredential !== undefined\n        ? { apiKeyConfigCredential: spawnDefaults.auth.apiKeyCredential }\n        : {}),\n      ...(apiKeyStoreCredential !== undefined ? { apiKeyStoreCredential } : {}),\n    })\n    if (result) {\n      authSpec = result.spec\n      authEcho = result.echo\n    }\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      ...(authSpec ? { auth: authSpec } : {}),\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      // Verifiability echo (never the credential) — see the auth\n      // resolution block above. Absent when no credential resolved,\n      // same as session-spawn.ts.\n      ...(authEcho?.fingerprint\n        ? {\n            auth: {\n              mode: authEcho.authMode,\n              fingerprint: authEcho.fingerprint,\n              provider: authEcho.provider,\n              credentialSource: authEcho.credentialSource,\n              setEnv: authEcho.setEnv,\n            } satisfies SessionAuthEcho,\n          }\n        : {}),\n    })\n    liveSessionId = desc.id\n    return desc\n  }\n\n  let desc: SessionDescriptor\n  let resumeFallback = false\n  // Tracks whether the spawn that actually SUCCEEDED carried a resume\n  // id — distinct from `strategy.resumeSessionId`, which reflects only\n  // what we *attempted*. A session that died before its first ACP turn\n  // never got one (`prev.adapterSessionId` is undefined), so the very\n  // first `spawnWithResume` call below \"succeeds\" with no continuity at\n  // all — that must be reported the same as an explicit not-found\n  // fallback, or the caller is told a resume happened when it didn't.\n  let usedResumeSessionId = strategy.resumeSessionId\n  try {\n    desc = await spawnWithResume(strategy.resumeSessionId)\n  } catch (err) {\n    const msg = err instanceof Error ? err.message : String(err)\n    if (strategy.resumeSessionId && /not found|Resource not found/i.test(msg)) {\n      desc = await spawnWithResume(undefined)\n      usedResumeSessionId = undefined\n      resumeFallback = true\n    } else {\n      throw err\n    }\n  }\n\n  // `describeResumePath` reports whatever `decideRestartStrategy` would\n  // naturally prefer (e.g. claude-code's native `claude --resume`, if a\n  // resume id was found on disk) — misleading when `forceAgentResume`\n  // skipped that preference and went straight to ACP resume instead.\n  const resumeVia = !usedResumeSessionId\n    ? \"\"\n    : opts.forceAgentResume\n      ? \"resumed via ACP\"\n      : describeResumePath(augmented)\n\n  return {\n    desc,\n    resumedFrom: prev.id,\n    resumeVia,\n    ...(resumeFallback ? { resumeFallback: true } : {}),\n  }\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 * Per-session usage snapshot — the single place that decides a session's\n * `costUsd` and where that number came from.\n *\n * Two cost sources feed a session:\n *   - an adapter's own usage reader (`readUsage`, e.g. hermes reads its\n *     state.db) or an ACP `usage_update` that carries a `cost` block — these\n *     are authoritative, tagged `source: \"adapter\"`.\n *   - raw input/output token counts with NO adapter cost (ACP adapters like\n *     claude-code / mastracode that report tokens but not dollars) — here we\n *     price them ourselves against agentproto's in-repo LLM pricing catalog,\n *     tagged `source: \"computed\"`.\n *\n * When tokens exist but the model is absent from the catalog we NEVER\n * fabricate a price: `costUsd` is left undefined and the snapshot is tagged\n * `source: \"no-pricing\"`. A session with neither cost nor tokens is\n * `source: \"none\"`.\n *\n * This module is pure (the catalog lookup is injected) so the decision tree is\n * unit-testable without building the whole model catalog.\n */\n\nimport { resolvePricing } from \"@agentproto/model-catalog/llm\"\n\n/** Where a session's `costUsd` came from — see the module doc. */\nexport type UsageSource = \"adapter\" | \"computed\" | \"no-pricing\" | \"none\"\n\n/** Per-token USD prices for a model (per 1M tokens), the subset of the\n *  catalog's `LLMPricing` this module needs. */\nexport interface TokenPricing {\n  inputPer1M: number\n  outputPer1M: number\n}\n\n/** Pluggable pricing accessor — defaults to the in-repo catalog's\n *  `resolvePricing`, overridable in tests. Returns undefined for an\n *  unknown model (the caller then tags `no-pricing`). */\nexport type PricingResolver = (model: string) => TokenPricing | undefined\n\n/** Raw signals gathered over a turn, handed to `deriveSessionUsage`. */\nexport interface UsageComputeInput {\n  /** Requested model id — needed to look up per-token prices. */\n  model?: string\n  /** Cost the adapter reported directly (readUsage or usage_update.cost).\n   *  Present → authoritative, wins over token-based computation. */\n  adapterCostUsd?: number\n  tokensIn?: number\n  tokensOut?: number\n  contextSize?: number\n  contextUsed?: number\n}\n\n/** The resolved usage snapshot — the shape `session_usage` returns and the\n *  durable `usage_snapshot` transcript record carries. Cost/token fields are\n *  omitted when absent so a missing value never reads as a measured zero. */\nexport interface SessionUsage {\n  model?: string\n  costUsd?: number\n  tokensIn?: number\n  tokensOut?: number\n  contextSize?: number\n  contextUsed?: number\n  source: UsageSource\n}\n\n/**\n * A `contextUsed` greater than the reported `contextSize` cannot be tokens\n * currently occupying the context window — a window can't hold more tokens\n * than it is wide. At least one adapter's ACP server has been observed\n * putting a cumulative session-lifetime token total in this field instead\n * of a point-in-time occupancy figure (a long-running session's running\n * total can land tens of times past a fixed window, e.g. 14.2M reported\n * against a 200K window). A value that fails this check is provably not\n * what the field claims to be, so it's dropped rather than clamped: an\n * absent `contextUsed` reads as \"unmeasured,\" a clamped one would read as\n * a plausible but fabricated occupancy percentage. `contextSize` itself is\n * untouched — it's a static model property, not the corrupted signal.\n *\n * When `contextSize` isn't known yet, `contextUsed` can't be disproven —\n * it's passed through unchanged rather than discarded.\n */\nexport function plausibleContextUsed(\n  contextSize: number | undefined,\n  contextUsed: number | undefined,\n): number | undefined {\n  if (contextUsed === undefined) return undefined\n  if (contextSize !== undefined && contextUsed > contextSize) return undefined\n  return contextUsed\n}\n\nconst defaultResolver: PricingResolver = model => resolvePricing(model)\n\n/** Cost of `tokens` at `pricePer1M` USD/1M tokens. */\nfunction tokenCost(tokens: number | undefined, pricePer1M: number): number {\n  return tokens === undefined ? 0 : (tokens * pricePer1M) / 1_000_000\n}\n\n/**\n * Decide a session's usage snapshot + cost source from the raw signals.\n *\n * Priority: an adapter-reported cost wins; else price the tokens against the\n * catalog; else `none`. Never fabricates a price for an unpriced model.\n */\nexport function deriveSessionUsage(\n  input: UsageComputeInput,\n  resolve: PricingResolver = defaultResolver,\n): SessionUsage {\n  // Re-validated here, not just at usage_update ingestion: a rejected\n  // ingress update leaves whatever was already on the descriptor in place\n  // rather than clearing it, so a stale out-of-window value written before\n  // that guard existed (or reloaded from a pre-guard persisted snapshot)\n  // can still reach this call at a session's exit-time recap. Same\n  // reasoning as `plausibleContextUsed`'s own doc comment — drop, don't\n  // clamp.\n  const contextUsed = plausibleContextUsed(input.contextSize, input.contextUsed)\n  const base: Omit<SessionUsage, \"source\" | \"costUsd\"> = {\n    ...(input.model !== undefined ? { model: input.model } : {}),\n    ...(input.tokensIn !== undefined ? { tokensIn: input.tokensIn } : {}),\n    ...(input.tokensOut !== undefined ? { tokensOut: input.tokensOut } : {}),\n    ...(input.contextSize !== undefined ? { contextSize: input.contextSize } : {}),\n    ...(contextUsed !== undefined ? { contextUsed } : {}),\n  }\n\n  // 1. Adapter reported a cost directly — authoritative.\n  if (input.adapterCostUsd !== undefined) {\n    return { ...base, costUsd: input.adapterCostUsd, source: \"adapter\" }\n  }\n\n  // 2. We have token counts — price them against the in-repo catalog.\n  const hasTokens = input.tokensIn !== undefined || input.tokensOut !== undefined\n  if (hasTokens) {\n    const pricing = input.model !== undefined ? resolve(input.model) : undefined\n    if (!pricing) {\n      // Model absent from the catalog — surface the tokens, but NEVER\n      // invent a dollar figure.\n      return { ...base, source: \"no-pricing\" }\n    }\n    const costUsd =\n      tokenCost(input.tokensIn, pricing.inputPer1M) +\n      tokenCost(input.tokensOut, pricing.outputPer1M)\n    return { ...base, costUsd, source: \"computed\" }\n  }\n\n  // 3. Neither cost nor tokens — nothing measured.\n  return { ...base, source: \"none\" }\n}\n\n/** Descriptor-shaped fields `projectSessionUsage` reads. */\nexport interface UsageDescriptorFields {\n  model?: string\n  costUsd?: number\n  tokensIn?: number\n  tokensOut?: number\n  contextSize?: number\n  contextUsed?: number\n  usageSource?: UsageSource\n}\n\n/**\n * Project a session descriptor's persisted usage fields into the\n * `session_usage` response shape. Omits absent fields; defaults an\n * unstamped `usageSource` to `\"none\"`.\n */\nexport function projectSessionUsage(desc: UsageDescriptorFields): SessionUsage {\n  // Same re-validation as `deriveSessionUsage`, for the same reason: this\n  // formats a descriptor that may have been reloaded from a persisted\n  // snapshot written before `plausibleContextUsed` existed — a session\n  // that's already dead never gets a fresh usage_update to self-correct\n  // it, so a stale out-of-window value would otherwise surface forever.\n  const contextUsed = plausibleContextUsed(desc.contextSize, desc.contextUsed)\n  return {\n    ...(desc.model !== undefined ? { model: desc.model } : {}),\n    ...(desc.costUsd !== undefined ? { costUsd: desc.costUsd } : {}),\n    ...(desc.tokensIn !== undefined ? { tokensIn: desc.tokensIn } : {}),\n    ...(desc.tokensOut !== undefined ? { tokensOut: desc.tokensOut } : {}),\n    ...(desc.contextSize !== undefined ? { contextSize: desc.contextSize } : {}),\n    ...(contextUsed !== undefined ? { contextUsed } : {}),\n    source: desc.usageSource ?? \"none\",\n  }\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/**\n * The denylist complement of `withToolSubset` — blocks registration of\n * specific tool NAMES while letting everything else through unchanged.\n *\n * Used on the plain, full `/mcp` gateway (unlike the orchestrator's\n * curated allowlist, this surface registers fs/command/remote/etc. and\n * must keep doing so) to enforce the spawn-role-profiles tool gate: an\n * executor-role child still needs `command_execute`/fs tools to do real\n * work, it just must never see `agent_start`/`agent_prompt`. See\n * `DELEGATION_TOOL_NAMES` in `role.ts` and the `denyTools` query param\n * on `/mcp` in `http-server.ts`.\n */\nexport function withToolExclusion(\n  server: McpServer,\n  excluded: ReadonlySet<string>,\n): McpServer {\n  return new Proxy(server, {\n    get(target, prop, receiver) {\n      if (prop === \"tool\") {\n        return (name: string, ...rest: unknown[]): unknown => {\n          if (excluded.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      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 { 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 { restartAgentSession } from \"./session-restart-core.js\"\nimport {\n  loadImportedMcps,\n  saveImportedMcps,\n  addImport,\n  removeImport,\n} from \"./mcp-imports.js\"\nimport type { McpProxyRegistry } from \"./mcp-proxy.js\"\nimport { projectSessionUsage } from \"./usage.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 type { SandboxProviderResolver } from \"./sandbox-adapters.js\"\nimport {\n  loadWorkspacesConfig,\n  findWorkspace,\n  findWorkspaceByPath,\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  /** Forwarded to `registerAgentTools` — see\n   *  `RegisterAgentToolsOptions.loadRoleRegistry`. */\n  loadRoleRegistry?: RegisterAgentToolsOptions[\"loadRoleRegistry\"]\n  /** Forwarded to `registerAgentTools` — see\n   *  `RegisterAgentToolsOptions.resolveSandboxProvider`. */\n  resolveSandboxProvider?: SandboxProviderResolver\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  // ── session_usage ────────────────────────────────────────────────\n  server.tool(\n    \"session_usage\",\n    \"Return the usage accounting for one session — model, cumulative cost \" +\n      \"(USD), input/output token counts, and the latest context-window size / \" +\n      \"tokens-in-context. `source` says where `costUsd` came from: `adapter` \" +\n      \"(the adapter's own usage reader, e.g. hermes state.db, or a usage_update \" +\n      \"cost block), `computed` (tokens priced against agentproto's in-repo LLM \" +\n      \"catalog), `no-pricing` (tokens present but the model isn't in the catalog \" +\n      \"— cost is deliberately omitted, never fabricated), or `none` (nothing \" +\n      \"measured). Absent fields are omitted rather than zeroed. Same lookup as \" +\n      \"`session_list` / `session_restart` (by id or name).\",\n    {\n      idOrName: z\n        .string()\n        .min(1)\n        .describe(\"Session id or name — from `session_list`, alive or historical.\"),\n    },\n    async input => {\n      const desc = registry.findByIdOrName(input.idOrName)\n      if (!desc) {\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): mirror session_restart — a scoped orchestrator\n      // only sees usage for sessions in its own subtree.\n      if (callerScope) {\n        const subtree = collectSubtree(callerScope.ownerSessionId, registry.list())\n        if (!subtree.has(desc.id)) {\n          return {\n            content: [\n              {\n                type: \"text\",\n                text: JSON.stringify({\n                  error: \"orchestrator_session_out_of_scope\",\n                  message:\n                    `session_usage: session \"${desc.id}\" is not in your subtree — ` +\n                    \"a scoped orchestrator can only inspect sessions it (transitively) spawned.\",\n                  sessionId: desc.id,\n                }),\n              },\n            ],\n            isError: true,\n          }\n        }\n      }\n      const usage = projectSessionUsage(desc)\n      return {\n        content: [\n          { type: \"text\", text: JSON.stringify({ sessionId: desc.id, ...usage }, 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        if (!prev.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        // Shared with the cron scheduler's `prompt-session` action —\n        // see session-restart-core.ts.\n        const restarted = await restartAgentSession(registry, resolveAgentAdapter, prev)\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify(\n                {\n                  ...restarted.desc,\n                  resumedFrom: restarted.resumedFrom,\n                  resumeVia: restarted.resumeVia,\n                  ...(restarted.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      } else if (!input.workspaceSlug) {\n        // cwd given but no explicit slug — reverse-map it, exactly as\n        // spawnAgentSession does (session-spawn.ts). Without this the session\n        // lands in \"default\" even when its cwd sits inside a registered\n        // workspace, so it can never be grouped or filtered by project.\n        try {\n          const config = await loadWorkspacesConfig()\n          const ws = findWorkspaceByPath(config, cwd)\n          if (ws) resolvedSlug = ws.slug\n        } catch {\n          // no registry readable — keep \"default\"\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. `text`/`b64` are CONTENT written \" +\n      \"verbatim (a `\\\\n` inside `text` is a real line break in the composer). \" +\n      \"`enter: true` presses Enter as an ISOLATED keystroke: the content is \" +\n      \"written first, then a lone carriage return (\\\\r) is written in a SECOND, \" +\n      \"separate write. This matters for TUIs that do paste-detection (Claude \" +\n      \"Code in bracketed-paste mode): a text block ending in CR arrives as a \" +\n      \"multi-line PASTE (the CR becomes a newline, no submit), whereas a CR \" +\n      \"arriving on its own is seen as the Enter key → reliable submit. Use \" +\n      \"`b64` to send exact control bytes (CR, arrows, Esc, Ctrl-*) that JSON \" +\n      \"can't carry cleanly.\",\n    {\n      sessionId: z\n        .string()\n        .describe(\"Session id OR name from terminal_start.\"),\n      text: z\n        .string()\n        .optional()\n        .describe(\n          \"Content to write. Sent as-is to the PTY's stdin; a `\\\\n` here is a \" +\n            \"real line break (not a submit).\"\n        ),\n      enter: z\n        .boolean()\n        .optional()\n        .describe(\n          \"Press Enter as an isolated keystroke: writes a lone carriage \" +\n            \"return (\\\\r) in a separate write AFTER any content, so paste-\" +\n            \"detecting TUIs (e.g. Claude Code) submit reliably instead of \" +\n            \"treating the trailing CR as a pasted newline.\"\n        ),\n      b64: z\n        .string()\n        .optional()\n        .describe(\n          \"Base64-encoded exact bytes to send instead of/around `text` (for \" +\n            \"control keys: CR, arrows, Esc, Ctrl-*). Decoded as latin1 (1-to-1 \" +\n            \"byte mapping) and written verbatim. Intended for ASCII control \" +\n            \"keys; binary bytes >0x7f may not transit unchanged.\"\n        ),\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      if (input.b64 === undefined && input.text === undefined && !input.enter) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: \"terminal_input: provide at least one of `text`, `b64`, or `enter`.\",\n            },\n          ],\n          isError: true,\n        }\n      }\n      const content =\n        input.b64 !== undefined\n          ? Buffer.from(input.b64, \"base64\").toString(\"latin1\")\n          : (input.text ?? \"\")\n      // Enter is sent as an ISOLATED write so paste-detecting TUIs treat the\n      // CR as the Enter key (submit) rather than a trailing pasted newline.\n      // See the tool description for the paste-detection rationale.\n      //\n      // TODO(follow-up): for multi-line `text` + `enter`, when the session is\n      // in bracketed-paste mode (PTY emitted `\\x1b[?2004h`), wrap the content\n      // in `\\x1b[200~`…`\\x1b[201~` before the isolated CR. Skipped here: it\n      // needs per-session 2004h/2004l tracking in sessions.ts onData (with\n      // escape-sequence-split handling across chunk boundaries) plus a new\n      // registry method — more than the isolated-CR fix warrants on its own.\n      let ok = true\n      if (content.length > 0) {\n        ok = registry.writeTerminalInput(desc.id, content) && ok\n      }\n      if (input.enter) {\n        ok = registry.writeTerminalInput(desc.id, \"\\r\") && ok\n      }\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/provider-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    //\n    // _meta is duplicated onto both the registration options (→ resources/list\n    // entry) AND the read handler's content item (→ resources/read result),\n    // because the ext-apps spec has hosts read csp from resources/read FIRST,\n    // falling back to resources/list only if that's absent. The SDK's\n    // registerResource() only auto-projects the options-level _meta into\n    // resources/list, not into the handler's own return value.\n    const resourceMeta = {\n      ui: {\n        prefersBorder: true,\n        ...(app.csp ? { csp: app.csp } : {}),\n      },\n    }\n    server.registerResource(\n      app.id,\n      resourceUri,\n      {\n        mimeType: MIME_TYPE,\n        description: app.description,\n        _meta: resourceMeta,\n      },\n      async () => ({\n        contents: [\n          {\n            uri: resourceUri,\n            mimeType: MIME_TYPE,\n            text: html,\n            _meta: resourceMeta,\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 * Shared MCP Apps client bridge for agentproto panels.\n *\n * One spec-correct copy of the JSON-RPC-over-postMessage bridge that every\n * ui:// panel embeds in its <script> block. Mirrors the behaviour of\n * @agstudio/mcp-apps' mcpAppClientScript() — which we cannot import here:\n * agentproto is a standalone pnpm workspace with no @agstudio/* dependency\n * (same isolation invariant as mcp-apps-adapter.ts).\n *\n * Handshake (MCP Apps ext spec 2026-01-26, ext-apps McpUiInitializeRequest):\n *   params REQUIRE `appInfo` (Implementation: {name, version}),\n *   `appCapabilities`, and `protocolVersion`. Sending `clientInfo` instead\n *   of `appInfo` fails the host's schema validation — hosts either reply\n *   with an error or silently drop the request, so the panel's initBridge()\n *   promise never resolves and the panel renders blank while every\n *   server-side surface (tools, resources) works. That exact bug shipped in\n *   4 copy-pasted bridges; this module is the single corrected source.\n *\n * The script defines, in panel scope:\n *   post / rpcRequest / rpcNotify      — raw JSON-RPC plumbing\n *   onHostNotification(cb)             — subscribe to host-pushed\n *                                        notifications (method, params)\n *   initBridge()                       — ui/initialize → ui/notifications/initialized\n *   callTool(name, args)               — tools/call + JSON text unwrap\n *   getHostContext() / onHostContext(cb) — host context (displayMode, theme, …),\n *                                        captured from the initialize result and\n *                                        merged on ui/notifications/host-context-changed\n *   requestDisplayMode(mode)           — ui/request-display-mode (inline|fullscreen|pip)\n *\n * Display-mode toggle: the bridge also injects two floating buttons\n * (fullscreen + pip) in the top-right corner of every panel, shown only for\n * the modes the host actually advertises via hostContext.availableDisplayModes\n * — same pattern as guilde's canvas.app.ts canvasShellHtml() (the reference\n * implementation that renders correctly in Claude hosts). No auto-request:\n * panels stay inline until the user clicks.\n */\n\nexport function panelBridgeScript(appName: string): string {\n  return `// ── MCP Apps bridge (shared: panel-bridge.ts) ──\n// JSON-RPC 2.0 over window.parent.postMessage · spec 2026-01-26\nvar _nextId = 1, _pending = {}, _notifyHandlers = [];\nvar _hostContext = null, _hostContextHandlers = [];\nfunction post(msg){ window.parent.postMessage(msg, '*'); }\nfunction getHostContext(){ return _hostContext; }\nfunction onHostContext(cb){\n  _hostContextHandlers.push(cb);\n  // Replay the last context so a late subscriber isn't stuck blind.\n  if (_hostContext){ try { cb(_hostContext); } catch(_) {} }\n}\nfunction _setHostContext(ctx){\n  if (!ctx || typeof ctx !== 'object') return;\n  // ui/notifications/host-context-changed carries only the changed keys —\n  // merge, matching the official ext-apps App behaviour.\n  _hostContext = Object.assign({}, _hostContext || {}, ctx);\n  for (var i = 0; i < _hostContextHandlers.length; i++){\n    try { _hostContextHandlers[i](_hostContext); } catch(_) {}\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}\nfunction rpcNotify(method, params){ post({jsonrpc: '2.0', method: method, params: params || {}}); }\nfunction onHostNotification(cb){ _notifyHandlers.push(cb); }\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    return;\n  }\n  if (msg.method){\n    if (msg.method === 'ui/notifications/host-context-changed'){\n      _setHostContext(msg.params || {});\n    }\n    for (var i = 0; i < _notifyHandlers.length; i++){\n      try { _notifyHandlers[i](msg.method, msg.params || {}); } catch(_) {}\n    }\n  }\n});\nfunction initBridge(){\n  return rpcRequest('ui/initialize', {\n    appInfo: {name: ${JSON.stringify(appName)}, version: '0.1.0'},\n    appCapabilities: {availableDisplayModes: ['inline', 'fullscreen', 'pip']},\n    protocolVersion: '2026-01-26'\n  }).then(function(result){\n    // The initialize result carries the initial hostContext (displayMode +\n    // availableDisplayModes) — capture it before notifying the host.\n    if (result && result.hostContext) _setHostContext(result.hostContext);\n    rpcNotify('ui/notifications/initialized', {});\n  });\n}\nfunction requestDisplayMode(mode){\n  return rpcRequest('ui/request-display-mode', {mode: mode});\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// ── Display-mode toggle buttons (NO auto-request) ──────────────────────\n// Injected by the shared bridge so every panel gets them without touching\n// its own markup. Mirrors guilde canvas.app.ts canvasShellHtml(): the\n// panel stays inline by default; the user expands on demand. Buttons only\n// appear for modes the host advertises in hostContext.availableDisplayModes.\n(function(){\n  function mount(){\n    var style = document.createElement('style');\n    style.textContent = '#dm,#pin{display:none;position:fixed;top:8px;z-index:10;'\n      + 'border:1px solid #d0d0d0;background:#fff;color:#1a1a1a;'\n      + 'font:600 13px/1 system-ui,sans-serif;padding:7px 12px;border-radius:6px;'\n      + 'cursor:pointer;box-shadow:0 1px 4px rgba(0,0,0,.18)}'\n      + '#dm{right:8px}#pin{right:118px}'\n      + '#dm:hover,#pin:hover{background:#f2f2f2;border-color:#b0b0b0}'\n      + '@media (prefers-color-scheme:dark){'\n      + '#dm,#pin{border-color:#555;background:#2a2a2a;color:#f0f0f0;box-shadow:0 1px 4px rgba(0,0,0,.5)}'\n      + '#dm:hover,#pin:hover{background:#333;border-color:#777}}';\n    document.head.appendChild(style);\n\n    var btn = document.createElement('button');\n    btn.id = 'dm'; btn.type = 'button'; btn.title = \"Basculer l'affichage\";\n    var pin = document.createElement('button');\n    pin.id = 'pin'; pin.type = 'button'; pin.title = 'Épingler sur le côté (pip)';\n    document.body.appendChild(pin);\n    document.body.appendChild(btn);\n\n    function has(avail, m){ return !!avail && avail.indexOf(m) >= 0; }\n\n    // Re-sync button visibility + label from the current host context.\n    function syncBtn(ctx){\n      ctx = ctx || {};\n      var avail = ctx.availableDisplayModes;\n      // Diagnostic: what does THIS host actually advertise? (inline/fullscreen/pip)\n      console.log('[mcp-app] displayMode=', ctx.displayMode,\n                  'availableDisplayModes=', avail);\n\n      // Fullscreen toggle button.\n      if (has(avail, 'fullscreen')){\n        btn.style.display = 'block';\n        btn.textContent = (ctx.displayMode === 'fullscreen') ? '⤡ Réduire' : '⤢ Agrandir';\n      } else { btn.style.display = 'none'; }\n\n      // Dedicated pip (\"pinned on side\") button — only if the host advertises pip.\n      if (has(avail, 'pip')){\n        pin.style.display = 'block';\n        pin.textContent = (ctx.displayMode === 'pip') ? '⤡ Détacher' : '📌 Épingler';\n      } else { pin.style.display = 'none'; }\n    }\n\n    onHostContext(syncBtn);\n\n    btn.addEventListener('click', function(){\n      var ctx = getHostContext() || {};\n      var inPanel = (ctx.displayMode === 'fullscreen' || ctx.displayMode === 'pip');\n      requestDisplayMode(inPanel ? 'inline' : 'fullscreen').catch(function(){});\n    });\n\n    pin.addEventListener('click', function(){\n      var ctx = getHostContext() || {};\n      requestDisplayMode(ctx.displayMode === 'pip' ? 'inline' : 'pip').catch(function(){});\n    });\n  }\n  if (document.body) mount();\n  else document.addEventListener('DOMContentLoaded', mount);\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\"\nimport { panelBridgeScript } from \"./panel-bridge.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${panelBridgeScript(\"agentproto-sessions-panel\")}\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: CR without LF)\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\n// Derive a turn-aware display badge. A session's 'status' only tracks process\n// liveness, so an agent-cli process stays \"running\" while idle between turns.\n// Read 'busy' / 'awaitingInput' to show real activity instead:\n//   working  — a turn is in flight (busy)\n//   waiting  — turn ended on awaiting-input (needs a reply)\n//   idle     — process alive, no turn running (last turn done)\nfunction displayBadge(s) {\n  if (s.status === 'running' && s.kind === 'agent-cli') {\n    if (s.busy) return { label: 'working', cls: 'br' };\n    if (s.awaitingInput) return { label: 'waiting', cls: 'bs' };\n    return { label: 'idle', cls: 'be' };\n  }\n  return { label: s.status, cls: badgeClass(s.status) };\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 db = displayBadge(s);\n    var active = s.id === activeId ? ' active' : '';\n    // blockedOn (set while the turn waits on a spawned sub-agent or a\n    // shell command) rides next to the status badge; waiting-on-user is\n    // NOT here — that's awaitingInput, a different signal.\n    var blocked = '';\n    if (s.blockedOn === 'subagent') blocked = '<span class=\"badge bs\">&#129513; sous-agent</span>';\n    else if (s.blockedOn === 'command') blocked = '<span class=\"badge bs\">&#9203; commande</span>';\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 ' + db.cls + '\">' + db.label + '</span>'\n          + blocked\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  /** Content-Security-Policy hints for the sandboxed host iframe, threaded\n   *  by `registerMcpApps` into the ui:// RESOURCE's `_meta.ui.csp` (spec\n   *  2026-01-26 — CSP is resource-only, the tool's `_meta.ui` never carries\n   *  it). Omit for apps that need no outbound connections beyond the host\n   *  bridge (e.g. sessions-panel/agents-overview/bureau-sessions, which\n   *  only ever talk to the host via postMessage). Apps that open their own\n   *  WebSocket/fetch from inside the iframe (e.g. terminal-panel-app.ts)\n   *  must declare the exact origin(s) they connect to here. */\n  csp?: { connectDomains?: string[]; resourceDomains?: 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 { panelBridgeScript } from \"./panel-bridge.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${panelBridgeScript(\"agentproto-agents-overview\")}\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 { panelBridgeScript } from \"./panel-bridge.js\"\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${panelBridgeScript(\"agentproto-bureau-sessions\")}\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 * MCP App resource: agentproto session story panel.\n *\n * Ported 1:1 from the validated mockup at docs/session-story-mockup.html —\n * same CSS, same DOM structure/classes, same interaction model (anchored\n * side panel, sticky collapsible chapter headers, Simple/Tech toggle,\n * composer with local chapter-routing classification). Fake data is\n * replaced with live data pulled through the MCP Apps postMessage bridge.\n *\n * The HTML must stay fully self-contained (CSP: inline CSS/JS only, no\n * CDN, no external fonts) — see mcp-apps-adapter.ts and the other panels\n * in this file family (sessions-panel.ts, agents-overview-app.ts) for the\n * same constraint. Because of that, this file cannot `import` the pure\n * `buildStory` module from session-story.ts — the folding/chaptering\n * heuristics are ported to vanilla JS below (`buildStoryJs`), mirroring\n * session-story.ts function-for-function so the two stay easy to diff.\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 (status/picker) + agent_export\n *     (timeline, re-fetched on turn boundaries) + agent_prompt (composer)\n */\n\nimport { panelBridgeScript } from \"./panel-bridge.js\"\n\nconst RESOURCE_URI = \"ui://agentproto_session_story/view\"\nconst MIME_TYPE = \"text/html;profile=mcp-app\"\nvoid RESOURCE_URI\nvoid MIME_TYPE\n\nexport const SESSION_STORY_PANEL_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\" />\n<title>session story</title>\n<style>\n  :root {\n    color-scheme: light;\n    --bg:#faf8f5; --panel:#fffdfa; --line:#ece5da; --line-soft:#f2ede3;\n    --ink:#241f1a; --ink-mute:#7d7060; --ink-faint:#a9997f; --ink-ghost:#b3a893;\n    --accent:#0d7a4f; --accent-soft:#e8f4ec;\n    --gold:#a6701b; --gold-soft:#fff2dc;\n    --blue:#1d4e80; --blue-soft:#e9f1fb;\n    --violet:#5b3fa6; --violet-soft:#ede9ff;\n    --sel:#fbeccd; --red:#b3261e; --red-soft:#fbeae8;\n  }\n  * { box-sizing:border-box; }\n  html,body { height:100%; }\n  body { margin:0; font-family:ui-sans-serif,system-ui,-apple-system,\"Segoe UI\",sans-serif; background:var(--bg); color:var(--ink); -webkit-font-smoothing:antialiased; }\n  .app { height:100vh; display:flex; flex-direction:column; }\n  .hidden { display:none !important; }\n\n  /* ── picker screen ── */\n  #pickerScreen { height:100vh; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px; padding:24px; }\n  #pickerScreen h1 { font-size:15px; font-weight:700; }\n  #pickerList { width:min(520px,90vw); max-height:60vh; overflow-y:auto; border:1px solid var(--line); border-radius:12px; background:var(--panel); }\n  .pk-item { padding:10px 14px; border-bottom:1px solid var(--line-soft); cursor:pointer; display:flex; align-items:center; gap:10px; }\n  .pk-item:last-child { border-bottom:none; }\n  .pk-item:hover { background:var(--line-soft); }\n  .pk-name { flex:1; min-width:0; font-size:13px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n  .pk-meta { flex:none; font-size:10.5px; color:var(--ink-faint); font-weight:600; }\n  .pk-empty { padding:24px; text-align:center; color:var(--ink-mute); font-size:12.5px; }\n  .badge { display:inline-block; padding:1px 8px; border-radius:999px; font-size:10px; font-weight:700; }\n  .badge.running { background:var(--accent-soft); color:var(--accent); }\n  .badge.starting { background:var(--blue-soft); color:var(--blue); }\n  .badge.exited { background:var(--line-soft); color:var(--ink-faint); }\n  .badge.killed, .badge.error { background:var(--red-soft); color:var(--red); }\n\n  /* ── big picture : mission + plan de sous-tâches ── */\n  .hero { flex:none; padding:13px 20px 0; border-bottom:1px solid var(--line); background:var(--panel); }\n  .hero-top { display:flex; align-items:center; gap:13px; }\n  .pulse { width:10px; height:10px; border-radius:50%; background:var(--accent); flex:none;\n           box-shadow:0 0 0 0 rgba(13,122,79,.35); animation:pulse 2.4s infinite; }\n  .pulse.off { background:var(--ink-ghost); animation:none; }\n  @keyframes pulse { 70% { box-shadow:0 0 0 9px rgba(13,122,79,0); } 100% { box-shadow:0 0 0 0 rgba(13,122,79,0); } }\n  .who { min-width:0; flex:1; }\n  .who .h1 { font-size:14.5px; font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n  .who .h2 { font-size:12px; color:var(--ink-mute); margin-top:1px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n  .modewrap { display:flex; border:1px solid var(--line); border-radius:9px; overflow:hidden; flex:none; }\n  .modewrap button { border:none; background:var(--panel); color:var(--ink-mute); font-size:11px; font-weight:700; padding:6px 11px; cursor:pointer; }\n  .modewrap button.on { background:var(--ink); color:#fdf9f2; }\n  button.sim, a.sim { border:1px solid var(--line); background:var(--panel); color:var(--ink-mute); font-weight:700;\n               font-size:11.5px; border-radius:8px; padding:6px 12px; cursor:pointer; flex:none; }\n  button.sim.on { background:var(--ink); border-color:var(--ink); color:#fdf9f2; }\n  a.sim { display:inline-flex; align-items:center; text-decoration:none; }\n  a.sim:hover { border-color:var(--ink-ghost); color:var(--ink); }\n\n  /* plan strip : les sous-tâches, l'avancement d'un coup d'œil */\n  .plan { display:flex; gap:6px; overflow-x:auto; padding:11px 0 12px; scrollbar-width:none; }\n  .plan::-webkit-scrollbar { display:none; }\n  .pt { flex:none; display:flex; align-items:center; gap:6px; font-size:11.5px; font-weight:700; padding:5px 11px;\n        border-radius:999px; border:1px solid var(--line); background:var(--bg); color:var(--ink-mute); cursor:pointer; white-space:nowrap; }\n  .pt:hover { border-color:var(--ink-ghost); }\n  .pt .st { font-size:10px; }\n  .pt.done { color:var(--accent); background:var(--accent-soft); border-color:transparent; }\n  .pt.cur { color:var(--gold); background:var(--gold-soft); border-color:transparent; }\n  .pt.cur .st { animation:blink 1.6s infinite; }\n  @keyframes blink { 50% { opacity:.35; } }\n\n  /* ── corps ── */\n  .body { flex:1; display:flex; min-height:0; }\n  .feedcol { flex:1; min-width:320px; display:flex; flex-direction:column; }\n  .feed { flex:1; overflow-y:auto; padding:4px 14px 10px; display:flex; flex-direction:column; scroll-behavior:smooth; }\n  .fspacer { flex:1; }\n\n  /* chapitres */\n  .chap { flex:none; position:sticky; top:0; z-index:5; margin:8px -4px 2px; padding:7px 12px; display:flex; align-items:center; gap:9px;\n          background:color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter:blur(6px);\n          border-radius:9px; cursor:pointer; font-size:11.5px; font-weight:800; letter-spacing:.03em; color:var(--ink-mute); }\n  .chap:hover { color:var(--ink); }\n  .chap .cst { flex:none; width:17px; height:17px; border-radius:50%; display:grid; place-items:center; font-size:9.5px; font-weight:900; }\n  .chap.done .cst { background:var(--accent-soft); color:var(--accent); }\n  .chap.cur .cst { background:var(--gold-soft); color:var(--gold); }\n  .chap .cnum { color:var(--ink-ghost); font-weight:700; }\n  .chap .csum { flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n  .chap .cmeta { flex:none; font-size:10.5px; color:var(--ink-ghost); font-weight:600; }\n  .chap .cchev { flex:none; color:var(--ink-ghost); transition:transform .15s; }\n  .chap.open .cchev { transform:rotate(90deg); }\n\n  .row { flex:none; min-height:44px; margin:1px 0 1px 10px; padding:5px 12px 5px 10px; display:flex; align-items:center; gap:11px;\n         cursor:pointer; border-radius:10px; border-left:3px solid transparent; transition:background .12s; }\n  .row:hover { background:var(--line-soft); }\n  .row[aria-selected=\"true\"] { background:var(--sel); border-left-color:var(--gold); }\n  .row .ico { width:24px; height:24px; border-radius:8px; flex:none; display:grid; place-items:center; font-size:11.5px; font-weight:800; }\n  .ico.k-text { background:var(--blue-soft); color:var(--blue); }\n  .ico.k-edit { background:var(--gold-soft); color:var(--gold); }\n  .ico.k-bash { background:var(--accent-soft); color:var(--accent); }\n  .ico.k-read { background:var(--violet-soft); color:var(--violet); }\n  .ico.k-user { background:var(--ink); color:#fdf9f2; }\n  .row .mid { flex:1; min-width:0; }\n  .row .sum { display:block; font-size:13.5px; line-height:1.35; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n  .row .raw1 { display:block; font-size:10.5px; color:var(--ink-faint); font-family:ui-monospace,Menlo,monospace;\n               white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:1px; }\n  body:not(.tech) .row .raw1 { display:none; }\n  .row .route { display:inline-block; font-size:10px; font-weight:800; padding:1px 8px; border-radius:999px; margin-top:2px; }\n  .route.cont { background:var(--blue-soft); color:var(--blue); }\n  .route.newt { background:var(--gold-soft); color:var(--gold); }\n  .row .cnt { flex:none; font-size:10px; font-weight:800; color:var(--gold); background:var(--gold-soft); padding:2px 7px; border-radius:999px; }\n  .row .ts { flex:none; font-size:10.5px; color:var(--ink-ghost); font-variant-numeric:tabular-nums; }\n  @keyframes slidein { from { opacity:0; transform:translateY(6px); } }\n  .row.new { animation:slidein .25s ease-out; }\n\n  /* ── panneau ancré ── */\n  .panel { flex:none; width:0; overflow:hidden; border-left:1px solid transparent; background:var(--panel);\n           display:flex; flex-direction:column; transition:width .22s ease, border-color .22s; }\n  .panel.open { width:min(430px,46vw); border-left-color:var(--line); }\n  .panel-inner { width:min(430px,46vw); flex:1; display:flex; flex-direction:column; min-height:0; }\n  .phead { flex:none; padding:14px 16px 12px; border-bottom:1px solid var(--line); display:flex; align-items:flex-start; gap:11px; }\n  .phead .ico { width:28px; height:28px; font-size:13px; border-radius:9px; }\n  .phead .tt { min-width:0; flex:1; }\n  .phead .t { font-size:14px; font-weight:700; line-height:1.4; }\n  .phead .s { font-size:11px; color:var(--ink-faint); margin-top:3px; font-variant-numeric:tabular-nums; }\n  .pnav { display:flex; gap:4px; flex:none; }\n  .pnav button { width:26px; height:26px; border:1px solid var(--line); background:var(--panel); border-radius:8px;\n                 color:var(--ink-mute); font-size:12px; cursor:pointer; display:grid; place-items:center; }\n  .pnav button:disabled { opacity:.3; cursor:default; }\n  .pbody { flex:1; overflow-y:auto; padding:16px; display:flex; flex-direction:column; gap:14px; }\n  .plain { font-size:14px; line-height:1.7; }\n  .plain .why { margin-top:8px; font-size:12.5px; color:var(--ink-mute); line-height:1.6; }\n  .facts { display:flex; flex-wrap:wrap; gap:6px; }\n  .fact { font-size:11px; font-weight:700; background:var(--bg); border:1px solid var(--line); color:var(--ink-mute); padding:4px 10px; border-radius:999px; }\n  .fact.ok { background:var(--accent-soft); border-color:transparent; color:var(--accent); }\n  details.techbox { border:1px solid var(--line); border-radius:12px; background:var(--bg); overflow:hidden; }\n  details.techbox summary { list-style:none; cursor:pointer; padding:10px 14px; font-size:11.5px; font-weight:800;\n          letter-spacing:.04em; text-transform:uppercase; color:var(--ink-faint); display:flex; align-items:center; gap:8px; }\n  details.techbox summary::-webkit-details-marker { display:none; }\n  details.techbox summary::after { content:\"▸\"; margin-left:auto; transition:transform .15s; }\n  details.techbox[open] summary::after { transform:rotate(90deg); }\n  .techlist { padding:0 12px 12px; display:flex; flex-direction:column; gap:8px; }\n  .titem { border:1px solid var(--line); border-radius:10px; background:var(--panel); overflow:hidden; }\n  .titem .th { padding:8px 12px; font-size:11.5px; font-weight:700; color:var(--ink-mute); display:flex; align-items:center; gap:8px; }\n  .titem .th .copy { margin-left:auto; border:none; background:none; color:var(--ink-ghost); font-size:11px; cursor:pointer; padding:2px 4px; border-radius:5px; }\n  .titem .th .copy:hover { color:var(--ink); background:var(--line-soft); }\n  .titem pre { margin:0; border-top:1px solid var(--line-soft); font-family:ui-monospace,Menlo,monospace; font-size:11.5px;\n               line-height:1.55; color:#4a4236; padding:9px 12px; overflow:auto; max-height:240px; white-space:pre-wrap; word-break:break-word; }\n  .d-text { font-size:13.5px; line-height:1.7; }\n  .d-text p { margin:0 0 8px; }\n  .d-text p:last-child { margin-bottom:0; }\n  .d-text h1, .d-text h2, .d-text h3, .d-text h4, .d-text h5, .d-text h6 { margin:12px 0 6px; line-height:1.3; }\n  .d-text h1:first-child, .d-text h2:first-child, .d-text h3:first-child { margin-top:0; }\n  .d-text ul, .d-text ol { margin:0 0 8px; padding-left:20px; }\n  .d-text code { font-family:ui-monospace,Menlo,monospace; font-size:12.5px; background:var(--bg); border-radius:4px; padding:1px 5px; }\n  .d-text pre { margin:0 0 8px; background:var(--bg); border:1px solid var(--line); border-radius:8px; padding:9px 12px; overflow:auto; }\n  .d-text pre code { background:none; border-radius:0; padding:0; }\n  .d-text table { border-collapse:collapse; margin:0 0 8px; font-size:12.5px; }\n  .d-text th, .d-text td { border:1px solid var(--line); padding:4px 8px; text-align:left; }\n  .d-text a { color:var(--blue); }\n  .pfoot { flex:none; border-top:1px solid var(--line); padding:9px 16px; font-size:11px; color:var(--ink-ghost); display:flex; gap:10px; }\n  .kbd { font-family:ui-monospace,Menlo,monospace; font-size:10px; border:1px solid var(--line); border-bottom-width:2px;\n         border-radius:5px; padding:1px 5px; background:var(--panel); color:var(--ink-mute); }\n\n  /* ── boîte d'envoi + routage IA ── */\n  .composer { flex:none; border-top:1px solid var(--line); background:var(--panel); padding:10px 14px; }\n  .composer .cbar { display:flex; gap:8px; }\n  .composer textarea { flex:1; resize:none; border:1px solid var(--line); border-radius:10px; padding:9px 12px; font:inherit; font-size:13px; max-height:110px; background:var(--bg); }\n  .composer textarea:focus { outline:2px solid #241f1a22; }\n  .composer textarea:disabled { opacity:.5; cursor:not-allowed; }\n  .composer button { border:none; border-radius:10px; padding:0 16px; background:var(--ink); color:#fdf9f2; font-weight:700; font-size:13px; cursor:pointer; }\n  .composer button:disabled { opacity:.4; cursor:not-allowed; }\n  .composer .routing { font-size:11px; color:var(--ink-faint); padding:6px 2px 0; min-height:22px; }\n  .composer .routing .r-cont { color:var(--blue); font-weight:700; }\n  .composer .routing .r-newt { color:var(--gold); font-weight:700; }\n  #statusbar { flex:none; padding:4px 20px; font-size:10.5px; color:var(--ink-ghost); border-top:1px solid var(--line-soft); }\n</style>\n</head>\n<body>\n<div id=\"pickerScreen\">\n  <h1>Choisis une session</h1>\n  <div id=\"pickerList\"><div class=\"pk-empty\">Connexion&#8230;</div></div>\n</div>\n\n<div class=\"app hidden\" id=\"storyScreen\">\n  <div class=\"hero\">\n    <div class=\"hero-top\">\n      <span class=\"pulse\" id=\"pulse\"></span>\n      <div class=\"who\">\n        <div class=\"h1\" id=\"heroTitle\"></div>\n        <div class=\"h2\" id=\"heroSub\"></div>\n      </div>\n      <div class=\"modewrap\"><button id=\"modeSimple\" class=\"on\" type=\"button\">Simple</button><button id=\"modeTech\" type=\"button\">Tech</button></div>\n      <a class=\"sim\" id=\"fullPanelLink\" href=\"#\" target=\"_blank\" rel=\"noopener\" title=\"Ouvrir le panneau complet (Terminal/Chat/JSON/TTY)\">&#8599; panneau complet</a>\n      <button class=\"sim\" id=\"switchBtn\" type=\"button\">&#8646; changer</button>\n    </div>\n    <div class=\"plan\" id=\"plan\"></div>\n  </div>\n\n  <div class=\"body\">\n    <div class=\"feedcol\">\n      <div class=\"feed\" id=\"feed\"><div class=\"fspacer\"></div><div id=\"rows\"></div></div>\n      <div class=\"composer\">\n        <div class=\"cbar\">\n          <textarea id=\"msgBox\" rows=\"1\" placeholder=\"Écris à l'agent… (la surcouche classe ton message : suite de la sous-tâche ou nouvelle sous-tâche)\"></textarea>\n          <button id=\"sendBtn\" type=\"button\">Envoyer</button>\n        </div>\n        <div class=\"routing\" id=\"routing\"></div>\n      </div>\n    </div>\n\n    <aside class=\"panel\" id=\"panel\" aria-label=\"Détail de l'étape\">\n      <div class=\"panel-inner\">\n        <div class=\"phead\">\n          <span class=\"ico\" id=\"pIco\"></span>\n          <div class=\"tt\"><div class=\"t\" id=\"pTitle\"></div><div class=\"s\" id=\"pSub\"></div></div>\n          <div class=\"pnav\"><button id=\"pPrev\" type=\"button\">↑</button><button id=\"pNext\" type=\"button\">↓</button><button id=\"pClose\" type=\"button\">✕</button></div>\n        </div>\n        <div class=\"pbody\" id=\"pBody\"></div>\n        <div class=\"pfoot\"><span class=\"kbd\">↑</span><span class=\"kbd\">↓</span> naviguer · <span class=\"kbd\">Esc</span> fermer</div>\n      </div>\n    </aside>\n  </div>\n  <div id=\"statusbar\"></div>\n</div>\n\n<script>\nvar $=function(id){ return document.getElementById(id); };\nvar esc=function(s){ return String(s==null?\"\":s).replace(/[&<>]/g,function(c){ return {\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\"}[c]; }); };\n\n// ============================================================\n// renderMd — vanilla-JS port of markdown-lite.ts. Kept\n// function-for-function identical so the two are easy to diff (same\n// self-contained-panel constraint as buildStoryJs below): headers,\n// bold/italic, inline/fenced code, bullet/numbered lists, pipe tables and\n// links, with every raw text run HTML-escaped before any generated tag\n// wraps it.\n// ============================================================\nfunction escHtmlMd(s){ return String(s).replace(/[&<>\"]/g,function(c){ if(c==='&') return '&amp;'; if(c==='<') return '&lt;'; if(c==='>') return '&gt;'; return '&quot;'; }); }\nfunction renderInlineMd(text){\n  var out=escHtmlMd(text);\n  out=out.replace(/\\`([^\\`]+)\\`/g,function(_m,code){ return '<code>'+code+'</code>'; });\n  out=out.replace(/\\\\[([^\\\\]]+)\\\\]\\\\((https?:\\\\/\\\\/[^\\\\s)]+)\\\\)/g,function(_m,label,url){ return '<a href=\"'+url+'\" target=\"_blank\" rel=\"noopener noreferrer\">'+label+'</a>'; });\n  out=out.replace(/\\\\*\\\\*([^*]+)\\\\*\\\\*/g,'<strong>$1</strong>');\n  out=out.replace(/(^|[^*])\\\\*([^*]+)\\\\*(?!\\\\*)/g,'$1<em>$2</em>');\n  return out;\n}\nfunction isTableSepMd(line){ return /^\\\\s*\\\\|?\\\\s*:?-+:?\\\\s*(\\\\|\\\\s*:?-+:?\\\\s*)+\\\\|?\\\\s*$/.test(line); }\nfunction splitRowMd(line){ return line.trim().replace(/^\\\\|/,'').replace(/\\\\|$/,'').split('|').map(function(c){ return c.trim(); }); }\nfunction renderMd(md){\n  var lines=String(md==null?'':md).replace(/\\\\r\\\\n?/g,'\\\\n').split('\\\\n');\n  var out=[], para=[], list=null;\n  function flushPara(){ if(para.length){ out.push('<p>'+para.map(renderInlineMd).join('<br>')+'</p>'); para=[]; } }\n  function flushList(){ if(list){ var tag=list.ordered?'ol':'ul'; out.push('<'+tag+'>'+list.items.map(function(i){ return '<li>'+renderInlineMd(i)+'</li>'; }).join('')+'</'+tag+'>'); list=null; } }\n  function flushAll(){ flushPara(); flushList(); }\n  var i=0;\n  while(i<lines.length){\n    var line=lines[i];\n    if(/^\\\\s*\\`\\`\\`/.test(line)){\n      flushAll();\n      var code=[]; i+=1;\n      while(i<lines.length && !/^\\\\s*\\`\\`\\`/.test(lines[i])){ code.push(lines[i]); i+=1; }\n      i+=1;\n      out.push('<pre><code>'+escHtmlMd(code.join('\\\\n'))+'</code></pre>');\n      continue;\n    }\n    var header=line.match(/^(#{1,6})\\\\s+(.*)$/);\n    if(header){\n      flushAll();\n      var level=header[1].length;\n      out.push('<h'+level+'>'+renderInlineMd(header[2].trim())+'</h'+level+'>');\n      i+=1;\n      continue;\n    }\n    if(/^\\\\s*\\\\|/.test(line) && i+1<lines.length && isTableSepMd(lines[i+1])){\n      flushAll();\n      var headCells=splitRowMd(line);\n      i+=2;\n      var bodyRows=[];\n      while(i<lines.length && /^\\\\s*\\\\|/.test(lines[i])){ bodyRows.push(splitRowMd(lines[i])); i+=1; }\n      out.push('<table><thead><tr>'+headCells.map(function(c){ return '<th>'+renderInlineMd(c)+'</th>'; }).join('')+'</tr></thead><tbody>'\n        +bodyRows.map(function(r){ return '<tr>'+r.map(function(c){ return '<td>'+renderInlineMd(c)+'</td>'; }).join('')+'</tr>'; }).join('')+'</tbody></table>');\n      continue;\n    }\n    var bullet=line.match(/^\\\\s*[-*+]\\\\s+(.*)$/);\n    var numbered=line.match(/^\\\\s*\\\\d+\\\\.\\\\s+(.*)$/);\n    if(bullet || numbered){\n      flushPara();\n      var ordered=!!numbered;\n      var item=(bullet||numbered)[1];\n      if(!list || list.ordered!==ordered){ flushList(); list={ordered:ordered,items:[]}; }\n      list.items.push(item);\n      i+=1;\n      continue;\n    }\n    if(line.trim()===''){ flushAll(); i+=1; continue; }\n    flushList();\n    para.push(line);\n    i+=1;\n  }\n  flushAll();\n  return out.join('');\n}\n\n${panelBridgeScript(\"agentproto-session-story-panel\")}\n// Best-effort: some hosts forward the triggering tool call's arguments as\n// a notification so the panel can auto-open the right session. Purely\n// additive — the session picker is the reliable path when this never\n// arrives.\nvar pendingSessionId=null;\nonHostNotification(function(method, params){\n  if(/tool-input|tool-call/.test(method)){\n    var args=(params && (params.arguments || params.input)) || {};\n    if(args && args.sessionId) pendingSessionId=args.sessionId;\n  }\n});\n\n// ============================================================\n// buildStory — vanilla-JS port of session-story.ts. Kept\n// function-for-function identical so the two are easy to diff; the panel\n// resource must be fully self-contained (no bundler/dynamic import), so it\n// cannot import the TS module directly.\n// ============================================================\n\nvar SALIENT_KEYS=[\"file_path\",\"path\",\"filePath\",\"file\",\"command\",\"pattern\",\"query\",\"q\",\"url\",\"todos\",\"description\",\"prompt\"];\nfunction truncateStr(v,max){ var o=String(v).replace(/\\\\s+/g,' ').trim(); return o.length>max? o.slice(0,max-1)+'…':o; }\nfunction formatArgValue(v){\n  if(typeof v==='string') return v;\n  if(Array.isArray(v)) return v.length+' item'+(v.length===1?'':'s');\n  if(v && typeof v==='object') return JSON.stringify(v);\n  return String(v);\n}\nfunction pickSalient(args){\n  for(var i=0;i<SALIENT_KEYS.length;i++){\n    var k=SALIENT_KEYS[i], v=args[k];\n    if(v!==undefined && v!==null && v!=='') return formatArgValue(v);\n  }\n  return null;\n}\nfunction formatToolCall(name,args){\n  name=name||'tool';\n  args=(args && typeof args==='object' && !Array.isArray(args)) ? args : {};\n  var salient=pickSalient(args);\n  if(salient!==null){\n    if(name.toLowerCase().indexOf(salient.toLowerCase())>=0) return truncateStr(name,120);\n    return truncateStr(name+' '+salient,120);\n  }\n  if(Object.keys(args).length===0) return name;\n  return truncateStr(name+' '+JSON.stringify(args),120);\n}\nfunction extractText(v){\n  if(v==null) return null;\n  if(typeof v==='string') return v;\n  if(Array.isArray(v)){\n    var parts=v.map(extractText).filter(function(x){ return x!=null; });\n    return parts.length? parts.join('\\\\n') : null;\n  }\n  if(typeof v==='object'){\n    if(typeof v.text==='string') return v.text;\n    if(typeof v.message==='string') return v.message;\n    if(Array.isArray(v.content)) return extractText(v.content);\n    if(typeof v.error==='string') return v.error;\n    if(v.error && typeof v.error==='object' && typeof v.error.message==='string') return v.error.message;\n    return null;\n  }\n  return null;\n}\nfunction formatToolResult(toolName,result,isError){\n  var text=extractText(result);\n  if(isError){\n    var message=text!=null? text : (result!=null? JSON.stringify(result) : 'failed');\n    var firstLine=String(message).split(/\\\\r?\\\\n/)[0] || message;\n    return truncateStr(firstLine,160);\n  }\n  if(text==null) return null;\n  var trimmed=text.trim();\n  if(!trimmed) return null;\n  var lines=trimmed.split(/\\\\r?\\\\n/);\n  if(lines.length>1){\n    var bytes=new TextEncoder().encode(trimmed).length;\n    return lines.length+' lines, '+bytes+'B';\n  }\n  return truncateStr(lines[0],160);\n}\n\nfunction classifyKind(toolCalls){\n  if(!toolCalls || toolCalls.length===0) return 'text';\n  var names=toolCalls.map(function(t){ return t.name.toLowerCase(); });\n  if(names.some(function(n){ return /edit|write/.test(n); })) return 'edit';\n  if(names.some(function(n){ return /bash|terminal|command/.test(n); })) return 'bash';\n  if(names.some(function(n){ return /read|grep|glob/.test(n); })) return 'read';\n  return 'text';\n}\nvar NEW_CHAPTER_RE=/\\\\b(aussi|autre|ensuite|nouveau|nouvelle|plut[oô]t|maintenant|apr[eè]s ça|il faudrait|peux[- ]tu|on pourrait|ajoute|g[eè]re)\\\\b/iu;\nfunction classifyRoute(text){\n  var newt=NEW_CHAPTER_RE.test(text);\n  if(!newt) return {route:'cont'};\n  var title=text.replace(/[.?!].*$/,'').slice(0,42);\n  return {route:'newt', title:title};\n}\nfunction formatTsJs(ts){\n  if(ts===undefined || ts===null || isNaN(ts)) return '';\n  return new Date(ts).toISOString().slice(11,19);\n}\nfunction firstMeaningfulLine(text){\n  if(!text) return undefined;\n  var lines=text.split('\\\\n').map(function(l){ return l.trim(); }).filter(function(l){ return l.length>0; });\n  return lines[0];\n}\nfunction lineCountOf(text){\n  var n=(text||'').split('\\\\n').filter(function(l){ return l.trim().length>0; }).length;\n  return n||1;\n}\nfunction parseArgsJson(s){ try{ return JSON.parse(s); }catch(e){ return {}; } }\n\nfunction foldToolStep(assistant,toolResults){\n  var toolCalls=assistant.toolCalls||[];\n  var kind=classifyKind(toolCalls);\n  var count=toolCalls.length||1;\n  var items=[], facts=[];\n  if(assistant.text && assistant.text.trim()) items.push({text:assistant.text.trim()});\n  toolCalls.forEach(function(tc,i){\n    var args=parseArgsJson(tc.args);\n    var h=formatToolCall(tc.name,args);\n    var resultMsg=toolResults[i];\n    var resultText=(resultMsg && resultMsg.text) || '';\n    var isError=resultText.indexOf('[error]')===0;\n    var r=isError? resultText.slice(7).trim() : resultText;\n    items.push({h:h,r:r});\n    var fact=formatToolResult(tc.name,r,isError);\n    if(fact) facts.push(fact);\n  });\n  var firstLine=firstMeaningfulLine(assistant.text);\n  var firstToolCall=toolCalls[0];\n  var sum=firstLine!==undefined? firstLine : (firstToolCall? formatToolCall(firstToolCall.name,parseArgsJson(firstToolCall.args)) : '…');\n  var raw1;\n  if(toolCalls.length===0) raw1='assistant · '+lineCountOf(assistant.text)+' ligne(s)';\n  else if(toolCalls.length===1) raw1=formatToolCall(firstToolCall.name,parseArgsJson(firstToolCall.args));\n  else raw1=(firstToolCall? firstToolCall.name : 'tool')+' ×'+toolCalls.length;\n  return {kind:kind, ts:formatTsJs(assistant.ts), sum:sum, raw1:raw1, count:count, facts:facts, items:items};\n}\nfunction foldUserStep(msg){\n  var text=msg.text||'';\n  return {kind:'user', ts:formatTsJs(msg.ts), sum:'« '+truncateStr(text,80)+' »', raw1:'user · '+lineCountOf(text)+' ligne(s)', count:1, facts:[], items:[{text:text}], userText:text};\n}\nfunction foldOrphanToolStep(msg){\n  var text=msg.text||'';\n  var isError=text.indexOf('[error]')===0;\n  var r=isError? text.slice(7).trim() : text;\n  var name=msg.toolName||'tool';\n  var fact=formatToolResult(name,r,isError);\n  return {kind:classifyKind([{name:name}]), ts:formatTsJs(msg.ts), sum: msg.toolName? (msg.toolName+' · résultat') : \"Résultat d'outil\", raw1: msg.toolName||'tool', count:1, facts: fact?[fact]:[], items:[{h:name,r:r}]};\n}\nfunction foldSystemStep(msg){\n  var text=msg.text||'';\n  var line=firstMeaningfulLine(text);\n  return {kind:'text', ts:formatTsJs(msg.ts), sum: line!==undefined? line : text, raw1:'system', count:1, facts:[], items: text?[{text:text}]:[]};\n}\nfunction foldMessages(messages){\n  var steps=[], i=0;\n  while(i<messages.length){\n    var msg=messages[i];\n    if(msg.role==='user'){ steps.push(foldUserStep(msg)); i+=1; continue; }\n    if(msg.role==='assistant'){\n      var j=i+1, toolResults=[];\n      while(j<messages.length && messages[j].role==='tool'){ toolResults.push(messages[j]); j+=1; }\n      steps.push(foldToolStep(msg,toolResults)); i=j; continue;\n    }\n    if(msg.role==='tool'){ steps.push(foldOrphanToolStep(msg)); i+=1; continue; }\n    steps.push(foldSystemStep(msg)); i+=1;\n  }\n  return steps;\n}\nfunction buildStoryJs(messages){\n  var folded=foldMessages(messages||[]);\n  var chapters=[], steps=[];\n  var currentChapterId, sawFirstUser=false;\n  function closeCurrent(){ var cur=chapters.filter(function(c){ return c.id===currentChapterId; })[0]; if(cur) cur.status='done'; }\n  function openChapter(title){ var id='c'+(chapters.length+1); chapters.push({id:id,title:title,status:'cur'}); return id; }\n  folded.forEach(function(step){\n    var route;\n    if(step.kind==='user' && step.userText!==undefined){\n      if(!sawFirstUser){ sawFirstUser=true; currentChapterId=openChapter('Cadrage'); }\n      else {\n        var verdict=classifyRoute(step.userText);\n        route=verdict.route;\n        if(verdict.route==='newt'){ closeCurrent(); currentChapterId=openChapter(verdict.title||'Nouvelle sous-tâche'); }\n      }\n    } else if(currentChapterId===undefined){ currentChapterId=openChapter('Cadrage'); }\n    var out={chap:currentChapterId, kind:step.kind, ts:step.ts, sum:step.sum, raw1:step.raw1, count:step.count, facts:step.facts, items:step.items};\n    if(route) out.route=route;\n    steps.push(out);\n  });\n  return {chapters:chapters, steps:steps};\n}\n\n// ============================================================\n// App state\n// ============================================================\nvar sessions=[];\nvar activeSessionId=null;\nvar story={chapters:[], steps:[]};\nvar open={};\nvar selected=-1;\nvar lastSeenOutputAt=null;\nvar pollTimer=null, polling=false;\nvar ICONS={text:[\"k-text\",\"A\"],edit:[\"k-edit\",\"✎\"],bash:[\"k-bash\",\"▸\"],read:[\"k-read\",\"⌕\"],user:[\"k-user\",\"T\"]};\nvar icoSpec=function(k){ return ICONS[k]||ICONS.text; };\nvar chapOf=function(id){ return story.chapters.filter(function(c){ return c.id===id; })[0]; };\nvar curChap=function(){ return story.chapters.filter(function(c){ return c.status==='cur'; })[0] || story.chapters[story.chapters.length-1]; };\n\nfunction setStatus(msg){ $('statusbar').textContent=msg; }\nfunction nowTs(){ return new Date().toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit',second:'2-digit'}); }\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\n// ============================================================\n// Picker screen\n// ============================================================\nfunction renderPicker(){\n  var el=$('pickerList');\n  if(!sessions.length){ el.innerHTML='<div class=\"pk-empty\">Aucune session</div>'; return; }\n  var html='';\n  sessions.forEach(function(s){\n    html+='<div class=\"pk-item\" data-id=\"'+esc(s.id)+'\">'\n        + '<span class=\"pk-name\">'+esc(titleOf(s))+'</span>'\n        + '<span class=\"badge '+esc(s.status)+'\">'+esc(s.status)+'</span>'\n        + '<span class=\"pk-meta\">'+esc(s.kind||'')+'</span>'\n        + '</div>';\n  });\n  el.innerHTML=html;\n  Array.prototype.forEach.call(el.querySelectorAll('.pk-item'), function(row){\n    row.onclick=function(){ openSession(row.getAttribute('data-id')); };\n  });\n}\n\nfunction showPicker(){\n  activeSessionId=null;\n  $('pickerScreen').classList.remove('hidden');\n  $('storyScreen').classList.add('hidden');\n  renderPicker();\n}\n\nfunction openSession(id){\n  activeSessionId=id;\n  story={chapters:[], steps:[]};\n  open={};\n  selected=-1;\n  lastSeenOutputAt=null;\n  $('pickerScreen').classList.add('hidden');\n  $('storyScreen').classList.remove('hidden');\n  $('fullPanelLink').href='https://cli.agentproto.sh/panel?session='+encodeURIComponent(id);\n  closePanel();\n  loadStory().then(renderAll);\n}\n\n// ============================================================\n// Story loading\n// ============================================================\nfunction activeSession(){ return sessions.filter(function(s){ return s.id===activeSessionId; })[0]; }\n\nfunction loadStory(){\n  return callTool('agent_export', {sessionId:activeSessionId, format:'json'}).then(function(data){\n    var messages=(data && data.messages) || [];\n    story=buildStoryJs(messages);\n    // Default open state: only the last (current) chapter is expanded.\n    var last=story.chapters[story.chapters.length-1];\n    if(last && !(last.id in open)) open[last.id]=true;\n  }).catch(function(e){\n    setStatus('Erreur export : '+e.message);\n  });\n}\n\nfunction canSend(){\n  var s=activeSession();\n  return !!s && s.kind==='agent-cli' && s.status==='running';\n}\n\nfunction renderComposer(){\n  var s=activeSession();\n  var box=$('msgBox'), btn=$('sendBtn');\n  var enabled=canSend();\n  box.disabled=!enabled;\n  btn.disabled=!enabled;\n  if(!s){ box.placeholder='Session introuvable.'; }\n  else if(!enabled) box.placeholder='Lecture seule — session '+esc(s.status)+'.';\n  else box.placeholder=\"Écris à l'agent… (la surcouche classe ton message : suite de la sous-tâche ou nouvelle sous-tâche)\";\n}\n\nfunction renderHero(){\n  var s=activeSession();\n  $('heroTitle').textContent=s? titleOf(s) : (activeSessionId||'');\n  var firstUser=story.steps.filter(function(st){ return st.kind==='user'; })[0];\n  var mission=firstUser? firstUser.userText || (firstUser.items[0] && firstUser.items[0].text) : null;\n  $('heroSub').textContent=mission? truncateStr(mission,200) : 'Aucun message pour le moment.';\n  var p=$('pulse');\n  p.classList.toggle('off', !(s && (s.status==='running' || s.status==='starting')));\n  renderComposer();\n}\n\nfunction renderAll(){\n  renderHero();\n  renderPlan();\n  renderRows('bottom');\n}\n\n// ============================================================\n// big picture strip\n// ============================================================\nfunction renderPlan(){\n  var done=story.chapters.filter(function(c){ return c.status==='done'; }).length;\n  $('plan').innerHTML=story.chapters.map(function(c,i){\n    return '<span class=\"pt '+c.status+'\" data-c=\"'+esc(c.id)+'\"><span class=\"st\">'+(c.status==='done'?'✓':'●')+'</span>'+(i+1)+'. '+esc(c.title)+'</span>';\n  }).join('') + '<span class=\"pt\" style=\"cursor:default\"><b>'+done+'/'+story.chapters.length+'</b>&nbsp;faites</span>';\n  Array.prototype.forEach.call($('plan').querySelectorAll('.pt[data-c]'), function(el){\n    el.onclick=function(){ open[el.getAttribute('data-c')]=true; renderRows(); jumpToChap(el.getAttribute('data-c')); };\n  });\n}\nfunction jumpToChap(cid){\n  var el=document.querySelector('.chap[data-c=\"'+cid+'\"]');\n  if(el) el.scrollIntoView({block:'start',behavior:'smooth'});\n}\n\n// ============================================================\n// feed segmenté par chapitres\n// ============================================================\nfunction rowHtml(s,i,isNew){\n  var spec=icoSpec(s.kind), cls=spec[0], ch=spec[1];\n  var route=s.route? '<span class=\"route '+(s.route==='newt'?'newt':'cont')+'\">'+(s.route==='newt'?'★ nouvelle sous-tâche':'↳ suite')+'</span>' : '';\n  return '<div class=\"row '+(isNew?'new':'')+'\" aria-selected=\"'+(i===selected)+'\" data-i=\"'+i+'\">'\n    + '<span class=\"ico '+cls+'\">'+ch+'</span>'\n    + '<span class=\"mid\"><span class=\"sum\">'+esc(s.sum)+'</span><span class=\"raw1\">'+esc(s.raw1||'')+'</span>'+route+'</span>'\n    + (s.count>1? '<span class=\"cnt\">×'+s.count+'</span>':'') + '<span class=\"ts\">'+esc(s.ts||'')+'</span>'\n    + '</div>';\n}\nfunction renderRows(keepScroll,newIdx){\n  var feed=$('feed');\n  var prevH=feed.scrollHeight, prevTop=feed.scrollTop;\n  var html='';\n  story.chapters.forEach(function(c,ci){\n    var chapSteps=[];\n    story.steps.forEach(function(s,i){ if(s.chap===c.id) chapSteps.push({s:s,i:i}); });\n    if(!chapSteps.length) return;\n    var isOpen=!!open[c.id];\n    html+='<div class=\"chap '+c.status+' '+(isOpen?'open':'')+'\" data-c=\"'+esc(c.id)+'\">'\n      + '<span class=\"cst\">'+(c.status==='done'?'✓':'●')+'</span><span class=\"cnum\">'+(ci+1)+'.</span>'\n      + '<span class=\"csum\">'+esc(c.title)+'</span>'\n      + '<span class=\"cmeta\">'+chapSteps.length+' étape'+(chapSteps.length>1?'s':'')+'</span><span class=\"cchev\">▸</span>'\n      + '</div>';\n    if(isOpen) html += chapSteps.map(function(x){ return rowHtml(x.s,x.i,x.i===newIdx); }).join('');\n  });\n  $('rows').innerHTML=html;\n  Array.prototype.forEach.call(document.querySelectorAll('.row'), function(el){\n    el.onclick=function(){ selectStep(Number(el.getAttribute('data-i'))); };\n  });\n  Array.prototype.forEach.call(document.querySelectorAll('.chap'), function(el){\n    el.onclick=function(){ var c=el.getAttribute('data-c'); open[c]=!open[c]; renderRows(); };\n  });\n  if(keepScroll==='bottom') feed.scrollTop=feed.scrollHeight;\n  else if(keepScroll==='preserve') feed.scrollTop=feed.scrollHeight-prevH+prevTop;\n}\n\n// ============================================================\n// panneau ancré\n// ============================================================\nfunction selectStep(i){\n  selected=i;\n  var s=story.steps[i]; if(!s) return;\n  open[s.chap]=true;\n  $('panel').classList.add('open');\n  var spec=icoSpec(s.kind), cls=spec[0], ch=spec[1];\n  var ico=$('pIco'); ico.className='ico '+cls; ico.textContent=ch;\n  $('pTitle').textContent=s.sum;\n  var c=chapOf(s.chap);\n  $('pSub').textContent=(s.ts? s.ts+' · ':'')+(c? ('sous-tâche : '+c.title) : '');\n  var facts=(s.facts||[]).map(function(f){\n    return '<span class=\"fact '+(/✓|exit 0|passed|0 match/.test(f)?'ok':'')+'\">'+esc(f)+'</span>';\n  }).join('');\n  var tech=(s.items||[]).map(function(it,k){\n    return it.text!==undefined\n      ? '<div class=\"d-text\">'+renderMd(it.text)+'</div>'\n      : '<div class=\"titem\"><div class=\"th\">'+esc(it.h)+'<button class=\"copy\" data-k=\"'+k+'\" type=\"button\">⧉</button></div><pre>'+esc(it.r)+'</pre></div>';\n  }).join('');\n  $('pBody').innerHTML=''\n    + '<div class=\"plain\"><div>'+esc(s.sum)+'.</div><div class=\"why\">'+esc(s.why||'')+'</div></div>'\n    + (facts? '<div class=\"facts\">'+facts+'</div>':'')\n    + '<details class=\"techbox\" '+(document.body.classList.contains('tech')?'open':'')+'>'\n    + '<summary>Détail technique · '+(s.items||[]).length+'</summary><div class=\"techlist\">'+tech+'</div>'\n    + '</details>';\n  Array.prototype.forEach.call($('pBody').querySelectorAll('.copy'), function(btn){\n    btn.onclick=function(e){\n      e.stopPropagation();\n      var it=(s.items||[])[Number(btn.getAttribute('data-k'))];\n      var payload=(it.h||'')+'\\\\n'+(it.r||it.text||'');\n      if(navigator.clipboard) navigator.clipboard.writeText(payload).catch(function(){});\n      btn.textContent='✓'; setTimeout(function(){ btn.textContent='⧉'; },900);\n    };\n  });\n  $('pPrev').disabled=i<=0; $('pNext').disabled=i>=story.steps.length-1;\n  renderRows();\n  var el=document.querySelector('.row[data-i=\"'+i+'\"]');\n  if(el) el.scrollIntoView({block:'nearest',behavior:'smooth'});\n}\nfunction closePanel(){ selected=-1; var p=$('panel'); if(p) p.classList.remove('open'); renderRows(); }\n$('pClose').addEventListener('click',closePanel);\n$('pPrev').addEventListener('click',function(){ if(selected>0) selectStep(selected-1); });\n$('pNext').addEventListener('click',function(){ if(selected<story.steps.length-1) selectStep(selected+1); });\ndocument.addEventListener('keydown',function(e){\n  if(e.key==='Escape'){ closePanel(); return; }\n  if($('storyScreen').classList.contains('hidden')) return;\n  if(selected<0 || e.target.tagName==='TEXTAREA') return;\n  if(e.key==='ArrowUp'){ e.preventDefault(); if(selected>0) selectStep(selected-1); }\n  if(e.key==='ArrowDown'){ e.preventDefault(); if(selected<story.steps.length-1) selectStep(selected+1); }\n});\n\n// ============================================================\n// Simple / Tech modes\n// ============================================================\nfunction setMode(tech){\n  document.body.classList.toggle('tech',tech);\n  $('modeTech').classList.toggle('on',tech);\n  $('modeSimple').classList.toggle('on',!tech);\n  if(selected>=0) selectStep(selected);\n}\n$('modeSimple').addEventListener('click',function(){ setMode(false); });\n$('modeTech').addEventListener('click',function(){ setMode(true); });\n$('switchBtn').addEventListener('click', function(){ if(pollTimer) clearTimeout(pollTimer); showPicker(); doPoll(); });\n\n// ============================================================\n// composer — local chapter-routing classification + agent_prompt\n// ============================================================\n$('sendBtn').addEventListener('click', sendMsg);\n$('msgBox').addEventListener('keydown', function(e){\n  if(e.key==='Enter' && !e.shiftKey){ e.preventDefault(); sendMsg(); }\n});\nfunction sendMsg(){\n  if(!canSend()) return;\n  var box=$('msgBox'), text=box.value.trim();\n  if(!text) return;\n  box.value='';\n  var cur=curChap();\n  var r=cur? classifyRoute(text) : {route:'cont'};\n  var chapId=cur? cur.id : null;\n  if(r.route==='newt' && cur){\n    cur.status='done';\n    var id='c'+(story.chapters.length+1);\n    story.chapters.push({id:id, title:r.title||'Nouvelle sous-tâche', status:'cur'});\n    chapId=id; open[id]=true;\n    $('routing').innerHTML='✦ classé : <span class=\"r-newt\">★ nouvelle sous-tâche « '+esc(r.title||'')+' »</span>';\n  } else {\n    $('routing').innerHTML='✦ classé : <span class=\"r-cont\">↳ suite de « '+esc(cur? cur.title : '')+' »</span>';\n  }\n  setTimeout(function(){ $('routing').textContent=''; },5000);\n  story.steps.push({\n    chap:chapId, kind:'user', ts:nowTs(),\n    sum:'« '+text.slice(0,80)+(text.length>80?'…':'')+' »',\n    raw1:'user · '+text.split('\\\\n').length+' ligne(s)',\n    route:r.route, facts:[], items:[{text:text}], userText:text,\n  });\n  renderPlan(); renderRows('bottom', story.steps.length-1);\n  callTool('agent_prompt', {sessionId:activeSessionId, prompt:text}).catch(function(e){\n    setStatus('Envoi échoué : '+e.message);\n  });\n}\n\n// ============================================================\n// Poll — session_list every ~5s; re-fetch agent_export only on turn\n// boundaries (lastOutputAt changed for the active session).\n// ============================================================\nvar POLL_MS=5000;\nfunction loadSessions(){\n  return callTool('session_list', {kind:'all'}).then(function(data){\n    sessions=data.sessions||[];\n    if($('pickerScreen') && !$('pickerScreen').classList.contains('hidden')) renderPicker();\n  }).catch(function(e){ setStatus('Erreur : '+e.message); });\n}\nfunction doPoll(){\n  if(polling) return;\n  polling=true;\n  loadSessions().then(function(){\n    if(!activeSessionId){ polling=false; pollTimer=setTimeout(doPoll,POLL_MS); return; }\n    var s=activeSession();\n    if(!s){ polling=false; pollTimer=setTimeout(doPoll,POLL_MS); return; }\n    renderHero();\n    var changed=s.lastOutputAt && s.lastOutputAt!==lastSeenOutputAt;\n    if(changed){\n      lastSeenOutputAt=s.lastOutputAt;\n      loadStory().then(function(){ renderPlan(); renderRows('bottom'); polling=false; pollTimer=setTimeout(doPoll,POLL_MS); });\n    } else {\n      polling=false; pollTimer=setTimeout(doPoll,POLL_MS);\n    }\n  }).catch(function(){ polling=false; pollTimer=setTimeout(doPoll,POLL_MS); });\n}\n\n// ============================================================\n// Boot\n// ============================================================\ninitBridge().then(loadSessions).then(function(){\n  setTimeout(function(){\n    var target=pendingSessionId && sessions.some(function(s){ return s.id===pendingSessionId; })\n      ? pendingSessionId\n      : null;\n    if(!target){\n      var agentSessions=sessions.filter(function(s){ return s.kind==='agent-cli'; });\n      if(agentSessions.length===1) target=agentSessions[0].id;\n    }\n    if(target) openSession(target); else showPicker();\n    pollTimer=setTimeout(doPoll,POLL_MS);\n  }, 50);\n}).catch(function(e){\n  setStatus('Bridge : '+e.message);\n  $('pickerList').innerHTML='<div class=\"pk-empty\">Échec connexion bridge : '+esc(e.message)+'</div>';\n});\n</script>\n</body>\n</html>`\n","/**\n * McpApp definition for the agentproto \"session story\" panel.\n *\n * A per-session readable timeline: a one-sentence mission + a plan strip of\n * inferred sub-task \"chapters\", a feed of steps segmented by chapter, and an\n * anchored side panel with plain-language + technical detail. Ported 1:1\n * from the validated mockup at docs/session-story-mockup.html.\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_session_story` is called by the host, optionally\n *      with a `sessionId`.\n *   2. execute() returns just enough for the panel to boot: when a\n *      `sessionId` is given, it echoes that back and skips the sessions\n *      list entirely — the panel's own JS never reads the initial snapshot,\n *      it always re-fetches via `session_list` over the postMessage bridge\n *      on boot (see session-story-panel.ts's `loadSessions()`/boot\n *      sequence), so shipping the full list here would just be dead\n *      payload. When no `sessionId` is given (the picker case) it still\n *      returns the full sessions snapshot, since the model/host may surface\n *      it before the panel's own bridge call lands.\n *   3. The HTML panel opens a JSON-RPC bridge (postMessage) and drives\n *      everything else live: `session_list` for status polling,\n *      `agent_export` for the transcript (folded into chapters/steps with a\n *      JS port of session-story.ts's heuristics — the panel HTML is fully\n *      self-contained, so it cannot import the TS module directly), and\n *      `agent_prompt` for the composer.\n */\n\nimport { z } from \"zod\"\nimport { SESSION_STORY_PANEL_HTML } from \"./session-story-panel.js\"\nimport type { SessionDescriptor } from \"./sessions.js\"\nimport type { AgnoMcpApp } from \"./sessions-panel-app.js\"\n\nexport const sessionStoryInputSchema = z.object({\n  sessionId: z\n    .string()\n    .optional()\n    .describe(\n      \"Session id to open directly. When omitted, the panel shows a session \" +\n        \"picker (built from session_list) and lets the user choose.\",\n    ),\n})\n\nexport type SessionStoryInput = z.infer<typeof sessionStoryInputSchema>\nexport type SessionStoryOutput = { sessions: SessionDescriptor[]; sessionId?: string } | { sessionId: string }\n\nexport interface SessionStoryOps {\n  listSessions(filter?: \"running\" | \"all\"): SessionDescriptor[]\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 makeSessionStoryPanelApp(\n  ops: SessionStoryOps,\n): AgnoMcpApp<SessionStoryInput, SessionStoryOutput> {\n  return {\n    id: \"agentproto_session_story\",\n    title: \"Session Story\",\n    description:\n      \"Open the session story panel — a readable, per-session timeline for \" +\n      \"two audiences at once: a plain-language summary of every step for \" +\n      \"beginners, expandable to raw tool-call detail for technical users. \" +\n      \"Shows a one-sentence mission, a plan strip of inferred sub-task \" +\n      \"chapters, a chapter-segmented feed, and a composer to keep driving \" +\n      \"the session. Polls live data and lets you jump to any step.\",\n    inputSchema: sessionStoryInputSchema,\n    execute: async input =>\n      input.sessionId\n        ? { sessionId: input.sessionId }\n        : { sessions: ops.listSessions(\"all\") },\n    html: SESSION_STORY_PANEL_HTML,\n  }\n}\n","/**\n * McpApp definition for a REAL interactive terminal — connects the MCP App\n * iframe directly to the daemon's live PTY WebSocket (`/sessions/:id/pty`),\n * not a poll loop. Distinct from sessions-panel-app.ts/agents-overview-app.ts/\n * bureau-sessions-app.ts, which are all read-only snapshots refreshed via\n * `tools/call`.\n *\n * Uses the same AgnoMcpApp contract (no @agstudio/mcp-apps dependency —\n * agentproto is a standalone workspace). Wire via `registerMcpApps`.\n *\n * Protocol flow:\n *   1. Tool `agentproto_terminal` is called (spawn a new PTY, or attach to\n *      an existing one by `sessionId`).\n *   2. execute() resolves/creates the session via `ops.spawnOrAttach`, then\n *      returns `{sessionId, wsUrl, token, cols, rows}` as the tool's JSON\n *      text result — the client's connection recipe.\n *   3. The HTML panel opens `ui/initialize` (the standard bridge handshake,\n *      for spec compliance) and, independently, opens a real `WebSocket` to\n *      `wsUrl` — bytes flow directly daemon <-> iframe, no `tools/call`\n *      round-trip on the data path.\n *\n * CSP: per the MCP Apps ext spec (2026-01-26), a sandboxed host iframe may\n * only open a WebSocket to an origin the resource's `_meta.ui.csp\n * .connectDomains` allowlist declares. `csp.connectDomains` below is set to\n * the exact origin `wsUrl` resolves to, threaded by `registerMcpApps`\n * (mcp-apps-adapter.ts) into the RESOURCE's `_meta.ui.csp` — CSP is\n * resource-only, never on the tool. Whether Cowork's host actually enforces\n * (or even reads) this declaration is unverified; this only builds the\n * correct declaration.\n */\n\nimport { z } from \"zod\"\nimport type { AgnoMcpApp } from \"./sessions-panel-app.js\"\n\nexport const terminalPanelInputSchema = z.object({\n  sessionId: z\n    .string()\n    .optional()\n    .describe(\n      \"Attach to an existing PTY session (id or name from terminal_start). \" +\n        \"Omit to spawn a new one from `argv`.\",\n    ),\n  argv: z\n    .array(z.string())\n    .min(1)\n    .optional()\n    .describe(\n      \"Argv for a new PTY session. Ignored when `sessionId` is set. \" +\n        \"Defaults to a login shell (`bash`).\",\n    ),\n  cwd: z\n    .string()\n    .optional()\n    .describe(\"Absolute cwd for a new session. Wins over workspaceSlug.\"),\n  workspaceSlug: z\n    .string()\n    .optional()\n    .describe(\"Workspace slug resolving cwd for a new session.\"),\n  cols: z\n    .number()\n    .int()\n    .min(1)\n    .max(500)\n    .optional()\n    .describe(\"Terminal columns. Default 80.\"),\n  rows: z\n    .number()\n    .int()\n    .min(1)\n    .max(200)\n    .optional()\n    .describe(\"Terminal rows. Default 24.\"),\n})\n\nexport type TerminalPanelInput = z.infer<typeof terminalPanelInputSchema>\n\nexport type TerminalPanelOutput = {\n  sessionId: string\n  wsUrl: string\n  /** Empty string when the daemon has no token configured (the sessions\n   *  gate is a no-op in that case — see checkSessionsToken). */\n  token: string\n  cols: number\n  rows: number\n}\n\nexport interface TerminalPanelOps {\n  /** Resolve `input.sessionId` to a live PTY session, or spawn a fresh one\n   *  from `input.argv`/`input.cwd`/`input.workspaceSlug`. Registry access\n   *  (findByIdOrName / spawnPty / workspace resolution) lives entirely on\n   *  the caller's side of this closure — this module never imports\n   *  SessionsRegistry, matching the sessions-panel-app.ts convention. */\n  spawnOrAttach(input: TerminalPanelInput): Promise<{ sessionId: string }>\n  /** The daemon's own PTY-WS origin, e.g. \"ws://127.0.0.1:18790\". Computed\n   *  once by the caller (packages/runtime/src/index.ts already knows its\n   *  own `port`/`bind` at server-construction time — no need to re-derive\n   *  it from `.agentproto/runtime.json` on disk, see the comment at the\n   *  call site). */\n  wsBaseUrl: string\n  /** Sessions-gate bearer token, or undefined when the daemon runs with no\n   *  token configured. Sent to the client as a query-string param (not a\n   *  header) because a browser/iframe WS upgrade can't set custom headers\n   *  — this is the same tradeoff `checkSessionsToken`'s `?token=` path\n   *  exists for. */\n  token?: string\n}\n\n/**\n * Factory: close over the daemon's own connection info + a spawn/attach\n * callback so execute() needs nothing beyond the tool input.\n */\nexport function makeTerminalPanelApp(\n  ops: TerminalPanelOps,\n): AgnoMcpApp<TerminalPanelInput, TerminalPanelOutput> {\n  // `new URL(...).origin` normalises \"ws://127.0.0.1:18790\" (no path) to\n  // itself — this is the exact connectDomains entry the CSP allowlist\n  // needs, derived from the one wsUrl this app will ever open.\n  const wsOrigin = new URL(ops.wsBaseUrl).origin\n\n  return {\n    id: \"agentproto_terminal\",\n    title: \"Interactive Terminal\",\n    description:\n      \"Open a REAL interactive terminal — a live PTY session streamed over \" +\n      \"a WebSocket, not a polling panel. Spawns a new shell (default `bash`) \" +\n      \"or attaches to an existing terminal/PTY session by id.\",\n    inputSchema: terminalPanelInputSchema,\n    execute: async input => {\n      const { sessionId } = await ops.spawnOrAttach(input)\n      const cols = input.cols ?? 80\n      const rows = input.rows ?? 24\n      return {\n        sessionId,\n        wsUrl: `${ops.wsBaseUrl}/sessions/${encodeURIComponent(sessionId)}/pty?cols=${cols}&rows=${rows}`,\n        token: ops.token ?? \"\",\n        cols,\n        rows,\n      }\n    },\n    html: (initData: TerminalPanelOutput) => TERMINAL_HTML(initData),\n    csp: { connectDomains: [wsOrigin] },\n  }\n}\n\n// ── HTML bundle (zero CDN, self-contained) ──────────────────────────────────\n\nfunction TERMINAL_HTML(initData: TerminalPanelOutput): string {\n  return `<!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 terminal</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;flex-direction:column;height:100%}\n#toolbar{padding:8px 12px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;background:var(--bg2);flex-shrink:0}\n#toolbar .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#output{flex:1;overflow-y:auto;padding:8px 12px;background:var(--bg);font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-all}\n#inputbar{display:flex;align-items:center;gap:6px;padding:8px 12px;border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}\n#inputbar .prompt{color:var(--green);font-weight:bold}\n#line{flex:1;background:var(--bg3);border:1px solid var(--border);border-radius:4px;color:var(--text);padding:6px 8px;font-family:inherit;font-size:12px;outline:none}\n#line:disabled{opacity:.5}\n#statusbar{padding:4px 12px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}\n/* ANSI SGR — copied verbatim from sessions-panel.ts (same PTY-output\n   rendering problem: colours 0-15, bold/dim/italic/underline). */\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=\"toolbar\">\n    <span class=\"title\" id=\"title\">Terminal</span>\n    <button class=\"abtn\" id=\"ctrlc-btn\" onclick=\"sendCtrlC()\">Ctrl-C</button>\n  </div>\n  <div id=\"output\"></div>\n  <div id=\"inputbar\">\n    <span class=\"prompt\">&gt;</span>\n    <input id=\"line\" type=\"text\" autocomplete=\"off\" autocapitalize=\"off\" spellcheck=\"false\" placeholder=\"type a command, press Enter to send&#8230;\">\n  </div>\n  <div id=\"statusbar\">Connecting&#8230;</div>\n</div>\n<script>\nwindow.__APP_INIT__ = ${JSON.stringify(initData)};\n\n// ============================================================\n// MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage\n// Spec: io.modelcontextprotocol/ui 2026-01-26\n// Copied verbatim from sessions-panel.ts — same handshake, same\n// wire shape. The terminal's data path never rides this bridge\n// (it talks to the PTY WebSocket directly); we still complete\n// ui/initialize for host-side spec compliance, and use tools/call\n// as a fallback source of connection info (see boot below).\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  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});\n\nfunction initBridge() {\n  return rpcRequest('ui/initialize', {\n    capabilities: {},\n    clientInfo: {name: 'agentproto-terminal-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\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 — copied verbatim from sessions-panel.ts\n// (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  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  var parts = text.split(/([\\\\x1b]\\\\[[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      var inner = part.slice(2, part.length - 1);\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      var safe = escHtml(part).replace(/\\\\x1b\\\\[[^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// Terminal state\n// ============================================================\n\nvar ws = null;\nvar ended = false;\n\nfunction setStatus(msg) {\n  document.getElementById('statusbar').textContent = msg;\n}\n\nfunction appendChunk(text) {\n  var el = document.getElementById('output');\n  var atBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 4;\n  var span = document.createElement('span');\n  span.innerHTML = ansiToHtml(text);\n  el.appendChild(span);\n  if (atBottom) el.scrollTop = el.scrollHeight;\n}\n\nfunction wsSend(obj) {\n  if (ws && ws.readyState === WebSocket.OPEN) {\n    ws.send(JSON.stringify(obj));\n  }\n}\n\n// Ctrl-C is the single most common interactive need (killing a hung\n// foreground command) and can't be typed into a plain <input>, so it\n// gets its own button + keydown intercept alongside line mode.\nfunction sendCtrlC() {\n  wsSend({kind: 'input', text: '\\\\u0003'});\n}\n\n// ------------------------------------------------------------\n// Input mode: LINE-BUFFERED, not raw keystroke-by-keystroke.\n//\n// Tradeoff (intentional prototype scope cut, not a bug): a real\n// terminal forwards every keydown (arrows -> ANSI escapes, Backspace\n// -> \\\\x7f, live single-char echo, etc). Doing that correctly inside a\n// sandboxed iframe means fighting the browser for key composition,\n// IME input, and OS-level shortcut interception — a lot of surface\n// for a prototype whose point is proving the PTY WebSocket + CSP\n// plumbing. Line mode (type a full command, Enter submits it as one\n// CR-terminated frame) covers the dominant use case — running shell\n// commands — with a small fraction of the code and no keyboard-replay\n// edge cases. Ctrl-C is special-cased (see sendCtrlC) since \"kill the\n// foreground thing\" is common enough to need a way in.\n// ------------------------------------------------------------\nfunction initInput() {\n  var input = document.getElementById('line');\n  input.addEventListener('keydown', function(evt) {\n    if (evt.key === 'Enter') {\n      evt.preventDefault();\n      var text = input.value;\n      input.value = '';\n      wsSend({kind: 'input', text: text + '\\\\r'});\n    } else if (evt.ctrlKey && (evt.key === 'c' || evt.key === 'C')) {\n      evt.preventDefault();\n      sendCtrlC();\n    }\n  });\n  input.focus();\n}\n\nfunction connect(conn) {\n  var url = conn.wsUrl + (conn.wsUrl.indexOf('?') === -1 ? '?' : '&') + 'token=' + encodeURIComponent(conn.token || '');\n  document.getElementById('title').textContent = 'Terminal · ' + conn.sessionId;\n  setStatus('Connecting to ' + conn.sessionId + '\\\\u2026');\n  ws = new WebSocket(url);\n  ws.addEventListener('open', function() {\n    setStatus('Connected \\\\u00b7 ' + conn.sessionId);\n    wsSend({kind: 'resize', cols: conn.cols || 80, rows: conn.rows || 24});\n  });\n  ws.addEventListener('message', function(evt) {\n    var frame;\n    try { frame = JSON.parse(evt.data); } catch (e) { return; }\n    if (!frame || typeof frame !== 'object') return;\n    if (frame.kind === 'data' && typeof frame.b64 === 'string') {\n      try {\n        var bytes = atob(frame.b64);\n        var text = decodeURIComponent(escape(bytes));\n        appendChunk(text);\n      } catch (e) {\n        // ignore malformed base64\n      }\n    } else if (frame.kind === 'exit') {\n      ended = true;\n      var code = typeof frame.exitCode === 'number' ? frame.exitCode : 0;\n      setStatus('Session ended \\\\u00b7 exit code ' + code);\n      document.getElementById('line').disabled = true;\n      appendChunk('\\\\n[session ended, exit code ' + code + ']\\\\n');\n    }\n  });\n  ws.addEventListener('close', function() {\n    if (!ended) setStatus('Disconnected');\n    document.getElementById('line').disabled = true;\n  });\n  ws.addEventListener('error', function() {\n    setStatus('WebSocket error');\n  });\n}\n\n// ============================================================\n// Boot\n// ============================================================\n\ninitInput();\ninitBridge().then(function() {\n  var init = window.__APP_INIT__ || {};\n  if (init.wsUrl) return init;\n  // The static ui:// resource is rendered once at server-registration\n  // time with an EMPTY initData (see registerMcpApps in\n  // mcp-apps-adapter.ts) — window.__APP_INIT__ above is therefore\n  // \"{}\" unless a future host wires the real tool-call result back\n  // into the iframe. Fall back to calling the tool ourselves over the\n  // bridge, same as the other panels' initial load.\n  return callTool('agentproto_terminal', {});\n}).then(function(conn) {\n  connect(conn);\n}).catch(function(e) {\n  setStatus('Bridge error: ' + e.message);\n  appendChunk('[failed to connect: ' + e.message + ']\\\\n');\n});\n</script>\n</body>\n</html>`\n}\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 * Per-session JSONL record of a completed `command_execute` invocation\n * (and cron's `kind: \"command\"` action jobs, which share the same\n * allowlist + `runCommand` path — see cron-scheduler.ts's \"one\n * enforcement path, not two\" comment).\n *\n * Each call gets its OWN `kind: \"command\"` session, minted via\n * `SessionsRegistry.recordCommand` — same as an agent-cli or PTY session,\n * so it shows up in `session_list` / `command_list` for free instead of\n * needing a bespoke query surface. Its result is stored at the exact\n * per-id path an agent-cli session's structured transcript already uses:\n * `~/.agentproto/sessions/<id>/events.jsonl` (see transcript-writer.ts).\n * A command session's file holds exactly one line — there's no seq/turn\n * machinery to reconstruct because the call is already finished by the\n * time this is written.\n *\n * This module only knows how to read/write that one line; minting the\n * session itself (and deciding the file's base directory) is\n * `sessions.ts`'s job via `recordCommand`.\n */\n\nimport { appendFile, mkdir, readFile } from \"node:fs/promises\"\nimport { dirname } from \"node:path\"\nimport { sessionEventsPath } from \"./transcript-writer.js\"\n\nexport interface CommandLogEntry {\n  ts: string\n  command: string\n  args: string[]\n  cwd: string\n  exitCode: number\n  signal: string | null\n  durationMs: number\n  stdout: string\n  stderr: string\n  truncated?: boolean\n}\n\n/** Append the entry to `<sessionId>`'s events.jsonl. Fire-and-forget —\n *  never throws; a failure is logged and dropped, matching the\n *  `persistSnapshot` best-effort convention in sessions.ts. A full disk\n *  or a permissions problem under `.agentproto/` must never break the\n *  command the caller actually asked to run. */\nexport function writeCommandLogEntry(\n  sessionId: string,\n  entry: CommandLogEntry,\n  baseDir?: string,\n): Promise<void> {\n  const path = sessionEventsPath(sessionId, baseDir)\n  // Returns the write promise so callers CAN await it (tests do, to avoid a\n  // flaky fixed-delay read); the daemon stays fire-and-forget by `void`-ing\n  // the result. The internal `.catch` keeps an un-awaited call from ever\n  // rejecting, so fire-and-forget is still safe.\n  return mkdir(dirname(path), { recursive: true })\n    .then(() => appendFile(path, `${JSON.stringify(entry)}\\n`, \"utf8\"))\n    .catch(err => {\n      console.warn(`[command-log] failed to write entry for session ${sessionId}:`, err)\n    })\n}\n\n/** Read back a command session's logged entry. Returns null when the\n *  file is missing, empty, or unreadable (e.g. the daemon was killed\n *  before the fire-and-forget write landed) — callers treat that as\n *  \"no result recorded\" rather than an error. */\nexport async function readCommandLogEntry(\n  sessionId: string,\n  baseDir?: string,\n): Promise<CommandLogEntry | null> {\n  try {\n    const raw = await readFile(sessionEventsPath(sessionId, baseDir), \"utf8\")\n    const line = raw.split(\"\\n\").find(l => l.trim().length > 0)\n    if (!line) return null\n    return JSON.parse(line) as CommandLogEntry\n  } catch {\n    return null\n  }\n}\n","/**\n * A per-session observer — the pluggable seam behind the runtime's transcript\n * tap. `sessions.ts` drives one observer per turn (prompt in, each stream event,\n * the turn-boundary usage snapshot, close). The transcript writer is the first\n * and, today, only member; additional observers (e.g. a Langfuse session tracer)\n * attach without touching the turn loop.\n *\n * The method set is exactly the subset of `TranscriptWriter` the session loop\n * calls, so `TranscriptWriter` IS a `SessionObserver` (see transcript-writer.ts).\n */\n\nimport type { AgentStreamEvent } from \"./sessions.js\"\nimport type { SessionUsage } from \"./usage.js\"\n\nexport interface SessionObserver {\n  /** Record the outgoing message that opens a new turn. */\n  recordPrompt(sessionId: string, message: unknown): void\n  /** Record one structured stream event (text-delta, tool-call, usage_update, …). */\n  recordEvent(sessionId: string, evt: AgentStreamEvent): void\n  /** Record the durable turn-boundary / exit usage snapshot. */\n  recordUsageSnapshot(sessionId: string, usage: SessionUsage): void\n  /** Flush and close this session's stream. Idempotent, fire-and-forget. */\n  close(sessionId: string): Promise<void>\n  /** Close every open session stream (synchronous shutdown path). */\n  closeAll(): Promise<void>\n}\n\n/**\n * Fan a `SessionObserver` out over many. Each `record*` call is forwarded to\n * every member in order; `close`/`closeAll` await all members.\n *\n * Every individual member call is isolated in try/catch so one throwing observer\n * can neither break its siblings nor propagate into the turn loop — the\n * transcript writer is effectively infallible today, but a future network-backed\n * observer (a Langfuse sink) must never be able to throw a turn. Failures are\n * swallowed here (no logging dependency at this layer); observers that need\n * visibility into their own failures own that internally.\n */\nexport function composeSessionObservers(\n  observers: readonly SessionObserver[],\n): SessionObserver {\n  const forEachSafe = (fn: (o: SessionObserver) => void): void => {\n    for (const o of observers) {\n      try {\n        fn(o)\n      } catch {\n        // isolate: a failing observer must not break siblings or the turn loop\n      }\n    }\n  }\n\n  const closeSafe = async (fn: (o: SessionObserver) => Promise<void>): Promise<void> => {\n    await Promise.all(\n      observers.map(async (o) => {\n        try {\n          await fn(o)\n        } catch {\n          // isolate close failures too — shutdown must not hang or throw\n        }\n      }),\n    )\n  }\n\n  return {\n    recordPrompt(sessionId, message) {\n      forEachSafe((o) => o.recordPrompt(sessionId, message))\n    },\n    recordEvent(sessionId, evt) {\n      forEachSafe((o) => o.recordEvent(sessionId, evt))\n    },\n    recordUsageSnapshot(sessionId, usage) {\n      forEachSafe((o) => o.recordUsageSnapshot(sessionId, usage))\n    },\n    async close(sessionId) {\n      await closeSafe((o) => o.close(sessionId))\n    },\n    async closeAll() {\n      await closeSafe((o) => o.closeAll())\n    },\n  }\n}\n\n/**\n * Wrap a `SessionObserver` so `record*` calls only reach `inner` for session\n * ids `shouldObserve` accepts — e.g. an opt-in Langfuse tracer that should\n * only see sessions that asked to be traced. `close`/`closeAll` always\n * forward: cleanup is idempotent and must run regardless of opt-in state so\n * the inner observer never leaks a per-session resource.\n *\n * Each forwarded call is isolated in try/catch, same as\n * `composeSessionObservers` — a throwing inner observer must not break the\n * turn loop.\n */\nexport function filterSessionObserver(\n  inner: SessionObserver,\n  shouldObserve: (sessionId: string) => boolean,\n): SessionObserver {\n  return {\n    recordPrompt(sessionId, message) {\n      if (!shouldObserve(sessionId)) return\n      try {\n        inner.recordPrompt(sessionId, message)\n      } catch {\n        // isolate: a failing observer must not break the turn loop\n      }\n    },\n    recordEvent(sessionId, evt) {\n      if (!shouldObserve(sessionId)) return\n      try {\n        inner.recordEvent(sessionId, evt)\n      } catch {\n        // isolate: a failing observer must not break the turn loop\n      }\n    },\n    recordUsageSnapshot(sessionId, usage) {\n      if (!shouldObserve(sessionId)) return\n      try {\n        inner.recordUsageSnapshot(sessionId, usage)\n      } catch {\n        // isolate: a failing observer must not break the turn loop\n      }\n    },\n    async close(sessionId) {\n      try {\n        await inner.close(sessionId)\n      } catch {\n        // isolate close failures too — shutdown must not hang or throw\n      }\n    },\n    async closeAll() {\n      try {\n        await inner.closeAll()\n      } catch {\n        // isolate close failures too — shutdown must not hang or throw\n      }\n    },\n  }\n}\n","/**\n * Per-session JSONL byte log for PTY (`terminal`) sessions — sibling to\n * transcript-writer.ts's events.jsonl, hooked at the same tap point PTY\n * bytes already flow through on their way into the RAM-only `recentBytes`\n * ring (`appendBytes` in sessions.ts). Gives terminal sessions the same\n * restart-survival property agent-cli sessions already have: today a\n * daemon restart loses every PTY byte that isn't still sitting in the\n * ring buffer.\n *\n * File layout: `~/.agentproto/sessions/<sessionId>/terminal.jsonl`, one\n * JSON object per chunk: `{ts, bytes: <base64>}`. Base64 because PTY\n * output is arbitrary bytes (ANSI escapes, partial multi-byte sequences\n * from full-screen apps) — a JSON string can't hold raw bytes safely.\n */\n\nimport { createWriteStream, mkdirSync, type WriteStream } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { sessionTranscriptDir } from \"./transcript-writer.js\"\n\nexport interface TerminalTranscriptWriter {\n  appendChunk(sessionId: string, chunk: Buffer): void\n  /** Flush and close the session's append stream. Safe to call more than\n   *  once and safe to call for a session that never wrote anything. */\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\nexport function terminalLogPath(sessionId: string, baseDir?: string): string {\n  return join(sessionTranscriptDir(sessionId, baseDir), \"terminal.jsonl\")\n}\n\nexport function createTerminalTranscriptWriter(opts?: {\n  baseDir?: string\n}): TerminalTranscriptWriter {\n  const baseDir = opts?.baseDir\n  const streams = new Map<string, WriteStream>()\n\n  const getStream = (sessionId: string): WriteStream => {\n    const existing = streams.get(sessionId)\n    if (existing) return existing\n    mkdirSync(sessionTranscriptDir(sessionId, baseDir), { recursive: true })\n    const stream = createWriteStream(terminalLogPath(sessionId, baseDir), { flags: \"a\" })\n    stream.on(\"error\", err => {\n      console.warn(`[terminal-transcript-writer] session ${sessionId}: ${err.message}`)\n    })\n    streams.set(sessionId, stream)\n    return stream\n  }\n\n  return {\n    appendChunk(sessionId, chunk) {\n      const stream = getStream(sessionId)\n      stream.write(`${JSON.stringify({ ts: new Date().toISOString(), bytes: chunk.toString(\"base64\") })}\\n`)\n    },\n    close(sessionId) {\n      const stream = streams.get(sessionId)\n      if (!stream) return Promise.resolve()\n      streams.delete(sessionId)\n      return new Promise<void>(resolve => {\n        stream.end(() => resolve())\n      })\n    },\n    closeAll() {\n      const closings: Promise<void>[] = []\n      for (const sessionId of Array.from(streams.keys())) {\n        const stream = streams.get(sessionId)\n        if (!stream) continue\n        closings.push(\n          new Promise<void>(resolve => {\n            stream.end(() => resolve())\n          }),\n        )\n      }\n      streams.clear()\n      return Promise.all(closings).then(() => undefined)\n    },\n  }\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, AcpPermissionResolution } 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 { readCommandLogEntry, writeCommandLogEntry } from \"./command-log.js\"\nimport type { SessionEventBus, SessionAwaitingQuestion } from \"./session-event-bus.js\"\nimport {\n  composeSessionObservers,\n  filterSessionObserver,\n  type SessionObserver,\n} from \"./session-observer.js\"\nimport { formatToolCall, formatToolResult } from \"./tool-presenter.js\"\nimport { createTranscriptWriter } from \"./transcript-writer.js\"\nimport { createTerminalTranscriptWriter } from \"./terminal-transcript-writer.js\"\nimport { deriveSessionUsage, plausibleContextUsed, type SessionUsage } from \"./usage.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  /** Resolve a permission request the driver parked in permission-hold mode\n   *  (see the pending-permissions inbox below). `requestId` is the driver's\n   *  own stable id, surfaced on the `agent-prompt` event's `toolCallId`.\n   *  Returns true when a matching parked request was resolved. Absent for\n   *  drivers that don't model held permissions (sandbox proxy, future\n   *  transports). */\n  respondPermission?(\n    requestId: string,\n    resolution: AcpPermissionResolution,\n  ): boolean | Promise<boolean>\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  /** True when a \"tool-call\" event ENRICHES one already announced under the\n   *  same `toolCallId` (the agent knew the input only after announcing the\n   *  call) rather than announcing a new one — see @agentproto/acp's\n   *  `StreamEvent`. Consumers merge by toolCallId; it is not a second call. */\n  isUpdate?: boolean\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  /** \"usage_update\" cumulative input/output token counts, when the adapter\n   *  reports them (lets the daemon price a session whose adapter gives tokens\n   *  but no `cost`). */\n  tokensIn?: number\n  tokensOut?: number\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\n/**\n * Narrow an `agent-prompt` event's `options` (typed `unknown`) into the ACP\n * `{ optionId, name?, kind? }` permission-option shape for the pending inbox.\n * Drops entries without a string `optionId` — those can't be responded to.\n */\nfunction normalizePermissionOptions(\n  raw: unknown,\n): Array<{ optionId: string; name?: string; kind?: string }> {\n  if (!Array.isArray(raw)) return []\n  const out: Array<{ optionId: string; name?: string; kind?: string }> = []\n  for (const o of raw) {\n    if (!o || typeof o !== \"object\") continue\n    const r = o as Record<string, unknown>\n    if (typeof r.optionId !== \"string\") continue\n    out.push({\n      optionId: r.optionId,\n      ...(typeof r.name === \"string\" ? { name: r.name } : {}),\n      ...(typeof r.kind === \"string\" ? { kind: r.kind } : {}),\n    })\n  }\n  return out\n}\n\n/**\n * Map an inbox decision onto one of the offered permission options.\n *   - explicit `optionId` wins (must be one of the offered options)\n *   - approve → an `allow_*` option (allow-always when `scope: \"always\"` and\n *     one is offered, otherwise allow-once, otherwise any allow-flavored)\n *   - deny → a `reject_*` option (undefined when none is offered → the caller\n *     resolves the request as `cancelled`)\n * Returns `null` only for an approve with no allow-flavored option — a hard\n * error (the request can't be granted through any offered option).\n */\nfunction selectPermissionOptionId(\n  options: ReadonlyArray<{ optionId: string; kind?: string }>,\n  input: { decision: \"approve\" | \"deny\"; optionId?: string; scope?: \"once\" | \"always\" },\n): { optionId: string } | { cancelled: true } | null {\n  if (input.optionId) {\n    return options.some(o => o.optionId === input.optionId)\n      ? { optionId: input.optionId }\n      : null\n  }\n  const kindStarts = (prefix: string) =>\n    options.find(o => typeof o.kind === \"string\" && o.kind.startsWith(prefix))\n  if (input.decision === \"approve\") {\n    const chosen =\n      (input.scope === \"always\"\n        ? options.find(o => o.kind === \"allow_always\")\n        : options.find(o => o.kind === \"allow_once\")) ??\n      kindStarts(\"allow\") ??\n      // Some agents label the grant \"proceed\"/\"yes\" without an `allow_` kind —\n      // fall back to the first non-reject option before giving up.\n      options.find(o => !(typeof o.kind === \"string\" && o.kind.startsWith(\"reject\")))\n    return chosen ? { optionId: chosen.optionId } : null\n  }\n  // deny — prefer an explicit reject option; else cancel the request outright.\n  const reject = options.find(o => o.kind === \"reject_once\") ?? kindStarts(\"reject\") ?? kindStarts(\"deny\")\n  return reject ? { optionId: reject.optionId } : { cancelled: true }\n}\n\n/**\n * Classify what a tool call blocks the turn on, from its tool name alone.\n * Powers `SessionDescriptor.blockedOn`: \"subagent\" for an `agent_start`\n * (the turn is waiting on a spawned child agent), \"command\" for shell /\n * terminal execution tools. Anything else — including fast local tools —\n * returns undefined and leaves the descriptor untouched. Matching is\n * intentionally loose on the command side (bash/terminal/command\n * substrings) so adapter-native tool names (e.g. claude-code's \"Bash\")\n * classify without a per-adapter table.\n */\nfunction classifyBlockedOn(toolName?: string): \"subagent\" | \"command\" | undefined {\n  if (!toolName) return undefined\n  const n = toolName.toLowerCase()\n  if (n === \"agent_start\") return \"subagent\"\n  if (/^(command_execute|terminal_start)$|bash|terminal|command/.test(n)) return \"command\"\n  return undefined\n}\n\n/**\n * Release `blockedOn` — the thing the turn was waiting on is no longer\n * pending.\n *\n * `blockedOn` is a claim about the PRESENT (\"this turn is waiting on a\n * command right now\"), so every path that disproves the claim has to clear\n * it. Keying the release solely on a tool-result whose `toolCallId` matches\n * made the flag latch: a tool that FAILS emits `error`, never a tool-result,\n * so the session kept advertising \"blocked on command · <id>\" for the rest of\n * the turn while the agent had long since recovered and moved on. The turn's\n * `finally` did eventually clear it, which is why the lie was invisible on\n * short turns and glaring on long ones.\n */\nfunction releaseBlockedOn(desc: SessionDescriptor): void {\n  desc.blockedOn = undefined\n  desc.pendingToolCallId = undefined\n}\n\n/**\n * True when a thrown value represents a turn ABORT rather than a genuine\n * error — a cancelled/killed turn surfaces as a DOMException-style\n * `AbortError` (`name`) or Node's `ABORT_ERR` (`code`). Lets the turn\n * finalizer synthesize a `turn-end` tagged `\"aborted\"` instead of\n * mislabelling a deliberate cancel as a turn error. Kill-driven aborts are\n * additionally caught by inspecting the descriptor status at the call site.\n */\nfunction isAbortError(err: unknown): boolean {\n  if (typeof err !== \"object\" || err === null) return false\n  const name = \"name\" in err ? err.name : undefined\n  const code = \"code\" in err ? err.code : undefined\n  return name === \"AbortError\" || code === \"ABORT_ERR\"\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\n/**\n * The billing-auth resolver's OBSERVABLE echo, recorded on a session\n * descriptor. `mode` + `fingerprint` are always present when recorded (a\n * credential resolved); `provider` / `credentialSource` / `setEnv` are the\n * multi-provider resolver's additions (DECISION 9③/10②) — optional for\n * back-compat with descriptors from before that resolver shipped.\n */\nexport interface SessionAuthEcho {\n  mode: \"subscription\" | \"api-key\"\n  fingerprint: string\n  provider?: string\n  credentialSource?: \"explicit-config\" | \"providers-store\" | \"none\"\n  setEnv?: string\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  /** Set alongside `status: \"killed\"` when the session ended NOT because an\n   *  operator targeted it (`kill()`) but because the daemon process it lived\n   *  in went away out from under it — a hard crash discovered at next boot\n   *  (`loadHistorySnapshot`'s wasAlive reclassification), or a graceful\n   *  shutdown/restart that force-kills whatever's still busy\n   *  (`shutdownImpl`). Absent for every other terminal path (operator kill,\n   *  natural exit, turn error) — the session's own fault, or at least not\n   *  the daemon's. Lets the UI show \"crashed with the daemon\" instead of a\n   *  bare \"killed\" that reads as deliberate. */\n  endedReason?: \"daemon-restart\"\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  /**\n   * Deterministic billing-auth mode + a non-secret credential fingerprint,\n   * recorded at spawn time for adapters that resolved an explicit\n   * credential (today: claude-code — see `AgentCliAuth.modes` in\n   * `@agentproto/driver-agent-cli`). The \"verifiability\" answer to \"what\n   * was used\": `mode` is the resolved `\"subscription\" | \"api-key\"`;\n   * `fingerprint` is `credentialFingerprint(mode, credential)` — e.g.\n   * `\"subscription · sk-ant-oat…3f9c\"` — NEVER the raw credential. Absent\n   * when no credential resolved (every adapter besides claude-code, in\n   * practice) or for a sandboxed spawn (the box's own daemon resolves its\n   * own credential independently). Surfaced in `agentproto sessions\n   * --watch`'s DETAIL pane and `agent_sessions_list`.\n   *\n   * Carries the resolver's OBSERVABLE echo (DECISION 9③/10②): `provider`,\n   * `credentialSource`, and the `setEnv` actually set — so a verifier checks\n   * the RESOLUTION, not the model's self-report. These are optional for\n   * back-compat with descriptors persisted before the multi-provider resolver.\n   */\n  auth?: SessionAuthEcho\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  /** Context-window size + tokens-in-context from the latest `usage_update`\n   *  event (ACP adapters that report a context window). Refreshed live as\n   *  usage_update events arrive, not just at turn-end. */\n  contextSize?: number\n  contextUsed?: number\n  /** Where `costUsd` came from — `\"adapter\"` (adapter's own reader or a\n   *  usage_update cost block), `\"computed\"` (tokens × in-repo catalog price),\n   *  `\"no-pricing\"` (tokens present but the model isn't in the catalog — cost\n   *  deliberately left undefined), or `\"none\"`. Stamped at each turn-end. */\n  usageSource?: import(\"./usage.js\").UsageSource\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  /** True while this session (spawned in permission-hold mode) has at least\n   *  one permission request parked in the inbox awaiting a human/orchestrator\n   *  decision. Distinct from `awaitingInput` (a conversational question) — a\n   *  held permission is resolved via `permissions_respond` / `agentproto\n   *  permissions approve|deny`, not a normal prompt. Set when a request is\n   *  registered, cleared when the last pending one for this session resolves.\n   *  Absent (never `false`) for sessions with no held permissions. */\n  awaitingPermission?: boolean\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  /** What the in-flight turn is currently blocked on, when classifiable\n   *  from the pending tool call: a spawned sub-agent (`agent_start`) or a\n   *  shell/terminal command. Deliberately NO \"user\" variant — waiting on\n   *  the user is already covered by `awaitingInput`/`awaitingQuestion`.\n   *\n   *  Set on tool-call; released (see `releaseBlockedOn`) on the MATCHING\n   *  tool-result, on `error` (a failing tool never emits a result), on the\n   *  next assistant `text-delta` (the model has the floor, so nothing is\n   *  pending), at turn start, and in the turn's finally. A claim about the\n   *  present tense — anything that disproves it must clear it. */\n  blockedOn?: \"subagent\" | \"command\"\n  /** toolCallId of the tool-call that set `blockedOn`. A tool-result only\n   *  clears `blockedOn` when its toolCallId matches — so a nested or\n   *  interleaved tool finishing first can't clear the flag early. */\n  pendingToolCallId?: string\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  /** Id of the most recently-completed `kind: \"command\"` session spawned\n   *  with the same `cwd`, found at spawn time — see `recordCommand` and\n   *  `findPriorCommandSessionId`. Deliberately a REFERENCE, not copied\n   *  content: a new session's own ring buffer / structured transcript\n   *  never gets a prior command_execute's stdout/stderr spliced in, it\n   *  just gets told where to look (`command_log_tail({sessionId})` or\n   *  `agent_export`/`command_list` resolve the id into the full record).\n   *  Set on `spawnAgent`/`spawnPty` when the registry already has a\n   *  matching command session; absent otherwise (including for legacy\n   *  rows persisted before this field existed). */\n  priorCommandSessionId?: string\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  /** True when this agent-cli session is running inside a sandbox (`agent_start.sandbox`)\n   *  rather than as a local subprocess — there's no local PID to check, so\n   *  `processAlive` never applies (it's already absent whenever `pid` is null). */\n  remote?: boolean\n  /** Provider-assigned sandbox id (`BootedSandbox.sandboxId`), when `remote` is true. */\n  sandboxId?: string\n  /** What session close does to the box (PR3 lifecycle) — `\"kill\"` (the\n   *  default, ephemeral) or `\"pause\"` (keeps `sandboxId` reconnectable via\n   *  `agent_start.sandbox.reuse`). Only set when `remote` is true. */\n  sandboxTeardown?: \"kill\" | \"pause\"\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  /** True once an authoritative cost has been observed from the adapter —\n   *  either its `readUsage` returned a `costUsd`, or a `usage_update` carried\n   *  a `cost` block. Drives the `\"adapter\"` vs `\"computed\"` source decision at\n   *  turn-end. */\n  adapterReportedCost?: boolean\n  /** True when the session was spawned in permission-hold mode — its\n   *  `agent-prompt` events carry respondable permission requests that get\n   *  registered in the pending-permissions inbox. Default false. */\n  permissionHold?: boolean\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/** Bound on how long `enqueuePrompt({interrupt: true})` waits for a\n *  cancelled turn to actually settle (busy → false) before giving up.\n *  A well-behaved adapter settles within a few event-loop turns of\n *  `cancel()` resolving; this is a safety net against an adapter that\n *  never delivers the corresponding turn-end, not the normal path. */\nconst INTERRUPT_SETTLE_TIMEOUT_MS = 30_000\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/** Find the most recently-completed `kind: \"command\"` session whose `cwd`\n *  matches, for stamping `priorCommandSessionId` on a freshly spawned\n *  agent-cli/PTY session in the same workspace. Scans the in-memory\n *  registry (not the filesystem) — that's the same source of truth\n *  `command_list`/`session_list({kind:\"command\"})` themselves read from,\n *  including sessions restored from sessions.json at boot. A pure map\n *  scan over what's typically a handful of entries; no I/O, so nothing to\n *  fail here the way a filesystem lookup could. */\nfunction findPriorCommandSessionId(\n  liveSessions: Map<string, SessionRuntime>,\n  cwd: string,\n): string | undefined {\n  let best: SessionRuntime | undefined\n  for (const rt of liveSessions.values()) {\n    if (rt.desc.kind !== \"command\" || rt.desc.cwd !== cwd) continue\n    const bestTs = best ? (best.desc.endedAt ?? best.desc.startedAt) : undefined\n    const candidateTs = rt.desc.endedAt ?? rt.desc.startedAt\n    if (!best || candidateTs > bestTs!) best = rt\n  }\n  return best?.desc.id\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\n/**\n * A `session/request_permission` request parked by a permission-hold session,\n * awaiting a human/orchestrator decision through the cross-session inbox\n * (`permissions_list` / `permissions_respond`, `GET /permissions` /\n * `POST /permissions/:id`, `agentproto permissions ls|approve|deny`).\n */\nexport interface PendingPermission {\n  /** Stable id — the driver's own request id, unique across sessions. Pass to\n   *  `respondPermission`. */\n  id: string\n  sessionId: string\n  /** ACP tool-call id the request was raised for (== `id` today; kept distinct\n   *  so a future driver can surface a separate correlation id). */\n  toolCallId: string\n  /** Tool title/kind the agent is asking permission for, when known. */\n  toolName?: string\n  /** Human-readable \"Allow X?\" line. */\n  text: string\n  /** Options the agent offered (ACP `requestPermission` shape). */\n  options: Array<{ optionId: string; name?: string; kind?: string }>\n  /** ISO timestamp the request was parked. */\n  requestedAt: string\n}\n\n/** How a caller resolves a pending permission — an explicit `optionId` wins\n *  over the `decision`→option mapping (approve → an allow-flavored option,\n *  deny → a reject-flavored option). `scope: \"always\"` prefers an\n *  allow-always option when the request offers one. */\nexport interface PermissionRespondInput {\n  decision: \"approve\" | \"deny\"\n  optionId?: string\n  scope?: \"once\" | \"always\"\n}\n\nexport type PermissionRespondResult =\n  | { ok: true; permission: PendingPermission; decision: \"approve\" | \"deny\"; optionId?: string }\n  | {\n      ok: false\n      error: \"not_found\" | \"session_gone\" | \"no_matching_option\" | \"unsupported\"\n      message: string\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 a COMPLETED `command_execute` (or cron `kind:\"command\"`\n   *  action) invocation as its own `kind: \"command\"` session. Unlike\n   *  `spawn`/`spawnAgent`/`spawnPty`, there's no live process to track —\n   *  the command already ran to completion via `runCommand` before this\n   *  is called — so the descriptor is minted already \"finished\"\n   *  (status exited/error, startedAt backdated by `durationMs`,\n   *  endedAt now) and its full result is written to that session's own\n   *  `events.jsonl` (see command-log.ts), the same per-id path an\n   *  agent-cli session's structured transcript uses. Synchronous: the\n   *  descriptor (and its id) is available immediately, the JSONL write\n   *  itself is fire-and-forget internally. */\n  recordCommand(input: RecordCommandInput): SessionDescriptor\n  /** Read back a `kind:\"command\"` session's full logged result (the\n   *  `CommandLogEntry` `recordCommand` wrote). Resolves to null when the\n   *  session isn't a command session or has no recorded entry. Routed\n   *  through the registry (rather than callers importing\n   *  `readCommandLogEntry` directly) so the read always targets the same\n   *  base directory `recordCommand` wrote to — that dir is test-overridable\n   *  (`transcriptDir`) and callers outside sessions.ts have no other way\n   *  to know it. */\n  readCommandLog(sessionId: string): Promise<import(\"./command-log.js\").CommandLogEntry | null>\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 and AWAIT it. Throws\n   *  when the session is missing, not an agent-cli kind, dead (exited/\n   *  killed/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   *\n   *  `opts.interrupt` behaves exactly as it does on `enqueuePrompt`:\n   *  a mid-turn session has its in-flight turn cancelled and settled\n   *  before admission, so this prompt redirects the SAME live session\n   *  instead of hitting the busy rejection. Ignored (identical to the\n   *  default) when the session is idle. Omitted or `false` reproduces\n   *  the previous mid-turn rejection byte-for-byte. */\n  sendPrompt(\n    id: string,\n    message: unknown,\n    opts?: { interrupt?: boolean }\n  ): 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   *\n   *  `opts.interrupt` lets a caller redirect a mid-turn session instead\n   *  of hitting the busy rejection: the in-flight turn is cancelled\n   *  (`agentSession.cancel()`), admission waits for that turn to\n   *  actually settle (busy flips false — no fixed sleep), then the new\n   *  prompt is admitted + fired on the SAME live session. Ignored\n   *  (identical to the default) when the session is idle. Omitted or\n   *  `false` reproduces today's mid-turn rejection byte-for-byte. */\n  enqueuePrompt(\n    id: string,\n    message: unknown,\n    opts?: { interrupt?: boolean }\n  ): 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 session's structured events.jsonl records as they're\n   *  written — the live-push half of `GET /sessions/:id/events/stream`'s\n   *  replay-then-subscribe handoff. Thin passthrough to the transcript\n   *  writer's own `subscribe` (see transcript-writer.ts for the exactly-\n   *  once contract this enables); no backfill, no existence check — a\n   *  session id with no writer state simply never calls back. Returns an\n   *  unsubscribe fn. */\n  subscribeToRecords(\n    id: string,\n    onRecord: (record: Record<string, unknown>) => void\n  ): () => void\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  /** List permission requests currently parked in the pending-permissions\n   *  inbox across all permission-hold sessions, newest last. Optionally\n   *  filtered to one session. */\n  listPendingPermissions(filter?: { sessionId?: string }): PendingPermission[]\n  /** Resolve a parked permission by id — maps the decision (or explicit\n   *  optionId) to one of the offered options, resolves the held driver RPC,\n   *  clears the session's awaiting-permission state, and emits\n   *  `session:permission-resolved`. */\n  respondPermission(\n    id: string,\n    input: PermissionRespondInput,\n  ): Promise<PermissionRespondResult>\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  /** Resolved auth echo (mode + fingerprint + provider/source/setEnv) —\n   *  recorded verbatim onto {@link SessionDescriptor.auth}. See that field's\n   *  doc for the full contract; the caller (`session-spawn.ts`) computes this\n   *  via the billing-auth resolver, never passing the raw credential here. */\n  auth?: SessionAuthEcho\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  /** Opt this session into Langfuse tracing (prompt/completion + tool spans +\n   *  tokens/cost). Effective opt-in is `trace ?? opts.langfuseTracingDefault ?? false`. */\n  trace?: boolean\n  /** True when `agentSession` is a `SandboxAgentSessionProxy` (`agent_start.sandbox`)\n   *  rather than a local subprocess-backed session — stamped onto the descriptor\n   *  as `remote` since there's no local PID to report. */\n  remote?: boolean\n  /** Provider-assigned sandbox id, when `remote` is true. */\n  sandboxId?: string\n  /** What session close does to the box, when `remote` is true — see\n   *  `SessionDescriptor.sandboxTeardown`. */\n  sandboxTeardown?: \"kill\" | \"pause\"\n  /** True when the driver session was started in permission-hold mode\n   *  (`AgentCliStartOptions.permissionHold`) — its `agent-prompt` events carry\n   *  respondable permission requests. Gates whether the registry registers\n   *  them in the pending-permissions inbox. Default false. */\n  permissionHold?: boolean\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\nexport interface RecordCommandInput {\n  workspaceSlug: string\n  /** Working directory the command actually ran in (post cwd-anchoring).\n   *  Matched against a fresh session's cwd by `findPriorCommandSessionId`. */\n  cwd: string\n  command: string\n  args: string[]\n  /** Fields mirror `command-tools.ts`'s `ExecuteResult` — kept inline here\n   *  (rather than importing that type) so sessions.ts has no dependency\n   *  on command-tools.ts. */\n  exitCode: number\n  signal: string | null\n  durationMs: number\n  stdout: string\n  stderr: string\n  truncated?: boolean\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  /** Shared, opt-in Langfuse session observer. Built once in the bootstrap\n   *  from eval-reporter creds. Events only reach it for sessions in the\n   *  registry's traced-session set — see `langfuseTracingDefault`. */\n  langfuseTracer?: SessionObserver\n  /** Default per-session tracing opt-in when `SpawnAgentInput.trace` is\n   *  omitted. Defaults to false (tracing off). */\n  langfuseTracingDefault?: boolean\n}): SessionsRegistry {\n  const persistPath = opts?.persistPath ?? SESSIONS_FILE_PATH()\n  const persist = opts?.persist ?? true\n  const transcriptBaseDir = opts?.transcriptDir ?? join(dirname(persistPath), \"sessions\")\n  const baseTranscriptWriter = createTranscriptWriter({ baseDir: transcriptBaseDir })\n  // Sibling writer for PTY (`terminal`) sessions — same per-id directory,\n  // a `terminal.jsonl` file instead of `events.jsonl` since raw bytes\n  // (not structured StreamEvents) are what a PTY has to persist.\n  const terminalTranscriptWriter = createTerminalTranscriptWriter({ baseDir: transcriptBaseDir })\n  // The transcript writer is the first (today only) per-session observer. The\n  // composite fans every prompt/event/usage/close call out to its members, so\n  // additional observers (e.g. an opt-in Langfuse session tracer) attach here\n  // without touching any of the turn-loop call sites below. With a single\n  // member the behaviour is identical to calling the writer directly.\n  const tracedSessions = new Set<string>()\n  const extraObservers: readonly SessionObserver[] = opts?.langfuseTracer\n    ? [filterSessionObserver(opts.langfuseTracer, (id) => tracedSessions.has(id))]\n    : []\n  const transcriptWriter: SessionObserver = composeSessionObservers([\n    baseTranscriptWriter,\n    ...extraObservers,\n  ])\n  const ptyFactory = opts?.spawnPty\n  const resumeAgent = opts?.resumeAgent\n  const sessionEvents = opts?.sessionEvents\n  const sessions = new Map<string, SessionRuntime>()\n  // Cross-session pending-permissions inbox: every request parked by a\n  // permission-hold session, keyed by the driver's stable request id.\n  // Insertion order is preserved so `listPendingPermissions` reads oldest→\n  // newest without a sort.\n  const pendingPermissions = new Map<string, PendingPermission>()\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, sessionEvents)\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 (rt.exitedEmitted) return\n    // A dying session must never leave a held permission RPC dangling — cancel\n    // its parked requests (resolves them as `cancelled`) before anything else.\n    // Runs even when no bus is wired, so the driver RPC always settles.\n    cancelPendingPermissionsForSession(rt)\n    if (!sessionEvents) 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      ...(rt.desc.endedReason ? { reason: rt.desc.endedReason } : {}),\n    })\n  }\n\n  // ── Pending-permissions inbox helpers ────────────────────────────────\n  //\n  // A permission-hold session surfaces each `session/request_permission` as an\n  // `agent-prompt` StreamEvent (see the driver's ACP arm). `projectEvent`\n  // routes that here to register a PendingPermission and emit\n  // `session:permission-request`; `respondPermission` resolves it back through\n  // the held driver RPC.\n\n  /** Recompute `desc.awaitingPermission` from the live pending set — true iff\n   *  the session still has at least one parked request. */\n  const refreshAwaitingPermission = (rt: SessionRuntime): void => {\n    let has = false\n    for (const p of pendingPermissions.values()) {\n      if (p.sessionId === rt.desc.id) {\n        has = true\n        break\n      }\n    }\n    if (has) rt.desc.awaitingPermission = true\n    else delete rt.desc.awaitingPermission\n  }\n\n  /** Register a permission request surfaced by an `agent-prompt` event on a\n   *  permission-hold session, and announce it on the bus. */\n  const registerPendingPermission = (\n    rt: SessionRuntime,\n    evt: AgentStreamEvent,\n  ): void => {\n    const id = evt.toolCallId\n    if (!id) return // nothing to respond to — treat as a plain awaiting-input\n    const options = normalizePermissionOptions(evt.options)\n    const toolName = evt.toolName\n    const text =\n      evt.text ?? (toolName ? `Allow \"${toolName}\"?` : \"The agent is requesting permission.\")\n    const pending: PendingPermission = {\n      id,\n      sessionId: rt.desc.id,\n      toolCallId: id,\n      ...(toolName ? { toolName } : {}),\n      text,\n      options,\n      requestedAt: new Date().toISOString(),\n    }\n    pendingPermissions.set(id, pending)\n    rt.desc.awaitingPermission = true\n    schedulePersist()\n    if (sessionEvents) {\n      sessionEvents.emit({\n        type: \"session:permission-request\",\n        sessionId: rt.desc.id,\n        permissionId: id,\n        ...(toolName ? { toolName } : {}),\n        text,\n        ...(rt.desc.label ? { label: rt.desc.label } : {}),\n        ts: pending.requestedAt,\n      })\n    }\n  }\n\n  /** Cancel (resolve as `cancelled`) every request parked for a dying session\n   *  so no held driver RPC dangles. Emits `session:permission-resolved` with\n   *  `decision: \"cancelled\"` for each. Best-effort — the driver session may\n   *  already be closing. */\n  const cancelPendingPermissionsForSession = (rt: SessionRuntime): void => {\n    for (const [id, pending] of pendingPermissions) {\n      if (pending.sessionId !== rt.desc.id) continue\n      pendingPermissions.delete(id)\n      try {\n        void rt.agentSession?.respondPermission?.(id, { cancelled: true })\n      } catch {\n        // driver already gone — the RPC is moot\n      }\n      if (sessionEvents) {\n        sessionEvents.emit({\n          type: \"session:permission-resolved\",\n          sessionId: rt.desc.id,\n          permissionId: id,\n          decision: \"cancelled\",\n          ...(rt.desc.label ? { label: rt.desc.label } : {}),\n          ts: new Date().toISOString(),\n        })\n      }\n    }\n    delete rt.desc.awaitingPermission\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    // Durable copy BEFORE the RAM ring drops anything — same ordering\n    // rule transcript-writer.ts follows for agent-cli StreamEvents.\n    terminalTranscriptWriter.appendChunk(rt.desc.id, chunk)\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        // Assistant text means the model has the floor again, so it cannot\n        // still be waiting on the tool that blocked it — the result landed\n        // (whether or not the adapter bothered to emit one; several don't).\n        // This is the catch-all behind the explicit releases below.\n        releaseBlockedOn(rt.desc)\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        // Surface what the turn is now blocked on (sub-agent / command) when\n        // the tool name classifies. The toolCallId is remembered so a nested\n        // tool's result can't clear an outer tool's block — but a matching\n        // result is only ONE of the ways the block ends; see releaseBlockedOn.\n        const blocked = classifyBlockedOn(evt.toolName)\n        if (blocked) {\n          rt.desc.blockedOn = blocked\n          rt.desc.pendingToolCallId = evt.toolCallId\n        }\n        // An enrichment restates a call already announced under this\n        // toolCallId (the agent only learned its input afterwards — see\n        // @agentproto/acp's tool_call_update handling). The structured\n        // transcript merges it by id; the ring buffer must NOT print a second\n        // [tool] line for one call.\n        if (!evt.isUpdate) {\n          appendLine(\n            rt,\n            `\\x1b[36m[tool] ${formatToolCall(evt.toolName ?? \"?\", evt.arguments)}\\x1b[0m`,\n            \"stdout\"\n          )\n        }\n        break\n      }\n      case \"tool-result\": {\n        if (rt.desc.blockedOn && evt.toolCallId === rt.desc.pendingToolCallId) {\n          releaseBlockedOn(rt.desc)\n        }\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        // Permission-hold sessions park the request in the cross-session inbox\n        // so a human/orchestrator can approve/deny it out-of-band. The RPC is\n        // held open by the driver until `respondPermission` resolves it.\n        if (rt.permissionHold) {\n          registerPendingPermission(rt, evt)\n          appendLine(rt, `\\x1b[33m[permission] ${evt.text ?? evt.toolName ?? \"requesting permission\"}\\x1b[0m`, \"stdout\")\n        } else {\n          appendLine(rt, `\\x1b[33m[awaiting input]\\x1b[0m`, \"stdout\")\n        }\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        // A failing tool reports `error`, NOT a tool-result — so this is the\n        // only signal that the thing we were blocked on is done. Without this\n        // release the flag survived the failure and the session advertised\n        // \"blocked on command · <toolCallId>\" while the agent worked on.\n        releaseBlockedOn(rt.desc)\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) — the\n      // ring buffer isn't the right place for it (cost is surfaced via\n      // rt.desc.costUsd at turn-end); it still lands in events.jsonl via the\n      // transcript writer tap point. We DO mirror its structured fields onto\n      // the descriptor here so the latest context window + any adapter-\n      // reported cost/tokens are available live to session_list / session_usage.\n      case \"usage_update\": {\n        if (typeof evt.size === \"number\" && evt.size > 0) rt.desc.contextSize = evt.size\n        // `used` claims to be tokens currently in context (see the field's\n        // doc comment above) — but at least one adapter's ACP server has\n        // been observed sending a cumulative session-lifetime token total\n        // in this same field instead, which routinely lands 10-70x past the\n        // window. A `used` that exceeds the window it's supposedly inside\n        // of is provably not that; `plausibleContextUsed` drops it rather\n        // than let a fabricated-looking >100% occupancy figure through.\n        if (typeof evt.used === \"number\" && evt.used > 0) {\n          const used = plausibleContextUsed(rt.desc.contextSize, evt.used)\n          if (used !== undefined) rt.desc.contextUsed = used\n        }\n        if (evt.cost) {\n          rt.desc.costUsd = evt.cost.amount\n          rt.adapterReportedCost = true\n        }\n        if (typeof evt.tokensIn === \"number\") rt.desc.tokensIn = evt.tokensIn\n        if (typeof evt.tokensOut === \"number\") rt.desc.tokensOut = evt.tokensOut\n        break\n      }\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   * Race-free wait for a mid-turn session to settle to idle: resolves\n   * the instant `rt.busy` flips false (the same flag `validateAgentTurn`\n   * reads), driven by the \"busy\" event `runAgentTurn`'s finally block\n   * emits — never a fixed sleep. Resolves immediately if the turn is\n   * already over by the time this is called. Rejects if the turn\n   * hasn't settled within `INTERRUPT_SETTLE_TIMEOUT_MS` (a hung/buggy\n   * adapter that never delivers a turn-end for the cancelled turn).\n   */\n  const waitForTurnSettled = (\n    rt: SessionRuntime,\n    id: string,\n    caller: string\n  ): Promise<void> => {\n    if (!rt.busy) return Promise.resolve()\n    return new Promise<void>((resolve, reject) => {\n      const onBusy = (busy: boolean): void => {\n        if (busy) return\n        cleanup()\n        resolve()\n      }\n      const cleanup = (): void => {\n        clearTimeout(timer)\n        rt.emitter.off(\"busy\", onBusy)\n      }\n      const timer = setTimeout(() => {\n        cleanup()\n        reject(\n          new Error(\n            `${caller}: session \"${id}\" did not settle after interrupt within ${INTERRUPT_SETTLE_TIMEOUT_MS}ms`\n          )\n        )\n      }, INTERRUPT_SETTLE_TIMEOUT_MS)\n      rt.emitter.on(\"busy\", onBusy)\n    })\n  }\n\n  /**\n   * The `{interrupt: true}` mid-turn arm, shared by `sendPrompt` and\n   * `enqueuePrompt`: cancel the in-flight turn via the session handle's\n   * `cancel()` (the CLI-side equivalent of Ctrl-C — ACP `session/cancel`,\n   * or an adapter-specific SIGINT for process/PTY-backed adapters), then\n   * await the turn actually settling before returning. Does NOT run\n   * admission itself — the caller still goes through `validateAgentTurn`\n   * afterward, now finding the session idle.\n   *\n   * `caller` only shapes error messages; both entry points reach the same\n   * logic, so a message naming the wrong one would misdirect debugging.\n   */\n  const interruptInFlightTurn = async (\n    rt: SessionRuntime,\n    id: string,\n    caller: string\n  ): Promise<void> => {\n    const session = rt.agentSession\n    if (!session) {\n      // Invariant: `runAgentTurn` requires `agentSession` before it\n      // ever sets `busy = true`, and nothing clears the field once set\n      // (see the `validateAgentTurn` doc comment on `kill()`) — this\n      // only fires if that invariant is ever violated.\n      throw new Error(\n        `${caller}: session \"${id}\" is mid-turn but has no live agent session to cancel`\n      )\n    }\n    try {\n      await session.cancel()\n    } catch (err) {\n      throw new Error(\n        `${caller}: session \"${id}\" does not support interrupt — cancelling the in-flight turn failed: ${\n          err instanceof Error ? err.message : String(err)\n        }`\n      )\n    }\n    await waitForTurnSettled(rt, id, caller)\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  /**\n   * Resolve a session's usage snapshot from the descriptor's accumulated\n   * signals: the adapter-reported cost (readUsage or a usage_update cost\n   * block) is authoritative; otherwise tokens are priced against the in-repo\n   * catalog (`deriveSessionUsage`), or tagged no-pricing when the model is\n   * unknown. Pure read of `rt` — mutation is the caller's job.\n   */\n  const buildUsageSnapshot = (rt: SessionRuntime): SessionUsage =>\n    deriveSessionUsage({\n      ...(rt.desc.model !== undefined ? { model: rt.desc.model } : {}),\n      ...(rt.adapterReportedCost && rt.desc.costUsd !== undefined\n        ? { adapterCostUsd: rt.desc.costUsd }\n        : {}),\n      ...(rt.desc.tokensIn !== undefined ? { tokensIn: rt.desc.tokensIn } : {}),\n      ...(rt.desc.tokensOut !== undefined ? { tokensOut: rt.desc.tokensOut } : {}),\n      ...(rt.desc.contextSize !== undefined ? { contextSize: rt.desc.contextSize } : {}),\n      ...(rt.desc.contextUsed !== undefined ? { contextUsed: rt.desc.contextUsed } : {}),\n    })\n\n  /**\n   * Write a final `usage_snapshot` recap when an agent session exits (kill,\n   * turn error, cost-cap, shutdown). Stamps `usageSource` on the descriptor\n   * and skips writing when there's nothing measured (`source: \"none\"`) so a\n   * never-run session doesn't leave an empty transcript file. Must run BEFORE\n   * `transcriptWriter.close(id)`.\n   */\n  const recordExitUsageSnapshot = (rt: SessionRuntime): void => {\n    if (rt.desc.kind !== \"agent-cli\") return\n    const usage = buildUsageSnapshot(rt)\n    rt.desc.usageSource = usage.source\n    if (usage.source === \"none\") return\n    transcriptWriter.recordUsageSnapshot(rt.desc.id, usage)\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.emitter.emit(\"busy\", true)\n    rt.desc.awaitingInput = false  // clear stale awaiting-input flag from prior turn\n    rt.desc.awaitingQuestion = undefined\n    releaseBlockedOn(rt.desc)      // clear stale blocked-on from prior turn\n    let turnCompleted = false\n    // Whether the adapter itself emitted a `turn-end` during this turn.\n    // Drives the P5 guarantee: when the event stream ends WITHOUT one\n    // (crash / exit / error / abort), the finally block synthesizes a\n    // terminal `turn-end` — but only if the adapter didn't already send\n    // one, so exactly one is emitted per turn.\n    let sawTurnEnd = false\n    // Set in `catch` to the abnormal-end reason (\"error\" | \"aborted\") so\n    // the finally block can tag the synthesized turn-end correctly.\n    let abnormalReason: string | undefined\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    // Productivity signals for empty-turn detection: a turn that produces\n    // ZERO assistant text AND zero tool calls is a silent no-op (a bad /\n    // unrecognized model id, or a provider that returned an empty\n    // completion) and must be flagged, not reported as a green turn-end.\n    let sawAssistantText = false\n    let sawToolCall = false\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        // `text-delta` is the sole assistant-text channel (see projectEvent);\n        // a whitespace-only delta doesn't count as real output.\n        if (evt.kind === \"text-delta\" && evt.text?.trim()) sawAssistantText = true\n        else if (evt.kind === \"tool-call\") sawToolCall = true\n        if (evt.kind === \"turn-end\") {\n          sawTurnEnd = true\n          turnEndReason = evt.reason\n        }\n      }\n      turnCompleted = true\n    } catch (err) {\n      // A turn that ends by throwing is either a genuine error or an\n      // ABORT (cancel()/kill()). Aborts must not be mislabelled as turn\n      // errors — kill() already flipped status to \"killed\" and emitted\n      // session:exited, and cancel() leaves the session alive for the\n      // next turn — so only the genuine-error branch marks the session\n      // errored. Either way the finally block below still guarantees a\n      // terminal turn-end.\n      if (isAbortError(err) || rt.desc.status === \"killed\") {\n        abnormalReason = \"aborted\"\n      } else {\n        abnormalReason = \"error\"\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        recordExitUsageSnapshot(rt)\n        schedulePersist()\n        emitExited(rt)\n      }\n    } finally {\n      rt.busy = false\n      rt.desc.busy = false           // mirror onto the public descriptor for session_monitor\n      rt.emitter.emit(\"busy\", false)\n      // Safety net: a tool-call that never receives its tool-result (child\n      // crashed, stream ended early) must not leave the session flagged\n      // blocked forever — the turn is over, nothing is pending anymore.\n      releaseBlockedOn(rt.desc)\n\n      // ── P5: guarantee exactly one terminal turn-end per turn ──────────\n      // If the adapter's event stream ended without a turn-end (generator\n      // returned early, subprocess exited, threw, or was aborted), inject\n      // one so downstream orchestration can rely on turn-end as a uniform\n      // completion signal instead of hanging. Idempotent — `sawTurnEnd`\n      // short-circuits when the adapter already produced one.\n      if (!sawTurnEnd) {\n        const reason =\n          abnormalReason ??\n          (rt.desc.status === \"killed\" ? \"aborted\" : \"exited\")\n        const synthetic: AgentStreamEvent = { kind: \"turn-end\", reason }\n        // Record to the durable transcript first (matches the in-loop\n        // order: recordEvent before projectEvent), then flatten into the\n        // ring buffer so /stream + events.jsonl consumers both see it.\n        transcriptWriter.recordEvent(rt.desc.id, synthetic)\n        projectEvent(rt, synthetic)\n        sawTurnEnd = true\n        turnEndReason = reason\n      }\n\n      if (turnCompleted) {\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 (best-effort) ───────────────────────────────\n        // The adapter's own reader (e.g. hermes state.db) is authoritative —\n        // a returned `costUsd` marks the session as adapter-priced.\n        if (rt.readUsage) {\n          try {\n            const usage = await rt.readUsage()\n            if (usage) {\n              if (usage.costUsd !== undefined) {\n                rt.desc.costUsd = usage.costUsd\n                rt.adapterReportedCost = true\n              }\n              if (usage.tokensIn !== undefined) rt.desc.tokensIn = usage.tokensIn\n              if (usage.tokensOut !== undefined) rt.desc.tokensOut = usage.tokensOut\n\n              // Record a `usage_update` into the transcript so non-claude\n              // adapters (hermes reads its state.db here; claude-code emits\n              // this inline over ACP) carry the SAME token/cost telemetry in\n              // events.jsonl. Only when the reader actually returned a signal\n              // — never synthesize a usage event from nothing. Shape is\n              // identical to the ACP-arm's usage_update: size/used default to\n              // 0 (this reader carries no context-window figure, and\n              // `projectEvent` guards on >0 so the 0s never clobber a real\n              // size already mirrored onto the descriptor).\n              if (\n                usage.costUsd !== undefined ||\n                usage.tokensIn !== undefined ||\n                usage.tokensOut !== undefined\n              ) {\n                const usageEvent: AgentStreamEvent = {\n                  kind: \"usage_update\",\n                  size: 0,\n                  used: 0,\n                  ...(usage.costUsd !== undefined\n                    ? { cost: { amount: usage.costUsd, currency: \"USD\" } }\n                    : {}),\n                  ...(usage.tokensIn !== undefined\n                    ? { tokensIn: usage.tokensIn }\n                    : {}),\n                  ...(usage.tokensOut !== undefined\n                    ? { tokensOut: usage.tokensOut }\n                    : {}),\n                }\n                transcriptWriter.recordEvent(rt.desc.id, usageEvent)\n              }\n            }\n          } catch {\n            // best-effort — swallow\n          }\n        }\n\n        // ── Resolve usage source (adapter / computed / no-pricing / none)\n        //    and write the durable turn-boundary recap. Runs on every\n        //    turn-end, even without a session-event bus wired.\n        const usage = buildUsageSnapshot(rt)\n        rt.desc.usageSource = usage.source\n        rt.desc.costUsd = usage.costUsd\n        transcriptWriter.recordUsageSnapshot(rt.desc.id, usage)\n\n        // ── Cost cap (best-effort, turn-granular) ────────────────────\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          tracedSessions.delete(rt.desc.id)\n        }\n\n        // ── Empty-turn detection (#1/#2) ─────────────────────────────\n        // A turn that completed the normal way (stream ended, no error/\n        // abort) yet produced NO assistant text, NO tool call, and isn't\n        // awaiting input is a silent no-op — the usual cause is a bad or\n        // unrecognized model id, or a provider that returned an empty\n        // completion at $0. Flag it loudly (a warning line + `empty` on\n        // the bus event) so an orchestrator doesn't mistake a green\n        // turn-end for real progress.\n        const emptyTurn =\n          !sawAssistantText && !sawToolCall && !(rt.desc.awaitingInput ?? false)\n        if (emptyTurn) {\n          appendLine(\n            rt,\n            `\\x1b[33m[warning] empty turn — no assistant output, no tool call, ` +\n              `cost ${rt.desc.costUsd !== undefined ? `$${rt.desc.costUsd}` : \"unknown\"}. ` +\n              `Likely an invalid model id or a provider that returned nothing; ` +\n              `verify the model slug (agentproto models <adapter>).\\x1b[0m`,\n            \"stderr\",\n          )\n        }\n\n        if (sessionEvents) {\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            ...(emptyTurn ? { empty: true } : {}),\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        }\n        if (overBudget) emitExited(rt)\n      } else {\n        // ── Abnormal turn end (error / abort) ────────────────────────\n        // The adapter's stream broke before a turn-end. We already\n        // synthesized the terminal turn-end above; still stamp\n        // turnsCompleted and emit the bus turn-end so a `session_monitor`\n        // (or any consumer waiting on completion) doesn't hang on a turn\n        // that will never signal done through the normal path.\n        rt.desc.turnsCompleted = (rt.desc.turnsCompleted ?? 0) + 1\n        if (sessionEvents) {\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: new Date().toISOString(),\n            ...(turnEndReason ? { reason: turnEndReason } : {}),\n          })\n        }\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 priorCommandSessionId = findPriorCommandSessionId(sessions, input.cwd)\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        ...(input.auth ? { auth: input.auth } : {}),\n        ...(priorCommandSessionId ? { priorCommandSessionId } : {}),\n        ...(input.remote ? { remote: true } : {}),\n        ...(input.sandboxId ? { sandboxId: input.sandboxId } : {}),\n        ...(input.sandboxTeardown ? { sandboxTeardown: input.sandboxTeardown } : {}),\n      }\n      if (input.trace ?? opts?.langfuseTracingDefault ?? false) {\n        tracedSessions.add(id)\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        ...(input.permissionHold ? { permissionHold: true } : {}),\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 priorCommandSessionId = findPriorCommandSessionId(sessions, input.cwd)\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        ...(priorCommandSessionId ? { priorCommandSessionId } : {}),\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        void terminalTranscriptWriter.close(rt.desc.id)\n        schedulePersist()\n        emitExited(rt)\n      })\n      schedulePersist()\n      return desc\n    },\n    recordCommand(input) {\n      const id = `sess_${randomUUID().slice(0, 8)}`\n      const now = new Date()\n      // Backdate startedAt by durationMs — the command already ran to\n      // completion by the time this is called, so this is the best\n      // available estimate of when it actually started.\n      const startedAt = new Date(now.getTime() - Math.max(0, input.durationMs)).toISOString()\n      const argv = [input.command, ...input.args]\n      const desc: SessionDescriptor = {\n        id,\n        kind: \"command\",\n        workspaceSlug: input.workspaceSlug,\n        command: argv.map(quoteArg).join(\" \"),\n        pid: null,\n        status: input.exitCode === 0 ? \"exited\" : \"error\",\n        startedAt,\n        endedAt: now.toISOString(),\n        exitCode: input.exitCode,\n        argv,\n        cwd: input.cwd,\n        ...(input.label ? { label: input.label } : {}),\n      }\n      const rt: SessionRuntime = {\n        desc,\n        recentLines: [],\n        recentBytes: [],\n        recentBytesSize: 0,\n        emitter: new EventEmitter(),\n        busy: false,\n        textBuf: \"\",\n        thoughtBuf: \"\",\n      }\n      sessions.set(id, rt)\n      // Fire-and-forget: the write is best-effort and must never delay the\n      // session's own lifecycle (its internal `.catch` swallows failures).\n      void writeCommandLogEntry(\n        id,\n        {\n          ts: now.toISOString(),\n          command: input.command,\n          args: input.args,\n          cwd: input.cwd,\n          exitCode: input.exitCode,\n          signal: input.signal,\n          durationMs: input.durationMs,\n          stdout: input.stdout,\n          stderr: input.stderr,\n          ...(input.truncated ? { truncated: true } : {}),\n        },\n        transcriptBaseDir,\n      )\n      schedulePersist()\n      // No live process — the session is already over, so emit its\n      // `session:exited` right away (mirrors kill()'s \"agent-cli has no\n      // OS exit event — emit here\" rule just below).\n      emitExited(rt)\n      return desc\n    },\n    async readCommandLog(sessionId) {\n      const rt = sessions.get(sessionId)\n      if (!rt || rt.desc.kind !== \"command\") return null\n      return readCommandLogEntry(sessionId, transcriptBaseDir)\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, opts) {\n      const rtPre = sessions.get(id)\n      // Same mid-turn arm as enqueuePrompt: cancel + await settle BEFORE\n      // admission, so `validateAgentTurn` finds the session idle instead\n      // of throwing the busy rejection. Without this, `interrupt` was\n      // silently dropped on the blocking path — the caller asked to\n      // redirect the session and got a 409 (or, worse, nothing).\n      if (opts?.interrupt && rtPre?.busy) {\n        await interruptInFlightTurn(rtPre, id, \"sendPrompt\")\n      }\n      if (rtPre) await maybeResumeAgent(rtPre)\n      const rt = validateAgentTurn(id, \"sendPrompt\")\n      await runAgentTurn(rt, message)\n    },\n    async enqueuePrompt(id, message, opts) {\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      // `interrupt` only ever changes behavior on a mid-turn session —\n      // an idle session falls straight through to the normal admission\n      // path below, byte-identical to `interrupt` omitted/false. Cancel\n      // THEN await the turn actually settling (busy → false) BEFORE\n      // `validateAgentTurn` runs, so admission is never bypassed — it's\n      // only ever reached once the prior turn is genuinely over.\n      if (opts?.interrupt && rtPre.busy) {\n        await interruptInFlightTurn(rtPre, id, \"enqueuePrompt\")\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    subscribeToRecords(id, onRecord) {\n      return baseTranscriptWriter.subscribe(id, onRecord)\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        // Durable usage recap on exit — before close() flushes the stream.\n        recordExitUsageSnapshot(rt)\n        void rt.agentSession.close().catch(() => undefined)\n        void transcriptWriter.close(rt.desc.id)\n        tracedSessions.delete(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        void terminalTranscriptWriter.close(rt.desc.id)\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    listPendingPermissions(filter) {\n      const all = Array.from(pendingPermissions.values())\n      const scoped = filter?.sessionId\n        ? all.filter(p => p.sessionId === filter.sessionId)\n        : all\n      // Defensive copies — callers must not mutate the live inbox records.\n      return scoped.map(p => ({ ...p, options: p.options.map(o => ({ ...o })) }))\n    },\n    async respondPermission(id, input) {\n      const pending = pendingPermissions.get(id)\n      if (!pending) {\n        return {\n          ok: false,\n          error: \"not_found\",\n          message: `no pending permission \"${id}\" (unknown or already resolved)`,\n        }\n      }\n      const rt = sessions.get(pending.sessionId)\n      if (!rt || !rt.agentSession) {\n        // Session vanished between registration and response — drop the stale\n        // entry so it stops showing up in the inbox.\n        pendingPermissions.delete(id)\n        if (rt) refreshAwaitingPermission(rt)\n        return {\n          ok: false,\n          error: \"session_gone\",\n          message: `session \"${pending.sessionId}\" for permission \"${id}\" is no longer alive`,\n        }\n      }\n      const respond = rt.agentSession.respondPermission\n      if (!respond) {\n        return {\n          ok: false,\n          error: \"unsupported\",\n          message: `session \"${pending.sessionId}\" driver does not support held permissions`,\n        }\n      }\n      const selected = selectPermissionOptionId(pending.options, input)\n      if (selected === null) {\n        return {\n          ok: false,\n          error: \"no_matching_option\",\n          message:\n            `permission \"${id}\" offers no ${input.decision === \"approve\" ? \"allow\" : \"reject\"}` +\n            `-flavored option; pass an explicit optionId (one of: ${pending.options\n              .map(o => o.optionId)\n              .join(\", \")})`,\n        }\n      }\n      // Resolve the held driver RPC — the agent's turn unblocks with the chosen\n      // outcome. Clear inbox state BEFORE awaiting so a slow driver can't leave\n      // a resolved request visible.\n      pendingPermissions.delete(id)\n      const chosenOptionId = \"optionId\" in selected ? selected.optionId : undefined\n      // The request is resolved either way — the agent's turn resumes, so it is\n      // no longer awaiting a human. Mirrors how a new turn clears these.\n      delete rt.desc.awaitingInput\n      rt.desc.awaitingQuestion = undefined\n      refreshAwaitingPermission(rt)\n      const okResolved = await respond(id, selected)\n      if (sessionEvents) {\n        sessionEvents.emit({\n          type: \"session:permission-resolved\",\n          sessionId: pending.sessionId,\n          permissionId: id,\n          decision: input.decision,\n          ...(chosenOptionId ? { optionId: chosenOptionId } : {}),\n          ...(rt.desc.label ? { label: rt.desc.label } : {}),\n          ts: new Date().toISOString(),\n        })\n      }\n      schedulePersist()\n      if (!okResolved) {\n        // The driver had already resolved this request (race with a\n        // session-death cancel). Report success anyway — the inbox entry is\n        // gone and the caller's intent is moot.\n        return { ok: true, permission: pending, decision: input.decision, ...(chosenOptionId ? { optionId: chosenOptionId } : {}) }\n      }\n      return {\n        ok: true,\n        permission: pending,\n        decision: input.decision,\n        ...(chosenOptionId ? { optionId: chosenOptionId } : {}),\n      }\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      void terminalTranscriptWriter.close(id)\n      tracedSessions.delete(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    //\n    // These sessions are being force-killed OUTSIDE their own turn loop —\n    // `runAgentTurn`'s `finally` (which normally clears busy/awaiting-*)\n    // never runs here, so without `clearInFlightFlags` a session that was\n    // mid-turn at shutdown would persist as \"killed\" yet forever \"busy\".\n    // `emitExited` announces the same way `kill()` does, so a watcher\n    // subscribed to `sessionEvents` (or polling after reconnect) learns\n    // these died with the daemon instead of finding out by accident.\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        rt.desc.endedReason = \"daemon-restart\"\n        clearInFlightFlags(rt.desc)\n        if (rt.agentSession) {\n          recordExitUsageSnapshot(rt)\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        emitExited(rt)\n      }\n    }\n    void transcriptWriter.closeAll()\n    void terminalTranscriptWriter.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 * Reset the ephemeral in-flight fields a descriptor accumulates mid-turn\n * (busy, awaiting-input/-question/-permission, blockedOn) back to idle.\n * `runAgentTurn`'s own `finally` block does exactly this whenever a turn\n * ends normally — including a live `kill()`, since that aborts the\n * in-flight `send()` and lets the same `finally` run. But a session\n * force-terminated from OUTSIDE that turn loop — the daemon process dying\n * underneath it (discovered at next boot) or a shutdown that SIGTERMs\n * whatever's still busy — never reaches that `finally`, so without this\n * the flags stay frozen at whatever they were the instant the daemon went\n * away: a session can end up \"killed\" yet forever \"busy\". Both forced-\n * termination sites below call this before persisting the terminal status.\n */\nfunction clearInFlightFlags(desc: SessionDescriptor): void {\n  desc.busy = false\n  desc.awaitingInput = false\n  desc.awaitingQuestion = undefined\n  delete desc.awaitingPermission\n  desc.blockedOn = undefined\n  desc.pendingToolCallId = undefined\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. Its\n * in-flight fields (busy, awaiting-*, blockedOn) get cleared the same\n * way — see `clearInFlightFlags` — since nothing else will ever clear\n * them for a process that's gone, and `endedReason: \"daemon-restart\"`\n * is stamped so the UI can tell this apart from an operator kill. When\n * `sessionEvents` is wired, each reclassified ghost also gets a\n * `session:exited` announcement so a watcher polling `session_events_poll`\n * (or long-polling `session_monitor`) learns its session died instead of\n * discovering it later by accident. The descriptor stays in the registry\n * for history; the dashboard sees it under SESSIONS, the user can `d` to\n * 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  sessionEvents?: SessionEventBus,\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          endedReason: \"daemon-restart\",\n        }\n      : desc\n    // Unconditional, not `if (wasAlive)`: a ghost carries no child/\n    // agentSession, so it is idle whatever the snapshot claimed — and rows\n    // that were ALREADY terminal can carry frozen flags too. Two ways in: a\n    // kill that raced the turn's `finally`, and — the one actually observed —\n    // a snapshot written by a daemon predating this reconciliation, whose\n    // \"killed + busy\" rows are already terminal by the time a fixed daemon\n    // reads them, so a wasAlive-only guard never revisits them and the lie\n    // survives every future boot. Clearing idle flags on an idle session is a\n    // no-op, so there is nothing to lose by not asking how it got there.\n    clearInFlightFlags(reclassified)\n    // Same reasoning as the in-flight flags above, for `contextUsed`: a\n    // snapshot written before `plausibleContextUsed` existed can carry an\n    // out-of-window value on disk, and a dead/historical ghost never gets\n    // a fresh usage_update to self-correct it — so re-validate on the way\n    // back into memory instead of resurrecting the stale figure forever.\n    reclassified.contextUsed = plausibleContextUsed(\n      reclassified.contextSize,\n      reclassified.contextUsed,\n    )\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      exitedEmitted: wasAlive,\n    }\n    rt.emitter.setMaxListeners(50)\n    sessions.set(desc.id, rt)\n    if (wasAlive) {\n      sessionEvents?.emit({\n        type: \"session:exited\",\n        sessionId: reclassified.id,\n        exitCode: reclassified.exitCode,\n        status: \"killed\",\n        ...(reclassified.label ? { label: reclassified.label } : {}),\n        reason: \"daemon-restart\",\n        ts: now,\n      })\n    }\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\", \"permission-request\", \"permission-resolved\", \"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  // ── Permission inbox tools ─────────────────────────────────────────\n  //\n  // Cross-session inbox for permission-hold sessions: each ACP permission\n  // request is surfaced + parked (see the pending-permissions registry in\n  // sessions.ts) rather than auto-answered, so a human/orchestrator can\n  // approve/deny it from one place. Mirrors `policy_ack`'s approve/deny shape.\n\n  /** True when a session is inside the caller's subtree (WP6 scoping). Root/\n   *  operator callers (no scope) see every session. */\n  const isSessionInScope = (sessionId: string): boolean => {\n    if (!callerScope) return true\n    if (!callerScope.ownerSessionId) return false\n    return collectSubtree(callerScope.ownerSessionId, registry.list()).has(sessionId)\n  }\n\n  const enrichPermission = (\n    p: ReturnType<SessionsRegistry[\"listPendingPermissions\"]>[number],\n  ): Record<string, unknown> => {\n    const desc = registry.get(p.sessionId)\n    const ageMs = Date.now() - new Date(p.requestedAt).getTime()\n    return {\n      ...p,\n      ...(desc?.adapterSlug ? { adapter: desc.adapterSlug } : {}),\n      ...(desc?.label ? { sessionLabel: desc.label } : {}),\n      ...(desc?.command ? { sessionTitle: desc.command } : {}),\n      ageMs: ageMs >= 0 ? ageMs : 0,\n    }\n  }\n\n  server.tool(\n    \"permissions_list\",\n    \"List permission requests currently HELD across all permission-hold \" +\n      \"sessions (spawned with `permissionHold`). Each entry: id, sessionId, \" +\n      \"session adapter/title, the tool being requested, the offered options, \" +\n      \"and age. Resolve one with `permissions_respond`. Optionally filter by \" +\n      \"`sessionId`. Empty list = nothing is waiting on a decision.\",\n    {\n      sessionId: z\n        .string()\n        .optional()\n        .describe(\"Filter to one session's pending permissions. Omit → all sessions.\"),\n    },\n    async input => {\n      const pending = registry\n        .listPendingPermissions(input.sessionId ? { sessionId: input.sessionId } : undefined)\n        .filter(p => isSessionInScope(p.sessionId))\n        .map(enrichPermission)\n      return {\n        content: [{ type: \"text\", text: JSON.stringify({ permissions: pending }, null, 2) }],\n      }\n    },\n  )\n\n  server.tool(\n    \"permissions_respond\",\n    \"Resolve a permission request parked by a permission-hold session \" +\n      \"(see `permissions_list`). `decision:\\\"approve\\\"` selects an allow \" +\n      \"option (allow-always when `scope:\\\"always\\\"` is offered, else \" +\n      \"allow-once); `decision:\\\"deny\\\"` selects a reject option (or cancels \" +\n      \"the request when none is offered). An explicit `optionId` overrides \" +\n      \"the decision→option mapping. Errors clearly on an unknown/already-\" +\n      \"resolved id. The agent's turn unblocks with the chosen outcome.\",\n    {\n      id: z.string().describe(\"Pending permission id from `permissions_list`.\"),\n      decision: z\n        .enum([\"approve\", \"deny\"])\n        .describe(\"approve → an allow option; deny → a reject option / cancel.\"),\n      optionId: z\n        .string()\n        .optional()\n        .describe(\"Explicit offered optionId — wins over `decision` mapping.\"),\n      scope: z\n        .enum([\"once\", \"always\"])\n        .optional()\n        .describe(\"For approve: prefer allow-always when the request offers it.\"),\n    },\n    async input => {\n      // WP6 scoping: a scoped child may only resolve permissions for sessions\n      // in its own subtree. Report \"not found\" for anything out of scope (no\n      // information leak about a sibling's pending requests).\n      const pending = registry.listPendingPermissions().find(p => p.id === input.id)\n      if (!pending || !isSessionInScope(pending.sessionId)) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify({ error: \"not_found\", message: `no pending permission \"${input.id}\"` }),\n            },\n          ],\n          isError: true,\n        }\n      }\n      const result = await registry.respondPermission(input.id, {\n        decision: input.decision,\n        ...(input.optionId ? { optionId: input.optionId } : {}),\n        ...(input.scope ? { scope: input.scope } : {}),\n      })\n      if (!result.ok) {\n        return {\n          content: [{ type: \"text\", text: JSON.stringify({ error: result.error, message: result.message }) }],\n          isError: true,\n        }\n      }\n      return {\n        content: [\n          {\n            type: \"text\",\n            text: JSON.stringify(\n              {\n                ok: true,\n                id: input.id,\n                sessionId: result.permission.sessionId,\n                decision: result.decision,\n                ...(result.optionId ? { optionId: result.optionId } : {}),\n              },\n              null,\n              2,\n            ),\n          },\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_run_file\",\n      \"Load an AIP-15 WORKFLOW.md (+ optional entry.mjs) via the workflow-loader \" +\n        \"and run it in the background through the same runner as `workflow_start`. \" +\n        \"Poll with `workflow_status`.\",\n      {\n        path: z.string().describe(\"Absolute or workspace-relative path to a WORKFLOW.md file.\"),\n        input: z.record(z.string(), z.unknown()).optional().describe(\"Workflow invocation input — bound to `$input` in the compiled workflow.\"),\n        cwd: z.string().optional().describe(\"Working directory for spawned sessions.\"),\n        workspaceSlug: z.string().optional().describe(\"Workspace slug passed to each spawned session.\"),\n        cacheKey: z.string().optional().describe(\"Enable journal caching for this run. Cacheable steps replay unchanged outputs on re-invocation with the same key.\"),\n      },\n      async input => {\n        try {\n          const run = await workflowRunner.startFromFile(input)\n          return {\n            content: [{ type: \"text\", text: JSON.stringify({ runId: run.runId, status: run.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            isError: true,\n          }\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      // Accept the natural shapes an agent already has on hand: a single id\n      // (the `id` agent_start returns, or `sessionId` from the drive tools),\n      // or the fan-in array. `sessionIds` additionally tolerates a bare\n      // string (not just an array) so a one-session monitor doesn't force\n      // array-wrapping. All three coalesce into the watched-id list below.\n      sessionIds: jsonTolerant(z.union([z.string(), z.array(z.string())]))\n        .optional()\n        .describe(\n          \"Session ids (or names) to watch — an array for fan-in, or a single \" +\n            \"id. Returns on the first hit. Provide this OR `sessionId`/`id`.\",\n        ),\n      sessionId: z\n        .string()\n        .optional()\n        .describe(\"Single session id/name — singular alias for `sessionIds`.\"),\n      id: z\n        .string()\n        .optional()\n        .describe(\"Alias for `sessionId` — the `id` returned by agent_start.\"),\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      // Coalesce the accepted arg shapes into the watched-id list.\n      const fromSessionIds =\n        input.sessionIds === undefined\n          ? []\n          : Array.isArray(input.sessionIds)\n            ? input.sessionIds\n            : [input.sessionIds]\n      const singular = input.sessionId ?? input.id\n      const sessionIds = [...fromSessionIds, ...(singular ? [singular] : [])]\n      if (sessionIds.length === 0) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify({\n                error:\n                  \"session_monitor: no sessions to watch — pass `sessionIds` (array or single id) or `sessionId`/`id`.\",\n              }),\n            },\n          ],\n          isError: true,\n        }\n      }\n      if (sessionIds.length > 20) {\n        return {\n          content: [\n            {\n              type: \"text\",\n              text: JSON.stringify({\n                error: `session_monitor: too many sessions (${sessionIds.length}); max 20 per call.`,\n              }),\n            },\n          ],\n          isError: true,\n        }\n      }\n\n      const result = await monitorSessionWait({\n        registry,\n        sessionEvents,\n        eventRing,\n        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 * Provider-preset family on top of `@agentproto/provider-kit` — the *thin,\n * honest* lister (Option B). Unlike tunnels/sandboxes/eval-reporters, presets\n * are bundled static data with no binary to install, no package to resolve, and\n * no setup ledger: their only \"setup\" is an ambient API-key env var. So this\n * module does NOT use `makeAdapterResolver` / `makeAdapterLister` / the wizard\n * (all install-oriented, a forced fit). It reuses only `makeListTool` — the one\n * kit primitive that's genuinely about \"JSON a lister's output as an MCP tool.\"\n *\n * Status is derived honestly from the daemon's own environment (the env agents\n * spawn into), not the CLI caller's:\n *   \"ready\"     — `process.env[preset.keyEnv]` is set (key available to spawn)\n *   \"available\" — key absent (preset known, usable once the env var is provided)\n *\n * There is no \"supported\" state: presets ship in-repo, so they're always at\n * least \"available.\" `version` is the literal \"built-in\".\n *\n * Security (Appendix B): `PresetInfo` carries only `keyEnv` (the env-var NAME),\n * never a key value. The list tool never returns creds — there are none to\n * return; keys live in the operator's environment, not a creds store.\n */\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { makeListTool, type AdapterEntry } from \"@agentproto/provider-kit\"\nimport { anthropicGatewayPresetList, type ProviderPreset } from \"@agentproto/provider-presets\"\n\n/**\n * Manifest-declared AIP-45 preset, the minimum the catalog needs to merge\n * an adapter-contributed preset into the listing. Mirrors\n * `AgentCliPresetDeclaration`'s fields without importing\n * `@agentproto/driver-agent-cli` into the runtime package (same structural-\n * type pattern as `DeclaredAdapterOption` in spawn-defaults.ts).\n */\nexport interface DeclaredAdapterPreset {\n  id: string\n  label: string\n  description?: string\n  schemaFlavor: ProviderPreset[\"schemaFlavor\"]\n  baseUrl: string\n  keyEnv: string\n  scrubEnv?: string[]\n  defaultModel?: string\n  homepage?: string\n}\n\n/**\n * Family descriptor surfaced as `AdapterEntry.info`. User-facing preset facts\n * only — no cred values (there are none in the registry), no adapter projection\n * detail (`scrubEnv` stays internal to adapter manifests).\n */\nexport interface PresetInfo {\n  /** API schema flavor — which adapter family can consume this preset. */\n  schemaFlavor: ProviderPreset[\"schemaFlavor\"]\n  /** Base URL the client hits. */\n  baseUrl: string\n  /** Env-var NAME holding the API key (never the value). */\n  keyEnv: string\n  /** Conventional default model id, if any. */\n  defaultModel?: string\n  /** Homepage/docs URL. */\n  homepage?: string\n}\n\n/**\n * Normalize a manifest-declared preset into the canonical `ProviderPreset`\n * shape the catalog lists. `scrubEnv` defaults to empty (an adapter that\n * scrubs in code may omit it); `description` defaults to empty. Pure.\n */\nexport function declaredPresetToProviderPreset(\n  decl: DeclaredAdapterPreset,\n): ProviderPreset {\n  return {\n    id: decl.id,\n    label: decl.label,\n    description: decl.description ?? \"\",\n    schemaFlavor: decl.schemaFlavor,\n    baseUrl: decl.baseUrl,\n    keyEnv: decl.keyEnv,\n    scrubEnv: decl.scrubEnv ?? [],\n    ...(decl.defaultModel ? { defaultModel: decl.defaultModel } : {}),\n    ...(decl.homepage ? { homepage: decl.homepage } : {}),\n  }\n}\n\n/**\n * Map the static preset registry → status-classified catalog entries, reading\n * the daemon's environment for key presence. Pure (no I/O) save the `process`\n * .env read; safe to call on every list invocation.\n *\n * `adapterPresets` — manifest-declared presets contributed by loaded adapters\n * (Stage 3 AIP-45 `presets` field). Merged AFTER the built-in registry and\n * deduped by id: an adapter-declared id that collides with a built-in is\n * ignored (the registry is the source of truth for canonical providers), so\n * an adapter can't silently override moonshot/openrouter facts. The live\n * wiring that reads each adapter's `.presets` and passes them here is Stage 4;\n * today this is the tested seam.\n */\nexport function listPresets(\n  env: Record<string, string | undefined> = process.env,\n  adapterPresets: readonly DeclaredAdapterPreset[] = [],\n): AdapterEntry<PresetInfo>[] {\n  const builtinIds = new Set(anthropicGatewayPresetList.map((p) => p.id))\n  const extra: ProviderPreset[] = []\n  for (const decl of adapterPresets) {\n    if (builtinIds.has(decl.id)) continue\n    extra.push(declaredPresetToProviderPreset(decl))\n  }\n  const all = [...anthropicGatewayPresetList, ...extra]\n  return all.map((preset) => {\n    const keyPresent = Boolean(env[preset.keyEnv])\n    return {\n      slug: preset.id,\n      name: preset.label,\n      description: preset.description,\n      packageName: \"@agentproto/provider-presets\",\n      status: keyPresent ? \"ready\" : \"available\",\n      version: \"built-in\",\n      info: {\n        schemaFlavor: preset.schemaFlavor,\n        baseUrl: preset.baseUrl,\n        keyEnv: preset.keyEnv,\n        ...(preset.defaultModel ? { defaultModel: preset.defaultModel } : {}),\n        ...(preset.homepage ? { homepage: preset.homepage } : {}),\n      },\n    }\n  })\n}\n\n/**\n * Register the preset family's MCP tool on the server:\n *   - `list_provider_presets` (parameterless; status + facts, no creds)\n *\n * No setup tool — presets have no creds store; an operator sets the env var\n * directly (or passes an adapter `auth_token` option at spawn).\n *\n * `adapterPresets` — manifest-declared presets (AIP-45 `presets` field) from\n * loaded adapters, merged into the listing. The caller (gateway boot) is\n * responsible for collecting them; absent today, this is the seam Stage 4\n * wires live.\n */\nexport function registerPresetTools(\n  server: McpServer,\n  opts: { adapterPresets?: readonly DeclaredAdapterPreset[] } = {},\n): void {\n  const adapterPresets = opts.adapterPresets ?? []\n  makeListTool<PresetInfo>({\n    server,\n    toolName: \"list_provider_presets\",\n    description:\n      \"List provider gateway presets (built-in e.g. moonshot, openrouter, \" +\n      \"plus any declared by loaded adapters) with their status (ready when \" +\n      \"the provider's API-key env var is set in the daemon's environment, \" +\n      \"else available), base URL, schema flavor, and default model. Presets \" +\n      \"are static data — no install/setup; set the listed key env var (e.g. \" +\n      \"MOONSHOT_API_KEY) to make one ready. No credentials are ever returned.\",\n    lister: async () => listPresets(process.env, adapterPresets),\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 { PairingRegistry } from \"./pairing-registry.js\"\nimport type { RoutineRunner, RoutineStep } from \"./routine-runner.js\"\nimport type { WorkflowRunner, WorkflowStage } from \"./workflow-runner.js\"\nimport {\n  loadWorkspacesConfig,\n  findWorkspace,\n  findWorkspaceByPath,\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 type {\n  DeclaredAdapterOption,\n  AdapterAuthDescriptor,\n  ResolvedAuthSpec,\n} from \"./spawn-defaults.js\"\nimport { spawnAgentSession, type BuildOrchestratorMcp } from \"./session-spawn.js\"\nimport { tryParseJson } from \"./json-tolerant.js\"\nimport { listPresets } from \"./preset-tools.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  // The canonical hosted agentproto panel (github.com/agentproto/cli-site,\n  // deployed at cli.agentproto.sh). It drives the user's OWN local daemon\n  // from the browser: read-only GETs (session list, SSE stream) are ungated\n  // and already work, but the /sessions/:id/pty WebSocket upgrade IS gated —\n  // so a PTY terminal in the panel 401s unless this first-party origin is\n  // trusted like localhost. A malicious page can't forge this Origin (the\n  // browser sets it), so the trust is scoped to agentproto's own panel,\n  // matching how guilde.work is trusted. Drop it via `strictOrigins`.\n  \"https://cli.agentproto.sh\",\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    /**\n     * Manifest-declared option id → value map forwarded from\n     * `agent_start` (AIP-45 `AgentCliHandle.options` — e.g. hermes'\n     * `skills`). Applied at spawn time via `composeSpawn`'s option\n     * patches (`bin_args_prepend` / `bin_args_template` /\n     * `bin_args_append_when_true` / `env`), validated against each\n     * option's declared `type`/`enum`/`min`/`max`. An id the adapter\n     * doesn't declare throws `RuntimeConfigError` (composeSpawn\n     * validates against the manifest, same as an unknown `mode`).\n     */\n    options?: Record<string, boolean | number | 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    /** Start the session in permission-hold mode — forwarded to the driver's\n     *  `runtime.start({ permissionHold })` so each ACP permission request is\n     *  surfaced + parked in the daemon's inbox instead of auto-answered.\n     *  Adapters/arms with no permission surface ignore it. Default false. */\n    permissionHold?: boolean\n    /** FULLY-RESOLVED billing-auth spec forwarded from `agent_start` to the\n     *  driver's `runtime.start({ auth })`, computed by the runtime's\n     *  `resolveAuthSpec` (provider, ordered mode, setEnv/scrub, credential\n     *  source all pre-decided). The driver applies it mechanically. Absent\n     *  when the resolver produced no spec (ambient). */\n    auth?: ResolvedAuthSpec\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  /** AIP-45 `options[]` this adapter's manifest declares (id + type only —\n   *  no spawn internals). Lets `session-spawn.ts` fold a config-level\n   *  `defaults.skills` list into `options.skills` using the shape the\n   *  manifest actually declared (e.g. hermes' comma-joined string),\n   *  instead of guessing. Omitted/empty ⇒ the skills normalization is a\n   *  documented no-op for that adapter (e.g. claude-code, which\n   *  auto-discovers skills and declares no such option). */\n  declaredOptions?: readonly DeclaredAdapterOption[]\n  /** Billing-auth descriptor projected from the adapter manifest\n   *  (`provider` / `authEnforce` / `authSubscription`) — the sole input the\n   *  runtime's `resolveAuthSpec` reads about the adapter's auth capability\n   *  (keeping the catalog coupling in the runtime, the driver mechanical).\n   *  Omitted ⇒ ambient (no credential injection). */\n  authDescriptor?: AdapterAuthDescriptor\n  /** Adapter's default model id (`models.default`) — lets the resolver derive\n   *  a provider for a by-model spawn that omitted `model`. */\n  defaultModel?: string\n} | null>\n\n/**\n * UI-safe projection of an AIP-45 `modes[]` entry as surfaced by\n * `adapter_list`. Mirrors `@agentproto/cli`'s `AdapterMode` without\n * importing it (the runtime deliberately carries no cli dep — see the\n * `AgentAdapterLister` note above). Spawn internals (`bin_args_*`, `env`)\n * are intentionally omitted; `status` is normalised to `\"active\"` by the\n * lister when the manifest omits it, so a declared mode is never\n * silently statusless.\n */\nexport interface AdapterListMode {\n  id: string\n  description?: string\n  status: \"active\" | \"noop\" | \"planned\"\n  status_note?: string\n}\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  /** Declared operation modes with their honest support status, so a\n   *  client can see e.g. hermes' `lean` mode is a measured no-op instead\n   *  of being silently accepted. Empty when the adapter declares none. */\n  modes: AdapterListMode[]\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   * `denyTools`, when non-empty, is parsed from the request's\n   * `?denyTools=a,b` query string (see `handleMcp` below) and is the\n   * spawn-role-profiles tool gate for THIS surface: the hermes-default\n   * `mcpServers` entry injected for an executor-role child (see\n   * `session-spawn.ts`) carries this query param so the resulting\n   * server excludes `agent_start`/`agent_prompt` while keeping every\n   * other tool (fs, command_execute, …) — unlike the orchestrator's\n   * curated allowlist, this surface can't just narrow to a small\n   * subset without breaking the child's ability to do real work.\n   */\n  mcpServerFactory: (denyTools?: ReadonlySet<string>) => 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 — when wired, exposes /pairings/* routes for minting offers,\n   *  listing pairings, and revoking them (E2E daemon pairing). Same service the\n   *  MCP `pair_offer` / `pair_list` / `pair_revoke` tools call. Without it the\n   *  routes 404. */\n  pairings?: PairingRegistry\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    /** Daemon start timestamp. Defaults to `Date.now()` at server start. */\n    startedAt?: number\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 = opts.meta.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  function parseDenyToolsQuery(url: string): Set<string> | undefined {\n    const qIdx = url.indexOf(\"?\")\n    if (qIdx === -1) return undefined\n    const raw = new URLSearchParams(url.slice(qIdx + 1)).get(\"denyTools\")\n    if (!raw) return undefined\n    const names = raw.split(\",\").map(s => s.trim()).filter(Boolean)\n    return names.length > 0 ? new Set(names) : undefined\n  }\n\n  async function handleMcp(req: IncomingMessage, res: ServerResponse): Promise<void> {\n    if (!authorize(req, res)) return\n    const denyTools = parseDenyToolsQuery(req.url ?? \"\")\n    const server = await opts.mcpServerFactory(denyTools)\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        // Preset routes — static data, always available (no registry opt-in).\n        // GET /presets → { presets: AdapterEntry<PresetInfo>[] }\n        if (path === \"/presets\" && req.method === \"GET\") {\n          const handled = await handlePresets(req, res, path)\n          if (handled) 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        // Permission inbox routes — GET /permissions (list pending across all\n        // permission-hold sessions), POST /permissions/:id (approve/deny).\n        // Mirrors the MCP `permissions_list` / `permissions_respond` tools —\n        // same SessionsRegistry inbox. Only mounted when a registry is wired.\n        if (opts.sessions && path.startsWith(\"/permissions\")) {\n          // Non-GET (approve/deny) is a mutating action — same per-boot token\n          // gate as the mutating /sessions/* routes. GET is read-only, ungated.\n          if ((req.method ?? \"GET\") !== \"GET\") {\n            const gate = checkSessionsToken(req)\n            if (gate !== \"ok\") {\n              rejectUnauthorizedSession(req, res, gate)\n              return\n            }\n          }\n          const handled = await handlePermissions(req, res, path, opts.sessions)\n          if (handled) return\n        }\n\n        // Pairing routes — E2E daemon pairing. POST /pairings/offer,\n        // GET /pairings, DELETE /pairings/:fingerprint. All mutating routes\n        // (and the offer route, which starts an outbound rendezvous dial) take\n        // the per-boot token gate; GET is read-only. Only mounted when a\n        // registry is wired.\n        if (opts.pairings && path.startsWith(\"/pairings\")) {\n          if ((req.method ?? \"GET\") !== \"GET\") {\n            const gate = checkSessionsToken(req)\n            if (gate !== \"ok\") {\n              rejectUnauthorizedSession(req, res, gate)\n              return\n            }\n          }\n          const handled = await handlePairings(req, res, path, opts.pairings)\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      // `server.close()`'s callback only fires once every existing\n      // connection has ended on its own — it does NOT sever them.\n      // This daemon's whole purpose is long-lived keep-alive/SSE\n      // connections (session_monitor long-polls, output streaming,\n      // WS PTYs), so under normal load at least one is always open\n      // and `close()` would hang forever, leaving SIGTERM/SIGINT\n      // looking \"ignored\". `closeAllConnections()` (Node 18.2+)\n      // forcibly destroys every open socket so shutdown actually\n      // completes.\n      server.closeAllConnections()\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 * The exactly-once replay→live handoff for `GET /sessions/:id/events/stream`,\n * pulled out of the route handler so the race it exists to close can be unit\n * tested with a fully controlled disk iterator and a fully controlled\n * subscribe callback instead of racing real fs/network timing.\n *\n * `subscribe` is called SYNCHRONOUSLY, before this function does anything\n * else — including before it starts consuming `diskRecords` — and the\n * returned `unsubscribe` is handed back to the caller before `done` even\n * starts resolving, so a caller can wire cleanup (e.g. `req.once(\"close\",\n * unsubscribe)`) immediately, with zero awaited statements between\n * subscribing and the disk read starting. That ordering is what makes the\n * handoff gap-free: a record written after subscribe() is ALWAYS observed\n * by the live callback, whether or not the disk read also happens to reach\n * it first.\n *\n * Both channels feed the same `gate`, keyed on the highest seq sent so far\n * (seeded at `since`). Live records arriving while the disk read is still\n * in flight are parked in `buffered` rather than sent immediately — sending\n * them immediately would risk interleaving them ahead of not-yet-read disk\n * records, breaking ordering. Once the disk read finishes, `gate` already\n * reflects the highest seq it actually delivered, so draining `buffered`\n * through it for-free skips anything the disk read already sent and\n * forwards only what's new — that's what makes the handoff dupe-free too.\n */\nexport function deliverRecordsExactlyOnce(opts: {\n  since: number\n  diskRecords: AsyncIterable<Record<string, unknown>>\n  subscribe: (onRecord: (record: Record<string, unknown>) => void) => () => void\n  send: (record: Record<string, unknown>) => void\n}): { unsubscribe: () => void; done: Promise<void> } {\n  let lastSeqSent = opts.since\n  let replaying = true\n  const buffered: Record<string, unknown>[] = []\n  const gate = (record: Record<string, unknown>): void => {\n    const seq = record.seq\n    if (typeof seq !== \"number\" || seq <= lastSeqSent) return\n    lastSeqSent = seq\n    opts.send(record)\n  }\n  const unsubscribe = opts.subscribe(record => {\n    if (replaying) {\n      buffered.push(record)\n    } else {\n      gate(record)\n    }\n  })\n  const done = (async (): Promise<void> => {\n    for await (const rec of opts.diskRecords) {\n      gate(rec)\n    }\n    // Synchronous from here — no `await` between flipping `replaying` and\n    // draining `buffered`, so no write can land in the gap between them.\n    replaying = false\n    for (const rec of buffered) gate(rec)\n    buffered.length = 0\n  })()\n  return { unsubscribe, done }\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/events/stream → SSE live-push sibling of /events: replays every\n *                                    record after since=<seq> (default 0) from disk, then\n *                                    switches to live push as new records are written — one\n *                                    `data:` frame per record, same JSON shape /events returns\n *                                    per array element. 404 {error:\"no_transcript\"} parity with\n *                                    /events. Read-only GET, no auth gate (same policy as /events).\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\n/** Parse the `options` body field — the same manifest-declared option\n *  id → value map (AIP-45 `options`, e.g. claude-code/claude-sdk's\n *  `base_url`/`auth_token`) the MCP `agent_start` tool accepts, tolerant of\n *  a JSON-stringified object (see `parseOrchestratorField`). Non-primitive\n *  values are dropped rather than failing the whole map — `composeSpawn`\n *  validates the survivors against each option's declared type. */\nfunction parseOptionsField(\n  raw: unknown,\n): Record<string, boolean | number | string> | undefined {\n  const value = typeof raw === \"string\" ? tryParseJson(raw) : raw\n  if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined\n  const out: Record<string, boolean | number | string> = {}\n  for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n    if (typeof v === \"boolean\" || typeof v === \"number\" || typeof v === \"string\") {\n      out[k] = v\n    }\n  }\n  return out\n}\n\n/** Parse the `auth` body field — `{ mode?, token?, apiKey? }`, tolerant of a\n *  JSON-stringified object (see `parseOrchestratorField`). Deliberately\n *  narrow: only the known keys survive, so an unrelated stray field can't\n *  smuggle anything unexpected into the resolved spawn config. */\nfunction parseAuthField(\n  raw: unknown,\n): { mode?: \"subscription\" | \"api-key\"; token?: string; apiKey?: string } | undefined {\n  const value = typeof raw === \"string\" ? tryParseJson(raw) : raw\n  if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined\n  const obj = value as Record<string, unknown>\n  const mode = obj.mode === \"subscription\" || obj.mode === \"api-key\" ? obj.mode : undefined\n  const token = typeof obj.token === \"string\" ? obj.token : undefined\n  const apiKey = typeof obj.apiKey === \"string\" ? obj.apiKey : undefined\n  return {\n    ...(mode ? { mode } : {}),\n    ...(token !== undefined ? { token } : {}),\n    ...(apiKey !== undefined ? { apiKey } : {}),\n  }\n}\n\n/**\n * Reverse-map a cwd onto a registered workspace slug — the same rule\n * spawnAgentSession applies (session-spawn.ts), hoisted here so the terminal\n * and raw spawn paths agree with the agent path.\n *\n * Why: a SessionDescriptor carries only `workspaceSlug`, and until this existed\n * only POST /sessions/agent derived it from cwd. Every other spawn path dumped\n * the session into \"default\" even when its cwd sat inside a registered\n * workspace — measured at 160/209 sessions on one real daemon — which made the\n * slug useless as a grouping key for any client.\n *\n * Never throws: an unreadable/absent registry yields undefined and the caller\n * keeps its \"default\".\n */\nasync function resolveSlugFromCwd(cwd: string): Promise<string | undefined> {\n  if (!cwd) return undefined\n  try {\n    const config = await loadWorkspacesConfig()\n    return findWorkspaceByPath(config, cwd)?.slug\n  } catch {\n    return undefined\n  }\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        ...(b.options !== undefined\n          ? (() => {\n              const parsed = parseOptionsField(b.options)\n              return parsed !== undefined ? { options: parsed } : {}\n            })()\n          : {}),\n        ...(b.auth !== undefined\n          ? (() => {\n              const parsed = parseAuthField(b.auth)\n              return parsed !== undefined ? { auth: parsed } : {}\n            })()\n          : {}),\n        ...(typeof b.prompt === \"string\" ? { prompt: b.prompt } : {}),\n        ...(typeof b.label === \"string\" ? { label: b.label } : {}),\n        ...(typeof b.idempotencyKey === \"string\" && b.idempotencyKey.length > 0\n          ? { idempotencyKey: b.idempotencyKey }\n          : {}),\n        ...(typeof b.role === \"string\" && b.role.length > 0 ? { role: b.role } : {}),\n        ...(typeof b.promptAppend === \"string\" ? { promptAppend: b.promptAppend } : {}),\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        // Opt this session into Langfuse tracing — the HTTP twin of the\n        // MCP `agent_start` tool's `trace` field. Tolerate a stringified\n        // boolean (JSON `true`, or `\"true\"`/`\"false\"` from form-ish callers)\n        // so the REST driver reaches the same registry gate the MCP tool does.\n        ...(b.trace !== undefined\n          ? (() => {\n              const t =\n                typeof b.trace === \"boolean\"\n                  ? b.trace\n                  : b.trace === \"true\"\n                    ? true\n                    : b.trace === \"false\"\n                      ? false\n                      : undefined\n              return t !== undefined ? { trace: t } : {}\n            })()\n          : {}),\n        // Permission-hold mode — the HTTP twin of the MCP `agent_start` tool's\n        // `permissionHold` field (and `agentproto sessions start\n        // --hold-permissions`). Tolerate a stringified boolean like `trace`.\n        ...(b.permissionHold !== undefined\n          ? (() => {\n              const h =\n                typeof b.permissionHold === \"boolean\"\n                  ? b.permissionHold\n                  : b.permissionHold === \"true\"\n                    ? true\n                    : b.permissionHold === \"false\"\n                      ? false\n                      : undefined\n              return h ? { permissionHold: true } : {}\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                result.code === \"role_spawn_denied\"\n              ? 409\n              : result.code === \"invalid_role\"\n                ? 400\n                : 500\n      json(status, {\n        error: result.code,\n        message: result.message,\n        ...result.details,\n      })\n      return true\n    }\n    json(201, {\n      ...result.descriptor,\n      ...(result.deduped ? { deduped: true } : {}),\n    })\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) {\n      // cwd given (or defaulted) but no explicit slug — reverse-map it, exactly\n      // as spawnAgentSession does (session-spawn.ts). Without this a terminal\n      // whose cwd sits inside a registered workspace still lands in \"default\",\n      // so it can never be grouped or filtered by project.\n      workspaceSlug = (await resolveSlugFromCwd(cwd)) ?? \"default\"\n    }\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[], interrupt?: boolean }\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  //   - interrupt             → when true and the session is mid-turn,\n  //                             cancel the in-flight turn and deliver\n  //                             this prompt on the same session instead\n  //                             of the usual mid-turn rejection. No-op\n  //                             on an idle session. Default false.\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. `interrupt` only\n  //   takes effect on this fire-and-forget arm (mirroring MCP\n  //   `agent_prompt`, which always calls `enqueuePrompt`).\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 interrupt = (body as { interrupt?: unknown } | null)?.interrupt === true\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        // `interrupt: true` lets a mid-turn session redirect instead of\n        // rejecting — see `SessionsRegistry.enqueuePrompt`'s doc comment.\n        await registry.enqueuePrompt(id, prompt, { interrupt })\n        json(202, { ok: true, id, queued: true })\n      } else {\n        // `interrupt` used to be parsed and then silently DROPPED on this\n        // arm — it only took effect under ?wait=false. A caller asking to\n        // redirect a mid-turn session got the busy 409 it explicitly asked\n        // not to get. Both arms now honour it identically.\n        await registry.sendPrompt(id, prompt, { interrupt })\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 rawCwd = typeof b.cwd === \"string\" ? b.cwd : process.cwd()\n      const desc = registry.spawn({\n        kind:\n          b.kind === \"terminal\" || b.kind === \"agent-cli\" || b.kind === \"command\"\n            ? b.kind\n            : \"command\",\n        // Same reverse-map as /sessions/terminal and spawnAgentSession: an\n        // explicit slug wins, otherwise derive it from cwd rather than\n        // dumping the session into \"default\".\n        workspaceSlug:\n          typeof b.workspaceSlug === \"string\"\n            ? b.workspaceSlug\n            : ((await resolveSlugFromCwd(rawCwd)) ?? \"default\"),\n        cwd: rawCwd,\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  // `/events/stream` MUST be tried before the bare `/events` alternative:\n  // both are valid suffixes and `/events` is a prefix of `/events/stream`,\n  // so putting the longer one first matches it directly instead of relying\n  // on regex backtracking (JS alternation does backtrack across `$`, so\n  // either order technically works today, but ordering by specificity\n  // keeps that from being a load-bearing accident).\n  const idMatch = path.match(\n    /^\\/sessions\\/([^/]+)(\\/events\\/stream|\\/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 === \"/events/stream\" && req.method === \"GET\") {\n    // SSE live-push sibling of /events — same source file, same record\n    // shape per `data:` frame, so a client's poll-route reducer works\n    // unchanged against this stream. Read-only GET, no auth gate (same\n    // policy as /events).\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\n    // Existence check up front, same ENOENT→404 contract as /events —\n    // lets a caller distinguish \"no transcript\" from \"connection refused\"\n    // before any SSE bytes go out.\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    res.writeHead(200, {\n      \"content-type\": \"text/event-stream\",\n      \"cache-control\": \"no-cache\",\n      connection: \"keep-alive\",\n    })\n    // Node buffers `writeHead` until the first `res.write` — without this,\n    // a session with nothing new to replay would leave the client's\n    // connection attempt hanging (no bytes at all) until the first live\n    // record or the 25s keep-alive ping, whichever comes first. Matches\n    // the `: connected` convention `/events` (the bus route) already uses.\n    res.write(`: connected\\n\\n`)\n    const ping = setInterval(() => {\n      try {\n        res.write(`: keep-alive\\n\\n`)\n      } catch {\n        clearInterval(ping)\n      }\n    }, 25_000)\n\n    async function* diskRecords(): AsyncGenerator<Record<string, unknown>> {\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        try {\n          yield JSON.parse(trimmed) as Record<string, unknown>\n        } catch {\n          continue\n        }\n      }\n    }\n\n    const { unsubscribe, done } = deliverRecordsExactlyOnce({\n      since,\n      diskRecords: diskRecords(),\n      subscribe: onRecord => registry.subscribeToRecords(id, onRecord),\n      send: record => {\n        try {\n          res.write(`data: ${JSON.stringify(record)}\\n\\n`)\n        } catch {\n          // Client gone — cleanup happens on `close`.\n        }\n      },\n    })\n    // Registered immediately after subscribing (deliverRecordsExactlyOnce\n    // subscribes synchronously before returning) so a client that\n    // disconnects mid-replay — a large backlog, a slow pipe — still tears\n    // down the subscription instead of leaking it for the rest of the\n    // daemon's life.\n    req.once(\"close\", () => {\n      unsubscribe()\n      clearInterval(ping)\n    })\n\n    await done\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 * /presets route — list built-in provider gateway presets with live key-env\n * status. Static data (no registry), so this route is registered\n * unconditionally — no opt-in flag like /tunnels's TunnelRegistry.\n *\n *   GET /presets → { presets: AdapterEntry<PresetInfo>[] }\n *\n * Status reflects THIS process's environment (the daemon's — i.e. where agents\n * spawn), not the CLI caller's: \"ready\" when the provider's key env var is set,\n * \"available\" otherwise.\n */\nasync function handlePresets(\n  req: IncomingMessage,\n  res: ServerResponse,\n  path: 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 === \"/presets\" && req.method === \"GET\") {\n    json(200, { presets: listPresets() })\n    return true\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 * /permissions routes — the cross-session permission inbox:\n *   GET  /permissions            → { permissions: [...] } across all sessions\n *                                  (optional ?sessionId=<id> filter)\n *   POST /permissions/:id        → { decision, optionId?, scope? } approve/deny\n *\n * Mirrors the MCP `permissions_list` / `permissions_respond` tools over the\n * same SessionsRegistry inbox. Each list entry is enriched with the owning\n * session's adapter/title for a self-contained render.\n */\nasync function handlePermissions(\n  req: IncomingMessage,\n  res: ServerResponse,\n  path: string,\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 === \"/permissions\" && req.method === \"GET\") {\n    const reqUrl = req.url ?? \"\"\n    const qs = new URLSearchParams(\n      reqUrl.includes(\"?\") ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1) : \"\",\n    )\n    const sessionId = qs.get(\"sessionId\") ?? undefined\n    const permissions = registry\n      .listPendingPermissions(sessionId ? { sessionId } : undefined)\n      .map(p => enrichPermission(p, registry))\n    json(200, { permissions })\n    return true\n  }\n\n  const idMatch = path.match(/^\\/permissions\\/([^/]+)$/)\n  if (idMatch && req.method === \"POST\") {\n    const id = decodeURIComponent(idMatch[1] ?? \"\")\n    const body = await readJsonBody(req)\n    const b = body && typeof body === \"object\" ? (body as Record<string, unknown>) : {}\n    const decision = b.decision\n    if (decision !== \"approve\" && decision !== \"deny\") {\n      json(400, {\n        error: \"invalid_decision\",\n        message: 'body.decision must be \"approve\" or \"deny\"',\n      })\n      return true\n    }\n    const optionId = typeof b.optionId === \"string\" ? b.optionId : undefined\n    const scope = b.scope === \"always\" || b.scope === \"once\" ? b.scope : undefined\n    const result = await registry.respondPermission(id, {\n      decision,\n      ...(optionId ? { optionId } : {}),\n      ...(scope ? { scope } : {}),\n    })\n    if (!result.ok) {\n      const status = result.error === \"not_found\" || result.error === \"session_gone\" ? 404 : 409\n      json(status, { error: result.error, message: result.message })\n      return true\n    }\n    json(200, {\n      ok: true,\n      id,\n      sessionId: result.permission.sessionId,\n      decision: result.decision,\n      ...(result.optionId ? { optionId: result.optionId } : {}),\n    })\n    return true\n  }\n\n  if (path === \"/permissions\" || idMatch) {\n    json(405, { error: \"method_not_allowed\", message: \"GET /permissions or POST /permissions/:id\" })\n    return true\n  }\n  return false\n}\n\n/** Enrich a raw PendingPermission with the owning session's adapter/title/age\n *  so a REST/MCP list entry is self-contained. */\nfunction enrichPermission(\n  p: import(\"./sessions.js\").PendingPermission,\n  registry: SessionsRegistry,\n): Record<string, unknown> {\n  const desc = registry.get(p.sessionId)\n  const ageMs = Date.now() - new Date(p.requestedAt).getTime()\n  return {\n    ...p,\n    ...(desc?.adapterSlug ? { adapter: desc.adapterSlug } : {}),\n    ...(desc?.label ? { sessionLabel: desc.label } : {}),\n    ...(desc?.command ? { sessionTitle: desc.command } : {}),\n    ageMs: ageMs >= 0 ? ageMs : 0,\n  }\n}\n\n/**\n * /pairings routes — E2E daemon pairing (design: DESIGN §6):\n *   POST   /pairings/offer         → { ttlMinutes?, rendezvous? } mint offer\n *                                    → { url, fingerprint, rendezvous,\n *                                        rendezvousIsHostedDefault, expiresAt }\n *   GET    /pairings               → { pairings: [...] }\n *   DELETE /pairings/:fingerprint  → revoke by fingerprint (or name)\n *\n * Mirrors the MCP `pair_offer` / `pair_list` / `pair_revoke` tools over the same\n * registry. Imitates the /permissions surface from #308.\n */\nasync function handlePairings(\n  req: IncomingMessage,\n  res: ServerResponse,\n  path: string,\n  registry: PairingRegistry,\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 === \"/pairings/offer\" && req.method === \"POST\") {\n    const body = await readJsonBody(req)\n    const b = body && typeof body === \"object\" ? (body as Record<string, unknown>) : {}\n    const ttlMinutes = typeof b.ttlMinutes === \"number\" ? b.ttlMinutes : undefined\n    const rendezvous = typeof b.rendezvous === \"string\" ? b.rendezvous : undefined\n    try {\n      const offer = await registry.createOffer({\n        ...(ttlMinutes ? { ttlMs: ttlMinutes * 60_000 } : {}),\n        ...(rendezvous ? { rendezvousUrl: rendezvous } : {}),\n      })\n      json(200, {\n        url: offer.url,\n        fingerprint: offer.fingerprint,\n        rendezvous: offer.rendezvousUrl,\n        rendezvousIsHostedDefault: offer.rendezvousIsHostedDefault,\n        expiresAt: new Date(offer.exp * 1000).toISOString(),\n      })\n    } catch (err) {\n      json(400, {\n        error: \"offer_failed\",\n        message: err instanceof Error ? err.message : String(err),\n      })\n    }\n    return true\n  }\n\n  if (path === \"/pairings\" && req.method === \"GET\") {\n    const pairings = (await registry.list()).map(p => ({\n      name: p.name,\n      fingerprint: p.fingerprint,\n      createdAt: p.createdAt,\n      lastSeen: p.lastSeen,\n      rendezvous: p.rendezvousUrl,\n    }))\n    json(200, { pairings })\n    return true\n  }\n\n  const fpMatch = path.match(/^\\/pairings\\/([^/]+)$/)\n  if (fpMatch && req.method === \"DELETE\") {\n    const target = decodeURIComponent(fpMatch[1] ?? \"\")\n    const revoked = await registry.revoke(target)\n    if (!revoked) {\n      json(404, { error: \"not_found\", message: `no pairing matched \"${target}\"` })\n      return true\n    }\n    json(200, { ok: true, revoked: target })\n    return true\n  }\n\n  if (path === \"/pairings\" || path === \"/pairings/offer\" || fpMatch) {\n    json(405, {\n      error: \"method_not_allowed\",\n      message: \"POST /pairings/offer · GET /pairings · DELETE /pairings/:fingerprint\",\n    })\n    return true\n  }\n  return false\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 * Langfuse agent-session tracer — a {@link SessionObserver} that projects the\n * per-session stream (prompt in, text/tool/usage events, turn boundaries) into\n * Langfuse traces + generations + tool spans, with native token/cost. It is the\n * SAME tap the transcript writer sits on, so ALL adapters (they converge on the\n * ACP stream) are covered from one place — no per-adapter instrumentation, and\n * the metadata telemetry port stays untouched.\n *\n * Every outbound payload (prompt, assistant text, tool args/results) is passed\n * through a resolved {@link Redactor} at the egress boundary — off by default at\n * the call site (the tracer is only attached when a session opts in), and\n * additionally scrubbable here.\n *\n * Mapping:\n *   recordPrompt        → open the trace once (input = prompt) + a generation for the turn\n *   recordEvent text-delta   → accumulate the generation's output\n *   recordEvent tool-call    → span-create (input = tool args), nested under the generation\n *   recordEvent tool-result  → span-update (output = result, ERROR level on failure)\n *   recordEvent usage_update → stash tokens/cost onto the open generation\n *   recordEvent turn-end     → close the generation (output, usageDetails, costDetails) + flush\n *   recordEvent error        → ERROR on the generation (or a trace event)\n *   recordUsageSnapshot      → authoritative cost/tokens onto the turn's generation\n *   close                    → finalize the trace + flush\n */\n\nimport {\n  createIngestionClient,\n  type FlushResult,\n  type IngestionClient,\n} from \"@agentproto/telemetry-langfuse\"\nimport {\n  resolveRedactor,\n  type JsonValue,\n  type Redactor,\n  type RedactionField,\n  type RedactorSpec,\n} from \"@agentproto/redaction\"\n\nimport type { SessionObserver } from \"./session-observer.js\"\nimport type { AgentStreamEvent } from \"./sessions.js\"\nimport type { SessionUsage } from \"./usage.js\"\n\n/** Configuration for {@link langfuseSessionTracer}. */\nexport interface LangfuseSessionTracerConfig {\n  readonly publicKey: string\n  readonly secretKey: string\n  readonly baseUrl: string\n  /** Environment label stamped on every Langfuse object (e.g. a guild id). */\n  readonly environment?: string\n  /** Redactor spec applied to every outbound payload. Default: `\"none\"`. */\n  readonly redactor?: RedactorSpec\n  /** Optional fetch implementation (defaults to `globalThis.fetch`). */\n  readonly fetchImpl?: typeof fetch\n  /** Optional clock (ISO string). Defaults to real time. */\n  readonly now?: () => string\n}\n\n/** A session tracer sink — a {@link SessionObserver} with a manual `flush`. */\nexport interface LangfuseSessionTracer extends SessionObserver {\n  flush(): Promise<FlushResult>\n}\n\n/** Per-turn generation state. */\ninterface GenerationState {\n  readonly id: string\n  output: string\n  open: boolean\n  tokensIn?: number\n  tokensOut?: number\n  costUsd?: number\n  model?: string\n}\n\n/** Per-session trace state. */\ninterface TraceState {\n  traceOpened: boolean\n  turnIndex: number\n  /** The most recent turn's generation (kept after close so a late usage\n   *  snapshot can still attach cost to it). */\n  generation: GenerationState | null\n}\n\n/**\n * Coerce an arbitrary value (ACP `arguments`/`result`/prompt are typed\n * `unknown`) into a {@link JsonValue} the redactor can walk — deep, total, and\n * cast-free. Non-JSON leaves (bigint, function, symbol, undefined, non-finite\n * numbers) degrade to their string form rather than being dropped.\n */\nfunction toJsonValue(value: unknown): JsonValue {\n  if (value === null) return null\n  switch (typeof value) {\n    case \"string\":\n    case \"boolean\":\n      return value\n    case \"number\":\n      return Number.isFinite(value) ? value : String(value)\n    case \"object\": {\n      if (Array.isArray(value)) return value.map(toJsonValue)\n      const out: { [key: string]: JsonValue } = {}\n      for (const [key, entryValue] of Object.entries(value)) {\n        out[key] = toJsonValue(entryValue)\n      }\n      return out\n    }\n    default:\n      return String(value)\n  }\n}\n\nexport function langfuseSessionTracer(\n  cfg: LangfuseSessionTracerConfig,\n): LangfuseSessionTracer {\n  const client: IngestionClient = createIngestionClient(cfg)\n  const redactor: Redactor = resolveRedactor(cfg.redactor)\n  const clock = cfg.now ?? (() => new Date().toISOString())\n  const states = new Map<string, TraceState>()\n\n  const redact = (value: unknown, field: RedactionField, sessionId: string): JsonValue =>\n    redactor.redact(toJsonValue(value), { field, sessionId })\n\n  const withEnv = <T extends object>(body: T): T =>\n    cfg.environment !== undefined ? { ...body, environment: cfg.environment } : body\n\n  const getState = (sessionId: string): TraceState => {\n    let state = states.get(sessionId)\n    if (state === undefined) {\n      state = { traceOpened: false, turnIndex: 0, generation: null }\n      states.set(sessionId, state)\n    }\n    return state\n  }\n\n  /** Fire-and-forget flush from a sync observer method — never throws a turn. */\n  const flushSoon = (): void => {\n    void client.flush().catch(() => {\n      // isolate: a Langfuse outage must never break the session loop\n    })\n  }\n\n  return {\n    recordPrompt(sessionId: string, message: unknown): void {\n      const state = getState(sessionId)\n      const at = clock()\n      const input = redact(message, \"prompt\", sessionId)\n      if (!state.traceOpened) {\n        state.traceOpened = true\n        client.enqueue({\n          id: `${sessionId}#trace-create`,\n          type: \"trace-create\",\n          timestamp: at,\n          body: withEnv({\n            id: sessionId,\n            name: \"agent-session\",\n            timestamp: at,\n            input,\n          }),\n        })\n      }\n      state.turnIndex += 1\n      const genId = `${sessionId}:turn:${state.turnIndex}`\n      state.generation = { id: genId, output: \"\", open: true }\n      client.enqueue({\n        id: `${genId}#gen-create`,\n        type: \"generation-create\",\n        timestamp: at,\n        body: withEnv({\n          id: genId,\n          traceId: sessionId,\n          name: `turn:${state.turnIndex}`,\n          startTime: at,\n          input,\n        }),\n      })\n    },\n\n    recordEvent(sessionId: string, evt: AgentStreamEvent): void {\n      const state = getState(sessionId)\n      const gen = state.generation\n      const at = clock()\n      switch (evt.kind) {\n        case \"text-delta\": {\n          if (gen?.open && typeof evt.text === \"string\") gen.output += evt.text\n          return\n        }\n        case \"tool-call\": {\n          if (evt.toolCallId === undefined) return\n          client.enqueue({\n            id: `${sessionId}:tool:${evt.toolCallId}#span-create`,\n            type: \"span-create\",\n            timestamp: at,\n            body: withEnv({\n              id: `${sessionId}:tool:${evt.toolCallId}`,\n              traceId: sessionId,\n              ...(gen ? { parentObservationId: gen.id } : {}),\n              name: typeof evt.toolName === \"string\" ? evt.toolName : \"tool\",\n              startTime: at,\n              input: redact(evt.arguments, \"tool-args\", sessionId),\n            }),\n          })\n          return\n        }\n        case \"tool-result\": {\n          if (evt.toolCallId === undefined) return\n          client.enqueue({\n            id: `${sessionId}:tool:${evt.toolCallId}#span-update`,\n            type: \"span-update\",\n            timestamp: at,\n            body: withEnv({\n              id: `${sessionId}:tool:${evt.toolCallId}`,\n              traceId: sessionId,\n              endTime: at,\n              output: redact(evt.result, \"tool-result\", sessionId),\n              ...(evt.isError === true ? { level: \"ERROR\" } : {}),\n            }),\n          })\n          return\n        }\n        case \"usage_update\": {\n          if (!gen) return\n          if (typeof evt.tokensIn === \"number\") gen.tokensIn = evt.tokensIn\n          if (typeof evt.tokensOut === \"number\") gen.tokensOut = evt.tokensOut\n          if (evt.cost && typeof evt.cost.amount === \"number\") gen.costUsd = evt.cost.amount\n          return\n        }\n        case \"turn-end\": {\n          if (gen?.open) {\n            gen.open = false\n            client.enqueue({\n              id: `${gen.id}#gen-update`,\n              type: \"generation-update\",\n              timestamp: at,\n              body: withEnv({\n                id: gen.id,\n                traceId: sessionId,\n                endTime: at,\n                output: redact(gen.output, \"output\", sessionId),\n                ...(gen.tokensIn !== undefined || gen.tokensOut !== undefined\n                  ? { usageDetails: { input: gen.tokensIn ?? 0, output: gen.tokensOut ?? 0 } }\n                  : {}),\n                ...(gen.costUsd !== undefined ? { costDetails: { total: gen.costUsd } } : {}),\n              }),\n            })\n          }\n          flushSoon()\n          return\n        }\n        case \"error\": {\n          const message = evt.error?.message ?? \"error\"\n          if (gen) {\n            client.enqueue({\n              id: `${gen.id}#gen-error`,\n              type: \"generation-update\",\n              timestamp: at,\n              body: withEnv({\n                id: gen.id,\n                traceId: sessionId,\n                level: \"ERROR\",\n                statusMessage: message,\n              }),\n            })\n          }\n          return\n        }\n        default:\n          return\n      }\n    },\n\n    recordUsageSnapshot(sessionId: string, usage: SessionUsage): void {\n      const state = states.get(sessionId)\n      const gen = state?.generation\n      if (!gen) return\n      const at = clock()\n      // Authoritative cost/tokens from the runtime's own pricing (usage.ts) —\n      // merged onto the turn's generation so Langfuse cost == the billing ledger.\n      const hasTokens = usage.tokensIn !== undefined || usage.tokensOut !== undefined\n      if (usage.costUsd === undefined && !hasTokens && usage.model === undefined) return\n      client.enqueue({\n        id: `${gen.id}#gen-usage`,\n        type: \"generation-update\",\n        timestamp: at,\n        body: withEnv({\n          id: gen.id,\n          traceId: sessionId,\n          ...(usage.model !== undefined ? { model: usage.model } : {}),\n          ...(hasTokens\n            ? { usageDetails: { input: usage.tokensIn ?? 0, output: usage.tokensOut ?? 0 } }\n            : {}),\n          ...(usage.costUsd !== undefined ? { costDetails: { total: usage.costUsd } } : {}),\n        }),\n      })\n    },\n\n    async close(sessionId: string): Promise<void> {\n      const state = states.get(sessionId)\n      if (state?.traceOpened) {\n        const at = clock()\n        client.enqueue({\n          id: `${sessionId}#trace-output`,\n          type: \"trace-create\",\n          timestamp: at,\n          body: withEnv({\n            id: sessionId,\n            name: \"agent-session\",\n            timestamp: at,\n            output: { turns: state.turnIndex },\n          }),\n        })\n      }\n      states.delete(sessionId)\n      await client.flush()\n    },\n\n    async closeAll(): Promise<void> {\n      states.clear()\n      await client.flush()\n    },\n\n    flush(): Promise<FlushResult> {\n      return client.flush()\n    },\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:permission-request\"\n  | \"session:permission-resolved\"\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   * True when the turn completed normally but produced ZERO assistant\n   * output AND zero tool calls (and wasn't awaiting input) — a silent\n   * no-op. Grok via hermes/OpenRouter, and any invalid/rejected model id,\n   * complete a turn this way: `turnsCompleted` bumps, `$0` cost, empty\n   * transcript. Surfaced so an orchestrator can flag it instead of\n   * treating a green turn-end as real progress. Absent (not `false`) on\n   * a normal, productive turn.\n   */\n  empty?: boolean\n}\n\nexport interface SessionAwaitingInputEvent {\n  type: \"session:awaiting-input\"\n  sessionId: string\n  label?: string\n  ts: string\n  question?: SessionAwaitingQuestion\n}\n\n/**\n * Emitted when a permission-hold session parks a `session/request_permission`\n * (see the pending-permissions inbox in sessions.ts). `permissionId` is the\n * stable id `permissions_respond` / `POST /permissions/:id` resolve it with.\n */\nexport interface SessionPermissionRequestEvent {\n  type: \"session:permission-request\"\n  sessionId: string\n  permissionId: string\n  toolName?: string\n  text: string\n  label?: string\n  ts: string\n}\n\n/**\n * Emitted when a parked permission is resolved — by an inbox\n * approve/deny, or auto-`cancelled` when the session is torn down while the\n * request is still pending.\n */\nexport interface SessionPermissionResolvedEvent {\n  type: \"session:permission-resolved\"\n  sessionId: string\n  permissionId: string\n  decision: \"approve\" | \"deny\" | \"cancelled\"\n  optionId?: string\n  label?: string\n  ts: string\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  /** Mirrors `SessionDescriptor.endedReason` — set when this exit was the\n   *  daemon dying underneath the session (crash-discovered-at-boot or a\n   *  forced shutdown kill), not an operator targeting it. Lets a watcher\n   *  (completion-policy supervisor, `session_monitor`) tell \"my agent died\n   *  because the daemon did\" apart from a deliberate kill. Absent otherwise. */\n  reason?: \"daemon-restart\"\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  | SessionPermissionRequestEvent\n  | SessionPermissionResolvedEvent\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 { loadWorkflowHandle } from \"@agentproto/workflow-loader\"\nimport type { WorkflowHandle } from \"@agentproto/workflow\"\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  startFromFile(input: {\n    path: string\n    input?: unknown\n    cwd?: string\n    workspaceSlug?: string\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  input?: unknown,\n): Promise<void> {\n  try {\n    await runWorkflow({\n      workflow: runtimeWf,\n      agents,\n      signal,\n      cwd: state.cwd,\n      workspaceSlug: state.workspaceSlug,\n      input,\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  /**\n   * Compile a loaded {@link WorkflowHandle} into a {@link RuntimeWorkflow}.\n   * Required for `startFromFile` when the WORKFLOW.md contains declarative\n   * tool/map/parallel/etc steps; omitted/unsupported workflows return an error.\n   */\n  compileWorkflow?: (handle: WorkflowHandle) => RuntimeWorkflow | Promise<RuntimeWorkflow>\n}): WorkflowRunner {\n  const { registry, sessionEvents, resolveAgentAdapter, compileWorkflow } = 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    startFromFile: async (args) => {\n      if (!compileWorkflow) {\n        throw new Error(\n          \"workflow file execution requires a compileWorkflow callback to be configured on the runner\",\n        )\n      }\n      const handle = await loadWorkflowHandle(args.path)\n      const workflow = await compileWorkflow(handle)\n      const runId = `wfrun_${randomUUID()}`\n      const run: WorkflowRun = {\n        runId,\n        workflowId: handle.id,\n        status: \"running\",\n        startedAt: new Date().toISOString(),\n        stages: [\n          {\n            index: 0,\n            status: \"pending\" as const,\n            steps: [{ index: 0, label: \"workflow\", status: \"pending\" as const }],\n          },\n        ],\n      }\n      const abort = new AbortController()\n      const state: RunState = {\n        run,\n        cancelled: false,\n        abort,\n        stages: [],\n        ...(args.cwd !== undefined ? { cwd: args.cwd } : {}),\n        ...(args.workspaceSlug !== undefined ? { workspaceSlug: args.workspaceSlug } : {}),\n      }\n      runs.set(runId, state)\n      persist()\n\n      const agents = new SessionsRegistryAgentHost(\n        registry,\n        sessionEvents,\n        resolveAgentAdapter,\n        {\n          workspaceSlug: args.workspaceSlug,\n          cwd: args.cwd,\n        },\n      )\n\n      const cache = args.cacheKey ? createFileStepCache(args.cacheKey) : undefined\n\n      void executeRunWorkflow(\n        state,\n        workflow,\n        agents,\n        abort.signal,\n        cache,\n        args.cacheKey,\n        args.input,\n      ).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\"\nimport { restartAgentSession } from \"./session-restart-core.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 cwd = action.cwd ?? workspace\n      const result = await runCommand({\n        command: action.command,\n        args: action.args ?? [],\n        cwd,\n        timeoutMs: action.timeoutMs ?? 60_000,\n      })\n      // Same session-based record as command_execute — cron \"command\" jobs\n      // already share its allowlist + runCommand (\"one enforcement path,\n      // not two\"), so they share its `kind:\"command\"` audit trail too:\n      // the fired job gets its own session row in command_list/session_list,\n      // not just a line in `job.lastResult`.\n      registry.recordCommand({\n        workspaceSlug: \"default\",\n        cwd,\n        command: action.command,\n        args: action.args ?? [],\n        exitCode: result.exitCode,\n        signal: result.signal,\n        durationMs: result.durationMs,\n        stdout: result.stdout,\n        stderr: result.stderr,\n        ...(result.truncated ? { truncated: true } : {}),\n        label: `cron:${job.id}`,\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        if (!resolveAgentAdapter) {\n          throw new Error(\n            `cron job '${job.id}': session '${action.sessionId}' is not alive and agent ` +\n              \"restart is not enabled (no resolveAgentAdapter)\",\n          )\n        }\n        const restarted = await restartAgentSession(\n          registry,\n          resolveAgentAdapter,\n          desc,\n          // A cron `prompt-session` job needs `sendPrompt` on the\n          // result, which only an agent-cli session has — never let\n          // decideRestartStrategy hand back a PTY-native resume (e.g.\n          // claude-code's `claude --resume`) here.\n          { forceAgentResume: true },\n        )\n        action.sessionId = restarted.desc.id\n        await registry.sendPrompt(restarted.desc.id, action.prompt)\n        return {\n          ok: true,\n          summary:\n            `session '${desc.id}' was gone — resumed as '${restarted.desc.id}' ` +\n            `(${restarted.resumeVia || \"fresh spawn, no continuity\"}) and re-prompted`,\n        }\n      }\n      if (desc.busy) {\n        return {\n          ok: true,\n          summary: `session ${action.sessionId} busy (mid-turn), tick skipped`,\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\"\nimport { SUPERVISOR_ROLE } from \"./role.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  \"permissions_list\",\n  \"permissions_respond\",\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   * Name of the resolved role that owns this scope (spawn-role-\n   * profiles / privilege lattice). This is the \"parent role\" the\n   * `canSpawn` gate checks against when this scope is used to spawn a\n   * further child (`session-spawn.ts`). Defaults to `\"supervisor\"` at\n   * mint time when the caller doesn't say — every role that can reach\n   * `orchestrator: true` today resolves to supervisor (executor's\n   * `toolPolicy.delegation: \"deny\"` already excludes it from ever\n   * minting a scope), so this preserves #214 behaviour exactly until a\n   * custom role is actually granted delegation.\n   */\n  role: string\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  /** Name of the resolved role that owns this scope. Default\n   *  `\"supervisor\"` — see `OrchestratorScope.role`. */\n  role?: string\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        role: opts?.role ?? SUPERVISOR_ROLE.name,\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  /** Name of the resolved role for the session THIS scope is being\n   *  minted for (i.e. the session becoming an orchestrator) — becomes\n   *  `OrchestratorScope.role`, the \"parent role\" a future spawn\n   *  through this scope is gated against. Default `\"supervisor\"`. */\n  role?: string\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      ...(opts?.role ? { role: opts.role } : {}),\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/provider-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/provider-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 * Shared cloudflared spawn helper for the quick + named tunnel providers.\n *\n * ## Why redirect stdout/stderr to a FILE instead of a pipe\n *\n * The obvious spawn is `stdio: [\"ignore\", \"pipe\", \"pipe\"]` and a\n * `proc.stdout/stderr.on(\"data\")` listener that watches for a readiness\n * marker. That works from an idle shell — but WEDGES when cloudflared is\n * spawned by a busy host process (the agentproto daemon serving MCP,\n * sessions, heartbeats, …).\n *\n * Mechanism: cloudflared emits a burst of startup log lines (the\n * connectivity precheck table, then `Registered tunnel connection`). Those\n * writes go to the OS pipe buffer (~64 KiB). If the host's Node event loop\n * doesn't drain the pipe promptly — which happens under load — the buffer\n * fills, cloudflared's next log WRITE BLOCKS, and its main path stalls\n * *before it ever opens the edge connection*. The tunnel never registers,\n * `start()` times out after 30 s, and the failure looks like a network or\n * credentials problem when it's actually stdio back-pressure.\n *\n * Redirecting stdout+stderr to a file makes those writes never block\n * (the kernel handles file writes), regardless of event-loop load — so\n * cloudflared always proceeds to the edge. Empirically verified 2026-07-05:\n * a plain-pipe spawn from the daemon wedged with zero outbound sockets;\n * the identical spawn with stdio → file registered all four edge\n * connections in <1 s.\n *\n * Bonus: because the full output lands in a file, on timeout / early exit\n * we surface the captured tail in the error — turning an opaque\n * \"did not register within 30s\" into an actionable message.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { closeSync, openSync, readFileSync } from \"node:fs\"\n\nexport interface CloudflaredSpawnOptions {\n  /**\n   * Absolute path of the log file that cloudflared's stdout+stderr are\n   * redirected into. The caller owns its lifecycle (delete it in `stop()`).\n   */\n  logPath: string\n  /**\n   * Regex tested against the captured output. `start()` resolves as soon\n   * as it matches; the resolved value is `match[0]` (the whole match) —\n   * e.g. the `Registered tunnel connection` marker (named) or the\n   * `*.trycloudflare.com` URL (quick).\n   */\n  readyRegex: RegExp\n  /** Max wait before the child is killed and the promise rejects. */\n  timeoutMs: number\n  /**\n   * Message used when the timeout fires. The captured output tail is\n   * appended so the caller sees why cloudflared never became ready.\n   */\n  timeoutMessage: string\n  /** Optional live line forwarder (the gateway's RuntimeEvents stream). */\n  onLog?: (line: string) => void\n  /**\n   * Binary to spawn. Defaults to `\"cloudflared\"`. Overridable so tests can\n   * drive the file-capture / readiness / timeout logic with a fake process\n   * instead of a real tunnel client.\n   */\n  binary?: string\n}\n\nexport interface CloudflaredSpawnResult {\n  /** The live cloudflared child. The caller keeps it as its tunnel process. */\n  proc: ChildProcess\n  /** The `match[0]` that satisfied `readyRegex`. */\n  match: string\n  /**\n   * Stop the background log-forwarder started for this child. Call it from\n   * the provider's `stop()` so the interval doesn't outlive the tunnel.\n   */\n  stopTail: () => void\n}\n\nconst POLL_INTERVAL_MS = 200\n\n/**\n * Spawn `cloudflared <argv>` with stdout+stderr redirected to\n * `opts.logPath`, and resolve once `opts.readyRegex` matches the captured\n * output. Rejects (killing the child) on timeout, spawn error, or early\n * exit — always with the captured output tail attached.\n */\nexport async function spawnCloudflaredUntil(\n  argv: string[],\n  opts: CloudflaredSpawnOptions,\n): Promise<CloudflaredSpawnResult> {\n  const logFd = openSync(opts.logPath, \"a\")\n  let proc: ChildProcess\n  try {\n    proc = spawn(opts.binary ?? \"cloudflared\", argv, {\n      // stdout+stderr → file (see file header for why not a pipe).\n      stdio: [\"ignore\", logFd, logFd],\n      shell: false,\n    })\n  } finally {\n    // The child dup'd the fd on spawn; the parent's copy is redundant.\n    closeSync(logFd)\n  }\n\n  const readAll = (): string => {\n    try {\n      return readFileSync(opts.logPath, \"utf8\")\n    } catch {\n      return \"\"\n    }\n  }\n  const tail = (n: number): string => {\n    const lines = readAll().split(/\\r?\\n/).filter(l => l.length > 0)\n    return lines.slice(-n).join(\"\\n\") || \"(no cloudflared output captured)\"\n  }\n\n  let settled = false\n  let forwardedLen = 0\n\n  return await new Promise<CloudflaredSpawnResult>((resolve, reject) => {\n    // One interval does double duty: forward newly-flushed complete lines\n    // to onLog, and (until settled) test the readiness marker. After the\n    // marker matches, it keeps running as a plain forwarder so ongoing\n    // tunnel chatter still reaches RuntimeEvents; `stopTail` clears it.\n    const poll = setInterval(() => {\n      const text = readAll()\n      if (opts.onLog) {\n        const lastNl = text.lastIndexOf(\"\\n\")\n        if (lastNl + 1 > forwardedLen) {\n          const chunk = text.slice(forwardedLen, lastNl + 1)\n          for (const line of chunk.split(/\\r?\\n/)) {\n            if (line.length > 0) opts.onLog(`[cloudflared] ${line}`)\n          }\n          forwardedLen = lastNl + 1\n        }\n      }\n      if (settled) return\n      const m = text.match(opts.readyRegex)\n      if (m) {\n        settled = true\n        clearTimeout(timer)\n        resolve({ proc, match: m[0], stopTail: () => clearInterval(poll) })\n      }\n    }, POLL_INTERVAL_MS)\n    if (poll.unref) poll.unref()\n\n    const fail = (err: Error): void => {\n      if (settled) return\n      settled = true\n      clearTimeout(timer)\n      clearInterval(poll)\n      reject(err)\n    }\n\n    const timer = setTimeout(() => {\n      if (settled) return\n      try {\n        proc.kill(\"SIGTERM\")\n      } catch {\n        /* noop */\n      }\n      fail(new Error(`${opts.timeoutMessage}\\ncloudflared output (tail):\\n${tail(20)}`))\n    }, opts.timeoutMs)\n\n    proc.once(\"error\", err => fail(err))\n    proc.once(\"exit\", (code, signal) =>\n      fail(\n        new Error(\n          `cloudflared exited before it was ready ` +\n            `(code=${code}, signal=${signal}).\\n` +\n            `cloudflared output (tail):\\n${tail(20)}`,\n        ),\n      ),\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 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 { spawnCloudflaredUntil } from \"./cloudflared-spawn.js\"\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  let logFilePath: string | null = null\n  let stopLogTail: (() => void) | 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\n      // cloudflared's stdout+stderr are redirected to this file rather than\n      // a pipe — see cloudflared-spawn.ts for why (stdio back-pressure\n      // wedges the tunnel when spawned under a busy host event loop).\n      const logPath = join(dir, `cloudflared-${id}.log`)\n      logFilePath = logPath\n\n      const { proc, match, stopTail } = await spawnCloudflaredUntil(\n        [\"tunnel\", \"--config\", configPath, \"--url\", targetUrl],\n        {\n          logPath,\n          readyRegex: URL_REGEX,\n          timeoutMs: STARTUP_TIMEOUT_MS,\n          timeoutMessage: `cloudflared did not emit a public URL within ${STARTUP_TIMEOUT_MS / 1000}s`,\n          onLog: opts.onLog,\n        },\n      )\n      child = proc\n      stopLogTail = stopTail\n\n      proc.once(\"exit\", (code, signal) => {\n        opts.onLog?.(\n          `[cloudflared] exited (code=${code ?? \"?\"} signal=${signal ?? \"-\"})`,\n        )\n      })\n\n      return { publicUrl: match, pid: proc.pid ?? null }\n    },\n\n    async stop(): Promise<void> {\n      const proc = child\n      const cfg = configPath\n      const log = logFilePath\n      const stopTail = stopLogTail\n      child = null\n      configPath = null\n      logFilePath = null\n      stopLogTail = null\n      // Stop the background log-forwarder before killing cloudflared.\n      stopTail?.()\n      // Best-effort cleanup of the sentinel config + log file — losing them\n      // means stale `.agentproto/cloudflared-<id>.{yml,log}` files, no\n      // functional 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 (log) {\n        try {\n          await rm(log, { 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 * MCP tools that drive the pairing registry — the daemon's \"let a client pair\n * with me over an untrusted rendezvous\" surface (design: DESIGN §6).\n *\n * Three tools, mirroring the CLI verbs:\n *\n *   pair_offer   — mint a one-time offer + start dialing the rendezvous; returns\n *                  the `agentproto://pair?…` URL, fingerprint, and expiry.\n *   pair_list    — list persisted pairings (name, fingerprint, lastSeen).\n *   pair_revoke  — drop a pairing by fingerprint or name; stops its rendezvous\n *                  connections so it can no longer reconnect.\n *\n * Registered beside `remote_*` (remote-tools.ts) — same closure-rebind pattern;\n * the registry singleton lives on the gateway.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { PairingRegistry } from \"./pairing-registry.js\"\n\nexport interface RegisterPairingToolsOptions {\n  registry: PairingRegistry\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 registerPairingTools(\n  server: McpServer,\n  opts: RegisterPairingToolsOptions,\n): void {\n  const { registry } = opts\n\n  server.tool(\n    \"pair_offer\",\n    \"Mint a one-time pairing offer and start listening for a client on the \" +\n      \"rendezvous broker. Returns an `agentproto://pair?…` offer URL (share it / \" +\n      \"render it as a QR), the daemon's identity fingerprint, and the offer \" +\n      \"expiry. The URL is the bootstrap secret — it carries the daemon's public \" +\n      \"keys (MITM-proof against the broker) and a short-lived single-use token. \" +\n      \"The client runs `agentproto pair accept \\\"<url>\\\"`.\",\n    {\n      ttlMinutes: z\n        .number()\n        .int()\n        .min(1)\n        .max(1440)\n        .optional()\n        .describe(\"Offer time-to-live in minutes (default 10).\"),\n      rendezvous: z\n        .string()\n        .optional()\n        .describe(\n          \"Rendezvous WS URL to route through (ws:// or wss://). Defaults to \" +\n            \"`pairing.rendezvous` from config.json, or the hosted broker \" +\n            \"(wss://rdv.agentproto.sh/v1) when neither is set. The response's \" +\n            \"`rendezvousIsHostedDefault` flags when that fallback applied.\",\n        ),\n    },\n    async ({ ttlMinutes, rendezvous }) => {\n      const offer = await registry.createOffer({\n        ...(ttlMinutes ? { ttlMs: ttlMinutes * 60_000 } : {}),\n        ...(rendezvous ? { rendezvousUrl: rendezvous } : {}),\n      })\n      return text({\n        url: offer.url,\n        fingerprint: offer.fingerprint,\n        rendezvous: offer.rendezvousUrl,\n        rendezvousIsHostedDefault: offer.rendezvousIsHostedDefault,\n        expiresAt: new Date(offer.exp * 1000).toISOString(),\n      })\n    },\n  )\n\n  server.tool(\n    \"pair_list\",\n    \"List clients paired with this daemon: name, fingerprint, when first paired, \" +\n      \"and last seen. Read-only.\",\n    {},\n    async () => {\n      const pairings = await registry.list()\n      return text({\n        pairings: pairings.map(p => ({\n          name: p.name,\n          fingerprint: p.fingerprint,\n          createdAt: p.createdAt,\n          lastSeen: p.lastSeen,\n          rendezvous: p.rendezvousUrl,\n        })),\n      })\n    },\n  )\n\n  server.tool(\n    \"pair_revoke\",\n    \"Revoke a pairing by fingerprint or name. Drops its rendezvous connections \" +\n      \"so the client can no longer reconnect, and removes it from pairings.json.\",\n    {\n      target: z\n        .string()\n        .describe(\"The pairing's fingerprint or name (see pair_list).\"),\n    },\n    async ({ target }) => {\n      const revoked = await registry.revoke(target)\n      return text(\n        revoked\n          ? { ok: true, revoked: target }\n          : { ok: false, message: `no pairing matched \"${target}\"` },\n      )\n    },\n  )\n}\n","/**\n * MCP tool for a cheap, read-only daemon liveness probe.\n *\n * `daemon_health` returns the same data as `GET /health` but in-process:\n * no HTTP round-trip, no side effects. It is intended for orchestrating\n * clients that want an unambiguous \"is the daemon still serving me?\" check\n * without shelling out or firing a heavier operation.\n *\n * Because the tool only runs if the daemon that hosts it is alive and\n * serving MCP requests, the `alive` field is always `true` on a successful\n * return. The real failure mode this protects against is the client's\n * request itself failing or timing out at the transport level — observed as\n * a thrown/failed tool call, not as a `false` field in the response.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\n\nexport interface RegisterDaemonHealthToolsOptions {\n  workspace: string\n  registered: readonly string[]\n  startedAt: number\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 registerDaemonHealthTools(\n  server: McpServer,\n  opts: RegisterDaemonHealthToolsOptions,\n): void {\n  server.tool(\n    \"daemon_health\",\n    \"Cheap, side-effect-free liveness probe for this daemon. Returns the same \" +\n      \"fields as GET /health but in-process. `alive` is always true when the tool \" +\n      \"returns successfully; if the daemon is unreachable the failure is observed \" +\n      \"as a thrown/failed tool call at the transport level, not as a false field.\",\n    {},\n    async () => {\n      return text({\n        alive: true,\n        status: \"ok\",\n        workspace: opts.workspace,\n        registered: opts.registered,\n        uptimeMs: Date.now() - opts.startedAt,\n      })\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 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 { spawnCloudflaredUntil } from \"./cloudflared-spawn.js\"\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  let logFilePath: string | null = null\n  let stopLogTail: (() => void) | 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      // cloudflared's stdout+stderr are redirected to this file rather than\n      // a pipe — see cloudflared-spawn.ts for why (stdio back-pressure\n      // wedges the tunnel when spawned under a busy host event loop).\n      const logPath = join(dir, `cloudflared-named-${id}.log`)\n      logFilePath = logPath\n\n      const { proc, stopTail } = await spawnCloudflaredUntil(\n        [\"tunnel\", \"--config\", configPath, \"run\", cfg.tunnelId],\n        {\n          logPath,\n          readyRegex: READY_REGEX,\n          timeoutMs: STARTUP_TIMEOUT_MS,\n          timeoutMessage: `cloudflared did not register a tunnel connection within ${STARTUP_TIMEOUT_MS / 1000}s`,\n          onLog: opts.onLog,\n        },\n      )\n      child = proc\n      stopLogTail = stopTail\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      const log = logFilePath\n      const stopTail = stopLogTail\n      child = null\n      configPath = null\n      logFilePath = null\n      stopLogTail = null\n      // Stop the background log-forwarder before killing cloudflared.\n      stopTail?.()\n      if (cfg2) {\n        try {\n          await rm(cfg2, { force: true })\n        } catch {\n          /* noop */\n        }\n      }\n      if (log) {\n        try {\n          await rm(log, { 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/provider-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  protected 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.credentialsFile) creds.credentialsFile = desc.credentialsFile\n    if (desc.tunnelId) {\n      creds.tunnelId = desc.tunnelId\n      // A stored `credentialsFile` is the provider-level default captured at\n      // `setup_tunnel_provider` time — it belongs to the stored `tunnelId`.\n      // When this descriptor targets a *different* tunnelId and carries no\n      // credentialsFile of its own, the stored one is another tunnel's secret\n      // (→ cloudflared \"Unauthorized: Invalid tunnel secret\"). Drop it so the\n      // named provider falls back to the per-tunnel ~/.cloudflared/<id>.json.\n      if (\n        !desc.credentialsFile &&\n        stored.credentialsFile &&\n        stored.tunnelId &&\n        stored.tunnelId !== desc.tunnelId\n      ) {\n        delete creds.credentialsFile\n      }\n    }\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/provider-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/provider-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 * Built-in `local` sandbox provider — a passthrough that boots a real\n * agentproto daemon on 127.0.0.1 in a fresh temp workspace dir, rather than\n * a cloud box. Lets `sandbox: \"local\"` (and the rest of this family's\n * plumbing) be exercised without any cloud credentials: the same\n * `boot()` → `mcpUrl` → `connectDaemonAgentSessionHost` seam every other\n * provider goes through, just pointed at a child process instead of\n * e2b/modal/daytona.\n *\n * Spawns the `agentproto` binary already on PATH (the same CLI a developer\n * would use to run this daemon in the first place) — this package\n * deliberately has no dependency on `@agentproto/cli` (that dependency runs\n * the other way).\n */\n\nimport { spawn } from \"node:child_process\"\nimport { createServer } from \"node:net\"\nimport { mkdtemp, rm } from \"node:fs/promises\"\nimport { tmpdir } from \"node:os\"\nimport { join } from \"node:path\"\nimport { randomUUID } from \"node:crypto\"\nimport type {\n  BootedSandbox,\n  SandboxBootOpts,\n  SandboxProvider,\n  SandboxSpec,\n} from \"@agentproto/sandbox\"\n\nconst HEALTH_TIMEOUT_MS = 15_000\nconst POLL_INTERVAL_MS = 250\n\n/** Built-in, zero-credential sandbox provider — see module docs. */\nexport const localSandboxProvider: SandboxProvider = {\n  async boot(_spec: SandboxSpec, opts: SandboxBootOpts): Promise<BootedSandbox> {\n    const port = await getFreePort()\n    const workspace = await mkdtemp(join(tmpdir(), \"agentproto-sandbox-local-\"))\n\n    const child = spawn(\n      \"agentproto\",\n      [\"serve\", \"--port\", String(port), \"--bind\", \"127.0.0.1\", \"--workspace\", workspace],\n      {\n        env: { ...process.env, ...opts.env },\n        stdio: \"ignore\",\n      },\n    )\n    let spawnErrorMessage: string | null = null\n    child.once(\"error\", (err) => {\n      spawnErrorMessage = err.message\n    })\n\n    const healthUrl = `http://127.0.0.1:${port}/health`\n    const ready = await probeHealth(healthUrl, HEALTH_TIMEOUT_MS)\n    if (!ready) {\n      if (child.exitCode === null) child.kill(\"SIGTERM\")\n      await rm(workspace, { recursive: true, force: true }).catch(() => {})\n      throw new Error(\n        spawnErrorMessage\n          ? `@agentproto/runtime: local sandbox failed to spawn 'agentproto serve' — ` +\n            `${spawnErrorMessage}. Is @agentproto/cli installed and on PATH?`\n          : `@agentproto/runtime: local sandbox daemon did not become healthy at ` +\n            `${healthUrl} within ${HEALTH_TIMEOUT_MS}ms.`,\n      )\n    }\n\n    return {\n      mcpUrl: `http://127.0.0.1:${port}/mcp`,\n      sandboxId: `local-${randomUUID()}`,\n      async stop(): Promise<void> {\n        if (child.exitCode === null) child.kill(\"SIGTERM\")\n        await rm(workspace, { recursive: true, force: true }).catch(() => {})\n      },\n    }\n  },\n}\n\n/** Allocate an OS-assigned free TCP port on loopback. */\nasync function getFreePort(): Promise<number> {\n  return new Promise((resolve, reject) => {\n    const srv = createServer()\n    srv.once(\"error\", reject)\n    srv.listen(0, \"127.0.0.1\", () => {\n      const address = srv.address()\n      if (address === null || typeof address === \"string\") {\n        srv.close(() => reject(new Error(\"failed to allocate a free port\")))\n        return\n      }\n      const { port } = address\n      srv.close(() => resolve(port))\n    })\n  })\n}\n\n/** Poll `url` until it responds OK, or return false once `timeoutMs` elapses. */\nasync function probeHealth(url: string, timeoutMs: number): Promise<boolean> {\n  const deadline = Date.now() + timeoutMs\n  for (;;) {\n    try {\n      const res = await fetch(url, { signal: AbortSignal.timeout(POLL_INTERVAL_MS) })\n      if (res.ok) return true\n    } catch {\n      // not up yet — fall through to the deadline check\n    }\n    if (Date.now() >= deadline) return false\n    await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS))\n  }\n}\n","/**\n * Slug-keyed sandbox provider registry — the sandbox family's counterpart to\n * `remote-providers/registry.ts`. `local` resolves in-process; everything\n * else is a dynamic import of `@agentproto/sandbox-<slug>` (e.g.\n * `@agentproto/sandbox-e2b`), wrapped with this registry's own capability/\n * setup metadata because those packages export a bare `@agentproto/sandbox`\n * `SandboxProvider` (just `boot()`) rather than a self-describing\n * adapter-kit handle the way the tunnel family's third-party packages do.\n *\n * `modal` and `daytona` are catalog placeholders — AIP-36 day-1 provider\n * ids with no published `@agentproto/sandbox-<slug>` package yet, so they\n * always resolve to `null` (status \"supported\") until one ships.\n */\n\nimport type { SetupField } from \"@agentproto/provider-kit\"\nimport type { SandboxProvider } from \"@agentproto/sandbox\"\n\nimport { localSandboxProvider } from \"./local.js\"\nimport type { SandboxProviderCapabilities, SandboxProviderHandle } from \"./types.js\"\n\n/** Per-slug credentials, as stored by the creds store / setup tool. */\nexport type SandboxCreds = Record<string, string>\n\n/** Factory for a built-in sandbox provider handle. */\nexport type SandboxProviderFactory = (\n  creds?: SandboxCreds | null,\n) => SandboxProviderHandle\n\nconst LOCAL_SLUG = \"local\"\n\n/** Capabilities every provider exposes today — identical across the built-in\n *  local passthrough and the third-party (e2b) wrapper until they diverge. */\nconst CAPABILITIES_TODAY: SandboxProviderCapabilities = {\n  networkEgress: true,\n  mounts: false,\n  lifecyclePause: false,\n  readOnly: false,\n}\n\n/** e2b alone can pause/reconnect (`Sandbox.pause()` + `Sandbox.connect()`) —\n *  the `local` passthrough tears down its temp workspace on `stop()`, and\n *  `modal`/`daytona` are unpublished catalog placeholders. */\nconst E2B_CAPABILITIES: SandboxProviderCapabilities = {\n  ...CAPABILITIES_TODAY,\n  lifecyclePause: true,\n}\n\n/** Built-in sandbox providers keyed by canonical slug — resolve without any import. */\nexport const BUILTIN_SANDBOX_PROVIDERS: Record<string, SandboxProviderFactory> = {\n  [LOCAL_SLUG]: () => ({\n    provider: localSandboxProvider,\n    slug: LOCAL_SLUG,\n    name: \"Local\",\n    // In-process provider — no npm package version to report.\n    version: \"builtin\",\n    description:\n      \"Boots a real agentproto daemon on 127.0.0.1 in a fresh temp workspace — no cloud credentials needed.\",\n    requiresSetup: false,\n    capabilities: CAPABILITIES_TODAY,\n    async check(): Promise<boolean> {\n      return true\n    },\n  }),\n}\n\n/** Everything the registry needs to wrap a bare third-party `SandboxProvider`\n *  into a full adapter-kit handle. */\ninterface ThirdPartySandboxDescriptor {\n  packageName: string\n  /** Named export the package exposes its `SandboxProvider` under. */\n  exportName: string\n  name: string\n  description: string\n  capabilities: SandboxProviderCapabilities\n  setupFields: readonly SetupField[]\n}\n\nconst THIRD_PARTY_SANDBOX_PROVIDERS: Record<string, ThirdPartySandboxDescriptor> = {\n  e2b: {\n    packageName: \"@agentproto/sandbox-e2b\",\n    exportName: \"e2bSandboxProvider\",\n    name: \"e2b\",\n    description:\n      \"Runs the agentproto daemon inside an e2b Firecracker microVM (agentproto-workstation template).\",\n    capabilities: E2B_CAPABILITIES,\n    setupFields: [\n      {\n        name: \"apiKey\",\n        description: \"e2b API key (from e2b.dev/dashboard).\",\n        required: true,\n        sensitive: true,\n      },\n    ],\n  },\n  modal: {\n    packageName: \"@agentproto/sandbox-modal\",\n    exportName: \"modalSandboxProvider\",\n    name: \"Modal\",\n    description: \"Modal sandbox backend — catalog placeholder, no package published yet.\",\n    capabilities: CAPABILITIES_TODAY,\n    setupFields: [],\n  },\n  daytona: {\n    packageName: \"@agentproto/sandbox-daytona\",\n    exportName: \"daytonaSandboxProvider\",\n    name: \"Daytona\",\n    description: \"Daytona sandbox backend — catalog placeholder, no package published yet.\",\n    capabilities: CAPABILITIES_TODAY,\n    setupFields: [],\n  },\n}\n\n/** Duck-type a dynamically-imported value as a bare `@agentproto/sandbox` provider. */\nfunction isSandboxProvider(x: unknown): x is SandboxProvider {\n  if (!x || typeof x !== \"object\") return false\n  return typeof (x as Record<string, unknown>).boot === \"function\"\n}\n\n/**\n * Import a third-party sandbox package and wrap its bare `SandboxProvider`\n * (just `boot()`) into a full adapter-kit handle using this registry's own\n * capability/setup metadata. Returns null on any failure (not importable /\n * wrong shape) — same \"supported but not installed\" signal the tunnel\n * family's resolver produces.\n */\nasync function importThirdPartyProvider(\n  descriptor: ThirdPartySandboxDescriptor,\n  slug: string,\n  creds: SandboxCreds | null,\n  importPackage: (packageName: string) => Promise<Record<string, unknown>>,\n): Promise<SandboxProviderHandle | null> {\n  let mod: Record<string, unknown>\n  try {\n    mod = await importPackage(descriptor.packageName)\n  } catch {\n    return null\n  }\n  const candidate = mod[descriptor.exportName]\n  if (!isSandboxProvider(candidate)) return null\n\n  return {\n    provider: candidate,\n    slug,\n    name: descriptor.name,\n    // No self-declared handle to read a real version off of — the wrapped\n    // package only exports a bare SandboxProvider. \"installed\" distinguishes\n    // a resolved third-party handle from the catalog's \"not installed\".\n    version: \"installed\",\n    description: descriptor.description,\n    requiresSetup: descriptor.setupFields.length > 0,\n    capabilities: descriptor.capabilities,\n    setupFields: descriptor.setupFields,\n    async check(): Promise<boolean> {\n      return creds !== null\n    },\n  }\n}\n\nconst defaultImportPackage = (\n  packageName: string,\n): Promise<Record<string, unknown>> => import(packageName)\n\nexport interface ResolveSandboxProviderOpts {\n  /** Stored creds for the slug (descriptor-only listing passes null). */\n  creds?: SandboxCreds | null\n  /** Injectable for tests — defaults to a real dynamic `import()`. */\n  importPackage?: (packageName: string) => Promise<Record<string, unknown>>\n}\n\n/**\n * Resolve a slug to a concrete sandbox provider handle. Built-ins first (no\n * import), then the fixed third-party catalog (`e2b`/`modal`/`daytona`).\n * Returns null when the slug is unknown, or a catalog third-party package\n * isn't installed — the kit's \"supported but unavailable\" signal.\n */\nexport async function resolveSandboxProvider(\n  slug: string,\n  opts?: ResolveSandboxProviderOpts,\n): Promise<SandboxProviderHandle | null> {\n  const builtin = BUILTIN_SANDBOX_PROVIDERS[slug]\n  if (builtin) return builtin(opts?.creds ?? null)\n\n  const descriptor = THIRD_PARTY_SANDBOX_PROVIDERS[slug]\n  if (!descriptor) return null\n  return importThirdPartyProvider(\n    descriptor,\n    slug,\n    opts?.creds ?? null,\n    opts?.importPackage ?? defaultImportPackage,\n  )\n}\n","/**\n * Sandbox family on top of `@agentproto/provider-kit` — mirrors\n * `tunnel-adapters.ts`. This module is the entire bridge between the\n * generic kit and `@agentproto/sandbox`'s `SandboxProvider` concept: it\n * contributes nothing the kit already owns (catalog/status/creds/ledger/\n * list/MCP-tool plumbing); it only supplies the sandbox-family `TInfo`\n * (`SandboxAdapterInfo`), the static `SANDBOX_CATALOG`, and the resolver\n * that maps a catalog slug to a concrete {@link SandboxProviderHandle}\n * (`./sandbox-providers/registry.js`).\n *\n * Kit primitives used:\n *   - `makeCredsStore`      → per-slug 0600 creds under `~/.agentproto/sandbox-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_sandbox_providers`\n *   - `makeSetupTool`       → registers `setup_sandbox_provider` (multi-field\n *                             form: e2b's `apiKey`, sensitive)\n *\n * This is pure additive plumbing (introspection + setup) — it does NOT wire\n * a `sandbox` field into `agent_start`. That lands in a follow-up PR; the\n * `resolveSandboxProvider`/`listSandboxProviders` overrides below exist now\n * so that later wiring can inject the same resolver/lister this module\n * builds by default, mirroring `resolveAgentAdapter`/`listAgentAdapters`.\n *\n * Security: `toSandboxInfo` exposes only `capabilities` — never a cred\n * value (Appendix B). The setup tool's fields are marked SENSITIVE and the\n * result 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 AdapterResolver,\n  type CredsStore,\n  type SetupField,\n  type SetupLedger,\n} from \"@agentproto/provider-kit\"\n\nimport {\n  resolveSandboxProvider,\n  type SandboxCreds,\n} from \"./sandbox-providers/registry.js\"\nimport type {\n  SandboxProviderCapabilities,\n  SandboxProviderHandle,\n} from \"./sandbox-providers/types.js\"\n\nexport type { SandboxProviderHandle, SandboxProviderCapabilities }\n\n/** Creds-store / ledger family key → `~/.agentproto/sandbox-creds/`. */\nexport const SANDBOX_FAMILY = \"sandbox\"\n\n/**\n * Family descriptor (`TInfo`). Pure metadata surfaced in\n * `list_sandbox_providers`. The kit's `AdapterEntry` already carries\n * slug/name/description/status/version, so the only sandbox-specific field\n * is the declared capability set. NEVER carries a cred value.\n */\nexport interface SandboxAdapterInfo {\n  capabilities: SandboxProviderCapabilities\n}\n\n/** Resolve a sandbox provider slug to a handle, or null when unavailable. */\nexport type SandboxProviderResolver = AdapterResolver<SandboxProviderHandle>\n\n/** List every sandbox provider with its live status + capabilities. */\nexport type SandboxProviderLister = AdapterLister<SandboxAdapterInfo>\n\n/** Static catalog: the built-in `local` provider plus the AIP-36 day-1 cloud ids. */\nexport const SANDBOX_CATALOG: AdapterCatalog = [\n  {\n    slug: \"local\",\n    name: \"Local\",\n    description:\n      \"Boots a real agentproto daemon on 127.0.0.1 in a temp workspace — no cloud credentials needed.\",\n    packageName: \"@agentproto/runtime\",\n    hint: \"local · zero-credential\",\n  },\n  {\n    slug: \"e2b\",\n    name: \"e2b\",\n    description:\n      \"Runs the agentproto daemon inside an e2b Firecracker microVM (agentproto-workstation template).\",\n    packageName: \"@agentproto/sandbox-e2b\",\n    hint: \"e2b · cloud\",\n  },\n  {\n    slug: \"modal\",\n    name: \"Modal\",\n    description: \"Modal sandbox backend. Catalog placeholder — no package published yet.\",\n    packageName: \"@agentproto/sandbox-modal\",\n    hint: \"modal · cloud (not yet published)\",\n  },\n  {\n    slug: \"daytona\",\n    name: \"Daytona\",\n    description: \"Daytona sandbox backend. Catalog placeholder — no package published yet.\",\n    packageName: \"@agentproto/sandbox-daytona\",\n    hint: \"daytona · cloud (not yet published)\",\n  },\n]\n\n/** Extract the safe descriptor from a resolved handle. No secrets. */\nexport function toSandboxInfo(handle: SandboxProviderHandle): SandboxAdapterInfo {\n  return { capabilities: handle.capabilities }\n}\n\n/** Build the sandbox-family creds store (per-slug, 0600). */\nexport function makeSandboxCredsStore(home?: string): CredsStore<SandboxCreds> {\n  return makeCredsStore<SandboxCreds>({\n    family: SANDBOX_FAMILY,\n    ...(home ? { home } : {}),\n  })\n}\n\n/**\n * Resolve a catalog slug to a concrete handle via the provider registry —\n * `local` in-process, `e2b`/`modal`/`daytona` dynamic-imported. Reads\n * stored creds first so `e2b` (and any future catalog entry) resolves\n * configured when possible; unconfigured slugs resolve to a descriptor-only\n * handle (listing never calls `start()`/`check()`). Throws on an unknown\n * slug so the kit's resolver wraps it to `null` (\"supported but not\n * installed\").\n */\nexport function makeSandboxResolver(\n  credsStore: CredsStore<SandboxCreds>,\n  opts?: {\n    /** Injectable for tests — defaults to a real dynamic `import()`. */\n    importPackage?: (packageName: string) => Promise<Record<string, unknown>>\n  },\n): SandboxProviderResolver {\n  return makeAdapterResolver<SandboxProviderHandle>({\n    load: async (slug: string): Promise<SandboxProviderHandle> => {\n      const creds = await credsStore.read(slug)\n      const handle = await resolveSandboxProvider(slug, {\n        creds,\n        ...(opts?.importPackage ? { importPackage: opts.importPackage } : {}),\n      })\n      if (!handle) throw new Error(`unknown sandbox adapter slug: ${slug}`)\n      return handle\n    },\n  })\n}\n\n/** Build the family lister: catalog → status-classified entries. */\nexport function makeSandboxLister(opts: {\n  credsStore: CredsStore<SandboxCreds>\n  ledger: SetupLedger\n  resolver?: SandboxProviderResolver\n}): SandboxProviderLister {\n  return makeAdapterLister<SandboxProviderHandle, SandboxAdapterInfo>({\n    catalog: SANDBOX_CATALOG,\n    resolver: opts.resolver ?? makeSandboxResolver(opts.credsStore),\n    ledger: opts.ledger,\n    credsStore: opts.credsStore,\n    toInfo: toSandboxInfo,\n  })\n}\n\n/**\n * Resolve every catalog slug and union the `setupFields` of whichever\n * resolve with a non-empty declaration, for the `setup_sandbox_provider`\n * tool. Because one tool spans providers with disjoint fields, the unioned\n * shape is relaxed to all-optional at the zod layer (`required: false`);\n * the genuine per-provider required-ness is enforced in `onSetup` against\n * the chosen provider's handle.\n */\nasync function collectSetupSchema(\n  resolver: SandboxProviderResolver,\n): Promise<{ validSlugs: string[]; fields: SetupField[] }> {\n  const handles: SandboxProviderHandle[] = []\n  for (const entry of SANDBOX_CATALOG) {\n    const handle = await resolver(entry.slug)\n    if (handle) handles.push(handle)\n  }\n  const setupHandles = handles.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 RegisterSandboxAdapterToolsOptions {\n  /** Home dir override (tests). Defaults to `AGENTPROTO_HOME ?? ~/.agentproto`. */\n  home?: string\n  /** Override the family's default resolver — mirrors `resolveAgentAdapter`\n   *  injection. Defaults to `makeSandboxResolver(credsStore)`. */\n  resolveSandboxProvider?: SandboxProviderResolver\n  /** Override the family's default lister — mirrors `listAgentAdapters`\n   *  injection. Defaults to a catalog-driven lister built off the resolver. */\n  listSandboxProviders?: SandboxProviderLister\n}\n\n/**\n * Register the sandbox family's adapter-kit MCP tools on the server:\n *   - `list_sandbox_providers`  (parameterless; status + capabilities, no creds)\n *   - `setup_sandbox_provider`  (multi-field; fields are union of every\n *     configurable provider's declared `setupFields`, all SENSITIVE and\n *     never echoed). Async because the field schema is derived from\n *     resolved handles.\n */\nexport async function registerSandboxAdapterTools(\n  server: McpServer,\n  opts: RegisterSandboxAdapterToolsOptions = {},\n): Promise<void> {\n  const credsStore = makeSandboxCredsStore(opts.home)\n  const ledger = makeSetupLedger(opts.home ? { home: opts.home } : {})\n  const resolver = opts.resolveSandboxProvider ?? makeSandboxResolver(credsStore)\n  const lister =\n    opts.listSandboxProviders ?? makeSandboxLister({ credsStore, ledger, resolver })\n\n  makeListTool<SandboxAdapterInfo>({\n    server,\n    toolName: \"list_sandbox_providers\",\n    description:\n      \"List known sandbox providers with their status (supported/available/\" +\n      \"ready), version, and declared capabilities (networkEgress, mounts, \" +\n      \"lifecyclePause, readOnly). Credentials are never returned. Use \" +\n      \"`setup_sandbox_provider` to configure a provider that needs creds.\",\n    lister,\n  })\n\n  const { validSlugs, fields } = await collectSetupSchema(resolver)\n\n  makeSetupTool({\n    server,\n    toolName: \"setup_sandbox_provider\",\n    description:\n      \"Configure a sandbox provider that requires credentials (e.g. e2b). \" +\n      \"Each field is SENSITIVE — stored 0600 and never echoed back in tool \" +\n      \"results. Only the fields a given provider declares are stored.\",\n    validSlugs,\n    fields,\n    onSetup: async (slug: string, fieldValues: Record<string, string>) => {\n      // Resolve the chosen provider so its OWN setupFields drive\n      // validation — works for built-ins and third-party providers alike.\n      const handle = await resolver(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 = fieldValues[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: SandboxCreds = {}\n      for (const f of declared) {\n        const v = fieldValues[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","/**\n * MCP tools that expose the eval-reporter adapter family to agents connected\n * to the daemon. Lets a remote operator list eval reporters and configure\n * Langfuse credentials without touching the terminal.\n *\n * Two tools:\n *   list_eval_reporters   browse known eval reporter backends\n *   setup_eval_reporter   configure Langfuse credentials\n *\n * Rides on @agentproto/eval-reporters; credentials live 0600 under\n * ~/.agentproto and are never exposed by the list tool.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { makeEvalReporterTools } from \"@agentproto/eval-reporters\"\n\n/** Register list_eval_reporters + setup_eval_reporter on the daemon MCP server.\n *  Rides on @agentproto/eval-reporters (adapter-kit family); creds live 0600 under\n *  ~/.agentproto, never exposed by the list tool. */\nexport function registerEvalReporterTools(server: McpServer): void {\n  const tools = makeEvalReporterTools()\n\n  server.tool(\n    tools.list_eval_reporters.name,\n    tools.list_eval_reporters.description,\n    async () => {\n      const r = await tools.list_eval_reporters.handler()\n      return { content: [...r.content], ...(r.isError ? { isError: true } : {}) }\n    },\n  )\n\n  server.tool(\n    tools.setup_eval_reporter.name,\n    tools.setup_eval_reporter.description,\n    tools.setup_eval_reporter.inputSchema.shape,\n    async (args) => {\n      const r = await tools.setup_eval_reporter.handler(args)\n      return { content: [...r.content], ...(r.isError ? { isError: true } : {}) }\n    },\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 * Daemon-side pairing registry (design: DESIGN §3/§4, PLAN deliverable 2).\n *\n * Owns everything the daemon needs to be *paired with* over an untrusted\n * rendezvous:\n *\n *   - **Offer store** — in-memory, single-use, expiry-checked one-time tokens\n *     minted by `pair offer`. A daemon restart voids outstanding offers\n *     (acceptable + documented). The P1 `verifyOfferToken` predicate plugs in\n *     here and SPENDS the token on the first successful handshake.\n *   - **Pairings store** — `~/.agentproto/pairings.json` (0600, atomic write),\n *     one record per paired client: `{clientPub, name, fingerprint, createdAt,\n *     lastSeen, pairRoot, rendezvousUrl}`. `pairRoot` is the long-term shared\n *     secret (`derivePairRoot`) from which reconnect routing tokens derive.\n *   - **Rendezvous connections** — for a fresh offer, and for every persisted\n *     pairing on boot (autoconnect), the daemon dials the rendezvous *outbound*\n *     (`side=daemon&t=<token>`), runs `daemonHandshakeOverSink` with the P1\n *     crypto, and — on success — serves the spliced, E2E-wrapped channel exactly\n *     like `serve --connect` serves a tunnel host. The serving path itself is\n *     injected (`serve`) so this module stays free of pty/adapter concerns and\n *     the CLI can reuse its `createTunnelServer` config verbatim.\n *   - **Reconnect epochs** — a persisted pairing's standing connection uses the\n *     pairing-derived routing token `t' = HKDF(pairRoot, \"rv-route\"‖epoch)`,\n *     rotated per UTC day. The daemon parks on BOTH the current and previous\n *     epoch tokens so a client whose clock straddles midnight still finds it;\n *     reconnect-with-backoff keeps the standing connection alive.\n *   - **Revocation** — removing a pairing drops its rendezvous connections and\n *     stops the daemon parking on its tokens, so it can no longer be reached.\n *\n * ## Reconnect authentication (why no stable client key)\n *\n * P1's handshake carries only a client *ephemeral* key (regenerated per\n * handshake) — there is no persistent client identity key, and the PLAN forbids\n * changing the handshake. So a reconnect authenticates the client by\n * **possession of the epoch routing token**, which derives from `pairRoot` — a\n * secret only the paired client and daemon share (it fell out of the original\n * ECDH). The daemon dials a pairing's epoch token, and on that connection the\n * `verifyOfferToken` predicate accepts a hello whose offer-token field equals\n * that same epoch token (constant-time). Token possession ⇒ paired party. The\n * stored `fingerprint` (of the first handshake's ephemeral key) is a stable\n * display/revocation handle, not an authentication input.\n */\n\nimport { randomBytes, createHmac, timingSafeEqual } from \"node:crypto\"\nimport { mkdir, readFile, writeFile, chmod, rename } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { dirname, join, basename } from \"node:path\"\nimport {\n  daemonHandshakeOverSink,\n  type FrameSink,\n  type E2eFrameSink,\n} from \"@agentproto/acp/tunnel\"\nimport {\n  decodePairingHello,\n  encodePairingMessage,\n  respondToHandshake,\n  derivePairRoot,\n  deriveEpochRoutingToken,\n  currentEpoch,\n  encodeOfferUrl,\n  HOSTED_RENDEZVOUS_URL,\n  PairingError,\n} from \"@agentproto/secrets/pairing\"\nimport {\n  identityFingerprint,\n  type DaemonIdentity,\n} from \"@agentproto/secrets/identity\"\n\nexport const PAIRINGS_VERSION = 1 as const\n\n/** One persisted pairing. Written verbatim to `pairings.json`. */\nexport interface PairingRecord {\n  /** The client ephemeral public key from the FIRST handshake (a snapshot —\n   *  reconnects use fresh ephemerals; this is not an auth input). */\n  clientPub: string\n  /** Human-facing label the client chose on `pair accept`. */\n  name: string\n  /** `identityFingerprint(clientPub)` from the first handshake — the stable\n   *  display + revocation handle. */\n  fingerprint: string\n  /** ISO-8601 first-pair timestamp. */\n  createdAt: string\n  /** ISO-8601 of the most recent successful (re)connect. */\n  lastSeen: string\n  /** Long-term shared secret (base64), from which epoch routing tokens derive. */\n  pairRoot: string\n  /** Rendezvous endpoint to reconnect through. */\n  rendezvousUrl: string\n}\n\ninterface PairingsFile {\n  v: typeof PAIRINGS_VERSION\n  pairings: PairingRecord[]\n}\n\n/** Mode of a served channel — first-contact offer vs. an established reconnect. */\nexport type PairingChannelMode = \"offer\" | \"reconnect\"\n\n/** Context handed to the injected `serve` when a channel comes up. */\nexport interface PairingChannelContext {\n  mode: PairingChannelMode\n  /** Stable pairing fingerprint (present for reconnect; for an offer it's the\n   *  freshly-derived one). */\n  fingerprint: string\n  /** Client label. */\n  name: string\n}\n\n/** Handle to a live served channel — the registry closes it on teardown. */\nexport interface PairingChannelHandle {\n  close(): Promise<void>\n}\n\nexport interface CreatedOffer {\n  /** The one-time offer token (base64url). */\n  token: string\n  /** Offer expiry, unix seconds. */\n  exp: number\n  /** The full `agentproto://pair?…` offer URL. */\n  url: string\n  /** The daemon's identity fingerprint (shown to the human at accept time). */\n  fingerprint: string\n  /** The rendezvous the offer routes through. */\n  rendezvousUrl: string\n  /** True when `rendezvousUrl` is the hosted default — i.e. neither an explicit\n   *  `--rendezvous` nor a configured `pairing.rendezvous` applied, so the offer\n   *  falls back to `HOSTED_RENDEZVOUS_URL`. Surfaced so `pair offer` can flag,\n   *  never silently, that the daemon is relaying through our infrastructure. */\n  rendezvousIsHostedDefault: boolean\n}\n\nexport interface CreateOfferInput {\n  /** Time-to-live in ms. Default 10 minutes. */\n  ttlMs?: number\n  /** Rendezvous URL override; falls back to the configured default. */\n  rendezvousUrl?: string\n}\n\nexport interface PairingRegistryDeps {\n  /** Lazily load (create on first use) the daemon identity. Kept lazy so a\n   *  daemon that never pairs never writes an identity file. */\n  loadIdentity: () => Promise<DaemonIdentity>\n  /** Path to `pairings.json`. Defaults to `~/.agentproto/pairings.json`. */\n  pairingsPath?: string\n  /** Configured rendezvous URL (from `config.pairing.rendezvous`). Three states:\n   *  - `undefined` (key absent) → `createOffer` falls back to the hosted default\n   *    (`HOSTED_RENDEZVOUS_URL`).\n   *  - a non-empty URL → that endpoint is the default for offers.\n   *  - `\"\"` (explicitly empty) → an explicit opt-out: no default applies, so an\n   *    offer without `--rendezvous` fails closed. Wire it through verbatim (do\n   *    not coerce `\"\"` to `undefined`) or the opt-out silently reverts to the\n   *    hosted default. */\n  defaultRendezvousUrl?: string\n  /** Dial a rendezvous WS and adapt it to a FrameSink. Injected by the CLI\n   *  (uses `ws` + `wrapWebSocket`). Rejects if the dial fails. The `signal`\n   *  aborts on registry shutdown. */\n  dial: (wsUrl: string, signal: AbortSignal) => Promise<FrameSink>\n  /** Serve the E2E-wrapped channel (the CLI builds `createTunnelServer` over\n   *  it with the same config `serve --connect` uses). */\n  serve: (sink: E2eFrameSink, ctx: PairingChannelContext) => PairingChannelHandle\n  /** Injectable clock (ms). Defaults to Date.now. */\n  now?: () => number\n  /** Diagnostic log sink. */\n  log?: (line: string) => void\n  /** Reconnect backoff floor / ceiling (ms). Defaults 1s / 30s. */\n  reconnectMinMs?: number\n  reconnectMaxMs?: number\n  /** How long a parked daemon socket waits for a client hello before recycling\n   *  the connection. Kept just under the broker's park timeout. Default 110s. */\n  handshakeTimeoutMs?: number\n}\n\nexport interface PairingRegistry {\n  /** Mint a one-time offer + start dialing the rendezvous for it. */\n  createOffer(input?: CreateOfferInput): Promise<CreatedOffer>\n  /** All persisted pairings (copies). Loads `pairings.json` on first call. */\n  list(): Promise<PairingRecord[]>\n  /** Drop a pairing by fingerprint or name; stops its rendezvous connections.\n   *  Returns false when nothing matched. */\n  revoke(idOrName: string): Promise<boolean>\n  /** Start standing reconnect connections for every persisted pairing. Call\n   *  after the gateway is up (so the injected `serve` can reach it). */\n  startAutoconnect(): Promise<void>\n  /** Tear down every offer + reconnect connection and served channel. */\n  shutdown(): Promise<void>\n}\n\nconst DEFAULT_TTL_MS = 10 * 60_000\nconst DEFAULT_RECONNECT_MIN_MS = 1_000\nconst DEFAULT_RECONNECT_MAX_MS = 30_000\nconst DEFAULT_HANDSHAKE_TIMEOUT_MS = 110_000\n\nfunction defaultPairingsPath(): string {\n  return join(homedir(), \".agentproto\", \"pairings.json\")\n}\n\nfunction b64url(bytes: Buffer): string {\n  return bytes.toString(\"base64\").replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\")\n}\n\n/** Constant-time string compare (HMAC-blind so length never leaks). Mirrors the\n *  rendezvous/relay `timing-safe` pattern; inlined so runtime gains no dep. */\nfunction constantTimeEqual(a: string, b: string): boolean {\n  const key = randomBytes(32)\n  const da = createHmac(\"sha256\", key).update(a, \"utf8\").digest()\n  const db = createHmac(\"sha256\", key).update(b, \"utf8\").digest()\n  return timingSafeEqual(da, db)\n}\n\ninterface OfferEntry {\n  token: string\n  exp: number // unix seconds\n  spent: boolean\n  rendezvousUrl: string\n}\n\n/** One managed rendezvous connection loop (offer or a single epoch). */\ninterface ConnectionLoop {\n  abort: AbortController\n  /** Resolves when the loop has fully stopped. */\n  done: Promise<void>\n}\n\nexport function createPairingRegistry(deps: PairingRegistryDeps): PairingRegistry {\n  const pairingsPath = deps.pairingsPath ?? defaultPairingsPath()\n  const now = deps.now ?? Date.now\n  const log = deps.log ?? (() => {})\n  const reconnectMinMs = deps.reconnectMinMs ?? DEFAULT_RECONNECT_MIN_MS\n  const reconnectMaxMs = deps.reconnectMaxMs ?? DEFAULT_RECONNECT_MAX_MS\n  const handshakeTimeoutMs = deps.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS\n\n  /** fingerprint → record. Source of truth in memory; disk is the mirror. */\n  const pairings = new Map<string, PairingRecord>()\n  /** token → offer. */\n  const offers = new Map<string, OfferEntry>()\n  /** Loops keyed for lifecycle: `offer:<token>` and `pair:<fp>:<slot>`. */\n  const loops = new Map<string, ConnectionLoop>()\n  /** Live served channels, so shutdown/revoke can close them. */\n  const channels = new Set<PairingChannelHandle>()\n\n  let shuttingDown = false\n\n  // Pairings are loaded lazily (ensureLoaded) on the first list/offer/autoconnect\n  // so construction stays synchronous and touches no disk.\n  let loaded = false\n  async function ensureLoaded(): Promise<void> {\n    if (loaded) return\n    loaded = true\n    try {\n      const raw = await readFile(pairingsPath, \"utf8\")\n      const parsed: unknown = JSON.parse(raw)\n      if (isPairingsFile(parsed)) {\n        for (const rec of parsed.pairings) pairings.set(rec.fingerprint, rec)\n      }\n    } catch (err) {\n      if (!isEnoent(err)) {\n        log(`[pairing] could not read ${pairingsPath}: ${errMsg(err)}`)\n      }\n    }\n  }\n\n  async function persist(): Promise<void> {\n    const file: PairingsFile = {\n      v: PAIRINGS_VERSION,\n      pairings: Array.from(pairings.values()),\n    }\n    const dir = dirname(pairingsPath)\n    await mkdir(dir, { recursive: true })\n    const tmp = join(dir, `.${basename(pairingsPath)}.tmp-${process.pid}`)\n    await writeFile(tmp, JSON.stringify(file, null, 2) + \"\\n\", { encoding: \"utf8\", mode: 0o600 })\n    await chmod(tmp, 0o600).catch(() => {})\n    await rename(tmp, pairingsPath)\n  }\n\n  // ── connection loop ────────────────────────────────────────────\n\n  interface LoopSpec {\n    key: string\n    rendezvousUrl: string\n    /** Token to dial this iteration (recomputed for epoch loops). */\n    token: () => string\n    /** Verify the presented offer-token against the expected token for this\n     *  connection. `expected` is what `token()` returned this iteration. */\n    verify: (presented: string, expected: string) => boolean\n    /** Whether to stop after the first successful serve (offers) vs. loop\n     *  forever re-parking (reconnect). */\n    singleUse: boolean\n    /** Should the loop keep running? (e.g. offer not yet expired/spent, or the\n     *  pairing still exists). Checked at the top of each iteration. */\n    shouldContinue: () => boolean\n    /** Build the serve context + persist side-effects on a successful pair. */\n    onPaired: (\n      session: import(\"@agentproto/secrets/pairing\").PairingSession,\n      hello: import(\"@agentproto/secrets/pairing\").PairingHello,\n    ) => Promise<PairingChannelContext>\n  }\n\n  function startLoop(spec: LoopSpec): void {\n    if (loops.has(spec.key)) return\n    const abort = new AbortController()\n    const done = runLoop(spec, abort.signal).catch(err => {\n      log(`[pairing] loop ${spec.key} ended: ${errMsg(err)}`)\n    })\n    loops.set(spec.key, { abort, done })\n  }\n\n  async function stopLoop(key: string): Promise<void> {\n    const loop = loops.get(key)\n    if (!loop) return\n    loops.delete(key)\n    loop.abort.abort()\n    await loop.done.catch(() => {})\n  }\n\n  async function runLoop(spec: LoopSpec, signal: AbortSignal): Promise<void> {\n    let backoff = reconnectMinMs\n    while (!signal.aborted && spec.shouldContinue()) {\n      const expected = spec.token()\n      let sink: FrameSink\n      try {\n        sink = await deps.dial(dialUrl(spec.rendezvousUrl, expected), signal)\n      } catch (err) {\n        if (signal.aborted) break\n        log(`[pairing] dial ${spec.key} failed: ${errMsg(err)}`)\n        await sleep(backoff, signal)\n        backoff = Math.min(backoff * 2, reconnectMaxMs)\n        continue\n      }\n\n      // Make the in-flight handshake abortable: closing the sink on shutdown\n      // makes `daemonHandshakeOverSink` reject promptly (transport closed),\n      // instead of blocking on its own timeout for up to handshakeTimeoutMs.\n      const onAbort = (): void => {\n        try {\n          sink.close(\"registry shutdown\")\n        } catch {\n          /* already closing */\n        }\n      }\n      signal.addEventListener(\"abort\", onAbort, { once: true })\n\n      try {\n        let capturedSession: import(\"@agentproto/secrets/pairing\").PairingSession | null = null\n        let capturedHello: import(\"@agentproto/secrets/pairing\").PairingHello | null = null\n        let wrapped: E2eFrameSink\n        try {\n          const identity = await deps.loadIdentity()\n          wrapped = await daemonHandshakeOverSink(\n            sink,\n            helloBytes => {\n              const hello = decodePairingHello(helloBytes)\n              const result = respondToHandshake(hello, {\n                identity,\n                verifyOfferToken: presented => spec.verify(presented, expected),\n              })\n              capturedSession = result.session\n              capturedHello = hello\n              return { reply: encodePairingMessage(result.reply), keys: result.session }\n            },\n            { timeoutMs: handshakeTimeoutMs },\n          )\n        } catch (err) {\n          if (signal.aborted) break\n          // A park timeout, a rejected offer, or a tampered hello. Fail closed\n          // and re-dial after a short backoff (park timeouts are common + benign).\n          void err\n          await sleep(backoff, signal)\n          backoff = Math.min(backoff * 2, reconnectMaxMs)\n          continue\n        }\n\n        backoff = reconnectMinMs // success resets\n\n        if (!capturedSession || !capturedHello) {\n          wrapped.close(\"internal: missing session\")\n          continue\n        }\n\n        let ctx: PairingChannelContext\n        try {\n          ctx = await spec.onPaired(capturedSession, capturedHello)\n        } catch (err) {\n          log(`[pairing] persist for ${spec.key} failed: ${errMsg(err)}`)\n          wrapped.close(\"persist failed\")\n          continue\n        }\n\n        const handle = deps.serve(wrapped, ctx)\n        channels.add(handle)\n        log(`[pairing] channel up (${ctx.mode}) for ${ctx.fingerprint} via ${spec.key}`)\n\n        await waitClosed(wrapped, signal)\n        channels.delete(handle)\n        await handle.close().catch(() => {})\n        log(`[pairing] channel closed (${ctx.mode}) for ${ctx.fingerprint}`)\n\n        if (spec.singleUse) break\n      } finally {\n        signal.removeEventListener(\"abort\", onAbort)\n      }\n    }\n  }\n\n  // ── offer handling ─────────────────────────────────────────────\n\n  async function createOffer(input: CreateOfferInput = {}): Promise<CreatedOffer> {\n    await ensureLoaded()\n    // Precedence (PLAN deliverable 2): `--rendezvous` flag → `pairing.rendezvous`\n    // in config → hosted default. A configured empty string is an explicit\n    // opt-out (deliverable 4b): no default applies, so an offer without an\n    // explicit `--rendezvous` fails closed — the reachable form of the branch\n    // that used to fire whenever nothing was configured.\n    let rendezvousUrl: string\n    let rendezvousIsHostedDefault = false\n    if (input.rendezvousUrl) {\n      rendezvousUrl = input.rendezvousUrl\n    } else if (deps.defaultRendezvousUrl !== undefined) {\n      if (deps.defaultRendezvousUrl === \"\") {\n        throw new PairingError(\n          \"malformed_offer\",\n          'rendezvous disabled — pairing.rendezvous is set to \"\" (explicit opt-out); ' +\n            \"pass --rendezvous to route this offer through a specific broker\",\n        )\n      }\n      rendezvousUrl = deps.defaultRendezvousUrl\n    } else {\n      rendezvousUrl = HOSTED_RENDEZVOUS_URL\n      rendezvousIsHostedDefault = true\n    }\n    const identity = await deps.loadIdentity()\n    const token = b64url(randomBytes(16))\n    const ttlMs = input.ttlMs ?? DEFAULT_TTL_MS\n    const exp = Math.floor((now() + ttlMs) / 1000)\n    offers.set(token, { token, exp, spent: false, rendezvousUrl })\n\n    const fingerprint = identityFingerprint(identity.x25519.pub)\n    const url = encodeOfferUrl({\n      v: 1,\n      rendezvousUrl,\n      fingerprint,\n      daemonX25519Pub: identity.x25519.pub,\n      daemonEd25519Pub: identity.ed25519.pub,\n      token,\n      exp,\n    })\n\n    startOfferLoop(token, rendezvousUrl)\n    log(\n      `[pairing] offer minted (exp ${new Date(exp * 1000).toISOString()}) via ${rendezvousUrl}` +\n        (rendezvousIsHostedDefault ? \" (hosted default)\" : \"\"),\n    )\n    return { token, exp, url, fingerprint, rendezvousUrl, rendezvousIsHostedDefault }\n  }\n\n  function offerValid(token: string): boolean {\n    const entry = offers.get(token)\n    return !!entry && !entry.spent && entry.exp * 1000 > now()\n  }\n\n  function startOfferLoop(token: string, rendezvousUrl: string): void {\n    startLoop({\n      key: `offer:${token}`,\n      rendezvousUrl,\n      token: () => token,\n      shouldContinue: () => offerValid(token),\n      singleUse: true,\n      verify: (presented, expected) => {\n        const entry = offers.get(expected)\n        if (!entry || entry.spent || entry.exp * 1000 <= now()) return false\n        if (!constantTimeEqual(presented, expected)) return false\n        entry.spent = true // SPEND — single use\n        return true\n      },\n      onPaired: async (session, hello) => {\n        const pairRoot = derivePairRoot(session)\n        const fingerprint = session.peerFingerprint\n        const nowIso = new Date(now()).toISOString()\n        const record: PairingRecord = {\n          clientPub: hello.ePub,\n          name: session.clientName ?? fingerprint,\n          fingerprint,\n          createdAt: pairings.get(fingerprint)?.createdAt ?? nowIso,\n          lastSeen: nowIso,\n          pairRoot,\n          rendezvousUrl,\n        }\n        pairings.set(fingerprint, record)\n        await persist()\n        // Start standing reconnect connections so the client can come back.\n        startReconnectLoops(record)\n        return { mode: \"offer\", fingerprint, name: record.name }\n      },\n    })\n  }\n\n  // ── reconnect handling ─────────────────────────────────────────\n\n  function startReconnectLoops(record: PairingRecord): void {\n    // Two standing connections — current + previous epoch — so a client whose\n    // clock sits on either side of the UTC-day boundary can still splice.\n    for (const slot of [\"cur\", \"prev\"] as const) {\n      const epochOf = () => (slot === \"cur\" ? currentEpoch(now()) : currentEpoch(now()) - 1)\n      startLoop({\n        key: `pair:${record.fingerprint}:${slot}`,\n        rendezvousUrl: record.rendezvousUrl,\n        token: () => deriveEpochRoutingToken(record.pairRoot, epochOf()),\n        shouldContinue: () => pairings.has(record.fingerprint),\n        singleUse: false,\n        verify: (presented, expected) => constantTimeEqual(presented, expected),\n        onPaired: async (session, _hello) => {\n          const existing = pairings.get(record.fingerprint)\n          if (existing) {\n            existing.lastSeen = new Date(now()).toISOString()\n            await persist().catch(err => log(`[pairing] lastSeen persist failed: ${errMsg(err)}`))\n          }\n          // Silence unused-session lint while keeping the signature uniform.\n          void session\n          return {\n            mode: \"reconnect\",\n            fingerprint: record.fingerprint,\n            name: existing?.name ?? record.name,\n          }\n        },\n      })\n    }\n  }\n\n  async function startAutoconnect(): Promise<void> {\n    await ensureLoaded()\n    for (const record of pairings.values()) {\n      startReconnectLoops(record)\n    }\n    if (pairings.size > 0) {\n      log(`[pairing] autoconnect: standing connections for ${pairings.size} pairing(s)`)\n    }\n  }\n\n  // ── revocation ─────────────────────────────────────────────────\n\n  async function revoke(idOrName: string): Promise<boolean> {\n    await ensureLoaded()\n    let target: PairingRecord | undefined = pairings.get(idOrName)\n    if (!target) {\n      for (const rec of pairings.values()) {\n        if (rec.name === idOrName) {\n          target = rec\n          break\n        }\n      }\n    }\n    if (!target) return false\n    pairings.delete(target.fingerprint)\n    await persist()\n    // Stop parking on this pairing's tokens so it can no longer be reached.\n    await stopLoop(`pair:${target.fingerprint}:cur`)\n    await stopLoop(`pair:${target.fingerprint}:prev`)\n    log(`[pairing] revoked ${target.fingerprint} (${target.name})`)\n    return true\n  }\n\n  async function list(): Promise<PairingRecord[]> {\n    await ensureLoaded()\n    return Array.from(pairings.values()).map(r => ({ ...r }))\n  }\n\n  async function shutdown(): Promise<void> {\n    if (shuttingDown) return\n    shuttingDown = true\n    for (const key of Array.from(loops.keys())) {\n      await stopLoop(key)\n    }\n    for (const handle of Array.from(channels)) {\n      await handle.close().catch(() => {})\n    }\n    channels.clear()\n  }\n\n  return { createOffer, list, revoke, startAutoconnect, shutdown }\n}\n\n// ── helpers ────────────────────────────────────────────────────\n\nfunction dialUrl(rendezvousUrl: string, token: string): string {\n  const sep = rendezvousUrl.includes(\"?\") ? \"&\" : \"?\"\n  return `${rendezvousUrl}${sep}side=daemon&t=${encodeURIComponent(token)}`\n}\n\nfunction waitClosed(sink: E2eFrameSink, signal: AbortSignal): Promise<void> {\n  return new Promise(resolve => {\n    if (!sink.isOpen) {\n      resolve()\n      return\n    }\n    let settled = false\n    const finish = (): void => {\n      if (settled) return\n      settled = true\n      resolve()\n    }\n    sink.onClose(() => finish())\n    signal.addEventListener(\"abort\", () => {\n      sink.close(\"registry shutdown\")\n      finish()\n    })\n  })\n}\n\nfunction sleep(ms: number, signal: AbortSignal): Promise<void> {\n  return new Promise(resolve => {\n    if (signal.aborted) return resolve()\n    const timer = setTimeout(resolve, ms)\n    if (typeof timer.unref === \"function\") timer.unref()\n    signal.addEventListener(\"abort\", () => {\n      clearTimeout(timer)\n      resolve()\n    })\n  })\n}\n\nfunction isPairingsFile(v: unknown): v is PairingsFile {\n  if (typeof v !== \"object\" || v === null) return false\n  const rec = v as Record<string, unknown>\n  if (rec[\"v\"] !== PAIRINGS_VERSION) return false\n  if (!Array.isArray(rec[\"pairings\"])) return false\n  return rec[\"pairings\"].every(isPairingRecord)\n}\n\nfunction isPairingRecord(v: unknown): v is PairingRecord {\n  if (typeof v !== \"object\" || v === null) return false\n  const r = v as Record<string, unknown>\n  return (\n    typeof r[\"clientPub\"] === \"string\" &&\n    typeof r[\"name\"] === \"string\" &&\n    typeof r[\"fingerprint\"] === \"string\" &&\n    typeof r[\"createdAt\"] === \"string\" &&\n    typeof r[\"lastSeen\"] === \"string\" &&\n    typeof r[\"pairRoot\"] === \"string\" &&\n    typeof r[\"rendezvousUrl\"] === \"string\"\n  )\n}\n\nfunction isEnoent(err: unknown): boolean {\n  return (\n    typeof err === \"object\" &&\n    err !== null &&\n    \"code\" in err &&\n    (err as { code?: unknown }).code === \"ENOENT\"\n  )\n}\n\nfunction errMsg(err: unknown): string {\n  return err instanceof Error ? err.message : String(err)\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 { makeSessionStoryPanelApp } from \"./session-story-panel-app.js\"\nimport { makeTerminalPanelApp } from \"./terminal-panel-app.js\"\nimport {\n  loadWorkspacesConfig,\n  findWorkspace,\n  getActiveWorkspace,\n} from \"./workspaces-config.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 { loadConfig } from \"./config.js\"\nimport { langfuseSessionTracer } from \"./langfuse-session-tracer.js\"\nimport { makeEvalReporterCredsStore } from \"@agentproto/eval-reporters\"\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 { compileWorkflow } from \"@agentproto/workflow-runtime\"\nimport { createFileStepCache } from \"./workflow-step-cache.js\"\nimport { withDeferredTools } from \"./deferred-tools.js\"\nimport { withToolExclusion } from \"./tool-subset.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  SandboxProviderResolver,\n  SandboxProviderLister,\n  SandboxAdapterInfo,\n} from \"./sandbox-adapters.js\"\nexport type {\n  SandboxProviderHandle,\n  SandboxProviderCapabilities,\n} from \"./sandbox-providers/types.js\"\nexport type {\n  AgentSessionLike,\n  AgentStreamEvent,\n  SessionDescriptor,\n  SessionKind,\n  SessionStatus,\n  SpawnSessionInput,\n  SpawnAgentInput,\n  SessionsRegistry,\n  RegisterBrowserInput,\n  RegisterSessionInput,\n  PendingPermission,\n  PermissionRespondInput,\n  PermissionRespondResult,\n} from \"./sessions.js\"\nexport { formatToolCall, formatToolResult } from \"./tool-presenter.js\"\nexport { deriveSessionUsage, projectSessionUsage } from \"./usage.js\"\nexport {\n  composeSessionObservers,\n  type SessionObserver,\n} from \"./session-observer.js\"\nexport {\n  getMcpCredentialDeps,\n  setMcpCredentialDeps,\n  type McpCredentialDeps,\n} from \"./mcp-credential-deps.js\"\nexport type {\n  UsageSource,\n  SessionUsage,\n  UsageComputeInput,\n  PricingResolver,\n  TokenPricing,\n} from \"./usage.js\"\nimport { RemoteController } from \"./remote-controller.js\"\nimport { registerRemoteTools } from \"./remote-tools.js\"\nimport { registerPairingTools } from \"./pairing-tools.js\"\nimport type { PairingRegistry } from \"./pairing-registry.js\"\nimport { registerDaemonHealthTools } from \"./daemon-health-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 {\n  registerSandboxAdapterTools,\n  makeSandboxResolver,\n  makeSandboxCredsStore,\n  type SandboxProviderResolver,\n  type SandboxProviderLister,\n} from \"./sandbox-adapters.js\"\nimport { registerEvalReporterTools } from \"./eval-reporter-tools.js\"\nimport { registerPresetTools } from \"./preset-tools.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 {\n  createPairingRegistry,\n  PAIRINGS_VERSION,\n  type PairingRegistry,\n  type PairingRegistryDeps,\n  type PairingRecord,\n  type PairingChannelContext,\n  type PairingChannelHandle,\n  type PairingChannelMode,\n  type CreatedOffer,\n  type CreateOfferInput,\n} from \"./pairing-registry.js\"\nexport { registerPairingTools, type RegisterPairingToolsOptions } from \"./pairing-tools.js\"\nexport { listPresets, declaredPresetToProviderPreset } from \"./preset-tools.js\"\nexport type { PresetInfo, DeclaredAdapterPreset } from \"./preset-tools.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  getProviderKey,\n  injectProviderKeysIntoEnv,\n  providerEnvVar,\n  providersPath,\n  PROVIDER_ENV_VARS,\n  type ProviderEntry,\n  type ProvidersFile,\n} from \"./providers-store.js\"\nexport {\n  resolveSpawnDefaults,\n  normalizeSkillsOption,\n  credentialFingerprint,\n  resolveAuthSpec,\n  AuthResolutionError,\n  type SpawnDefaultsConfig,\n  type DefaultsAdapterConfig,\n  type DefaultsAdapterAuthConfig,\n  type ResolvedSpawnDefaults,\n  type ResolvedSpawnAuthMaterial,\n  type AdapterAuthDescriptor,\n  type ResolvedAuthSpec,\n  type AuthEcho,\n  type CredentialSource,\n  type DeclaredAdapterOption,\n} from \"./spawn-defaults.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   * Optional sandbox provider resolver — overrides the sandbox family's\n   * default resolver (built-ins + `@agentproto/sandbox-<slug>` dynamic\n   * import) used by `list_sandbox_providers` / `setup_sandbox_provider`\n   * AND `agent_start.sandbox`. Mirrors `resolveAgentAdapter`'s injection\n   * shape.\n   */\n  resolveSandboxProvider?: SandboxProviderResolver\n  /** Optional sandbox provider lister — mirrors `listAgentAdapters`.\n   *  Overrides the default catalog-driven lister behind `list_sandbox_providers`. */\n  listSandboxProviders?: SandboxProviderLister\n  /**\n   * Optional E2E pairing registry (see `createPairingRegistry`). When wired,\n   * the gateway mounts the `/pairings/*` REST routes and the `pair_*` MCP\n   * tools, and exposes the registry on the handle. The CLI builds it (injecting\n   * the ws `dial` + a `createTunnelServer`-backed `serve`) and passes it here so\n   * the runtime stays free of pty/adapter concerns while the pairing surface is\n   * reachable over MCP + HTTP. Autoconnect is the caller's to start (after this\n   * returns) so the injected `serve` can capture the finished gateway.\n   */\n  pairingRegistry?: PairingRegistry\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  \"daemon_health\",\n  \"agent_start\",\n  \"agent_prompt\",\n  \"agent_output\",\n  \"agent_kill\",\n  \"session_list\",\n  \"session_monitor\",\n  \"session_events_poll\",\n  \"permissions_list\",\n  \"permissions_respond\",\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  /** E2E pairing registry, when one was wired via\n   *  `CreateGatewayOptions.pairingRegistry`. Undefined otherwise. Exposed so\n   *  the CLI can `startAutoconnect()` after boot and `shutdown()` it. */\n  pairing?: PairingRegistry\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 startedAt = Date.now()\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  // Sandbox provider resolver — powers both `list_sandbox_providers` /\n  // `setup_sandbox_provider` (registerSandboxAdapterTools below) AND\n  // `agent_start.sandbox` (registerSessionTools → spawnAgentSession). Built\n  // once here (rather than each call defaulting separately) so both surfaces\n  // resolve the exact same provider set for the exact same slug. Falls back\n  // to the family's own built-in resolver (built-ins + `@agentproto/sandbox-\n  // <slug>` dynamic import) when the host doesn't inject an override —\n  // mirrors `resolveAgentAdapter`'s optional-injection shape.\n  const resolveSandboxProviderResolved: SandboxProviderResolver =\n    opts.resolveSandboxProvider ?? makeSandboxResolver(makeSandboxCredsStore())\n  // Same loopback reasoning as `daemonMcpUrl` above, for the terminal MCP\n  // app's PTY WebSocket: this process already knows its own bind/port, so\n  // there's no need to shell out to `.agentproto/runtime.json` (the CLI's\n  // discovery path in packages/cli — see sessions.ts) just to re-learn\n  // something we're holding in a local variable. Prototype shortcut: a\n  // genuinely remote host would need the daemon's LAN-reachable address\n  // instead, which isn't modelled here.\n  //\n  // Override via AGENTPROTO_PUBLIC_WS_ORIGIN when the daemon sits behind a\n  // public reverse proxy/tunnel (e.g. a Cloudflare Quick Tunnel) — hosts\n  // like Claude.ai appear to reject a `connectDomains` CSP entry pointing\n  // at `ws://` + a private/loopback address outright, before ever trying\n  // the WS handshake. Pointing this at the tunnel's public `wss://` origin\n  // instead makes the panel's WebSocket ride the same hostname the `/mcp`\n  // endpoint is already reachable on (Quick Tunnel proxies the whole port,\n  // including the WS upgrade). No trailing slash expected — it's used as\n  // `${origin}/sessions/:id/pty`.\n  const ptyWsBaseUrl =\n    process.env.AGENTPROTO_PUBLIC_WS_ORIGIN?.trim().replace(/\\/+$/, \"\") ||\n    `ws://127.0.0.1:${port}`\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  // Opt-in Langfuse session tracer — built once here (shared, pure) from the\n  // eval-reporter's stored langfuse creds, same store `setup_eval_reporter`\n  // writes to. Absent creds ⇒ undefined, and the registry never gates\n  // anything on a tracer that doesn't exist — tracing-off behaviour is\n  // unchanged from before this existed.\n  const configDefaults = (await loadConfig()).defaults\n  const lfCreds = await makeEvalReporterCredsStore().read(\"langfuse\").catch(() => null)\n  const langfuseTracer = lfCreds\n    ? langfuseSessionTracer({\n        publicKey: lfCreds.publicKey,\n        secretKey: lfCreds.secretKey,\n        baseUrl: lfCreds.baseUrl,\n        ...(lfCreds.environment ? { environment: lfCreds.environment } : {}),\n        redactor: configDefaults?.traceRedactor ?? \"secrets\",\n      })\n    : undefined\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    ...(langfuseTracer ? { langfuseTracer } : {}),\n    langfuseTracingDefault: configDefaults?.langfuseTracing ?? false,\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        // Compile a loaded WORKFLOW.md handle into a runnable RuntimeWorkflow\n        // for `workflow_run_file` / `startFromFile`. The daemon's workflow\n        // surface is agent-step based (like the stage primitive), so no tool/\n        // driver registry is wired here — `tool` steps in a WORKFLOW.md fail\n        // clearly (\"no tool registered\") until a workflow tool registry is\n        // added. Agent-step workflows compile + run.\n        compileWorkflow: handle => compileWorkflow(handle, { tools: {}, candidates: [] }),\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 (denyTools?: ReadonlySet<string>) => {\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    let server = opts.deferredTools\n      ? withDeferredTools(rawServer, { alwaysOn: new Set(opts.deferredTools.alwaysOn ?? DEFAULT_ALWAYS_ON_TOOLS) })\n      : rawServer\n    // Spawn-role-profiles tool gate (the hard part of the executor/\n    // supervisor primitive — see role.ts). Per-request denylist parsed\n    // from `?denyTools=a,b` on THIS `/mcp` call (see `handleMcp` in\n    // http-server.ts) — outermost wrap so it wins over deferred-tools\n    // unconditionally: an excluded name never reaches registration at\n    // all, regardless of `alwaysOn`.\n    if (denyTools && denyTools.size > 0) {\n      server = withToolExclusion(server, denyTools)\n    }\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    // Cheap, read-only liveness probe. Registered early so it is available\n    // even when deferred tools hide the rest of the surface.\n    registerDaemonHealthTools(server, { workspace, registered, startedAt })\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, registry: sessions })\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    // E2E daemon-pairing tools (pair_offer / pair_list / pair_revoke) — only\n    // when a pairing registry was wired. Same closure-rebind pattern as the\n    // remote tools above; the registry singleton lives on the gateway.\n    if (opts.pairingRegistry) {\n      registerPairingTools(server, { registry: opts.pairingRegistry })\n    }\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      resolveSandboxProvider: resolveSandboxProviderResolved,\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      makeSessionStoryPanelApp({ listSessions: listSessionsFiltered }),\n      // Same ptyEnabled gate as terminal_start/terminal_input/… in\n      // session-tools.ts — the panel would be able to open the WS but\n      // every spawn/attach would fail once node-pty isn't available, so\n      // just don't register the tool/resource at all in that case.\n      ...(opts.spawnPty != null\n        ? [\n            makeTerminalPanelApp({\n              wsBaseUrl: ptyWsBaseUrl,\n              ...(token ? { token } : {}),\n              async spawnOrAttach(input) {\n                if (input.sessionId) {\n                  const desc = sessions.findByIdOrName(input.sessionId)\n                  if (!desc) {\n                    throw new Error(\n                      `agentproto_terminal: no session \"${input.sessionId}\"`,\n                    )\n                  }\n                  if (desc.pty !== true) {\n                    throw new Error(\n                      `agentproto_terminal: session \"${input.sessionId}\" is not a PTY session`,\n                    )\n                  }\n                  return { sessionId: desc.id }\n                }\n                let cwd = input.cwd\n                let resolvedSlug = input.workspaceSlug ?? \"default\"\n                if (!cwd) {\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                }\n                if (!cwd) cwd = workspace\n                const desc = sessions.spawnPty({\n                  argv: input.argv && input.argv.length > 0 ? input.argv : [\"bash\"],\n                  cwd,\n                  workspaceSlug: resolvedSlug,\n                  cols: input.cols ?? 80,\n                  rows: input.rows ?? 24,\n                })\n                return { sessionId: desc.id }\n              },\n            }),\n          ]\n        : []),\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/provider-kit\n    // (list_tunnel_adapters + setup_tunnel_provider). Stateless wrt the\n    // gateway — creds/ledger live under ~/.agentproto.\n    await registerTunnelAdapterTools(server, {})\n    // Sandbox adapter introspection/setup, riding on @agentproto/provider-kit\n    // (list_sandbox_providers + setup_sandbox_provider) — same resolver\n    // `agent_start.sandbox` resolves slugs through above.\n    await registerSandboxAdapterTools(server, {\n      resolveSandboxProvider: resolveSandboxProviderResolved,\n      ...(opts.listSandboxProviders\n        ? { listSandboxProviders: opts.listSandboxProviders }\n        : {}),\n    })\n    // Eval-reporter introspection/setup, riding on @agentproto/eval-reporters\n    // (list_eval_reporters + setup_eval_reporter). Credentials live 0600 under\n    // ~/.agentproto and are never exposed by the list tool.\n    registerEvalReporterTools(server)\n    // Provider-gateway preset introspection (list_provider_presets), riding on\n    // @agentproto/provider-presets via the thin honest lister. Static data —\n    // no install/setup/creds; status is key-env presence in this process.\n    // Stage 4: thread loaded adapters' manifest-declared `presets` (AIP-45)\n    // into `adapterPresets` here so adapter-contributed gateways surface in\n    // the catalog. Today the seam exists and is tested but is passed none.\n    registerPresetTools(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    ...(opts.pairingRegistry ? { pairings: opts.pairingRegistry } : {}),\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, startedAt },\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    ...(opts.pairingRegistry ? { pairing: opts.pairingRegistry } : {}),\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      // Tear down pairing rendezvous connections + served channels before HTTP\n      // so no half-open E2E channel outlives the gateway it forwards to.\n      if (opts.pairingRegistry) {\n        await opts.pairingRegistry.shutdown().catch(() => {})\n      }\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"]}