# Roll — 浏览器操作（受管通道 + 交互通道）

Roll 可以驱动一个**受管、隔离的 Chrome（经真实的 `chrome-devtools-mcp` 侧车）**
来采集浏览器诊断——导航检查、DOM 快照、控制台与网络捕获、诊断截图。每次受管操作
会启动一个固定版本的 `chrome-devtools-mcp` stdio 会话（临时 Chrome 档案），会话
完成 MCP initialize + tools/list、校验最小工具清单后，才执行所请求的操作。档案在
操作后删除。

另一条**交互式 owner-Chrome 通道**支持对已打开的本地 Chrome 调试端点执行单次、
低风险操作，需前台 owner 批准并受严格租约控制。

两条通道都需显式开启、依赖受控、范围刻意收窄。

它们**不是**两件事：

- 它们**不是安装器**。Roll 绝不往你的产品仓 `package.json` 加依赖，也绝不擅自
  开启你自己（owner）Chrome 的远程调试。`setup` 只在你确认后写入一份机器级配置。
- 它们的产物**不是视觉验收证据**。受管诊断截图或交互式 owner 运行结果只能证明
  页面动作成功，不能满足故事的视觉验收（visual AC）。在 best-effort 截图下，
  视觉 AC 由任一有效且绑定目标的图像满足：**Roll Capture · 物理**（对真实终端/
  应用的物理截图），或 **Playwright · 渲染**（`finalUrl` 等于声明目标面的渲染回执）；
  两者都合格，绑定目标的渲染回执不同于诊断截图——见[验收证据](acceptance-evidence.md)。

---

## 隐私与安全边界

以下不变量对每次操作（受管或交互）都成立：

- **仅临时档案。** 受管 Chrome 在全新临时档案下运行，操作后删除。owner 浏览器
  状态（cookie、登录态、历史、localStorage）绝不进入、不读取、不导出。
- **禁止凭证导出。** cookie、storage 与 network bodies 没有任何 CLI 或适配器
  暴露面。两条通道都无法导出 owner 凭证。
- **遥测已禁用。** `chrome-devtools-mcp` 以 `--no-usage-statistics` 启动。
  不向 Chrome、CrUX、Lighthouse 或任何外部遥测服务发送数据。
