diff --git a/doc/staffdeck/JOB_SPEC.md b/doc/staffdeck/JOB_SPEC.md index 0bbdfe7..d190c8d 100644 --- a/doc/staffdeck/JOB_SPEC.md +++ b/doc/staffdeck/JOB_SPEC.md @@ -116,15 +116,23 @@ ## 4. 工作流(SOP) +> 详细规则与闸门见 `doc/staffdeck/KNOWLEDGE_BASE.md` §5(操作纪律)、§6(开跑前状态检查)、§7(执行中状态判据)、§8(SOP 全流程)。本节只给岗位层概览。 + +**五阶段**: ``` -接收指令 - → 澄清(目标 App / 目标动作 / 哪台设备 / 时长,缺失就问) - → 选设备(de_list_devices,排除 busy/offline) - → 预检(de_foreground_app + de_screenshot 确认当前状态) - → 执行(拆小步;L1 写操作,每步截图验证) - → 判定(成功 / 失败原因 / 需人工确认) - → 汇报(看板摘要 §2 + 证据) - → 收尾(如需还原:de_stop_app / 返回上一页;不强制改变设备状态) +P0 接收与澄清 → P1 选设备与预检(含"屏幕是否点亮/解锁") → P2 到达起点 + → P3 主流程:观察-行动-验证(OAV)循环 → P4 收尾与还原 → P5 汇报 +``` + +- **P0**:澄清目标 App/动作/设备/时长/成功标准;缺失且影响执行就先问;L2/L3 停下要授权。 +- **P1**:`de_list_devices` 选在线空闲设备;`de_screenshot` 确认**亮屏且非锁屏**(黑屏先 `de_wake`);`de_foreground_app` 确认前台;确认起点页特征与坐标基线。 +- **P2**:`de_open_app` 或 `back` 到起点;起点特征文本出现才算到位。 +- **P3**:每拍"观察(`de_screenshot`) → 决策(单步) → 行动 → 验证";定位优先 `de_tap_text` > `de_ui_tree`+`de_tap_element` > `de_tap`(坐标兜底);**每步要有推进证据**。 +- **P4**:`de_stop_app`/`back` 把设备留在明确状态;不做非任务要求的破坏性操作。 +- **P5**:按 JOB_SPEC §2 看板摘要 + §3.5 证据口径汇报。 + +**卡住即停**:同坐标无变化禁止重复点;连续 2 步无变化换策略;**连续 6 步无进展停止并汇报**。 +**注意设备/运行时特性**:观察类工具(截图/UI树)若被你的平台做幂等重放(`idempotent_replay`),会拿到过期画面 → 必须确保每次观察是新结果(见 KNOWLEDGE_BASE §7.4)。 ``` --- diff --git a/doc/staffdeck/KNOWLEDGE_BASE.md b/doc/staffdeck/KNOWLEDGE_BASE.md index 8959d03..207d011 100644 --- a/doc/staffdeck/KNOWLEDGE_BASE.md +++ b/doc/staffdeck/KNOWLEDGE_BASE.md @@ -1,151 +1,251 @@ -# 知识库 · 设备自动化平台(auto_control)接入说明 +# 知识库 · 设备自动化平台(auto_control)接入与操作手册 > 读者:StaffDeck 数字员工(外部 Agent)。 -> 目的:让你知道**能做什么、怎么调、什么不能做**,从而安全地代为操作手机设备。 -> 版本:2026-09-10 | 权威工具清单以 `doc/MCP.md` 为准,配置以 `mcp_server/config.py` 为准。 +> 目标:让你达到**与平台内置 AI 控制台同等**的操作水平——不是"能调工具",而是"会看、会判断、会收尾"。 +> 版本:2026-09-10 | 工具清单权威版:`doc/MCP.md`|配置权威版:`mcp_server/config.py` --- -## 1. 这个平台是什么 +## 0. 快速开始(30 秒版) -一台**安卓设备自动化中台**:管理一批手机(网络 `IP:5555` 或 USB 串号),支持定时任务、步骤编排、看屏/操作,以及本知识库要用的 **MCP 工具**。 +``` +1) de_list_devices → 选一台 online 且 worker_status 非 running/connecting 的设备 +2) de_screenshot(serial) → 看当前屏;若画面黑/锁屏 → de_wake 后重截(见 §6、§7) +3) 判断当前页 → 不对就 de_open_app(package) 或 de_press_key(back) 回到起点 +4) 循环体:观察 → 操作 → 验证(见 §8) + - 优先 de_tap_text(文字);有歧义用 de_ui_tree + de_tap_element;纯图形才 de_tap(坐标) + - 每次关键操作后再 de_screenshot 验证是否生效 +5) 连续 6 步无进展 → 停止并如实汇报(不要空转、不要臆测成功) +``` -- 平台本体:Web 服务(默认 `http://:18050`),提供任务/分组/设备/看板等管理能力。 -- 你能用的入口:**MCP Server(推荐)**,它把平台已有的设备能力封装成 19 个工具。 +--- + +## 1. 平台与能力边界 + +安卓设备自动化中台:管理一批手机(网络 `IP:5555` / USB 串号),支持任务调度、步骤编排、看屏与操作。 + +- 你能用的入口:**MCP Server**(推荐,19 个 `de_*` 工具);备选 REST(§2.2)。 +- **可做**:看屏、截图、UI 树、OCR、开/关 App、点击、滑动、按键、输入、剪贴板、亮/熄屏、看前台包名、列应用、只读看平台任务。 +- **不可做**:创建/修改/启停平台任务、分组/设备池/备份管理(MCP 未提供)。 --- ## 2. 接入方式 ### 2.1 首选:MCP(HTTP / streamable) -- 地址:`http://:8033/mcp`(FastMCP,`transport="http"`)。 -- 调用方式:支持 MCP 的客户端直接连;工具名即 `de_*`(见 §3)。 -- **鉴权现状**:MCP 层**无独立鉴权**——它自身用 `MCP_PLATFORM_USER/PASS` 登录平台(会话 + CSRF 由服务端内部处理,你不用管)。因此**谁能访问 8033 谁就能操控设备**,务必只在内网/Tailscale 内暴露,不要裸露公网。 -- **审计**:每次调用(含只读)都会写一行 JSON 审计(工具、serial、参数摘要、结果)。 +- 地址:`http://:8033/mcp`。 +- **鉴权现状**:MCP 层**无独立鉴权**(服务端内部用平台账号登录),**谁能连 8033 谁就能操控设备** → 只走内网/Tailscale,不要公网裸露。 +- **审计**:每次调用(含只读)写一行 JSON。 ### 2.2 备选:平台 REST(`http://:18050`) -仅在你不支持 MCP 时使用。认证是「表单登录 → 会话 Cookie + `X-CSRF-Token`」,无 API Token,接入成本较高。常用端点见 §9。 +认证 = 表单登录 → 会话 Cookie + `X-CSRF-Token`。无 API Token。端点见 `doc/API.md`。 -### 2.3 服务端配置(由部署方设置,你只需知道含义) - -| 变量 | 默认 | 含义 / 对你的影响 | +### 2.3 服务端配置(部署方设置,你只需知道含义) +| 变量 | 默认 | 对你的影响 | |---|---|---| -| `MCP_HTTP_HOST` / `MCP_HTTP_PORT` | `0.0.0.0` / `8033` | 监听地址与端口 | -| `MCP_ALLOW_WRITE` | `0`(**只读**) | `1` 才允许点按/滑动/输入等**写操作**;为 0 时写工具返回 `write_disabled` | -| `MCP_ALLOWED_SERIALS` | 空 | 逗号分隔设备白名单;非空时只允许这些 serial。**注意:为空时当前代码只校验 serial 非空,并不自动限平台设备池**——如需收紧请让部署方配置白名单 | -| `MCP_PLATFORM_URL` | `http://127.0.0.1:18050` | 平台地址 | -| `MCP_PLATFORM_USER` / `_PASS` | `admin` / 空 | 服务端登录平台用,与你无关 | -| `MCP_PLATFORM_TIMEOUT` | `30` | 平台请求超时(秒) | -| `MCP_SCREENSHOT_WIDTH` / `MCP_JPEG_QUALITY` | `540` / `70` | 截图缩放宽/JPEG 质量(见坐标约定) | -| `MCP_AUDIT_FILE` | `/var/log/mcp/audit.log` | 审计文件路径 | - -启动(部署方操作,供排障参考): -- 220 生产容器:`scripts/start.sh` 会自动后台拉起(`MCP_ENABLED=0` 可关)。 -- 本机/手工:`MCP_ALLOW_WRITE=1 MCP_PLATFORM_USER=admin MCP_PLATFORM_PASS=<密码> python -m mcp_server.mcp_server` +| `MCP_ALLOW_WRITE` | `0` | `0` 时写工具全返回 `write_disabled`(只能看不能动) | +| `MCP_ALLOWED_SERIALS` | 空 | 非空=白名单;**为空时不自动限设备池**(仅校验非空) | +| `MCP_HTTP_HOST` / `MCP_HTTP_PORT` | `0.0.0.0` / `8033` | 监听 | +| `MCP_SCREENSHOT_WIDTH` / `MCP_JPEG_QUALITY` | `540` / `70` | 截图尺寸/质量 | +| `MCP_PLATFORM_TIMEOUT` | `30` | 平台请求超时 | +| `MCP_AUDIT_FILE` | `/var/log/mcp/audit.log` | 审计文件 | --- -## 3. 工具清单(19 个 `de_*`) +## 3. 工具清单(19 个) -### 只读(观测,不触发设备占用锁;任务运行中也安全) -| 工具 | 入参 | 返回要点 | 用途 | -|---|---|---|---| -| `de_list_devices()` | — | `[{serial, model, online, worker_status, foreground_app}]` | 先看有哪些设备可用 | -| `de_screenshot(serial)` | serial | `{image(JPEG base64), width, height, native_size, screen_state}` | 看当前屏(**必须**先截图才能坐标点按) | -| `de_ui_tree(serial, limit=150)` | serial, limit | `{count, elements:[{text,id,desc,class,clickable,bounds}]}` | 拿可点击元素(**优先用它定位**) | -| `de_ocr(serial)` | serial | `{count, texts:[{text,score}]}` | UI 树里没有的渲染文字(WebView/图片) | -| `de_foreground_app(serial)` | serial | `{foreground_app: pkg}` | 当前前台 App | -| `de_list_apps(serial, keyword?)` | serial, keyword | `{count, packages:[pkg]}` | 找包名(配合 `de_open_app`) | -| `de_read_clipboard(serial)` | serial | `{clipboard}` | 读剪贴板 | -| `de_list_tasks()` | — | 平台任务计划列表 | 只读了解平台任务(**不能增改**) | +**只读(不触发占用锁)**:`de_list_devices` · `de_screenshot` · `de_ui_tree` · `de_ocr` · `de_foreground_app` · `de_list_apps` · `de_read_clipboard` · `de_list_tasks` -### 写操作(会先检查设备是否被任务占用;`MCP_ALLOW_WRITE=1` 才可用) -| 工具 | 入参 | 说明 | -|---|---|---| -| `de_tap_text(serial, text)` | serial, text | **首选**语义点击:按屏上文字找并点(UI 树→OCR 兜底);找不到返回 `text_not_found` | -| `de_tap_element(serial, by, value, index=1)` | by=`text/id/desc/text_contains/desc_contains`, value, index | 元素定位点击(配合 `de_ui_tree`) | -| `de_tap(serial, x, y)` | serial, x, y | 坐标点击(截图坐标系,自动吸附到最近可点元素;返回 `snapped`/`label`) | -| `de_swipe(serial, x1,y1,x2,y2, duration?)` | 坐标 | 滑动 | -| `de_press_key(serial, key)` | key=`back/home/enter/menu/recent/delete` | 按键 | -| `de_type_text(serial, text)` | serial, text | 输入文字(中文/引号/换行可用) | -| `de_set_clipboard(serial, text)` | serial, text | 写剪贴板 | -| `de_open_app(serial, package)` | serial, package | 冷启动 App(adb monkey) | -| `de_stop_app(serial, package)` | serial, package | 强制结束 App | -| `de_wake(serial)` / `de_sleep(serial)` | serial | 亮屏解锁 / 息屏(走平台 `/api/device/screen_all`) | +**写(受占用锁约束)**:`de_tap_text` · `de_tap_element` · `de_tap` · `de_swipe` · `de_press_key` · `de_type_text` · `de_set_clipboard` · `de_open_app` · `de_stop_app` · `de_wake` · `de_sleep` -> 平台级工具(**任务创建/修改/启停、分组、设备池管理、备份等**)**目前没有 MCP 工具**,只有上面这些设备能力;需要它们时请通过 REST(§9)或在平台 Web 后台操作。 +参数与返回详见 `doc/MCP.md`。 --- -## 4. 通用调用约定 +## 4. 通用约定 -### 4.1 设备标识 `serial` -- 网络设备:`IP:5555`(如 `100.100.10.13:5555`、`192.168.20.206:5555`)。 -- USB 设备:纯串号(无冒号,如 `ZY322XXXX`)。 -- 用 `de_list_devices()` 获取当前可用清单,**不要凭空猜 serial**。 +### 4.1 serial +- 网络 `IP:5555`(如 `100.100.10.13:5555`);USB 纯串号(如 `ZY322XXXX`)。 +- **用 `de_list_devices` 取,别猜。** ### 4.2 坐标空间(重要) -- `de_screenshot` 返回的是**缩放图(≤540px 宽)+ `native_size`(原生分辨率)**。 -- `de_tap` / `de_swipe` 的坐标用**截图坐标系(display 空间)**,服务端按最近一次截图比例换算原生。 -- **必须先 `de_screenshot` 再坐标操作**,否则报「请先执行 de_screenshot」。 -- 屏幕可能旋转/滚动,坐标随时会变——**优先文字/元素定位,坐标仅兜底**。 +- `de_screenshot` 返回**缩放图(≤540px 宽)+ `native_size`**;`de_tap`/`de_swipe` 用**截图坐标系**,服务端换算原生。 +- **必须先截图再坐标操作**;否则报「请先执行 de_screenshot」。 +- 屏可能旋转/滚动 → **优先文字/元素,坐标仅兜底**。 -### 4.3 设备占用锁(busy) -- 写工具执行前会检查该设备是否有平台任务在跑:`running`/`connecting` → 返回 **`device_busy`**(“AI 不与任务抢设备”)。此时**换设备或等待**,不要硬重试。 -- 只读工具(截图/UI树/OCR/列表)不受此限制。 +### 4.3 占用锁(busy) +- 写工具执行前查设备任务状态:`running`/`connecting` → **`device_busy`**(不与任务抢设备)。换设备或等待,别硬试。 +- 只读工具不受限(任务运行中也能安全截图)。 ### 4.4 错误码 | 错误 | 含义 | 应对 | |---|---|---| -| `write_disabled` | 服务端未开写门控 | 告知部署方开 `MCP_ALLOW_WRITE=1` | -| `device_busy` | 设备正被任务占用 | 换设备 / 等任务结束 | +| `write_disabled` | 写门控关闭 | 上报部署方 | +| `device_busy` | 设备被任务占用 | 换设备/等待 | | `device_offline` | 设备不可达 | 换设备;报运维 | -| `device_not_allowed` | 不在白名单 | 换设备;让部署方加白名单 | -| `text_not_found` | 屏上没有该文字 | 截图确认;改用 `de_ui_tree`/`de_ocr` | -| `platform_unavailable` | 平台不可达 | 稍后重试;报运维 | +| `device_not_allowed` | 不在白名单 | 换设备;加白名单 | +| `text_not_found` | 屏上无该文字 | 重截图/`de_ui_tree`/`de_ocr` 复核 | +| `platform_unavailable` | 平台不可达 | 稍后重试 | | `invalid_param` | 参数不合法 | 修参数 | --- -## 5. 推荐操作模式(务必遵守,能显著提高成功率) +## 5. 操作纪律(**与平台内置 AI 控制台等价**,务必遵守) -1. **文字语义点击优先**:`de_tap_text("关注")` > `de_ui_tree` 找元素 + `de_tap_element` > `de_tap` 坐标兜底。 -2. **每关键步后截图验证**:操作是否生效看截图/UI 树,别连续盲点。 -3. **不重复同坐标**:点击后画面无变化,禁止反复点同一坐标(多数 App 会误触)。 -4. **先确认前台与页面**:`de_foreground_app` / 截图确认在正确页面再操作。 -5. **一次一个明确目标**:拆成小步,每步可验证。 +> 这是平台内置 Agent 的系统规范,逐条对齐即可达到同等效果。 -### 常见配方 -- **看视频养号(示意)**:`de_list_devices` → 选设备 → `de_open_app(pkg)` → 循环〔`de_screenshot` 确认在视频页 → 等待 → `de_swipe` 上滑〕→ 结束 `de_stop_app`。 -- **打开指定 App**:`de_list_apps(keyword)` 拿包名 → `de_open_app(package)` → 截图确认首页。 -- **输入文字**:`de_tap_text` 或 `de_tap_element` 点输入框 → `de_type_text` → 截图确认。 -- **巡检截图**:`de_screenshot` + `de_foreground_app` + `de_ocr`,只读汇报。 +1. **先看设备**:`de_list_devices` 确定目标设备(在线才可操作)。 +2. **先看屏**:任何决策前 `de_screenshot` 理解当前界面(图会给你)。 +3. **点击优先级**(不要自己推算像素坐标——精度最差): + a) 有可见文字(按钮/菜单/标题/标签/输入框提示)→ **`de_tap_text`** 一步"找到并点"(原生与 WebView/图片文字都支持); + b) 文字有歧义或未命中 → **`de_ui_tree(limit=80)`** 看可点元素 → **`de_tap_element`**(`text`/`text_contains`); + c) 只有纯图形(视频/无文字图标且树里没有)→ 才 **`de_tap`** 给坐标(**大致对准中心即可,服务端自动吸附**)。 +4. **验证点击**:`de_tap` 返回 `snapped=true` 表示已吸附命中(可核对 `label`);**截图有变化=成功,无变化=未命中**。 +5. **输入文字**:先 `de_tap_text`/`de_tap` 点中输入框 → 再 `de_type_text`。 +6. **每关键步后再截图验证**,直到完成目标。 +7. **无变化不重复点**:同坐标点完没变化,**禁止再点同一位置**;换 `de_tap_text`/`de_tap_element`,或先 `de_ui_tree` 核对文案。 +8. **如实汇报**:做了什么、当前状态、注意事项;失败就说失败,**不臆测成功**。 +9. **效率**:界面没变就别重复截图/点击;每步都要推进目标。 +10. **收敛**:**连续 6 步无进展**(截图内容未变/操作无效)→ 停止并总结原因。 --- -## 6. 红线与安全(**不可违反**) +## 6. 开跑前状态检查清单(Pre-flight,逐项过) -1. **绝不 `adb kill-server`、绝不 `adb disconnect`**(会断开所有设备共享的 adb 通道,影响全部运行中任务)。你也不需要这些操作。 -2. **不抢任务设备**:遇到 `device_busy` 就避开。 -3. **写操作前先确认**:不确定后果的操作(发送评论/私信、删除、支付类)**不要执行**,先截图回报请人工确认。 -4. **不做破坏性动作**:卸载应用、清除数据、改系统设置等一律不做。 -5. **留痕**:你的每次调用都进审计,请让动作与目标一致。 -6. **隐私**:不要把设备上读到的个人信息/凭据复述或外传。 +| # | 检查 | 怎么做 | 通过条件 | 不通过怎么办 | +|---|---|---|---|---| +| 1 | 设备在线且空闲 | `de_list_devices` | `online=true` 且 `worker_status` 非 running/connecting | 换设备;全忙则上报 | +| 2 | **屏幕是否点亮/解锁** | `de_screenshot` 看 `screen_state` 与画面 | 亮屏且非锁屏界面 | **`de_wake`**(亮屏解锁)→ 重新 `de_screenshot` | +| 3 | 是否能看清画面 | 截图 | 非纯黑/非"正在加载"白屏 | 黑屏→`de_wake`;白屏→等 2~3s 重截 | +| 4 | 前台 App 是否正确 | `de_foreground_app` | 是目标 App(或桌面,准备开) | `de_open_app(package)` 或 `de_press_key(back)` 回退 | +| 5 | 是否在起点页 | `de_ui_tree`/截图 | 元素文案符合"首页/入口"预期 | 逐级 `de_press_key(back)` 或重开 App | +| 6 | 有无拦截弹窗 | 截图/`de_ui_tree` | 无权限/更新/广告弹窗 | 找"取消/关闭/允许(按需)/以后再说"文字点掉,或 `back` | +| 7 | 坐标基线 | 记下最近一次截图 | 本轮坐标操作前**必须有一次新截图** | 补一次 `de_screenshot` | + +> **判断"屏幕有没有开启"的标准做法**:`de_screenshot` 的 `screen_state` + 画面是否可辨认。**黑屏/息屏一律先 `de_wake`**,再重新截图确认;**不要在未确认亮屏的情况下点按/滑动**。 --- -## 7. 当前边界(别越界期待) +## 7. 执行中的状态判据与规则 -- MCP **没有任务创建/修改/启停**(只有只读 `de_list_tasks`)。 -- MCP **无独立鉴权**(靠网络隔离),不要假设有 token。 -- `MCP_ALLOWED_SERIALS` 为空时**不会**自动限制为平台设备池(设计语义未实现)。 -- 平台 REST 的 CSRF 校验在当前版本可能未强制(按端点契约使用即可)。 +### 7.1 屏幕与锁屏 +- 息屏/黑屏 → `de_wake` → 重截确认;长任务中途可能再次息屏,**每轮循环先确认一次**。 +- 锁屏界面(有锁/时间/上滑提示)→ `de_wake` 解锁后重截;仍锁 → 上报(可能需要人工)。 +- 需要保持常亮时:没有专门工具,可在长流程中周期性 `de_wake` 兜底。 + +### 7.2 页面判据(怎么算"到位了") +| 目标 | 判据(以 `de_ui_tree`/截图文字为准) | 未达成的处置 | +|---|---|---| +| 已到 App 首页 | 出现底部导航/搜索框等首页特征文本 | `back` 一次或重开 App | +| 已到视频页 | 出现点赞/评论/分享等交互图标或全屏画面 | 等待/滑一次再看 | +| 已到目标详情 | 目标条目标题文本可见 | 继续上滑查找(有上限,见 §10) | +| 输入框已聚焦 | 出现键盘/光标或输入法界面 | 重新点输入框 | +| 弹窗已处理 | 弹窗文本消失 | 换"取消/关闭/以后再说"再点 | + +### 7.3 加载与抖动 +- "正在加载/白屏/骨架屏" → 等 2~3s 重截,**不要连续狂点**。 +- 连续两次截图完全一致且不符预期 → 视为**卡住**,走 §8.3。 + +### 7.4 幂等重放(**注意你的运行时特性**) +- 若你的平台会对"相同参数的工具调用"做**幂等重放/去重缓存**(如返回 `idempotent_replay`): + **观察类工具**(`de_screenshot`/`de_ui_tree`/`de_ocr`/`de_foreground_app`)**必须每次拿到新结果**,否则你会基于**过期画面**决策(表现为"屏幕没变/点不动")。 + - 处置:请让编排方**对观察类工具关闭去重**;或在参数/调用上确保不被判定为重复。 + - 兜底:用 `de_ui_tree`(文本随页面变化)作为"状态是否变化"的佐证;`de_screenshot` 用于确认视觉。 --- -## 8. 相关文档 +## 8. SOP(标准作业流程) -- 工具手册(逐工具参数/返回/示例):`doc/MCP.md` -- MCP 设计/分层与现状对照:`doc/MCP_DESIGN.md` -- 平台接口目录:`doc/API.md` -- AI 生成任务(规划,未实现):`doc/AI_TASK_GEN.md` +### 8.0 总体:五个阶段 + 一个循环 +``` +P0 接收与澄清 → P1 选设备与预检(§6) → P2 到达起点 → P3 主流程(观察-行动-验证循环) → P4 收尾与还原 → P5 汇报 + └──────────── 循环体 ────────────┘ +``` + +### P0 接收与澄清 +- **输入**:用户指令(自然语言)。 +- **必查**:目标 App?要做什么动作?哪台设备(或指定)?时长/次数?成功标准是什么? +- **闸门**:任一缺失且影响执行 → **先问,不猜**。 +- **拒绝项**:L2/L3 级操作(见 §11)→ 停下要授权。 + +### P1 选设备与预检 +- 动作:跑完 §6 的 7 项。 +- **闸门**:设备在线 + 空闲 + **亮屏可达** + 前台/起点已就位。任一不过 → 按 §6 处置;仍不过 → 上报。 +- 产出:记下 `serial`、起点页特征、最近一次截图基线。 + +### P2 到达起点 +- 动作:`de_open_app`(冷启动到首页)→ `de_screenshot`/`de_ui_tree` 确认;或 `back` 逐级回退。 +- **闸门**:起点特征文本出现(§7.2)。 +- 失败:重开 App 一次;仍不行 → 上报(App 异常/未安装:`de_list_apps` 核对包名)。 + +### P3 主流程 —— 观察-行动-验证(OAV 三拍循环) +每一拍都按下面的节奏,**不许跳步**: +1. **观察**:`de_screenshot`(必要时 `de_ui_tree`)→ 用一句话说清"现在在哪、看到什么"。 +2. **决策**:选定下一步**唯一**动作(按 §5 的定位优先级)。 +3. **行动**:执行单个工具调用。 +4. **验证**:再观察一次 → 变化符合预期?→ 是:进入下一拍;否:见 §8.3。 +- **闸门**:每拍结束必须"状态有推进"的证据(文字/画面变化)。 +- **边界**:只在目标 App 内活动,不跳出到系统设置等无关界面(除非任务要求)。 + +### 8.3 卡住判定(重要) +| 情形 | 判定 | 处置 | +|---|---|---| +| 同坐标点击无变化 | 未命中 | **禁止重复点**;换 `de_tap_text`/`de_tap_element`,或先 `de_ui_tree` 看文案 | +| 连续 2 步无变化 | 策略无效 | 换定位方式 / 检查是否在正确页面 | +| **连续 6 步无进展** | 卡死 | **停止**,汇报"卡在哪、试过什么、可能原因" | +| `device_busy`/`device_offline` | 设备不可用 | 换设备;无可用则中止汇报 | + +### P4 收尾与还原 +- 动作:`de_stop_app`(结束 App)或 `back` 回到桌面;确认设备状态(亮/熄屏按需)。 +- **闸门**:设备处于明确的已知状态(不留在中间页/输入框)。 +- 注意:**不做**非任务要求的破坏性/不可逆操作。 + +### P5 汇报(固定口径) +``` +【设备操作员 · 汇报】 +设备: | 目标:<一句话> +过程:<关键 3~5 步:做了什么 → 是否生效> +结果:✅完成 / ⚠️部分完成 / ❌失败(原因) +证据:<关键步骤截图/元素文本> +遗留:<需人工处理 / 未做的高危步骤 / 设备状态> +``` + +--- + +## 9. 常见异常与处置(速查) + +| 现象 | 可能原因 | 处置 | +|---|---|---| +| 截图全黑/息屏 | 屏幕关闭 | `de_wake` → 重截 | +| 停在锁屏 | 未解锁 | `de_wake`;仍锁 → 上报 | +| 停在启动页/闪屏 | App 未就绪 | 等 2~3s 重截;不行重开 | +| 权限/更新弹窗遮挡 | 系统弹窗 | 点"取消/关闭/以后再说";`back` | +| 点不动、画面不变 | 未命中/被遮挡/图是旧的 | 换定位方式;核对截图是否新鲜(§7.4) | +| `text_not_found` | 文字不在当前屏 | 重截、`de_ocr`、滑一屏再找 | +| `device_busy` | 设备跑任务 | 换设备/等待 | +| 一直加载 | 网络/内容未就绪 | 等待重截,勿狂点 | + +--- + +## 10. 效率与预算 +- 每步必须推进目标;界面未变不重复截图/点击(但**每拍开始时需要一次新鲜观察**)。 +- 找不到目标时:滑动查找设上限(建议 ≤ 5 屏),超出即停止汇报。 +- 连续 6 步无进展 → 停止(§8.3)。 +- 不要为"确认"而反复截图同一画面(除非上一拍是写操作,需要验证)。 + +--- + +## 11. 安全红线(不可违反) +1. **绝不 `adb kill-server` / `adb disconnect`**。 +2. **不抢任务设备**(`device_busy` 就避开)。 +3. **L2 敏感写**(发评论/私信、关注取关、发布、下单支付、改资料)→ **默认不做**,先截图请人工确认。 +4. **L3 破坏性**(卸载/清数据/改系统设置/恢复出厂/删文件)→ **一律不做**。 +5. **不泄露**设备上的个人信息与凭据;不外传截图。 +6. **不绕过**写门控/白名单/审计。 + +--- + +## 12. 当前边界与相关文档 +- MCP 无任务 CRUD、无独立鉴权(靠网络隔离)。 +- `doc/MCP.md`(工具手册)|`doc/MCP_DESIGN.md`(设计与现状对照)|`doc/API.md`(REST 目录) +- 岗位职责与授权分级:`doc/staffdeck/JOB_SPEC.md`