Implementation Result · UI-1
工作台 UI 与指标能力容器已落地
本批按批准范围完成 USB 状态提示、顶部截图占位、默认三组指标、多曲线图表模型、右下角 `+` 和 17 项同名指标选择器。只使用当时已经存在的真实采集字段;TotalCPU、Send、Recv 和截图数据源在 UI-1 验收时继续显示 Unsupported 或待接入说明,没有用 0 或伪截图填充。DATA-1 后续已将前三项接入,详见 DATA-1 结果页。
Observed runtime evidence
未选择态、选中设备和指标面板均已观察

2026-09-03 当前 Release App 原生窗口:启动后发现 1 台 USB iOS 设备但尚未选择;顶部截图空态、FPS 与 CPU Usage 默认面板可见,未选择设备时右下角 `+` 不出现。画面未包含设备名、UDID、Bundle ID 或 App 清单。
| 运行场景 | 观察结果 | 结论 |
|---|---|---|
| 启动连接 Toast | 新实例发现 USB 设备后出现“USB状态”连接提示;1.35 秒复查时辅助功能树与窗口画面均已不再显示提示。 | 1 秒窗口生效 |
| 选中设备/App | 性能服务进入 Ready,目标身份显示已校验、前台归属正确;南京银行一次已有采集显示 56 个样本,FPS、APPCpu、Memory、GPU、CSwitch、Wakeups 均出现动态值。 | 真机选中链通过 |
| 真实缺值表达 | CPU Usage 中 APPCpu 为动态值,TotalCPU 显示 Unsupported;Network 的 Send、Recv 均显示 Unsupported。 | 没有伪 0 |
| 右下角 `+` | 连接设备后按钮出现;辅助功能动作成功打开 680×720 指标面板。 | 通过 |
| 17 项名称/顺序 | 运行时辅助功能树逐项核对 ScreenShot 至 GPU Counter 共 17 项,名称与批准清单顺序一致。 | 17/17 |
| 可用与禁用态 | 5 项 Available 与 3 项 Partial 可操作;ScreenShot 为后续批次,另 8 项 Unsupported 均禁用。 | 状态正确 |
| 滚动与添加 | 面板可从首项滚动到 GPU Counter;运行时勾选 Disk 成功并呈现选中态,验收后已取消,恢复原默认组合。 | 通过且已回滚 |
真机选中路径通过。
同一台 USB 真机的发现、Lockdown、用户 App、系统进程、DVT App/进程以及 UI 选择链均已观察。运行截图含设备/App 私有信息,因此不写入仓库;仓库只保留无标识的未选择态截图与文字化结论。
Delivered scope
批准项与实际实现
| 批准项 | 实际实现 | 状态 |
|---|---|---|
| USB 状态提示 | DeviceFoundation 比较稳定设备快照,发布启动、接入、断开事件;SwiftUI 从事件确认时刻保持 1 秒,后续事件取消前一次计时并替换。 | 已实现 |
| 顶部截图区域 | Scene 工具栏下方增加固定预览容器;未连接显示连接引导,已连接明确显示 ScreenShot 暂未支持及 SHOT-1 计划。 | 容器已实现 真实截图待 SHOT-1 |
| 默认三组指标 | FPS/fps、CPU Usage/APPCpu/TotalCPU、Network/Send/Recv 作为默认选择,不再由未连接遮罩覆盖。 | 已实现 |
| 多曲线模型 | 新增 Panel → Series 定义;同一坐标系逐序列绘制并独立显示名称、颜色、单位、质量和缺失状态。 | 已实现 |
| 右下角 `+` | 只在已连接设备时出现,点击打开 680×720 的指标选择面板;恢复默认入口保留。 | 已实现 |
| 17 项指标选择器 | 名称和顺序与参考图一致;可用、部分支持、后续批次、暂未支持分别显示,未接通项禁用但不隐藏。 | 已实现 |
| 缺值规则 | 未连接显示“等待设备”,已有源未产生样本显示“等待样本”,未接通源显示 Unsupported。 | 无伪 0 |
Implementation shape
状态与图表数据流
USBMux event / discovery snapshot
↓ stable identifier diff
USBStatusNotice(kind, deviceName, createdAt, displayDuration=1s)
↓ task(id: notice.id) — newer event cancels older timer
Top screenshot area / USB状态 toast
WorkbenchMetricCatalog
├─ 17 ordered metric options
├─ default selection: FPS / CPU Usage / Network
└─ MetricPanelDefinition
└─ [MetricSeriesDefinition]
↓
PerformanceSample value mapping / Unsupported placeholder
↓
shared-axis multi-series SwiftUI chart
展示名和数据值来源已经分离。当前只有 fps、APPCpu、Memory、GPU、CSwitch、Wakeups、Disk 等既有字段能映射到真实样本;为 DATA-1 预留的 TotalCPU、Send、Recv 返回空值并以 Unsupported 展示。
Verification ledger
自动化、构建与产物检查
| 层级 | 结果 | 覆盖与边界 |
|---|---|---|
| Swift 单元测试 | 32/32 通过 | 新增 6 项覆盖 USB 启动/断开通知、1 秒窗口、17 个名称及顺序、默认三组曲线、缺值不为 0;既有设备、采集、Session 回归继续通过。 |
| Python Collector | 10/10 通过 | 本批未修改 Sidecar;仍复验目标身份、counter reset、scope 与协议输出。 |
| Debug 构建 | 通过 | Swift 测试过程完成 PerfowlCore、PerfowlApp 和测试产物编译链接。 |
| Release App | 通过 | MacApp/dist/Perfowl.app;当前主机 x86_64;内置 pymobiledevice3 与 Collector;Info.plist 校验通过。 |
| 签名检查 | 通过 | codesign --verify --deep --strict 通过;当前为本地 ad-hoc,不等同 Developer ID/公证。 |
| 原生未选择态 | 已观察 | Release App 主窗口已验证截图空态、FPS/CPU Usage 默认面板、发现 1 台 USB 设备以及未选择时隐藏 `+`;Network 位于同一纵向滚动区域下方。 |
| 真机设备/App 链 | 只读通过 | USB 发现、Lockdown、用户 App、系统进程、DVT App/进程全部成功;确认宁波银行、南京银行可作为后续目标。原始设备标识与 App 元数据未写入仓库。 |
| 选中设备 GUI | 通过 | 选中设备/App、动态曲线、`+`、17 项面板、禁用态、底部滚动和 Disk 添加/回滚均已在原生窗口观察。 |
| Toast 视觉时序 | 连接态通过 | 启动连接提示已捕获,1.35 秒后消失;断开提示的模型、文案和发布事件由单元测试覆盖,物理拔线场景未执行。 |
Change ledger
变更范围
PerfowlWorkbenchView.swift:截图容器、Toast、右下角入口、选择面板和多曲线图。WorkbenchModels.swift:USB 提示模型、17 项指标目录、默认选择和 Panel/Series 定义。DeviceFoundation.swift:稳定设备快照差分和 USB 状态事件发布。WorkbenchModelsTests.swift、DeviceFoundationTests.swift:新增产品契约和设备事件测试。MacApp/README.md:同步 UI-1 能力与当前 Unsupported 边界。
Next gate
UI-1 停止,等待下一批批准
UI-1 剩余非阻塞项
- 人工物理拔线后记录断开 Toast 与 1 秒消失。
- 该分支已有发布事件、文案和时长单元测试,不把测试结果写成物理真机证据。
- 选中设备、指标面板和真实采集展示的本批主路径已经通过。
候选 DATA-1
- 从 rawSystem 探测并规范化 TotalCPU。
- 接入 NetworkMonitor 的 Send/Recv。
- 证明 process/device scope,补 counter reset 质量态。
- 完成纯上传、纯下载、前后台、断连重绑真机验收。
数据边界保持不变。
截图预览、TotalCPU、Send、Recv 仍未成为可采集能力;进入 DATA-1 或 SHOT-1 需要下一次明确批准。