# Claw-WS 开发执行顺序卡片

> 配套计划：[`2026-04-01-claw-ws-parallel-transport.md`](./2026-04-01-claw-ws-parallel-transport.md)
>
> 使用方式：严格按卡片顺序执行。每张卡片完成后先跑卡片内测试，再进入下一张。不要跳卡，不要提前接线，不要先写 service/client 再回头抽象底层。

---

## 卡片 0：执行前约束

**目标**
先锁定边界，避免实现过程中把 pipe 模式改坏。

**必须遵守**
- 现有 pipe 模式必须保持可用
- 新增的是并行 `claw-ws` 模式，不是替换 pipe
- v1 只做单客户端、单任务串行
- `browser_action` / `superrpa_browser` 外部命名保持稳定
- 如果 WS `Eval` 不完整，先禁用相关 browser-script skill 暴露
- 不要提前做多客户端、任务队列、管理接口

**完成标准**
- 开发者明确后续所有改动都围绕“抽象复用 + 并行新增”进行

---

## 卡片 1：抽共享 SubmitTask Runner

**目标**
把当前 `BrowserMessage::SubmitTask` 的主执行逻辑从 pipe 入口里抽出来，变成共享执行器。

**先做什么**
1. 新增 `tests/task_runner_test.rs`
2. 先写失败用例：
   - 空 instruction
   - 无 LLM 配置
   - 日志顺序仍然是 `LogEntry` -> `TaskComplete`

**要改哪些文件**
- `src/agent/mod.rs`
- `src/lib.rs`
- `src/agent/task_runner.rs`
- `tests/task_runner_test.rs`

**实现动作**
1. 建 `SubmitTaskRequest`
2. 建 `AgentEventSink`
3. 建 `run_submit_task(...)`
4. 让 pipe 入口只做：
   - 解包 `BrowserMessage::SubmitTask`
   - 转成 `SubmitTaskRequest`
   - 调共享 runner

**绝对不要做**
- 不要在这一张卡里引入 ws backend
- 不要改 tool adapter
- 不要碰 service/client

**本卡测试命令**

```bash
cargo test --test runtime_task_flow_test --test task_runner_test
```

**通过标准**
- 老的 `runtime_task_flow_test` 继续绿
- 新的 `task_runner_test` 通过
- pipe 行为无变化

**完成后提交**

```bash
git commit -m "refactor: extract shared submit-task runner"
```

---

## 卡片 2：抽 BrowserBackend 抽象

**目标**
把上层 runtime / orchestration / tool adapter 从 `BrowserPipeTool<T>` 解耦，统一依赖浏览器后端接口。

**先做什么**
1. 新增 `tests/browser_backend_capability_test.rs`
2. 先写失败用例：
   - pipe backend 元数据不变
   - pipe backend 支持 `Eval`
   - `supports_eval() == false` 时不暴露 browser-script tools

**要改哪些文件**
- `src/browser/mod.rs`
- `src/browser/backend.rs`
- `src/browser/pipe_backend.rs`
- `src/compat/browser_tool_adapter.rs`
- `src/compat/browser_script_skill_tool.rs`
- `src/compat/runtime.rs`
- `src/compat/orchestration.rs`
- `src/compat/workflow_executor.rs`
- `src/lib.rs`
- `tests/browser_backend_capability_test.rs`

**实现动作**
1. 定义 `BrowserBackend`
2. 写 `pipe_backend` 包装当前 `BrowserPipeTool`
3. 把上层签名改成 `Arc<dyn BrowserBackend>`
4. 保持工具名不变：
   - `browser_action`
   - `superrpa_browser`
5. 增加 `supports_eval()` gating

**绝对不要做**
- 不要在这一张卡里接浏览器 ws 协议
- 不要建 service
- 不要加 client 协议

**本卡测试命令**

```bash
cargo test --test browser_tool_test --test compat_browser_tool_test --test browser_backend_capability_test
```

**通过标准**
- 现有 browser tool 相关测试不回归
- 新 capability test 通过
- 上层逻辑已脱离 `BrowserPipeTool<T>` 的硬耦合

**完成后提交**

```bash
git commit -m "refactor: abstract browser backend from pipe transport"
```

---

## 卡片 3：写死浏览器 WS 协议 Codec

**目标**
单独做浏览器固定 WebSocket 协议编解码层，不把协议细节散落到 backend 和 service 里。

**先做什么**
1. 新增 `tests/browser_ws_protocol_test.rs`
2. 先写失败用例：
   - outbound frame 精确编码
   - callback payload 解析
   - 异常格式拒绝
   - v1 action 覆盖完整

**要改哪些文件**
- `src/browser/ws_protocol.rs`
- `tests/browser_ws_protocol_test.rs`

**实现动作**
1. 按浏览器文档编码数组消息
2. 只支持 v1 必需动作：
   - `Navigate`
   - `GetText`
   - `Click`
   - `Type`
   - `Eval`
3. 定义 callback 解析和关联规则
4. 对 unsupported / malformed 早失败

**绝对不要做**
- 不要在这张卡里连真实浏览器
- 不要写 service 协议
- 不要把网络连接逻辑塞进 codec

**本卡测试命令**

```bash
cargo test --test browser_ws_protocol_test
```

**通过标准**
- codec 单测全绿
- 无网络依赖
- 已能作为 backend 的纯协议层基础

**完成后提交**

```bash
git commit -m "test: codify fixed browser websocket protocol"
```

---

## 卡片 4：实现 Browser WS Backend

**目标**
在 codec 之上提供和 pipe backend 类似的阻塞式 `invoke(...)` 能力。

**先做什么**
1. 新增 `tests/browser_ws_backend_test.rs`
2. 先写失败用例：
   - `0 + 无 callback` 成功
   - 非 `0` 失败
   - `0 + callback` 成功
   - callback timeout
   - socket drop

