# sgClaw 浏览器团队开发启动文档

**适用对象**：Chromium / C++ 浏览器开发团队（P2）
**目标**：浏览器团队拿到本文档后即可独立启动开发，并在一个周期后与 sgClaw 项目团队完成 Pipe 联调。
**协议版本**：`1.0`
**冻结日期**：`2026-03-24`

---

## 1. 开发目标

浏览器团队本周期只负责浏览器侧 Pipe 接入，不负责 LLM、Skill、Memory、Agent 推理。

本周期结束时，浏览器侧必须具备以下能力：

1. 能从浏览器主进程启动 `sgclaw` Rust 子进程。
2. 能通过 `stdin/stdout` 与 `sgclaw` 进行双向 `JSON Line` 通信。
3. 能解析 sgClaw 发来的 `command` 消息，并路由到现有 `CommandRouter`。
4. 能执行最小可联调动作：`click`、`type`、`navigate`、`getText`。
5. 能返回结构化 `response` 消息。
6. 能在浏览器侧执行域名和 action 白名单校验。

本周期不做：

1. 不改现有 `CommandRouter` 的核心接口。
2. 不新造一套浏览器操作 API。
3. 不改为 HTTP、WebSocket、Named Pipe。
4. 不实现 Rust 侧逻辑。

---

## 2. 架构边界

浏览器侧是父进程，`sgclaw` 是子进程。浏览器侧新增三个模块：

1. `SgClawProcessHost`
   负责子进程启动、停止、状态管理、异常退出处理。
2. `PipeListener`
   负责异步读取 `sgclaw stdout`，按行解析 JSON 并分发。
3. `MacWhitelistCheck`
   负责浏览器侧二次安全校验，防止越权 action 落到 `CommandRouter`。

浏览器侧数据流固定如下：

`Side Panel / UI -> SgClawProcessHost -> STDIO Pipe -> sgclaw`

`sgclaw -> STDIO Pipe -> PipeListener -> MacWhitelistCheck -> CommandRouter -> response`

---

## 3. 浏览器团队负责的交付物

本周期交付以下文件或等价模块：

1. `sgclaw_process_host.h`
2. `sgclaw_process_host.cc`
3. `pipe_listener.h`
4. `pipe_listener.cc`
5. `mac_whitelist_check.h`
6. `mac_whitelist_check.cc`
7. `rules.json`
8. `sgclaw_unittests` 中对应单元测试

建议目录：

```text
chrome/browser/superrpa/sgclaw/
  sgclaw_process_host.h
  sgclaw_process_host.cc
  pipe_listener.h
  pipe_listener.cc
  mac_whitelist_check.h
  mac_whitelist_check.cc
  test/
    sgclaw_process_host_unittest.cc
    pipe_listener_unittest.cc
    mac_whitelist_check_unittest.cc
  resources/
    rules.json
```

---

## 4. 冻结接口

### 4.1 传输协议

1. 传输层固定为 `STDIO Pipe`。
2. 编码固定为 `UTF-8`。
3. 消息边界固定为 `JSON Line`，每行一条完整 JSON。
4. 单条消息最大 `1 MB`。
5. `stdout` 只允许输出协议消息，日志必须走 `stderr`。

### 4.2 握手协议

浏览器发送：

```json
{"type":"init","version":"1.0","hmac_seed":"0123456789abcdef","capabilities":["browser_action"]}
```

sgClaw 返回：

```json
{"type":"init_ack","version":"1.0","agent_id":"uuid-v4","supported_actions":["click","type","navigate","getText","getHtml","waitForSelector","pageScreenshot","select","scrollTo","getAomSnapshot","storageSet","storageGet","zombieSpawn","zombieKill"]}
```

约束：

1. 浏览器必须在子进程启动后 `5s` 内发送 `init`。
2. `5s` 内收不到 `init_ack`，判定启动失败。
3. `version` 不一致，必须立即终止会话。

### 4.3 command 消息格式

```json
{
  "type":"command",
  "seq":12,
  "action":"click",
  "params":{"selector":"#submit","wait_after":300},
  "security":{
    "expected_domain":"oa.example.com",
    "hmac":"<hex>"
  }
}
```

字段要求：

1. `seq` 为正整数，必须唯一。
2. `action` 必须在白名单内。
3. `params` 必须是对象。
4. `security.expected_domain` 和 `security.hmac` 必须存在。

### 4.4 response 消息格式

成功：

```json
{
  "type":"response",
  "seq":12,
  "success":true,
  "data":{"text":"提交成功"},
  "aom_snapshot":[],
  "timing":{"queue_ms":2,"exec_ms":38}
}
```

失败：

```json
{
  "type":"response",
  "seq":12,
  "success":false,
  "data":{
    "error":{
      "code":"CMD_SELECTOR_NOT_FOUND",
      "message":"selector '#submit' not found"
    }
  },
  "aom_snapshot":[],
  "timing":{"queue_ms":1,"exec_ms":10}
}
```

约束：

1. 一个 `command.seq` 只能对应一个 `response.seq`。
2. 失败必须返回结构化错误，不允许只返回字符串。
3. `timing` 必须始终带上。

---

## 5. 本周期最小 Action 集

联调周期只强制四个动作：

1. `click`
2. `type`
3. `navigate`
4. `getText`

动作语义：

1. `click`
   调用现有点击能力，支持可选 `wait_after`。
2. `type`
   在目标输入框输入文本，支持 `clear_first`。
3. `navigate`
   导航到目标 URL。
4. `getText`
   获取目标节点文本。

其余 action 可保留接口但不进入本周期强制验收。

---

## 6. 浏览器侧实现要求

### 6.1 SgClawProcessHost

必须实现：

