# 安卓原生动作验证记录 对应 [实现计划](2026-11-02-native-actions.md) 与 [能力说明](../android-native-actions.md)。主程序基于 2.5.0 的 main 开发,未改变主程序版本或第三方依赖;助手独立升级为 1.3.0 / protocol 3 / versionCode 15。 ## 已验证的基础能力 | 层次 | 实际验证 | 结果与边界 | | --- | --- | --- | | 默认确定性测试 | `uv run --no-sync pytest -q` | 3824 passed、2 skipped、8 deselected;299.20s;使用最终 Python 实现,未依赖设备或私有服务 | | 静态质量 | Ruff format/check、质量基线、核心 Pyright | 均通过;核心类型检查 0 错误、0 警告;未放宽质量基线 | | Java 状态机 | 编译生产 TouchGestures/GestureController,模拟 Android 回调 | 694 项通过;覆盖取消注册竞态、迟到回调、所有权及提前完成的静止段;不代替真实触摸交付 | | Java 窗口解析 | 编译生产 ControlWindowRoots/NativeControls,模拟窗口与节点 | 57 场景、361 项通过;涵盖真实选区工具栏形状、联合遮挡、区域空洞、旧 API、枚举失败、全局唯一与预算、取消及编辑后禁用 | | 独立原生 Activity | 生产 helper → driver → actuator,5 轮完整回归 | 321 项通过;包含范围设值、唯一/缺失/歧义选择、UTF-16 编辑/光标/IME、等待、双指缩放/旋转、连续停留,以及两轮容器内往返滚动 | | 真实设备取消 | 提前取消、重复取消、双指接触后取消 Python task、原始非法参数 | 30 项通过;仅一笔原手势及一笔取消;取得中断回执并释放,返回后 500ms 没有新增触点 | | 普通 Pro 只读 | `9430c6fd-966d-4f00-94c8-79b91be320ee` | passed;模型与最终 Checker 均收到真实 range、文本与选区回执 | | Flash 原生编辑 | `a3149abd-326b-40fd-99b9-816cf6a0299d` | passed;范围 42、emoji 选区替换、光标和一次 IME 提交由 APP 状态证明;保留一次错误包名查询的 NOT_FOUND | | 普通 Pro 连续触摸 | `0955486c-38b0-4eb9-9e41-bafaa4caaefe` | passed;三次真实首 MOVE−DOWN 为 280/266/266ms,UP−DOWN 为 760/752/757ms,工具 elapsed 为 763/755/771ms;每次一次 DOWN/UP、无 CANCEL、同一 pointer | 真实设备报告保存在本次本地 `artifacts/native-actions-fixture/` 下,未将 APK 夹具、设备输出或模型请求正文提交源码。主程序分发所需的既有助手 APK 与 manifest 同步更新;其 SHA256 为 `544c38d5c135518fe6796aa4e03f804e87342687125a383ff3244952c8160d1f`。 ## 失败样本与修正 - 旧助手中,中间静止路径的 Android callback 会提前完成:750ms 计划曾实际约 509ms,不能按回调成功视为时长正确。现在按 uptime 保持该段的最早结束时间,再续接下一段;真实 APP 事件及三次正式 Pro 任务均验证了修正。 - 原生滚动仅表示接受动画,200ms 后继续滚动曾产生错误的 NO_PROGRESS。现在等待容器和目标状态连续停稳;目标超出容器签名的有界采样时,也独立跟踪目标可见性及身份,避免短暂进入视口就成功。 - 一次编辑框位置异步变化使新读 token 与派发时 token 不符,返回 STALE_TARGET / not_started,未输入。夹具改为在后续编辑前显式等待该控件稳定,没有放宽 token 或隐式重发,随后 5 轮全部通过。 - 多窗口写入检查最初把任何高层窗口交叠都当作遮挡,真实选区工具栏及手柄只遮住编辑框边缘,也会错误阻止选区替换。保留 code14 失败证据;改为扣除高层覆盖后仍须存在可见区域,不按包名或工具栏类名豁免,多个窗口共同完全遮挡仍拒绝。 - 窗口退出期间曾短暂返回 READ_FAILED,等待工具原先也立即退出。现在仅对 READ_FAILED/UNAVAILABLE 在原始截止时间内继续只读轮询,并重置稳定计时;失败不证明消失,歧义、非法参数等仍立即拒绝。新增确定性回归后,原生执行器 72 项通过;夹具编辑前后显式等待稳定,最终助手的 5 轮 321 项全部通过。 - 取消脚本最初把 IME 内部 mIsInputViewShown 当作屏幕键盘可见,错误阻塞测试。现在使用系统唯一 mInputShown 状态并保留窗口覆盖检查;失败报告保留。 - 早期夹具运行还保留了坐标空间拼写、UTF-8 解码、已有焦点不再支持 focus,以及键盘遮挡导致 APP 未收到触摸的样本。参数拒绝、Android 输入完成和 APP 接收分别判定,没有将这些运行记为完整通过。 ## Checker 证据规则 原历史任务 `4794dc4b-8164-4996-b489-2a2899bb4078` 保持原来的 inconclusive,未改写历史。使用完整 final prompt、真实 `run_final_check`、当前配置的 `gpt-6.1-terra / medium` 与完整报告解析器,独立验证: - 真实暂停状态中,绑定当前选时的常驻 17:41:59 读数、重复停稳观测及粗指针一致:两次均 passed。 - 五个离线候选反例:事件卡片、水印、短暂浮层、读数/指针真实冲突、缺少稳定或暂停证据,均 inconclusive;理由明确引用各自缺口。 - 资格集 7 次均单请求、无传输重试,保存实际请求/服务端 ID、原始完整输出及解析结果,system prompt 字节完全一致。 两次正例复用同一历史暂停状态,五类反例为离线候选,不能冒充设备定位成功率。审计不完整的首组记录及候选作用域不充分的反例也保留,共 19 次实际模型运行;仅上述 7 次计入资格集。 ## 目标 APP 实测 探索 `a51b55d8-46da-436e-a5f1-7288e3b9a6a0` 已通过。当前摄像头监控回看时间轴没有暴露原生 range/actions,不能用 set_progress 直接设置秒数;播放按钮和常驻选时则有独立节点。 - 小跨度 120→160px:工具完成,但实际刻度未见可辨变化,未计作 APP 缩放成功。 - 同一区域 100→400px:10 分钟刻度约 120–122→211px,实际约放大 1.73–1.76 倍;说明需要读取 APP 刻度,不能把手指跨度倍数直接当作比例尺。 - 日期面板选择 17:00 可到目标小时,但会自动播放;通过实际播放按钮转为三角形后确认暂停。 Flash 的三次独立缩放与精确定位验收全部 passed: | 独立任务 | 目标 | 暂停后稳定读数 | 误差 | | --- | --- | --- | --- | | `af8c38b7-6a6b-435a-86da-6820c3843242` | 17:42:00 | 17:41:57 | −3s | | `ca5a5cb9-351f-4639-940e-41880af95766` | 17:43:00 | 17:42:57 | −3s | | `7d809bff-a529-4174-8cc7-d5494cb2a267` | 17:42:00 | 17:42:01 | +1s | 每次均有真实刻度变化、常驻选时与固定指针一致、三角形暂停状态及至少 1 秒后的独立稳定观测。三次都在 ±5s 内,不代表所有设备或后续任意输入的保证。 收尾的无输入复验又发现多窗口问题:APP 的空壳窗口被 Android 标为 active,而完整播放器在同包上层窗口;观察接口看得见的日期与播放按钮,在只搜索 active 的原生接口中返回 NOT_FOUND。已修复为有界前台窗口解析、跨根全局唯一以及每次写入前的精确区域遮挡检查;枚举不完整明确失败,旧系统保留已说明的矩形近似。修复前后的只读证据均保留,最终 code15 的夹具与取消回归已通过。 最终普通 Flash 任务 `54115cf7-4332-41fe-8c25-3daef8a82a18` passed:修正到暂停 17:42:00 后,在同一 action_sequence 原生 click→等待 1000ms→原生 click,两次均完成,selected 依次 false→true→false。常驻选时推进至 17:42:01,约 6.9 秒后独立截图仍为同一读数与三角形暂停状态。收尾再次从原生接口读取日期、播放节点与前台包名,确认保持此状态,仅卸载本次独立夹具,未清空或停止用户 APP。 ## 验证环境与范围 本机 Python 3.14.0;Android 模拟器上实际执行。助手以 JDK 21.0.8、Android SDK/build-tools 36 构建,Java 8 目标。未把本次单一设备结果外推到所有 Android/OEM;多段/多指手势最低 API 26,工具仍按助手实际能力声明启用。 未进行主程序发版或最终 ZIP 的空 npm 缓存安装构建;本次没有前端输入或第三方锁文件改动。正式发版仍须单独通过仓库发布门槛。