**要改哪些文件**
- `src/browser/mod.rs`
- `src/browser/ws_backend.rs`
- `tests/browser_ws_backend_test.rs`

**实现动作**
1. 建长连接管理器
2. 先做串行单飞请求
3. 发送前过 `MacPolicy`
4. 统一即时返回和 callback 返回
5. 输出统一 `CommandOutput`

**绝对不要做**
- 不要在这一张卡里接 service 层
- 不要做多并发 browser request
- 不要直接把浏览器 ws 代码散进 runtime

**本卡测试命令**

```bash
cargo test --test browser_ws_backend_test
```

**通过标准**
- backend 在 mocks/fakes 下稳定通过
- invoke 语义与 pipe backend 接近
- 可供上层 runtime 直接替换使用

**完成后提交**

```bash
git commit -m "feat: add browser websocket backend"
```

---

## 卡片 5：实现 sg_claw Service

**目标**
新增本地长驻服务端，承接 client 请求并复用共享 task runner。

**先做什么**
1. 新增 `tests/service_ws_session_test.rs`
2. 先写失败用例：
   - 首个客户端接入成功
   - 第二个客户端收到 busy
   - 断开后状态释放
   - 任务重入被拒绝

**要改哪些文件**
- `src/service/mod.rs`
- `src/service/protocol.rs`
- `src/service/server.rs`
- `src/bin/sg_claw.rs`
- `src/lib.rs`
- `Cargo.toml`
- `tests/service_ws_session_test.rs`

**实现动作**
1. 定义 client/service 协议
2. 实现 service 端事件 sink
3. 建单活 session 状态机：
   - `Idle`
   - `ClientAttached`
   - `TaskRunning`
4. 路由 `SubmitTask` 到共享 runner
5. 保持 pipe 入口不变

**绝对不要做**
- 不要在这一张卡里做 client 交互体验优化
- 不要加任务队列
- 不要支持多客户端并发

**本卡测试命令**

```bash
cargo test --test service_ws_session_test
```

**通过标准**
- 服务端会话锁生效
- 共享 runner 可被 service 复用
- pipe 模式入口未受影响

**完成后提交**

```bash
git commit -m "feat: add claw-ws service entrypoint"
```

---

## 卡片 6：实现 sg_claw_client

**目标**
新增一个薄客户端，提供类似 `claude/codex` 的交互式命令行体验。

**先做什么**
1. 新增 `tests/service_task_flow_test.rs`
2. 先写失败用例：
   - submit-task 送达 service
   - 日志按顺序流回
   - completion 只到一次
   - 完成后断开处理清晰

**要改哪些文件**
- `src/bin/sg_claw_client.rs`
- `Cargo.toml`
- `tests/service_task_flow_test.rs`

**实现动作**
1. 建立到本地 service 的 ws 连接
2. 读取用户输入
3. 发送 `SubmitTask`
4. 实时打印日志
5. 收到 `TaskComplete` 结束本轮

**绝对不要做**
- 不要把 runtime、skills、browser backend 复制进 client
- 不要让 client 直接连浏览器
- 不要让 client 承担业务逻辑

**本卡测试命令**

```bash
cargo test --test service_task_flow_test
cargo build --bin sg_claw --bin sg_claw_client
```

**通过标准**
- client 是薄壳
- task flow 正常
- 两个新 binary 可编译

**完成后提交**

```bash
git commit -m "feat: add interactive claw-ws client"
```

---

## 卡片 7：最终接线与回归验证

**目标**
把 ws 路径接起来，同时确认 pipe 路径零回归。

**先做什么**
1. 只增加最小配置项：
   - `browser_ws_url`
   - `service_ws_listen_addr`
2. 检查外部工具命名保持稳定

**要改哪些文件**
- `Cargo.toml`
- `src/lib.rs`
- `src/config/settings.rs`
- `src/runtime/engine.rs`（如确有必要）

**实现动作**
1. 接入最小配置面
2. 确保 pipe / ws 下工具命名一致
3. 跑旧 pipe 回归
4. 跑新 ws 测试
5. 跑全量 Rust tests
6. 编译所有 binary
7. 做一次真实本地 smoke test

**本卡 pipe 回归命令**

```bash
cargo test --test browser_tool_test --test compat_browser_tool_test --test runtime_task_flow_test --test pipe_handshake_test --test pipe_protocol_test --test task_protocol_test
```

**本卡 ws 测试命令**

```bash
cargo test --test task_runner_test --test browser_ws_protocol_test --test browser_ws_backend_test --test browser_backend_capability_test --test service_ws_session_test --test service_task_flow_test
```

**本卡全量命令**

```bash
cargo test --tests
cargo build --bin sgclaw --bin sg_claw --bin sg_claw_client
```

**手工验证**
1. 启动浏览器，确认 `ws://127.0.0.1:12345` 可用
2. `cargo run --bin sg_claw`
3. 新终端运行 `cargo run --bin sg_claw_client`
4. 发一个简单浏览器任务
5. 确认日志流和单次 completion
6. 确认旧 `cargo run` pipe 入口仍可启动

**通过标准**
- pipe 模式零回归
- ws 模式可独立工作
- 两套模式并行存在

**完成后提交**

```bash
git commit -m "feat: wire parallel claw-ws transport"
```

---

## 一句话执行顺序

严格按下面顺序做：

1. 共享 runner
2. browser backend 抽象
3. ws 协议 codec
4. ws backend
5. service
6. client
7. 配置接线 + 回归

如果顺序乱了，最容易出现的问题是：
- 上层重复实现
- pipe 被误伤
- ws 协议细节扩散到整个工程
- service/client 提前写完后又被迫重构
