Files
actionbook__actionbook/.docs/cli-devflow.md

192 lines
6.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Actionbook CLI — 标准功能开发工作流
> 源自 snapshot transform (PR #348) 和 cursor detection (PR #353) 的实践总结。
>
> **SPEC**: [`packages/cli-v2/docs/api-reference.md`](../packages/cli-v2/docs/api-reference.md) — 所有命令的 JSON/Text 输出合约、参数定义、错误码均以此为准。
---
分支, 基于 release/1.0.0 , 合并也是到这个
## Phase 0: 分析对齐
- 读 PRD / SPEC(`packages/cli-v2/docs/api-reference.md`)确认合约
- 对比参考实现(agent-browser / actionbook-cli-rs)分析差异、优劣: 代码在
- agent-browser: /Users/junliangfeng/Documents/code/next/thirds/browser-cli/agent-browser
- actionbook-cli-rs /Users/junliangfeng/Documents/code/next/thirds/browser-cli/actionbook-cli-rs
- 和用户确认方案,输出简洁 plan
- **输出**: 明确的修改文件列表 + 关键设计决策
## Phase 1: 写测试(TDD)
- **E2E 测试**(`tests/e2e/snapshot.rs`):基于 SPEC 定义端到端行为
- JSON 信封结构
- Text 输出格式
- Error path(SESSION_NOT_FOUND, TAB_NOT_FOUND 等)
- Flag 组合(--interactive --compact, --cursor 等)
- **UT 合约测试**(`src/browser/observation/snapshot_transform.rs`):
- 定义核心函数的输入 → 输出契约
- 当前实现应 **fail**(TDD red phase)
### 断言三原则
1. **验证值,不只验证类型** — `context.url` 包含目标 domain,不只是 `is_string()`
2. **严格白名单** — `data` keys 精确匹配 spec(`format`, `content`, `nodes`, `stats`),禁止多余字段
3. **否定基线** — 无 flag 时无 ref → 有 flag 时有 ref,形成对照组
### 验收标准
- 编译通过
- 合约测试预期失败,非合约测试全部通过
## Phase 2: 测试 review
```
code-reviewer agent (基于 /code-review:code-review) ← 审查逻辑正确性、覆盖度、convention,对抗性审查,找 edge case、弱断言、合约漏洞
```
### 重点检查
- Fixture 是否真的测了目标逻辑(不是碰巧通过)
- Edge case 覆盖(空输入、重复、组合 flag、已有 ARIA role 重叠)
- 断言强度(`assert_eq` 比内容,不只比 `len()`)
### 输出
- 修复所有发现直到测试合约正确
- 合约测试仍然 fail(red phase)
## Phase 3: 实现
实现代码使所有测试通过。
### 验收标准
```bash
cargo fmt -- --check # 格式
cargo clippy --all-targets -- -D warnings # lint(注意 --all-targets 包括测试)
cargo test --lib # 所有 UT 通过
```
## Phase 4: 双 Review agent 实现
并行启动两个 reviewer
- claude code: 基于 /code-review:code-review
- code cli: 启动做技术 review。
### 典型问题类型
| 类型 | 示例 |
|------|------|
| Filter 顺序 | `--interactive --cursor` 组合丢节点 |
| Error path 清理 | DOM 属性未在错误路径清理 |
| Silent failure | `.ok()` 吞掉错误无提示 |
| 死代码 | 函数存在但从未调用 |
| 安全 | 名字未转义导致树注入 |
### 输出
- 修复所有发现
- 67+ UT 全通过,clippy clean
## Phase 5: 真实浏览器验证
**UT 无法替代此步骤。**
```bash
cargo build --release
# 杀旧 daemon
kill $(ps aux | grep 'actionbook __daemon' | grep -v grep | awk '{print $2}')
# 启新 daemon + 测试
./target/release/actionbook browser start --headless --open-url https://example.com --json
./target/release/actionbook browser snapshot --session <SID> --tab <TID> --json | jq
./target/release/actionbook browser snapshot --session <SID> --tab <TID> # text 模式
```
### 对比验证
- 和 agent-browser 对比同一页面输出
- 检查:StaticText 是否保留、refs 是否 e1-based、url/title 是否正确
### 发现的 Bug → 立即补测试
每个在浏览器验证中发现的 bug,必须:
1. 修复代码
2. 添加对应 E2E/UT 测试(防止回归)
3. 反思为什么之前的测试没抓到
## Phase 6: PR → CI → Review Comments
**语言要求**: PR title、body、review comment 回复一律使用英文。
```bash
git push -u origin <branch>
gh pr create --base release/1.0.0 --title "..." --body "..."
```
### CI 配置
- **PR**: 只跑 Lint + Unit Tests(快速反馈)
- **Merge 到 main/release**: 跑 Lint + Unit Tests + E2E(完整验证)
### PR Review Comments
提交 PR 后启动定时轮询,直到 CI 全绿 + review comments 全部处理:
```bash
# 定时检查 CI 状态 + review comments(每 2 分钟一次,直到全部解决)
while true; do
echo "=== CI Status ==="
gh pr checks <PR_NUMBER>
echo "=== Review Comments ==="
gh api repos/{owner}/{repo}/pulls/<PR_NUMBER>/comments \
--jq '.[] | "\(.id) [\(.user.login)] \(.path):\(.line // "N/A") — \(.body[:80])"'
echo "=== Pending Reviews ==="
gh pr view <PR_NUMBER> --json reviews \
--jq '.reviews[] | select(.state != "COMMENTED" and .state != "APPROVED") | "\(.author.login): \(.state)"'
sleep 120
done
```
处理流程:
1. **CI 失败** — 读日志定位原因 → 修复 → commit → push
2. **有新 review comment**:
- **修复的**: 修改代码 → commit → push → 在 comment 下回复修复内容和 commit hash
- **不修复的**: 在 comment 下回复原因(如"有意为之"、"不在本 PR 范围"等)
3. **每次 push 后重新等 CI** — 确认修复没有引入回归
4. **全部条件满足后合并**: CI 全绿 + review comments 全部回复 + 无 blocking review
---
## 核心原则
1. **测试先行,review 先于实现** — Phase 1-2 在 Phase 3 之前
2. **每个 bug 修复必须伴随测试** — 无测试的修复等于没修
3. **双 review 不可省略** — 两个独立视角互补,单一 review 覆盖率不足
4. **真实浏览器验证不可用 UT 替代** — CDP 行为、daemon 生命周期、格式化路径只有 E2E 能覆盖
---
## 教训记录
| 教训 | 来源 |
|------|------|
| `is_string()` 不够,要验证值 | snapshot url=chrome://newtab/ |
| data 要白名单,不能有多余字段 | __ctx_url 泄漏到 data |
| text formatter 要有对应分支 | snapshot text 无 body |
| RefCache::default() 和 ::new() 要一致 | ref 从 e0 开始 |
| TAB_NOT_FOUND context 要 null tab_id | E2E 测到 |
| interactive filter 和 cursor 的顺序 | codex challenge 发现 |
| DOM 属性清理要用 nonce | PR review comment |
| compact 顺序影响 depth gap | code-reviewer 发现 |
| 非默认 profile close 时删、默认 profile 保留 | codex-connector review comment |
| registry lock 内不做慢 I/O(cdp.close、child.wait) | codex challenge 发现 |
| kill_and_reap_option 要 take() 防 Drop 双杀 | codex challenge 发现 |