# 可靠 Click 協議 (Reliable Click Protocol)
**定位:** 瀏覽器自動化的 ≈ 80% 問題都是 **click 沒中** 或 **誤判狀態**。這份檔案是把 OiiOii demo 裡踩到的所有坑整合成可重複使用的 SOP。每個網站都套得上。
**核心原則:** 每個 irreversible action (click 生成按鈕、送出表單、確認付費) 都要 **先驗證 → 再執行 → 後驗證**。不要相信你以為的狀態,要相信 screenshot。
---
## Part 1 — Click 決策樹 (Decision Tree)
遇到「我需要點一個元素」時,依這個順序:
```
1. 是否有確定性連結 (href)?
├── 是 → 直接 navigate (最可靠,一步到位)
└── 否 → 2
2. 是否有穩定 accessibility tree?
├── 是 (find 能穩定找到 + ref 短期有效)
│ └── find → 立刻 left_click ref (中間不插螢幕截圖)
└── 否 → 3
3. 是否能用座標?
├── screenshot → 目視定位元素中心 (x, y)
│ → left_click coordinate → screenshot 驗證
└── 坐標打不中 → 4
4. Fallback 連鎖:
a. hover (x, y) 確認 cursor 在元素上 → left_click
b. 改用 scroll_to ref 先把元素捲到 viewport 中心 → 再 click
c. 用 keyboard Tab 跳到元素 → Enter
d. 若都失敗 → **停下來問使用者** (不要亂戳)
```
---
## Part 2 — ref (accessibility reference) 的正確用法
### ref 的特性
- `find` / `read_page` 回傳的 `ref_N` 是 **該次查詢的短期快照**
- 多數網站 ref 有效 30 秒~幾分鐘;**React / Vue / tldraw 等動態渲染站** (如 OiiOii) ref 可能 **下一秒就失效**
- ref 失效的訊號:`"No element found with reference: 'ref_N'. The element may have been removed from the page."`
### ref 使用 SOP
**✅ 對:**
```
find "送出按鈕" → ref_42
left_click ref_42 # 立刻點
```
**❌ 錯:**
```
find "送出按鈕" → ref_42
screenshot # ← 這一步可能讓頁面 re-render,ref_42 失效
zoom ... # ← 這一步也會
left_click ref_42 # 💥 "Element may have been removed"
```
### 原則
- **find → click** 中間 **不插螢幕截圖/zoom/read_page 以外的動作**
- 如果需要先看才能決定 click 哪個 → 用 screenshot 決定後 **用座標**,不要先 find 再拖延
- 如果一定要 read_page 拿結構 → read_page 回來後立刻 click,**不 screenshot 再 click**
---
## Part 3 — 座標 click 的精準技巧
### 座標系統
`computer.left_click coordinate=[x, y]` 使用的是 **viewport 座標**,而 screenshot 回傳常見 1568×751 或 1568×708。**多數環境中座標 ≈ screenshot 像素座標** (不需要手動 1920/1568 縮放)。實測:OiiOii 在 1568×708 的 (290, 410) 打中「中文」按鈕。
### 定位精度提升
**❌ 粗暴取中心:**
```
看起來按鈕在 (190, 205) → click (190, 205) # 可能打到邊緣或 padding
```
**✅ 先 zoom 看清 hit area:**
```
zoom region=[x0, y0, x1, y1] # 把按鈕放大
# zoomed image 顯示:按鈕視覺範圍 y 175-230,中心 y=203
# 按鈕實際可能有 4px 內距,實際 hit area 是 y 179-226
# 安全 click 在正中 y=203,x 同理
```
### 按鈕 hit area 經驗值
| 按鈕視覺大小 | 安全 click 區 |
|---|---|
| 40×40 px 小圖示 | 取視覺中心,誤差容忍 ±3 px |
| 100×40 px 文字按鈕 | 取中心,誤差 ±5 px |
| 大 CTA (400×50 px) | 中心 ±10 px 都 OK,但**避開按鈕邊界 5 px** |
| 卡片整塊可點 | 取卡片中心,不要點在卡片內文字上 |
### click 失敗的診斷
若 click 沒反應,**先排查這三件事再重點**:
| 症狀 | 原因 | 對策 |
|---|---|---|
| 點了毫無反應、UI 沒變化 | 座標在 padding 或透明 overlay | zoom 看實際 hit area,往中心挪 |
| 出現紅色錯誤 toast (如「選項暫不支援重選」) | 這個 action 已經送出過 | 不要再點,UI 已在下一階段 |
| 按鈕視覺變粉框但送不出 | 這是 selected state,不是 activated | 找真正的「送出/確認」按鈕再點 |
| 出現 paywall / modal 遮罩 | 有彈窗擋在按鈕上 | 先處理彈窗 (關閉或互動),再回來 |
| 頁面在滾動中 | 元素位置漂移 | 先 `wait 1 秒` 或滾到停,再取 screenshot → click |
---
## Part 4 — 驗證狀態:Selected vs Hover vs Active
OiiOii demo 的關鍵誤判:**把 hover ring 當成 selected**,導致誤以為 click 沒中。
### 視覺狀態辨識
| 狀態 | 常見視覺 |
|---|---|
| **Unselected / default** | 淡色背景、默認邊框 |
| **Hover (focus ring)** | **粉色 / 亮色外圈 ring**,但背景還是默認色 |
| **Selected / committed** | **填底色變深** (或變 brand 色),邊框也可能變色 |
| **Disabled** | 灰化 + 降透明度 |
| **Active (正在點擊)** | 短暫的按下陰影,1 幀 |
### 驗證選中的 SOP
click 後 **必做**:
```
1. screenshot (或 zoom 該按鈕區域)
2. 看填底色是否變深 / 變 brand 色
3. 若填底沒變 → click 沒中 → 回 Part 3 重試
4. 若填底有變、但下一步 UI 沒出現 → 正常的「agent 背後處理」,等 60-90s 再看
```
### Selected 的其他信號
- 按鈕旁/底部出現「小型確認泡泡」(OiiOii 的粉色氣泡) — 這是系統訊息,強指標
- Checklist 項目加 ✓ (綠勾)
- 右下/左下 toast 提示「已送出」「信息已確認」
- URL 改變 (跳到 `/space/xxx` 之類)
---
## Part 5 — Scroll-aware 座標 (對抗漂移)
### 漂移現象
長對話或動態 panel 裡,同一個按鈕的 (x, y) 會因 scroll 位置變化。實測 OiiOii 的「滿意」按鈕 y 在 385 → 573 → 428 之間來回漂。
### 對策
**Rule of thumb:每次要 click 按鈕,前 5 秒內必須有 screenshot 驗證該按鈕的當前 y 座標。**
```
BAD:
screenshot -> see button at y=428
scroll down 10 ticks
click (290, 428) # ❌ y 已經變了,打到別處
GOOD:
scroll down 10 ticks
screenshot # 必須重照
see button at y=290 # 位置變了
click (290, 290) # ✓
```
### 避免漂移的招
- **不要在 panel 中隨便 scroll** — 只有在要看 above/below 的內容才 scroll
- **click 前不滾動** — 若一定要滾,滾完立刻 screenshot
- **固定位置按鈕**:有些按鈕是 sticky (如底部 submit bar),這類座標穩定
---
## Part 6 — 文字輸入的陷阱
### 輸入框類型判斷
| HTML 元素 | form_input 支援 | 對策 |
|---|---|---|
| `` / `