- **有界脱敏诊断。** 诊断产物（控制台摘要、网络元数据、性能计数器）限定在固定
  白名单数值指标内，URL、资源名、trace 均脱敏。见[可选诊断 profile](#可选诊断-profile)。
- **无通用 MCP 绕过。** 只注册了固定版本的 `chrome-devtools-mcp` 传输用于浏览器
  操作。指向 DevTools 的通用 `mcp.call` 会被拒绝（fail-closed）。
- **DevTools 产物绝不满足视觉 AC。** 诊断截图与 DOM 快照被归类为仅诊断产物，
  无法获得视觉验收结论。见[证据边界](#证据边界)。
- **不自动启动 Chrome。** Roll 绝不启动或关闭你的 owner Chrome。交互通道仅连接
  你自行以 loopback 地址启动的 Chrome 调试端点。
- **仅机器级配置。** `setup` 写入 `~/.roll/browser-operations.yaml`——绝不写产品
  仓文件——且仅在 `--confirm` 时写入。

---

## 受管通道

受管通道是**浏览器操作的主路径**。它用全新临时档案启动 Chrome、拉起固定版本的
`chrome-devtools-mcp` 侧车、对白名单目标执行一次操作，结束后删除档案。

### 前置条件与体检

受管通道需要固定版本的 `chrome-devtools-mcp` 传输和一个 Chrome 可执行文件。
Roll 不会替你安装——它只报告缺什么、怎么修。先跑静态体检：

```bash
roll browser doctor
```

```
Browser operations doctor
浏览器操作体检

~ managed:     degraded — chrome-devtools-mcp not ready; existing Playwright and Roll Capture paths remain usable
    → roll browser setup --dry-run
    → install the missing dependency, then re-run roll browser doctor
✓ interactive: ready    owner Chrome reachable on 127.0.0.1:9222
~ capture:     degraded — Roll Capture readiness probe skipped (headless / CI / ROLL_NO_SCREENCAP).
```

每条通道只报告三种诚实状态之一：

| 状态 | 含义 |
|------|------|
| `ready` | 该通道的前置条件已满足。 |
| `degraded` | 通道不可用或仅部分可用。已有的 Playwright 与 Roll Capture 路径照常工作——缺前置绝不会被报成通过。 |
| `blocked` | 存在硬性前置阻断通道运行；会打印原因与修复命令。 |

静态体检只检查机器环境与配置，**不会**启动 `chrome-devtools-mcp`——静态体检的
`ready` 仅表示二进制与配置存在，不能证明 MCP 侧车能正确初始化。

### 实时 MCP 探测（`doctor --probe`）

`doctor --probe` 会运行**一次真实的临时 `chrome-devtools-mcp` 会话**，端到端验证
整个传输生命周期。只有通过探测，受管通道才会在 doctor 输出中显示为 `ready`。

```bash
roll browser doctor --probe
```

```
Browser operations doctor --probe
浏览器操作体检 --probe

⏳ Running live MCP lane probe — this will:
   1. Spawn the pinned chrome-devtools-mcp session (temporary process)
   2. Run MCP initialize + tools/list + manifest validation
   3. Close the session and clean up the temporary Chrome profile
The probe may take a few seconds. No owner state enters the temporary profile.

⏳ 正在运行实时 MCP 通道探测——将会：
   1. 启动固定版本的 chrome-devtools-mcp 会话（临时进程）
   2. 运行 MCP initialize + tools/list + 清单验证
   3. 关闭会话并清理临时 Chrome 档案
探测可能需要几秒。绝不会进入 owner 状态。

✅ Live probe passed — managed lane is ready.
✅ 实时探测通过——受管通道就绪。

✓ managed:     ready    chrome-devtools-mcp 1.5.0 (8 tools) — live probe passed
```

探测生命周期：

1. **启动** —— 临时 `chrome-devtools-mcp` stdio 进程以固定版本 +
   `--no-usage-statistics` 启动。
2. **初始化** —— MCP `initialize` 握手完成。
3. **验证** —— 运行 `tools/list`，校验响应是否符合最小工具清单
   （navigate、snapshot、console、network、screenshot）。
4. **关闭与清理** —— MCP 进程与临时 Chrome 档案被移除。

探测失败时如实分类报告：

```
❌ Live probe failed — see categorized failures below.
❌ 实时探测失败——见下方分类失败信息。
   transport: chrome-devtools-mcp not installed or not on PATH
   manifest: tool manifest missing required entries (expected: navigate, snapshot, console, network, screenshot; got: [])
   chrome: chrome binary not found at expected path
```

修复后重跑 `doctor --probe`。不带 `--probe` 的静态体检仍可用于快速环境检查；
当二进制与配置存在但尚未通过探测时，报告通道为 `configured`。

### 安装（先 dry-run）

`setup --dry-run` 展示 Roll 将要写入的机器级配置全文，并跑依赖预检。它**什么都不写**：

```bash
roll browser setup --dry-run
```

```
Browser operations setup
浏览器操作安装

  target (machine-level, never committed): ~/.roll/browser-operations.yaml

  proposed ~/.roll/browser-operations.yaml:
    devtools:
      command: npx
      args: ["-y", "chrome-devtools-mcp@1.5.0", "--no-usage-statistics"]
      package: chrome-devtools-mcp
      package_version: 1.5.0
      chrome_channel: stable
      remote_debugging: { host: "127.0.0.1", port: 9222 }
  ...
  Roll never installs into a product package.json and never enables owner Chrome remote debugging.
  Roll 绝不改动产品仓 package.json，也绝不自动开启 owner Chrome 的远程调试。

  dry-run: no configuration was written.
```

你审阅之后才写入配置，且必须显式确认：

```bash
roll browser setup --confirm
```

没有 `--confirm`（也没有 `--dry-run`）时，`setup` 会拒绝并且什么都不写。

### 运行受管操作（真实 MCP 通道）

`roll browser run` 带 `--story` 和 `--url` 会经**真实、策略控制的 MCP 通道**
执行。这是生产路径。项目须先在 `.roll/policy.yaml` 显式开闸（默认全部关闭）：

```yaml
browser_operations:
  enabled: true
  managed:
    enabled: true
    allowed_origins: [https://example.com]
    allowed_actions: [navigate, snapshot, console, network, screenshot]
    max_runs_per_cycle: 20
    timeout_ms: 30000
```

```bash
roll browser run \
  --story US-BROW-021 \
  --url https://example.com \
  --action screenshot
```

真实运行逐字输出（2026-07-16 实录）：

```
Managed browser operation — real MCP
受管浏览器操作 — 真实 MCP

  mcp package / MCP 包:  1.5.0
  transport initialized / 传输初始化:  yes
  manifest verified / 清单验证:  yes
  lane / 通道:            managed
  action / 动作:          screenshot
  target / 目标:          https://example.com
  run state / 运行状态:   passed
  result / 结果:          pass (action: ok)
  temp profile / 临时档案: removed (owner state never entered / 绝不进入 owner 状态)
  diagnostics / 诊断产物:  1 (diagnostic-only, NOT visual acceptance / 仅诊断，非视觉验收)
  summary / 摘要:         diagnostic screenshot recorded

  Diagnostic success is not visual acceptance evidence.
  诊断通过不等于视觉验收证据。
```

支持的动作：`navigate`（默认）、`snapshot`、`console`、`network`、`screenshot`。

MCP 会话生命周期：

1. **策略检查** —— 项目 `.roll/policy.yaml` 必须启用受管通道
   （`browser_operations.enabled: true` 加 `managed.enabled: true` 与 origin
   白名单）。无显式策略时默认全部关闭，运行在启动任何进程前即被**拒绝**。
2. **会话启动** —— 固定版本的 `chrome-devtools-mcp` 以全新临时 Chrome 档案
   启动。
3. **MCP 握手** —— `initialize` → `tools/list` → 清单验证。任何一步失败即中止
   运行（`devtools-error`）。
4. **动作执行** —— 所请求的动作对白名单目标执行。
5. **清理** —— MCP 进程组终止，包含 `npx` 包装器和它的 DevTools server 子进程；
   临时档案删除（超时或崩溃时也不例外）。无法确认清理时，运行会大声失败并报告
   `MCP process cleanup failed`，绝不会声称会话已清理。

白名单之外的目标——包括从请求 origin 跳走的重定向——会被**拒绝**，不会跟随。
真实通道**必须**提供 `--story` 标识符；它会记入操作账本（ledger）以备审计。

#### 阻塞/不可用实录

受管通道不可用或被策略拒绝时，运行会大声失败。无 `.roll/policy.yaml` 时的
逐字输出（2026-07-16 实录）：

```
Managed browser operation — real MCP
受管浏览器操作 — 真实 MCP

  denied / 已拒绝:       Browser operations are disabled in project policy

  Diagnostic success is not visual acceptance evidence.
  诊断通过不等于视觉验收证据。
```

修复：把上文的 `browser_operations:` 开闸块加进 `.roll/policy.yaml`，跑
`roll browser doctor --probe` 验证后重试。

失败模式与修复：

| 失败 | Doctor 信号 | 修复 |
|------|------------|------|
| `chrome-devtools-mcp` 未安装 | `managed: degraded — transport not found` | `npm i -g chrome-devtools-mcp@<version>` 或 `roll browser setup --confirm` |
| Chrome 二进制未找到 | `managed: degraded — chrome not found` | 安装 Chrome（stable 渠道） |
| 策略禁用受管通道 | run → `denied` | 在 `.roll/policy.yaml` 加 `browser_operations:` 开闸块（`enabled: true` + `managed.enabled: true` + origin 白名单） |
| MCP 握手失败 | `doctor --probe` → `manifest` 失败 | 检查 `chrome-devtools-mcp` 版本；重跑 `roll browser update --check` |
| MCP 进程运行中崩溃 | run → `devtools-error` | 重跑；持续崩溃 → `roll browser doctor --probe` |
| 运行超时 | run → `timeout` | 目标可能较慢；档案无论如何都会清理 |

### Fixture 路径（仅测试）

`--fixture` 标志走一条**假目标路径**，用于在不启动真实 MCP 进程的情况下测试接缝、
查看通道报告格式。它**不是**受管通道的回落——fixture 使用硬编码测试数据，永远
无法证明真实 MCP 传输正常工作。

```bash
roll browser run --fixture --action screenshot
```

```
Managed browser operation — fixture (fake target)
受管浏览器操作 — fixture（假目标）

  lane / 通道:            managed (fixture — TEST ONLY / 仅测试)
  action / 动作:          screenshot
  target / 目标:          https://fake.target.test
  run state / 运行状态:   passed
  result / 结果:          pass (action: ok)
  temp profile / 临时档案: removed (owner state never entered / 绝不进入 owner 状态)
  diagnostics / 诊断产物:  1 (diagnostic-only, NOT visual acceptance / 仅诊断，非视觉验收)
  summary / 摘要:         diagnostic screenshot captured at https://fake.target.test

  Diagnostic success is not visual acceptance evidence.
  诊断通过不等于视觉验收证据。
```

Fixture 支持注入标志以探究失败模式：`--fail timeout|crash|devtools-error`、
`--redirect <url>`、`--perf-fail`。这些都是仅测试用途——对真实 MCP 通道无效。

**Fixture 运行永远无法获得 `verified` 结论。** 只有真实 MCP 通道（不带
`--fixture`）才真正驱动传输。实况回归闸（见下文）在 CI 层面强制执行这一点：
`fixture` 来源的报告可以测试接缝，但永远无法产生 `verified` 结果。

### 传输更新

DevTools 传输版本是**固定的**。`update --check` 比较固定版本与候选版本，不下载、
不改任何东西：

```bash
roll browser update --check
```

应用更新与 setup 同样受控——需显式确认，先跑冒烟检查，再跑**真实 MCP 探测**，
任何失败都保留原版本不动：

```bash
roll browser update --apply --confirm
```

更新生命周期：

1. **检查** —— 比较固定版本与候选版本。
2. **冒烟检查** —— 验证候选版本二进制可启动。
3. **MCP 探测** —— 以候选版本运行 `doctor --probe`。若探测失败，更新**中止**，
   保留原版本不动。
4. **应用** —— 仅当冒烟 + 探测均通过，才重写配置，新版本成为固定传输。

```
Update applied: 1.5.0 → 1.6.0
更新已应用：1.5.0 → 1.6.0
  wrote: ~/.roll/browser-operations.yaml

  smoke check: passed
  冒烟检查：通过

  MCP probe: passed (1.6.0)
  MCP 探测：通过 (1.6.0)

✓ managed:     ready    chrome-devtools-mcp 1.6.0 (8 tools) — live probe passed
```

更新失败时保留原版本：

```
Update aborted: live MCP probe failed for 1.6.0
更新中止：1.6.0 实时 MCP 探测失败

  Prior version 1.5.0 is kept intact.
  已保留原版本 1.5.0。

  transport: process exited before initialize completed
```

---

## 可选诊断 profile

受管通道提供两个**可选、需显式选启**的诊断 profile：一个性能 profile 和一小组
设备仿真 profile。两者都只在受管隔离通道（真实 MCP 路径）内运行，产物都是**仅诊断**
材料。

采用前先看清边界：

- **需显式选启**。不在命令行显式选择就不会采集任何 profile；不带 profile 时基础
  受管操作行为不变。
- 产物**仅诊断**，既不是视觉验收证据，也不是多浏览器测试矩阵。profile 摘要只能
  证明本地诊断跑过，不满足故事的视觉 AC。视觉验收请用
  [Roll Capture](acceptance-evidence.md)。
- **数据最小化**，不向机器外发送任何内容。

### 性能 profile（需选启）

`--perf-profile web-vitals-lite` 采集一组有界、脱敏的本地 DevTools 性能计数器
（documents、frames、layout/style 的计数与耗时、script/task 耗时、JS 堆大小——
一份固定的数值指标白名单）。不选就不启用，而"选择"这一动作正是打开本通道
性能诊断策略的开关。

```bash
roll browser run --story US-BROW-021 --url https://example.test --perf-profile web-vitals-lite
```

```
  perf profile / 性能诊断: web-vitals-lite (opt-in, diagnostic-only / 需选启，仅诊断)
    metrics / 指标 (12, bounded & redacted / 有界脱敏):
      - LayoutCount: 3
      - ScriptDuration: 0.021
      ...
```

数据最小化与范围保证：

- **只有白名单内的数值指标名会被保留。** 绝不保留任何 URL、资源名或 trace，因此
  该 profile 无法变成分析或证据通道。
- **无外部遥测。** 不向 CrUX、Lighthouse 或任何服务上传。要加外部上传，须另立
  一份单独设计、经同意授权的策略契约。
- **优雅降级。** 采集失败时运行报告 `degraded — no signal collected`，底层动作
  结论不变。

未知 profile 名会 fail-fast 拒绝，而非静默忽略。

### 设备仿真 profile（需选启）

`--profile <name>` 用一个命名的 Chrome 设备/视口 profile 运行受管操作。白名单是
有限的——调用方不能提交任意 DevTools 仿真参数：

| Profile | 视口 | 缩放 | 移动端 |
|---------|------|------|--------|
| `Pixel 7` | 412 × 915 | 2.625 | 是 |
| `iPhone 14` | 390 × 844 | 3 | 是 |
| `iPad Pro` | 1024 × 1366 | 2 | 否 |

```bash
roll browser run --story US-BROW-021 --url https://example.test --action screenshot --profile "iPhone 14"
# device profile / 设备仿真: iPhone 14
```

范围保证：

- **仅限有限白名单。** 未知 profile 名 fail-fast 拒绝；无法借它传入原始仿真参数。
- **这是 Chrome DevTools 仿真，不是多浏览器矩阵。** 对比声明的视口行为在范围内；
  真正的跨浏览器（Playwright 式）farm 明确不在范围，需另立单独设计的提案。
- **安全不变量不变。** 设备 profile 不改变源策略、临时 profile 清理、Capture
  结论或交互式 owner-Chrome 行为。

---

## 交互通道

交互通道让你对自己 Chrome 中**已经打开的页面**执行单次低风险操作。它用于
手动举证（manual-attest）工作流，而非后台自动化。

### 先决条件

Roll **不会替你启动 Chrome**，也**不会开启远程调试**。你必须先自行启动带有
本地调试端点的 Chrome，再运行 `roll browser interactive`：

```bash
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
  --remote-debugging-port=9222 \
  --user-data-dir=/tmp/owner-chrome-profile
```

仅允许 `127.0.0.1:9222`（或其他 loopback 地址）。非 loopback 端点会被拒绝。

### 运行一次交互操作

```bash
roll browser interactive \
  --story US-EXAMPLE-001 \
  --origin https://example.test \
  --action navigate --url https://example.test/login
```

支持动作：`navigate`、`click`、`fill`、`press_key`。

该命令要求**已连接的 TTY**。它会打印待执行内容（story、origin、动作、最长
15 分钟的租约），然后请求**一次 owner 批准**：

```
Owner Chrome approval required (one operation only)
  story: US-EXAMPLE-001
  origin: https://example.test
  action: navigate to https://example.test
  expiry: 2026-07-15T08:34:00.000Z (15 minutes maximum)
  credential export: denied (cookies, storage, and network bodies are unavailable)
Approve this owner-run operation? [y/N]
```

如果你拒绝，不会尝试任何连接。如果批准，Roll 会连接本地调试端点、执行单次
操作、打印结果，并立即释放租约：

```
manual owner-run result: ok (tab: 1234)
This interactive result does not make CI pass and is not background automation.
```

### 租约到期与取消

每次交互操作最多持有 **15 分钟** 租约。租约绑定到持有进程与 loopback 端点；
操作结束后立即释放。若进程死亡或租约到期，Roll 会自动回收。你无法批准持久
后台租约——每次操作都需要独立的前台批准。

### 交互通道永远不会做的事

- 在没有 TTY 和显式 owner 批准的情况下运行。
- 连接非 loopback 或远程调试端点。
- 导出 cookie、storage、network bodies 或任何其他凭证。
- 自动启动 Chrome 或留下后台调度器。
- 独自让 CI 通过——它只是一个 **owner-run manual-attest** 工具。

---

## 证据边界

受管浏览器诊断与交互式 owner 运行结果**仅为诊断 / 仅为 manual-attest**。每次
run 报告都重复这句：*诊断通过不等于视觉验收证据*。诊断截图或交互结果会被归类
为诊断产物，而非视觉验收产物，因此绝不可能伪造故事的视觉验收。

在 best-effort 截图下，视觉 AC 由任一有效且绑定目标的图像满足：
**Roll Capture · 物理**（对真实终端/应用的物理截图），或 **Playwright · 渲染**
（`finalUrl` 等于声明目标面的渲染回执）；两者都合格。物理图像绝不声称它无法观测到的
`finalUrl`。见[验收证据](acceptance-evidence.md)。

当 `roll attest` 收到物理捕获响应时，会把已验证的 CaptureBridge link 写入
`.roll/browser-operations/events.ndjson`。doctor、truth 与 dossier 都读取这条持久化
事实：通过验证的 `roll.capture.v1` 物理捕获可以满足视觉 AC，绑定目标的
`roll.capture.v2` 渲染回执同样可以；只有未绑定目标的 Playwright 与 DevTools*诊断*仍
不具资格。没有已落盘的 link 时，capture truth 诚实保持 unknown，dossier 也不会
凭空生成捕获事件。

---

## Dossier 时间线（可选）

当故事已有声明的浏览器操作事实（ledger 的 start/finish、lease 的
grant/expiry/release，或物理截图结果）时，交付 dossier 的 Execution 区会显示紧凑的
**浏览器操作时间线**。排序只来自已声明时间戳——缺失类别以诚实的 absent + 原因
呈现，绝不虚构时间点或结论。脱敏诊断产物与物理截图只有在既有 dossier 授权规则
（本地 href 映射）允许时才会变为链接；否则只显示标签。没有浏览器事实的故事保持
原先 dossier 形态不变。

**unknown 与 degraded 状态如实呈现。** 某类别没有已声明时间戳时，时间线把它渲染
成明确的 absent + 原因（例如 *lease: unknown — no grant recorded*），而不虚构
时间点或结论。降级的 profile（见上文[性能 profile](#可选诊断-profile)）显示为
degraded 诊断，而非 pass。若某行时间线意外为空或降级，请按下文[排障](#排障)
排查——受管通道 degraded 是缺少前置依赖，不是交付坏了。

---

## 安全恢复

- 若 `doctor` 报告 `managed: degraded`，已有的 Playwright 与 Roll Capture 路径
  照常可用——你原本依赖的东西没有被破坏。装上缺失依赖后重跑
  `roll browser doctor --probe`。
- 临时 profile 每次运行后都会删除；owner Chrome 状态绝不进入。运行被中断后重跑
  是安全的——每次都从全新 profile 开始。
- 不会向你的产品仓写任何东西。Roll 唯一可能写入的是机器级
  `~/.roll/browser-operations.yaml`，且仅在 `--confirm` 时。

---

## 排障

### `roll browser doctor` 报告 `managed: degraded`

静态体检发现缺少前置依赖。跑 `roll browser setup --dry-run` 查看需要什么，
装上缺失依赖后重跑 `roll browser doctor --probe` 验证。

### `doctor --probe` 报 "transport" 或 "manifest" 错误

真实 MCP 侧车无法初始化。常见原因：

- `chrome-devtools-mcp` 未全局安装（`npm i -g chrome-devtools-mcp`）。
- `~/.roll/browser-operations.yaml` 中固定的版本与已安装版本不匹配。跑
  `roll browser update --check` 对比。
- Chrome 未安装或不在 PATH 中。

### `roll browser run` 提示 "Browser operations are disabled in project policy"

项目 `.roll/policy.yaml` 未启用受管通道。添加 `browser_operations` 开闸块
（与上文「运行受管操作」一节相同的 schema）：

```yaml
browser_operations:
  enabled: true
  managed:
    enabled: true
    allowed_origins: [https://example.com]
    allowed_actions: [navigate, snapshot, console, network, screenshot]
```

然后重跑 `roll browser doctor --probe` 验证通道就绪。

### `roll browser run` 不带 `--story` 或 `--url` 失败

真实 MCP 通道**必须**提供 `--story <US-ID>` 和 `--url <targetUrl>`。这些参数
会记入操作账本以备审计。仅在 `--fixture`（仅测试路径）下可省略。

### `roll browser interactive` 提示 "requires an attached TTY"

交互式 owner-Chrome 操作需要前台终端。它们不能从后台调度器、CI 作业或非交互式
shell 中运行。这是设计如此：每次操作都需要实时的 owner 批准。

### "Connects only to an already-open loopback Chrome debug endpoint"

Roll 不会启动 Chrome，也不会打开远程调试端口。你需要自行用
`--remote-debugging-port=9222` 绑定到 `127.0.0.1` 来启动 Chrome。非 loopback
地址会被拒绝。

### 交互模式能导出 cookie 或保持会话吗？

不能。凭证导出（cookie、storage、network bodies）始终被拒绝。租约在操作结束后
立即释放，并在 15 分钟内过期；没有后台调度器，也没有持久会话。

### 我能把交互模式指向远程 Chrome 实例吗？

不能。仅支持 loopback 端点。没有远程端点、隧道或云浏览器集成。

---

## 实况回归闸

受管通道由一个真实、封闭的端到端回归闸守护（`pnpm test:browser-live`）。它会启动
一个本地临时 HTTP 目标、一个真实的精确版本 `chrome-devtools-mcp` 进程，以及一个
受管的临时 Chrome 档案，然后通过公开的受管路径（`roll browser run`，不带
`--fixture`）执行导航、DOM 快照、真实的 console/network 摘要、诊断截图，以及需选启
的性能/设备档案。它同时验证最终 origin 的跳转拒绝，并验证超时、Chrome 崩溃、MCP
协议错误、redaction 失败各自都会清理 MCP 进程、Chrome 与临时档案。它**不发起任何
外部网络请求**。

两个环境，刻意分离：

- **默认 `roll test` / `pnpm -r test`** —— 永不运行实况闸（它需要 Chrome）。这些
  套件在任何机器上都保持绿。闸本身的逻辑（能力探测、证据判分、本地目标）由始终运行
  的封闭单元测试覆盖。
- **Chrome-capable CI 通道**（`.github/workflows/browser-live-gate.yml`）——
  设置 `ROLL_BROWSER_LIVE=1`，装配真实 Chrome，真跑实况闸。

该闸**失败即大声报错，绝不静默 skip**。本地运行：

```bash
ROLL_BROWSER_LIVE=1 pnpm test:browser-live
```

若缺少 Chrome 或 `npx`，或未设置 `ROLL_BROWSER_LIVE`，闸会作为*显式的不可用环境闸*
退出——报告缺失的能力，并明确声明受管通道**未验证**。它绝不会把 skip 或 fixture
运行报告为已验证：`fixture` 来源的报告可以测试接缝，但永远无法获得 `verified` 结论。

`verified` 结果会打印真实的传输验证（`transport initialized`、`manifest
verified`）、每个场景的清理状态，以及 diagnostic-only 边界——正是物理终端截图所
捕获的同一份摘要。

---

## 相关

- [工具与策略](tools.md) —— `browser.*` 工具访问如何被治理。
- [验收证据](acceptance-evidence.md) —— 为什么诊断不是视觉验收。
- [FAQ](faq.md) —— 常见问题与解答。
- [English](../en/browser-operations.md)
