外观
P4 Session 截图、标注与导出契约
批次目标
在已有 Session Store 与 session-timeline.v1 之上补齐三类可复查产物:低频设备截图、与时间轴绑定的用户标注,以及带口径元数据的 JSONL / CSV 导出。实现继续保持无侵入:只调用设备 DVT 截图服务,不修改、注入或重签目标 App。
先冻结的口径
SHOT-1:低频截图
| 项 | 口径 |
|---|---|
| 目标频率 | 1 秒一次;同一设备最多一个在途请求,避免并发 DVT 请求互相抢读 |
| 原始事实 | pymobiledevice3 developer dvt screenshot 返回的 PNG 字节;文件写入 screenshots/shot-######.png |
| 时间 | capturedAt 为 Host wall clock;hostReceiveMonotonicNs 为 Host monotonic 采集时刻;Review 通过 session-timeline.v1 派生 elapsed |
| 有效条件 | PNG 签名 89 50 4e 47 0d 0a 1a 0a 且字节数大于 0;否则事件保留 failed / 原因,文件不生成 |
| 缺失语义 | 截图失败、取消或设备断开保持空路径与质量原因,绝不写入 0 或伪造图片 |
| 版本 | screenshot-capture.v1 |
NOTE-1:用户标注
| 项 | 口径 |
|---|---|
| 输入 | 去除首尾空白后的非空文本;空文本不落盘 |
| 原始事实 | append-only NormalizedPerformanceEvent(eventType=note),包含创建时间、Host monotonic、文本和生成代数 |
| 时间 | Note 不自行猜测秒数;Review 使用同一 session-timeline.v1 计算 elapsedSeconds,因此与样本、截图共享游标 |
| 编辑 | 本批不覆盖历史事件;删除和修改以后续 tombstone 方案处理 |
| 版本 | session-note.v1 |
EXPORT-1:导出
导出是只读派生物,不改变 Session 原始文件。
- JSONL 第一行是
recordType=export_meta,随后每行一个事件;元数据必须带exportVersion=\session-export.v1`、timelineAlgorithmVersion=`session-timeline.v1`、clockSource、anchorMonotonicNs、anchorWallTimestamp、timelineQuality`。 - CSV 第一行是同一组元数据列,随后每行一个事件;样本行保留常用指标、scope、unit 与 quality,缺值留空。
clockSource规则:所有事件 monotonic 大于 0 为host-monotonic;存在 0 哨兵时为wall-clock-estimated;无事件时为missing。锚点取首事件对应时钟,不能混合两种时钟。elapsedSeconds复用session-timeline.v1的输出;坐标缺失保持空值。导出数值使用小数点和固定六位精度,避免本地化逗号造成二义性。
验收边界
- Fixture 测试覆盖:PNG 校验、截图失败不造文件、Note 空文本拒绝、Note 与样本共享 elapsed、JSONL/CSV 元数据和空值保留。
- 真机验收使用当前已连接设备:连接后显示一次截图;开始短 Session 后至少产生一张截图和一条 Note;停止后从“会话”打开 Review,截图、Note、指标按同一时间轴显示。
- 本批通过构建和 Fixture 只能记为 E2;只有当前连接设备上的人工闭环才能记为 E4。逐帧 Display/Hitches 仍不在本批冒充真值。
变更前置
本文件先于代码提交,作为 SHOT-1 / NOTE-1 / EXPORT-1 的公式与质量语义基线。若后续 PerfDog 同场资料改变频率、展示或导出字段,先新增版本并保留历史 Session 的原始口径。