1. 单例，避免重复创建多个 `sgclaw` 子进程。
2. `Start()` 创建匿名管道并启动子进程。
3. `Stop()` 正常关闭并在超时后强制结束。
4. `OnProcessCrash()` 记录错误并更新状态。
5. 状态机至少包含 `Idle -> Starting -> Running -> Stopped / Crashed`。

建议接口：

```cpp
class SgClawProcessHost {
 public:
  bool Start();
  void Stop();
  bool IsRunning() const;
  bool SendLine(std::string json_line);
};
```

### 6.2 PipeListener

必须实现：

1. 持续读取 `stdout`。
2. 以换行符切分 `JSON Line`。
3. 拒绝空行、非 JSON、超过 1MB 的消息。
4. 能按 `seq` 追踪一次请求的完整生命周期。
5. 管道断开时通知 `SgClawProcessHost`。

### 6.3 CommandRouter 对接

必须实现：

1. `command.action` 到现有浏览器命令的映射表。
2. 尽量复用现有 `CommandRouter`。
3. 不允许在 Pipe 层直接写新的页面控制逻辑。
4. response 必须从实际执行结果构造，不允许伪造成功。

建议映射：

1. `click -> CommandRouter.click`
2. `type -> CommandRouter.type`
3. `navigate -> CommandRouter.navigate`
4. `getText -> CommandRouter.getText`

### 6.4 MacWhitelistCheck

必须实现：

1. action 白名单校验。
2. expected_domain 与当前页面域名比对。
3. `rules.json` 加载失败时默认拒绝。
4. 拒绝时返回统一错误码。

建议错误码：

1. `MAC_ACTION_NOT_ALLOWED`
2. `MAC_DOMAIN_NOT_ALLOWED`
3. `MAC_RULES_LOAD_FAILED`
4. `PIPE_INVALID_JSON`
5. `PIPE_MESSAGE_TOO_LARGE`

---

## 7. 浏览器团队开发顺序

### Day 1-2

1. 完成 `SgClawProcessHost` 骨架。
2. 用 dummy 子进程验证启动和退出。
3. 打通 `stdin/stdout` 读写通道。

验收：

1. 能启动 `echo` 或测试进程。
2. 能发送一行字符串并收到回写。

### Day 3-4

1. 完成 `PipeListener`。
2. 完成 `init -> init_ack` 握手。
3. 建立 `command` / `response` 解析结构。

验收：

1. 能与 Rust 侧互发 JSON Line。
2. 能处理 `seq` 对应关系。

### Day 5-6

1. 接入 `CommandRouter`。
2. 完成 4 个最小 action。
3. 完成 `MacWhitelistCheck`。

验收：

1. Rust 发起 `click/type/navigate/getText` 时浏览器真实执行。
2. 非白名单域名被拒绝。

### Day 7

1. 完成浏览器侧单元测试。
2. 提供联调分支和运行说明。
3. 预留半天与项目团队联调。

---

## 8. 浏览器团队自测清单

- [ ] `Start()` 成功启动真实 `sgclaw` 二进制。
- [ ] `Start()` 重复调用不会启动多个实例。
- [ ] `Stop()` 能正常关闭进程。
- [ ] `init -> init_ack` 成功。
- [ ] 超过 1MB 的 JSON 消息会被拒绝。
- [ ] 非 JSON 行会被拒绝。
- [ ] `click/type/navigate/getText` 能成功返回。
- [ ] 域名不匹配时返回 `MAC_DOMAIN_NOT_ALLOWED`。
- [ ] `rules.json` 缺失时默认拒绝。
- [ ] 日志中能按 `seq` 查到请求和响应。

---

## 9. 联调输入输出样例

### 9.1 手动握手

浏览器发：

```json
{"type":"init","version":"1.0","hmac_seed":"00112233445566778899aabbccddeeff","capabilities":["browser_action"]}
```

期待 Rust 回：

```json
{"type":"init_ack","version":"1.0","agent_id":"00000000-0000-0000-0000-000000000000","supported_actions":["click","type","navigate","getText","getHtml","waitForSelector","pageScreenshot","select","scrollTo","getAomSnapshot","storageSet","storageGet","zombieSpawn","zombieKill"]}
```

### 9.2 最小 click 联调

Rust 发：

```json
{"type":"command","seq":1,"action":"click","params":{"selector":"#login-btn"},"security":{"expected_domain":"oa.example.com","hmac":"<hex>"}}
```

浏览器回：

```json
{"type":"response","seq":1,"success":true,"data":{},"aom_snapshot":[],"timing":{"queue_ms":1,"exec_ms":35}}
```

---

## 10. 联调日必须提供的东西

浏览器团队在联调前必须准备：

1. 可运行的浏览器分支。
2. `sgclaw` 子进程启动入口。
3. `rules.json` 默认测试配置。
4. 最小测试页面，至少包含一个输入框、一个按钮、一个文本节点。
5. 一份 action 到 `CommandRouter` 的映射表。
6. 一份错误码表。

---

## 11. 周期结束验收标准

以下全部满足，浏览器团队本周期完成：

1. 能在浏览器中稳定启动和停止 `sgclaw`。
2. `init -> init_ack` 成功率 100%。
3. `click/type/navigate/getText` 联调通过。
4. 所有失败场景均返回结构化错误。
5. 域名和 action 白名单生效。
6. 与项目团队在同一测试页完成一次端到端演示。

---

## 12. 依赖与协作方式

浏览器团队只依赖以下冻结输入：

1. Pipe 协议版本：`1.0`
2. 消息结构：`init / init_ack / command / response`
3. 最小 action：`click/type/navigate/getText`
4. 安全字段：`expected_domain`、`hmac`

除以上四项外，本周期内其他细节不应阻塞浏览器侧开发。

