Skip to content

Latest commit

 

History

History
130 lines (128 loc) · 39.6 KB

regression-cases.md

File metadata and controls

130 lines (128 loc) · 39.6 KB

必须覆盖的回归用例

#1~#34 来自 toolkit 和本项目早期实际踩过的坑,#35~#45 是多设备和 HID 横屏,#46~#58 是实时画面、开发者工具和英文界面,#59~#63 是 iPhone 18 Pro Max(iOS 27.2.1)真机全量测试发现的问题,#64 起是 viewer 的 AI 任务和新页面,#116~#122 是任务的控制权、控制台的局域网访问与登录、跨主机,#123 起是 0.2.4 发版前回归中发现的。能单测的写单测,不能单测的进真机回归清单。每个 PR 都必须保持这里的全部用例通过:单测的由 cargo test 覆盖;改到的范围里测试方式是真机、无头 Chrome 或手动测量的,要重跑并在 PR 里列出编号,写明设备和 iOS 版本;修了清单里没有的问题,要加一行。完整要求见 CONTRIBUTING.md 的 Required tests。

# 坑 正确行为 测试方式
1 锁屏密码键盘不显示时,Key 元素仍留在元素树里(visible=false) 不以"树里有键盘"判断键盘已出现;固定先唤醒再上滑 单测(脱敏 XML 样本)+ 真机
2 displayed 接口在锁屏上返回 false,即使键盘可见 以密码栏「已输入 N 位」为准 真机
3 锁屏界面 Face ID 动画使 WDA 每请求等 idle 至 10 秒,键盘随后自动收起 解锁期间 waitForIdleTimeout=1、animationCoolOffTimeout=0.2,结束恢复;0 会导致唤醒失败 真机
4 多位密码合成一个 W3C 手势会漏键 每位单独一个手势并逐位核对 真机
5 锁屏上 /wda/tap 每次约 2.9 秒 解锁用 W3C 单手势(约 0.7 秒) 真机计时
6 同名「设置」有 5 个 SBAppTags 含 hidden 的后台服务 按名字解析 App 时跳过 hidden 单测
7 容器无 udev,手机重启/重插后 usbmuxd 看不到设备 不再适用:2026-11-10 起不发布 Docker,守护进程不再自管 usbmuxd,热插拔由系统的 usbmuxd 和 udev 处理(D5、D14) —
8 手机重启后 XCTest 弹「Enable UI Automation」密码框 识别错误、只推送一次、每次等 25 秒、5 秒后重试、恢复后再推送 单测(错误识别)+ 真机
9 plumesign 不签 .xctest,WDA 报 XCTest 103 .xctest 签名、无 entitlements 单测(签完检查 _CodeSignature)+ 真机
10 ios forward 监听所有网卡,WDA 无认证,局域网可直接控制手机 默认不监听任何端口;bridge 只绑 127.0.0.1 集成测试(检查监听地址)
11 依赖大版本漂移(mcp 2.x 把 FastMCP 改名、idevice 0.1.x 每版破坏性变更) 所有依赖锁定精确版本 + Cargo.lock 入库;升级单独提交 CI
12 host 侧 runner 退出后手机上残留 WDA 仍响应几十秒 就绪 = 本进程 XCTest 会话存活 且 /status ready 真机
13 App 冷启动后立即点击会被吞 launch_app 等到前台再停 1 秒 真机
14 完整元素树 7~8 秒 excluded_attributes 排除可见性等属性(约 0.3 秒),可见性按坐标判断 单测 + 计时
15 铺满全屏的 Application/Window/Toolbar 等元素没有定位价值 列表中过滤 单测
16 区域放大倍数只保留 2 位有效数字导致边缘约 1.4 点误差 保留 3 位 单测
17 只有 ToolError 的消息能透传给 MCP 客户端(Python SDK) 所有预期错误都转成工具错误文本 单测
18 锁屏(未首次解锁)时隧道报 PasswordProtected 进入 NeedsUnlock,提示人工 真机
19 Apple ID 会话过期只在重签时才发现 每日独立验证会话 单测(模拟过期)
20 WDA 在锁屏时启动,/wda/locked 一直报 false(只靠变化通知维护,初值 false) 本次 WDA 启动后确认过一次未锁屏之前,用元素树核对(锁图标 proud-lock / passcode-view) 单测(iOS 27 真机样本)+ 真机
21 下拉通知中心时 /wda/locked 报 true WDA 说锁了时核对元素树:只有 lockscreen-date-view、没有锁图标的是通知中心 单测(真机样本)+ 真机
22 iOS 27 上锁屏密码键盘有残留输入时,按 Home 不清空(键隐藏但仍可按) 用右下角删除键逐位删到 0(按位置认,不依赖语言),每删一位核对 单测(真机样本 + 假锁屏)+ 真机
23 熄屏锁屏时第一个无障碍查询等约 8 秒;锁屏 0.5 秒内唤醒,第一下上滑卡约 16 秒后报 point.x != INFINITY 能自动解锁时先按 Home 再核对;本进程锁屏后 3 秒内不解锁;唤醒/上滑报错算这轮落空重来 单测 + 真机计时
24 HID 会话的屏幕媒体流没正常停止时,手机端一直挂着:灵动岛「配对的电脑」图标常驻、不自动锁屏,进程退出和拔插都清不掉 HID 空闲 30 秒关闭;所有丢弃路径(含退出)先停流;WDA 锁屏报错时确认已锁就不退到 HID 真机
25 自动解锁第 2 位之后出错(点击报错、核对锁屏报错、进程被杀)会跳过写停用标记,下次可能把同一个错误密码再输一遍 输第 2 位之前先写停用标记,只有确认解开或确认没凑满整串才撤掉;出错返回 UnlockError::Uncertain 并推送通知 单测(ictl-unlock:error_after_second_digit_keeps_auto_unlock_disabled、double_press_that_fills_the_entry_disables、dropped_last_digit_is_not_a_wrong_attempt)
26 最后一位输完后用 WDA 的锁屏状态确认结果:WDA 在锁屏时启动会报 false,把输错当成解开 确认时用严格判断 WdaClient::check_lock(_, strict = true):核对出错一律算仍锁着 单测(stale_wda_lock_state_cannot_turn_a_wrong_entry_into_unlocked)
27 HID 会话在屏幕媒体流起来之后才失败,媒体流没停(症状同 #24) HidSession::open、media::start 出错时先停流;HID 会话归 Tunnel 所有,关隧道必先停流 真机
28 一个长操作(启动 WDA 等自动化密码最长 120 秒)挡住所有工具、status 和 SIGTERM,排队的点击几分钟后才执行 启动 WDA、重签、会话检查不持设备锁;status 读快照;改变手机状态的请求排队超过 30 秒就放弃;停止信号优先处理(architecture §2 并发模型) 真机
29 WDA 请求超时或中途断开后退到 HID,同一个动作做了两遍 传输层区分连不上(WdaError::Unavailable,可以退到 HID)和请求已发出之后的超时、断开、响应不完整(不退,报错让 agent 先截图确认) 单测 + 代码审查
30 设置文件里留空的 ICTL_LOG= 生成一个什么都不放行的过滤器,日志全没了 空值当作没设 真机(看守护进程的输出)
31 /wda/tap 每次先等界面空闲:主屏点图标约 1.7 秒(调小等待设置也没用);W3C actions 手势做完又要等动画冷却(默认 2 秒),App 里切标签约 1.9 秒 点击用单个 actions 手势,期间临时把 waitForIdleTimeout/animationCoolOffTimeout 调成 1/0.2,做完恢复(原值只读一次)。真机:主屏点图标 1.70→0.91 秒(到前台 1.80→1.01 秒),App 里 0.62→0.72 秒 单测(请求顺序、恢复原值)+ 真机计时
32 /wda/keys 没有输入框获得焦点时也返回成功,什么都没输(真机:Safari 地址栏没点中、主屏上直接输入) 输入前查屏幕上有没有软键盘(XCUIElementTypeKeyboard,约 0.2 秒),没有就报错让先点输入框 真机
33 系统弹窗(定位、通知权限)挡着时 Home 不生效、App 到不了前台,WDA 照样报成功;弹窗属于 SpringBoard,看前台 App 发现不了 按 Home 前查 /alert/text(App 静止时约 0.4 秒;按下后动画中查要好几秒);有弹窗就说明并不按。launch_app 没到前台时同样带上弹窗文字。按 Home 后等主屏到前台再返回 真机计时;弹窗路径待弹窗再出现时复测
34 /wda/touchAndHold 前后都等界面空闲:主屏长按图标 1.2 秒要约 12 秒 长按和点击一样用单个 actions 手势、临时调小等待:约 2 秒 真机计时
35 接着多台时,devices / iphone_list_devices 漏设备或标错正在控制的那台 列出 USB 上每一台的名字、型号、iOS 版本、UDID,标出正在控制哪台、有没有设自动解锁密码 真机(两台)
36 按 usbmuxd 的列表顺序选设备,列表顺序一变就换了台 选定了只认那一台,没接就是离线、不换;没选定时正在控制的那台一直用到它断开 单测(device_pick_is_pinned_or_sticky)+ 真机(拔掉选定的那台)
37 select 按名字选到了别的设备 先比 UDID,再比设备名,最后是名字包含这段文字且只有一台;对上多台就报错,让用 UDID 指定 单测(device_is_found_by_udid_then_name)
38 选定的设备重启守护进程后丢了;设了 IPHONE_UDID 还能切走 选定的写进 state.json;IPHONE_UDID 优先,设了就拒绝切到别的设备 真机(select 后重启;设 IPHONE_UDID 后 select 另一台)
39 切换后操作还落在上一台,或用了上一台的 App 列表、方向、屏幕尺寸 切换时拆掉上一台的会话,清掉 App 列表和方向;屏幕尺寸记录是别的设备的就不用。切换后等 iphone_status 就绪,截图、iphone_list_apps、点击都要作用在新设备上 真机(iPhone + iPad,各做一遍 iphone_select_device → 截图 → 点击)
40 一台的密码输进另一台 密码按设备存(secrets/passcodes/<UDID>);旧的 secrets/passcode 只在 USB 上只接着一台时归到那台,接着多台时不用 单测(passcode_file_is_per_device_and_stays_in_its_dir)+ 真机
41 已接着一台时再插一台,没有 udev 的 usbmuxd 认不到第二台 不再适用:同 #7,守护进程不再自管 usbmuxd —
42 自动选设备时 iphone_batch 执行到一半换了设备(拔线后换到另一台),剩下的步骤落到另一台上 控制的设备变了就停下报错 真机(batch 里放 wait,中途拔线)
43 Apple 键盘等配件被当成手机:doctor 误报 USB 上有设备(以前自管 usbmuxd 时还会被反复重启) 只算 iPhone/iPad/iPod(厂商号 05ac 且产品名匹配) 单测 + 真机
44 横屏时 WDA 掉线,HID 触摸按竖屏坐标换算,点错位置 每次 HID 触摸前重新截图核对横竖;横屏要有 30 秒内且匹配的 WDA 旋转角才发送,否则拒绝,不猜方向;截图和按键不受影响 单测(hid_rotation_requires_fresh_matching_landscape)+ 真机(iOS 27 横屏下让 WDA 掉线,点击落点正确;守护进程重启后横屏触摸被拒绝)
45 WDA 在横屏时就绪,记下的是横屏尺寸,之后 HID 换算错 state.json 只存竖放尺寸和对应的 UDID,换算时再按当前方向转 真机(iOS 27,横屏下启动 WDA,再让它掉线后点击)
46 浏览器里的其他网页向 viewer 发请求,借它操作手机 操作要求 Origin 是页面本身、内容类型是 JSON;Host 必须是回环地址 单测(actions_need_own_origin_and_json)
47 viewer 开着时 select 到别的设备,点击落到用户没在看的手机上 每个操作带启动时的 UDID,守护进程控制的不是这台就拒绝 单测(request_for_another_device_is_refused)+ 真机(viewer 开着时 select 另一台,再点击)
48 不需要开发者工具的 agent 多读工具说明,或没开时也能调用 开关关闭时工具列表还是 17 个,调用这些工具报错并说明要设 IPHONE_CONTROL_DEV_TOOLS=1 单测(工具列表:toolkit_tools_plus_wait_for_batch_and_devices);调用被拒:代码审查(call_tool 里的判断,还没有单测)
49 os_log 开着 Debug 时手机上每个进程都产生 Debug 消息(约 650 行/秒),手势变慢、失败 只要默认、Error、Fault 级别(约 80 行/秒) 真机(iphone_app_logs 采集时跑回归脚本默认步骤,和不采集时对比耗时)
50 日志采集的缓冲把内存撑大(全部进程,每秒几十行) 行数和总量都封顶(20,000 行、8 MB),单行截断,结果说明最早一行是多久前 单测(buffer_is_bounded_by_size)
51 每次调用重开 Web Inspector 连接:约 8 秒一次,几轮后手机不再报告 Safari,要重启 Safari 复用一条连接;只有连接层的错误才重开,页面超时或页面报错不断开 单测(only_a_page_timeout_keeps_the_connection)+ 真机(连续多次 iphone_web_targets、iphone_web_eval 都快且找得到页面;重启 Safari 后仍能找到)
52 iphone_web_eval 失败后换新连接重试,脚本执行两遍 只有列页面(不改手机状态)时才换连接重试,执行脚本不重试 代码审查(web_eval)
53 卸载 App 按模糊匹配,删错 App 连同数据;卸载 WDA 后无法再控制手机 只接受 Bundle ID 或完整显示名(不分大小写),空的、部分匹配、同名多个都拒绝并列出候选;拒绝卸载 WDA 单测(uninstall_needs_an_exact_name、wda_runner_cannot_be_uninstalled)
54 滚动条的标签随系统语言变化,只认中英文时其他语言的滚动条出现在元素列表里 按百分比的值和细长的形状认,不看标签 单测(scroll_bars_are_dropped_in_any_language)
55 升级时新旧版本混用:旧客户端按中文开头认结果,旧守护进程不带 outcome 不带语言的请求照旧回中文;outcome 可选,没有时按中文开头认 单测(outcome_is_optional_on_the_wire)
56 安装和重签同时进行:idevice 把每个 .ipa 上传到手机上同一个文件(PublicStaging/idevice.ipa),互相覆盖 安装(iphone_install_app、重签、sign)互相排队 真机(安装和重签同时进行,两个都成功)
57 iPhone 横屏时 viewer 画面还是竖的、内容是歪的,点击也错位 iPhone 上 WDA 每个会话开 mjpegFixOrientation,帧随界面转正 真机:Safari 转横屏,/stream 的帧是 2796×1290 且内容正立
58 持设备锁的调用不返回:之后的请求全部排队到过期,进程却还活着,服务管理器不会重启 完成巡检或请求时记心跳,约 10 分钟没有心跳就退出(watchdog.rs),巡检因为锁被占而跳过时不算 单测 a_beat_ends_the_silence
59 iPhone 18 Pro Max(iOS 27.2.1)上按住 0.5 秒的 IOHID 电源键没反应,每次锁屏都退到 WDA 的锁屏:约 10 秒,日志里还记一次超时 电源键按 0.1 秒(0.05~0.15 秒都约 0.7 秒锁屏) 单测(hid_buttons_send_consumer_page_events)+ 真机计时(锁屏约 0.9 秒)
60 IOHID 的 AC Home 在 iPhone 18 Pro Max(iOS 27.2.1)上基本不起作用,按住多久都一样;XCTest 的 home 在 iPhone 12 mini 上不起作用,正相反。只按固定顺序的话,前者每次 Home 都先白等 2 秒 按设备记住上次让主屏回到前台的按法,下次先用它;不起作用再换另一种,换成功了就改记 真机计时(iPhone 18 Pro Max:第一次约 3.7 秒,之后约 1.3 秒);iPhone 12 mini 待复测
61 点击、长按用 0.2 秒的动画冷却:界面上一直有动画时(键盘弹着)WDA 要约 26 秒才返回(同 NO_COOL_OFF 注释里滑动的情况) 点击、长按和滑动一样用冷却 0(IdleSettings::NO_COOL_OFF);解锁仍用 QUICK 单测(tap_is_one_gesture_with_quick_waits_then_restores_baseline)+ 真机计时(设置里搜索后点结果:26 秒 → 1.4 秒;主屏点图标、App 里切标签不变慢)
62 网页检查器没开时手机直接断开 Web Inspector 连接,工具只报一句 TLS 错误 连接被手机断开时提示打开 设置 → Safari → 高级 → 网页检查器 单测(a_closed_connection_points_at_the_web_inspector_setting)+ 真机(开关关着时调 iphone_web_targets)
63 不带调试消息的日志流里仍有 Info 级别的条目,和 iphone_app_logs 的说明不符 采集时丢掉 Info、Debug 单测(info_and_debug_entries_are_not_kept)+ 真机
64 Codex 对标了 destructiveHint 的 MCP 工具默认要审批,codex exec 非交互运行时直接拒绝(「requires approval, but approval policy is never」),点击、滑动全都做不了 给 iphone 这个 MCP 服务设 default_tools_approval_mode="approve",由 iphone_confirm 把关 真机(Codex 任务里点击、按名字点都执行了)
65 viewer 已经停了、任务已经停了,agent 的 MCP 服务还在继续操作手机 连不上守护进程或任务已结束一律拒绝,并告诉 agent 停下;开任务的程序断开,任务就结束(abandoned) 单测(without_the_daemon_a_task_call_is_refused、an_ended_or_unknown_token_is_refused_for_everything、an_opened_task_holds_the_phone_until_its_lease_goes)+ 真机(任务中途停止,之后没有新步骤,agent 进程组已结束)
66 暂停只挡住了界面上的按钮,agent 照样继续点 暂停、接管、等确认时,任务的请求在守护进程里挂住(包括一个工具调用中间的请求,如 iphone_batch 的下一步),恢复后才放行 单测(a_paused_task_holds_its_requests_until_resumed、a_held_request_whose_caller_left_is_dropped)+ 真机(暂停 8 秒没有新步骤)
67 用户接管时动过手机,交还后 agent 按旧的界面接着点 交还后、或别人动过手机后,任务的操作一直被拒,直到它截图或读过元素 单测(after_someone_else_acted_the_agent_looks_before_acting)+ 真机(交还后先截图)
68 用户拒绝确认后 agent 正常结束,页面显示「已完成」 有被拒绝的一步就按「已停止」结束 单测(a_rejected_confirmation_tells_the_agent_not_to_do_it)+ 真机(拒绝删除世界时钟城市,没有删)
69 按结果文字里的 @(x,y) 给所有步骤画点击标记,读元素的一步也被标成点击 只给 iphone_tap_element 的结果解析点击位置 单测(only_a_tap_by_text_gets_a_mark_from_its_result)
70 其他网站用 <img src="http://127.0.0.1:8200/api/elements"> 触发读元素,顺带自动解锁手机 浏览器标明 Sec-Fetch-Site 不是 same-origin / none 的读请求一律 403 单测(reads_from_other_sites_are_refused)+ curl
71 AI 任务执行中,用户在页面上点击和 agent 同时操作 没有接管时 viewer 拒绝手动操作(409 并说明),页面也锁住 真机(任务中 /api/tap 被拒,接管后按 Home 生效)
72 设计稿在 1024×768 下横向溢出 26px:中间栏各行按内容最小宽度把栏撑出窗口 中间栏各行 min-width: 0;两栏区间「设备面板」只留图标;状态标签先让出空间 Playwright:360×800 到 1920×1080 共 11 个视口横向溢出都是 0
73 viewer 的手动操作走 WDA:点击约 530 毫秒,滑动要等列表停下(1.8~3 秒),松开鼠标后才滑,画面不跟手 iOS 27 起经 HID 实时发按下、移动、松开(Request::Touch),移动只发最新位置;滚轮换成手指拖动 单测(page_actions_map_to_daemon_requests)+ 真机(iPhone 18 Pro Max / iOS 27.2.1:移动约 2 毫秒,点击约 20 毫秒;拖动、滚轮滚动设置列表,点击进入「通用」,按住 1 秒出主屏菜单)
74 每次 HID 触摸前截图核对方向(几百毫秒),实时移动跟不上 只在 down 时核对一次(有 WDA 时读它的旋转角),移动、抬起直接用已开的会话 真机计时
75 WDA 的 MJPEG 默认每秒 10 帧,画面比操作慢 每秒 60 帧、75% 尺寸(fast_stream);只在有客户端时采集 真机:约 48 fps、34 KB/帧,读元素树不变慢
76 viewer 页面只有中文 页面文字中英两套(tr()),默认跟着 IPHONE_CONTROL_LANG,可切换;请求带 X-Ictl-Lang,守护进程的提示和 AI 任务用同一种语言 单测(the_page_says_its_default_language)+ Playwright(英文页面除切换按钮和手机上的数据外没有中文;360×800 到 1920×1080 中英文都没有横向溢出)+ 真机(英文 AI 任务)
77 控制台画面每秒 4~10 MB,经隧道在外网看会卡 装了 ffmpeg 时改用 H.264(/video),显卡编码优先,约为 MJPEG 的 1/15 真机:设置里来回滚动,/video 约 250~430 KB/s,静止时为零
78 ffmpeg 扣住最新一帧,画面静止时最后一次变化一直出不来 每帧后面紧跟 K 份副本,K 在探测时测出 单测 encodes_with_the_local_ffmpeg;真机:每帧延迟 16 毫秒
79 裸 H.264 流要等下一帧开头才知道这一帧结束 ffmpeg 输出 FLV,每帧带长度 单测 tags_come_out_whole_however_the_bytes_arrive
80 链路慢时系统和 SSH 隧道的缓冲吞下几 MB,画面越来越滞后(每秒读 30 KB 落后 40 秒) 页面每 100 毫秒回报收到多少;落后时新画面先不编码,追上后只编最新的 单测 behind_means_late_beyond_the_usual_round_trip、no_more_on_the_way_than_the_link_carries_in_the_slack;手动 slow_page_stays_close_to_live;真机:每秒 200 KB 时滚动停下后约 0.6 秒追上
81 一次回报丢了,服务端一直等,画面卡住 页面收到确认才算报过;服务端 3 秒没收到回报就不再等 单测 behind_means_late_beyond_the_usual_round_trip
82 转屏后帧的尺寸变了 尺寸一变就开新的编码会话,页面按新的解码配置重新配置 真机:Safari 横竖屏切换,解码配置发 3 次,ffmpeg 解码无错
83 浏览器没有 WebCodecs 或解不了 H.264 这一页从没出过画面就改用 MJPEG 无头 Chrome:删掉 VideoDecoder 后画面是 MJPEG
84 MJPEG 去重后画面静止时不显示(Chrome 要看到下一部分的头部才显示上一帧) 每帧后面紧跟下一部分的分隔线和头部,不带 Content-Length 无头 Chrome:静止画面下 MJPEG 有图
85 macOS 上要装 ffmpeg 才有 H.264 本程序直接调 VideoToolbox:JPEG 由它的硬件解码器解成 NV12,直接交给 H.264 编码器;ffmpeg 的 VideoToolbox 作备用 单测 encodes_natively_without_holding_frames、encodes_with_the_local_ffmpeg(没装 ffmpeg 也选中原生的);真机(Apple 芯片):从送进到出帧 3.5~6 毫秒;手机真实画面(990×2151)中位 17 毫秒,qp 20 时流量为 MJPEG 的 11.4%,SSIM 中位 0.9976(手动测试 measure_recording)
86 VideoToolbox 把奇数尺寸的最后一列、一行裁掉(481×1041 编成 480×1040) JPEG 解码时就拉成偶数尺寸(482×1042),和 ffmpeg 的 scale 一样 单测 odd_sizes_grow_to_even;无头 Chrome 用 WebCodecs 解出 482×1042
87 比 macOS 11 新的 VideoToolbox 键直接链接的话,旧系统上程序起不来 MinAllowedFrameQP 等运行时用 dlsym 找,没有就按 Quality 近似 qp 代码审查
88 页面画面滞后 4 帧,手势结束后停在动作中间那一帧(Chrome 的硬件解码器扣着帧等后面的帧来挤) VideoToolbox 的 SPS 没有 VUI,解码器按 Level 4.2 的缓冲最坏情况扣 4 帧;发给页面前改写 avcC 里的 SPS,写明 max_num_reorder_frames=0(video/sps.rs),已经写明的不动 单测 videotoolbox_sps_gets_no_reordering、vui_without_restriction_keeps_its_fields;无头 Chrome 逐帧喂:硬件解码器从扣 4 帧变为 0 帧
89 控制台开着时 WDA 每隔几分钟被 iOS 杀掉(cpu_resource_fatal:一分钟平均 84%,限额 80%),守护进程跟着记「WDA 不可用」 iOS 27 及以上改用手机自己的视频(ScreenStream),WDA 不再截图 真机:页面看了 70 秒,WDA 的 CPU 平均 3%、最高 11%(原来 110~120%),没有再重启
90 新页面一直黑屏:刚开流时要的关键帧手机不理,流自带的第一个关键帧在订阅前就过去了 没收到关键帧时每 250 毫秒再要一次 真机:刚开流 1.6~1.8 秒出第一帧
91 手机按请求补发的关键帧不带参数集,新页面从它开始解不了 组帧时记下 VPS/SPS/PPS,补到这样的关键帧前面 单测 keyframes_get_the_parameter_sets
92 横屏时页面上的画面上下颠倒(转正方向写反) 按「竖放顶边顺时针转过的角度」同向转回来;方向每秒问一次 真机:向左、向右横屏的画面和手机截图一致,1.1~2.7 秒跟上;横屏点地址栏点中
93 在本机运行 iphone-control update 只出现子命令帮助,还要再查该用哪种升级命令 先检查当前版本。已是最新则提示并结束,有可升级版本时按核实的安装渠道处理,固定版本仍需显式解除 单测(user_update_checks_the_release_before_choosing_an_installer)
94 Debian 升级只对照同一发布页上的 .sha256 就用 sudo 以 root 安装:能替换发布附件的人可以同时换掉包和校验值 发布流程给每个 .deb 签名清单(release.py sign-deb);没有签名清单不提供升级,下载后大小和 SHA-256 要和签名清单一致才交给 APT 单测 deb_manifest_is_bound_to_its_package、deb_upgrade_waits_for_its_signed_manifest;packaging/test_installer.py test_debian_package_is_signed_for_its_own_name
95 iphone-control update 不问就开始安装,受管服务会重启,打断正在执行的任务 先说明要做什么并询问,没有终端时要 --yes 单测 update_accepts_no_subcommand_and_preserves_read_only_check;手动:终端里运行,回答 n 不升级
96 Homebrew、Debian 升级后后台服务还在跑旧版本 升级后服务在运行就重启,并确认守护进程报告的是新版本;确认不了时写出手动重启命令 单测 brew_upgrades_the_exact_active_formula_only_after_the_tap_is_ready(已是最新时不重启);真机:deb 安装下升级
97 APT 锁定(hold)的包仍提示可直接升级,运行后才报错 hold 当作“已固定”:升级命令带上 sudo apt-mark unhold,直接运行时先提示解除锁定 单测 a_held_deb_is_reported_like_a_pinned_installation
98 发布清单只允许从声明过的某一个版本升级,其他版本一律“需要手动迁移” 去掉回滚兼容标记和 update rollback;任何更新的签名稳定版都能升级,新版本起不来时仍自动换回旧版本;清单保留两个旧字段让 0.2.2 还能升级 单测 verifies_publisher_signed_bytes_before_staging_an_executable、unhealthy_daemon_restores_last_verified_executable_and_service;test_installer.py test_archive_manifest_still_lets_0_2_2_upgrade
99 iphone-control status | head -1:读者先退出,后面的 println! 遇到 EPIPE 就 panic(退出码 101,打出崩溃信息)。Rust 启动时把 SIGPIPE 设成了忽略 只打印结果就结束的命令恢复 SIGPIPE 默认行为,安静退出;守护进程、MCP、viewer、wda-bridge 和跨守护进程重启的 update、service、setup 保持忽略 单测 sigpipe_default_only_for_commands_that_print_and_end、集成测试 a_closed_stdout_ends_printing_commands_quietly
100 0.2.2 起控制台每次按下都先请求 /wda/screen(约 0.1~0.2 秒),HID 会话空闲 30 秒关掉后,鼠标一直停在画面里时第一下还要等约 0.5 秒重开 按下只问方向,尺寸在转屏时和距上次测量满 60 秒后才重量;鼠标在画面上移动时每 20 秒最多预热一次 HID 会话 单测 display_poll_remeasures_size_only_when_needed;页面测试 hovering keeps the HID session warm at most every 20 seconds;真机:控制台连按,按下往返在几十毫秒内
101 控制台开着、页面走 WDA 截图的画面(浏览器解不了 HEVC,或低于 iOS 27)时,WDA 每 1.5~2.5 分钟被 iOS 杀掉(cpu_resource_fatal:60 秒内平均 86%~93% CPU,上限 80%)。MJPEG 缩到 75% 让 WDA 逐帧解码、缩放(CoreGraphics)、重新编码;横屏时 mjpegFixOrientation 让它逐帧旋转、重新编码,同样超限 MJPEG 原尺寸、不转正(MJPEG_SCALE = 100,mjpegFixOrientation = false):WDA 直接转发 testmanagerd 硬件编好的 JPEG,帧率不变(约 34 fps)。横屏的竖帧由页面转正(H.264 按 display.rotation,MJPEG 的 img 由浏览器按 EXIF) 真机(iPhone 15 Pro Max,iOS 27.0.1):拉本机编码的 /video,竖屏 25 分钟、横屏 5 分钟不再被杀(开着转正时横屏 2 分钟被杀);无头 Chrome:横屏下 H.264 和 MJPEG 画面方向正确、坐标换算正确
102 iPhone 15 Pro Max(iOS 27.0.1)每次锁屏约 10 秒:经 IOHID 短按电源键(0.05~0.1 秒)调用卡约 5.3 秒且不锁,再等 3 秒才退回 /wda/lock(约 1.9 秒)。iPhone 18 Pro Max(iOS 27.2.1)正相反 按设备记住哪种锁屏有效(PerDevice::lock_via_wda),之后先用它;先用的不灵仍会试另一种 单测 lock_order_follows_what_worked_on_this_device;真机:同一台连续锁屏,第一次约 10 秒、之后约 2 秒
103 WDA 半死:/status 照常 200,前台 App、截图、读元素、/wda/locked 全部超时(iPad mini 5,iPadOS 26.7.3,后台启动的 WDA 跑 20~40 分钟后)。守护进程只看 /status,一直显示「就绪」,不重启;后台模式下守护进程重启还会把它接回来。只靠巡检探测也不够:卡死时工具调用一个接一个等满超时(每个 10~30 秒),设备被占好几分钟,巡检抢不到锁 WDA 客户端数经 XCTest 的请求(/status 之外都是,工具调用和巡检探测 /wda/activeAppInfo 一样算)连续几次送到了却没有应答,有应答(哪怕是错误)就清零;连续 3 次就算卡死:之后经 XCTest 的请求直接报不可用,巡检和每个设备请求开头都会忘掉记下的后台 WDA、丢掉会话重新启动 单测 three_unanswered_requests_mean_stalled、xctest_probe_counts_only_missing_answers;真机:绕过守护进程让 WDA 长按(期间 /status 5 毫秒 200,/wda/activeAppInfo 超时)。空闲时 0.2.3 一直「就绪」,修复后约 28 秒判定卡死、34 秒恢复;同时经守护进程背靠背发工具调用时,main(#60)180 秒里 8 次调用各等 10~30 秒、不重启,修复后第 3 次超时(约 50 秒)就重启,13 秒后就绪,其间的调用立即返回;经守护进程连续长按 6×10 秒不误判
104 iOS 27 以下(iPad mini 5,iPadOS 26.7.3)锁屏没锁上:经 IOHID 按电源键 3 秒后未锁、/wda/lock 报「Timed out while waiting until the screen gets locked」,之后退到 HID 后备路线,而低版本没有 HID,报的是「WDA 不可用(刚掉线)」,WDA 其实正常 WDA 在、两种办法都没锁上、又没有 HID 后备时,报「没锁上屏」和两种办法各自的原因;有 HID 后备时照旧退到 HID 单测 a_failed_lock_says_why_not_that_wda_is_down;真机:见 PR
105 iPad mini 5(iPadOS 26.7.3)一直锁不上屏:经 IOHID 按电源键 0.1 秒调用卡约 5.4 秒、不锁;/wda/lock(iOS 27 以下是 XCTest 的 pressLockButton)10 秒后报「Timed out while waiting until the screen gets locked」。iPhone 15 Pro Max(iOS 27.0.1)上 0.1 秒同样不认,每台第一次锁屏要退到 /wda/lock,约 10 秒 电源键按 0.15 秒(POWER_PRESS_SECS):iPad mini 5、iPhone 15 Pro Max 上 0.15~0.3 秒都能锁,iPhone 18 Pro Max(iOS 27.2.1)上 0.05~0.15 秒能锁、0.5 秒不行 单测 hid_buttons_send_consumer_page_events;真机:经 wda-bridge 每次先解锁再按不同时长,看 /wda/locked;经守护进程连续锁屏 3 次
106 AI 任务进行中,另一个 MCP 客户端或命令行照样能点手机,和 agent 抢着操作(监管只在 viewer 里) 任务由守护进程管:不带任务口令的请求可以看,操作一律拒绝并说明是哪个任务,用户接管后才放行;切换设备一律拒绝 单测(others_may_look_but_not_act_until_the_user_takes_over、an_opened_task_holds_the_phone_until_its_lease_goes)+ 真机(任务进行中用 iphone-control 另开的 MCP 点击被拒,截图照常)
107 任务进行中在别处 select 或自动选设备换了一台,任务接着操作另一台手机 任务的请求固定发往开任务时的设备;控制的设备变成另一台时任务中断(interrupted) 单测(the_task_goes_to_its_own_device、another_device_interrupts_the_task)
108 守护进程重启后任务和步骤记录都没了,也说不清任务怎么结束的 任务事件逐条落盘(tasks/<id>.jsonl,最多 50 个),重启后没结束的记成 interrupted,旧口令失效 单测(logs_survive_a_restart_and_unfinished_tasks_are_interrupted、tasks_keep_their_order_across_a_restart_even_within_a_millisecond、only_the_newest_logs_are_kept)
109 控制台刷新后不再跟踪正在进行的任务;在别处开的任务页面上看不到 页面接着跟刷新前的任务(事件从头重放),也接上在别处开的任务;守护进程不记得的才标成已停止 单测(tests/viewer/tasks.test.mjs)+ 无头 Chrome 或手动(任务进行中刷新页面)
110 AI 任务只该改设置,却点进了微信、打开了 tel: 链接或别的 App,没人拦 限定了 App 范围的任务,每个操作前看它碰到哪个 App(启动目标、链接、当时的前台),超出范围就停下来等人确认;tel: 这类链接、安装和卸载一律先问;看不出前台时不操作;拒绝只拒这一步,任务可以回到范围内继续 单测(what_is_outside_the_scope、what_each_request_checks_against_the_scope、an_approved_app_joins_the_scope_for_the_rest_of_the_task、a_rejected_app_refuses_that_step_but_the_task_can_go_back、a_question_nobody_waits_for_leaves_the_page、the_scope_survives_a_restart)+ 真机(task run --app 设置 的任务启动「信息」时页面出现确认)
111 控制台上 AI 任务的总结直接显示 Markdown 原文(**iOS 27.0.1**、- **设置**:…),换行也被合并成一行 总结先整体转义,再按一小部分 Markdown 显示(粗体、斜体、行内代码、列表、标题、分隔线、换行、http(s) 链接),原始 HTML 一律当文字 页面测试(tests/viewer/summary.test.mjs)+ 真机(Claude Code、Codex 任务的总结)
112 iOS 27 上控制台用手机自己的视频时,系统权限弹窗(「允许“日历”使用你的位置?」)在画面里只剩变暗的屏幕,看不到弹窗本身,接管的人不知道该点哪里;agent 的截图里有 画面是手机自己的视频时,页面问守护进程有没有系统弹窗(AlertCheck;在 App 里每 2 秒,主屏幕上查一次约 0.6 秒,没弹窗时放慢到 6 秒,刚触摸后 3 秒内不问),有就照 iOS 弹窗的样子把它画在画面里它所在的位置(文字、按钮);按钮按坐标点(按名字点「允许」会点到「不允许」);AI 任务进行中按钮要先接管 单测(a_system_alert_with_its_own_buttons)+ 页面测试(tests/viewer/alert.test.mjs)+ 真机(弹出权限请求时页面显示弹窗和按钮,点按钮生效)
113 在控制台画面上拖动、滑动时,触控板双指一碰就变成了缩放画面(双指捏合在浏览器里是按住 Ctrl 的滚轮) 画面只用上方的加减号缩放;画面区域里的 Ctrl/⌘ + 滚轮、Safari 的 gesture 事件都拦下,既不缩放画面也不缩放整页;触屏上画面周围不允许双指缩放(touch-action: pan-x pan-y) 页面测试(tests/viewer/zoom.test.mjs)+ 真机(在画面上双指捏合,缩放比例不变)
114 设置菜单不能用方向键,长按方向键时重画期间会打开回显,取消后可能留下终端输入模式 菜单从第一帧到退出都关闭输入回显;方向键和编号选择一致,Esc/Ctrl+C 恢复原模式;基础终端保留逐行输入 菜单状态单测 + PTY 回归(含长按 ↓、输入输出在不同终端、取消和外部信号)
115 生成 Shell 补全触发配置读取或设备维护锁,脚本与 CLI 定义不同步 Bash/Zsh/Fish 从实际命令树生成,生成路径不读取设置、不连接设备、不申请维护锁 补全单测、CLI 子进程回归、Bash/Fish 候选断言及 Zsh 交互验证
116 AI 任务的 Agent 用自己的 Bash 跑 iphone-control task approve <id>,就能批准它本该问人的越界确认和 iphone_confirm,或在用户暂停后自己继续 带任务口令、或来自开任务进程之下(Agent 及其子进程)的控制请求一律拒绝,停止除外;控制台接口在 Linux 上按调用进程同样拒绝 单测 the_agent_cant_control_its_own_task;真机 tasks.py self
117 task run 下的命令自己 task finish 后正常退出,却被立刻发 SIGTERM,task run 退出码变成 1,平台当成失败 任务是命令自己结束的(completed/failed/rejected)就给它 5 秒退出,退出码用它自己的;在别处停止的照旧马上停 单测 a_command_that_finished_its_task_is_given_time_to_exit、the_exit_code_is_the_command_s_or_the_task_s_result;真机 tasks.py run
118 IPHONE_CONTROL_VIEWER_LAN=1(文档写的值)让控制台启动就退出:invalid value '1' for '--lan' 布尔设置接受 1/0、yes/no、on/off、true/false 单测 viewer_settings_from_the_environment
119 从局域网地址(HTTP)打开控制台一直停在「正在连接」:不是安全上下文,没有 crypto.randomUUID 页面不用只在安全上下文里才有的接口生成画面编号(getRandomValues) 页面测试 lan.test.mjs
120 带请求体的请求被提前拒绝(没登录 401、403、413)时,控制台没读请求体就关连接,TCP 发 RST,客户端收不到回复(connection reset by peer,复用连接的程序约三次一次) 回复后先关写方向,读完对方剩下的数据(最多 1 秒、1 MB)再关 单测 every_request_needs_the_login(256 KB 请求体仍收到 401);真机 tasks.py remote 连跑 8 次
121 任务事件流(SSE)的一块数据断在中文字符中间时,先整体转成文字会把这个字变成乱码 在字节里找事件边界,只转换完整的事件 单测 remote::reads_server_sent_events
122 升级时运行新程序的 --version 偶尔失败:Text file busy(同一进程的其他线程 fork 时,新程序还以写方式打开) 遇到 ETXTBSY 等 50 毫秒重试,最多 20 次 单测 the_candidate_runs_once_it_is_no_longer_open_for_writing(修复前稳定复现)
123 iPad(iPadOS 26)重启后要输入密码启用 UI 自动化时,通知写的是「iPhone 需要输入锁屏密码」;所有通知标题都写死「iPhone」,多台设备时看不出是哪一台 标题用设备名(没有名字时用型号类别),密码提示按设备类别写系统弹窗的说法;离线通知用离线前记下的名字 单测 a_notification_names_its_device;真机 notify-test pin(控制 iPad,经本地假 Bark 截到标题)
124 切到另一台设备再切回 iPhone(iOS 27)后,WDA 卡在「Enable UI Automation」密码框期间,HID 后备路线的截图、按键都报「WDA 不可用,也不知道屏幕尺寸」:state.json 只记最后一台的尺寸 每台设备的尺寸按 UDID 记下(screens),screen/screen_udid 照旧写给旧版本 单测 every_device_keeps_its_screen_size;真机:iPhone 和 iPad 来回切换后,iPhone 的 WDA 还没起来时截图、按 Home