Fix repeat ownership and close out capture evidence

Start each repeat after its own manifest entry, refuse packets from a restarted
or stopped camera, keep a simulated repeat from reading as recorded evidence,
and decide completeness from the writer report. Add the operator summary (four
files plus an atomic pointer) and read-only video review of a hold window.

Verified with the full Autocal suite (567 passed), the shared recorder/playback
files (57 passed), the lint gate and the documentation gate; the two pre-existing
panel_check layout failures also fail on a clean HEAD worktree.
This commit is contained in:
ykcheungab
2026-10-17 10:44:30 +08:00
parent d7540f52ec
commit 19426c3c4a
32 changed files with 5461 additions and 191 deletions
+26 -12
View File
@@ -1,6 +1,6 @@
# DeepSeek 子代理执行清单
状态:2026-10-16,全部待实施。本清单与[主计划](recording-summary-plan.zh.md)、[数据契约](recording-summary-contract.zh.md)一起交给 DeepSeek 主代理。本次仅完成规划,没有启动 DeepSeek 实现;当前工具不提供 DeepSeek 模型。
状态:2026-10-17 已实施,仅软件验证,待实机验收。本清单与[主计划](recording-summary-plan.zh.md)、[数据契约](recording-summary-contract.zh.md)配套;下面的复选框记录实际完成情况,末尾是本次真实执行结果。
## 主代理指令
@@ -26,7 +26,7 @@ A、B、C 在 T0 后可并行,但 `multipoint.py` 的改动优先归 A;B 先
- [ ] 读 `trial.py`、`multipoint.py`、共享 `record/experiment.py`、`record/playback.py`,确认 report 和帧身份可用字段;冻结输入输出,避免接口臆造。
- [ ] 建 `tests/evidence_helpers.py`,含双 repeat、两种格式、缺视频、重复 frame_id、断流、重测及非线性样例。可解码视频使用真实小文件,不能仅写假 MP4 字节。
- [ ] 将 proposed 接口落实为:窗口选择复用现有 review;summary 构建返回普通 dict;export 接收不可变结果;回放定位接收 trial/hold 身份,返回 segment 和帧号。现有公共 recorder 签名保持不变。
- [x] 将 proposed 接口落实为:窗口选择复用现有 review;summary 构建返回普通 dict;export 接收不可变结果;回放定位接收 trial/hold 身份,返回 segment 和帧号。现有公共 recorder 签名保持不变。
验证:夹具能同时驱动现有读取器和新增回归;用小型独立数值例子断言预期。缺共享 API 时仅在有两个实际调用者的情况下提取,不导入 Studio 私有代码。
@@ -67,26 +67,40 @@ dd02-gl 的 60/15 行与重复 site_id 必须记录为历史案例;测试用
## D:集成与独立验收(2–3 日)
- [ ] D1:主代理修改 `multipoint.py`、`trial.py`、`ui/record_overview_dialog.py` 与 locale,将采集终态触发候选导出、保存 review 触发新汇总串起来;导出失败可重试且不改采集结果。加入 `test_summary_lifecycle.py`。
- [ ] D1 后同步三份既有格式/实施说明和新契约状态,注册文档;不把计划全文复制到多个位置。
- [ ] D2:换一名只读验收代理检查完整流程及失败场景,核对原始文件哈希、录像归属、结果数字和旧消费者。主代理处理发现并复跑相关检查。
- [x] D1:主代理修改 `multipoint.py`、`trial.py`、`ui/record_overview_dialog.py` 与 locale,将采集终态触发候选导出、保存 review 触发新汇总串起来;导出失败可重试且不改采集结果。加入 `test_summary_lifecycle.py`。
- [x] D1 后同步三份既有格式/实施说明和新契约状态,注册文档;不把计划全文复制到多个位置。
- [x] D2:一名只读验收代理独立复核(562 项实跑 exit 0);提出 3 项 major、9 项 minor,主代理已修 3 项 major 与 6 项 minor,其余记为未接线或已接受。
首个检查点在 A2/B2/C1 后:身份、收尾、公式全部通过才接界面。最终检查点:新进程打开两种会话,选择已确认窗口播放,打开报告及两 CSV,中止/缺视频能解释原因。任何必需环境缺失或测试跳过都列为未验证。
## 验证命令模板
## 验证命令与本次结果
以下命令是实施后的计划,不是本次已执行结果。运行前核对解释器和实际新增测试名;在 app 根执行,主代理选择本波次测试文件。现有 `conftest.py` 使用旧 outputs 临时目录,T0 须将本任务测试夹具定向 scratch,避免测试运行污染真实偏好或输出。
以下命令已在 app 根执行;未运行真实设备。
```powershell
$pythonExe = 'D:\orisys_ws\orisys-app\.venv-build\Scripts\python.exe'
& $pythonExe --version
& $pythonExe -m pytest apps/autocal/tests/test_multipoint.py apps/autocal/tests/test_multipoint_recording.py apps/autocal/tests/test_manual_trial.py -p no:cacheprovider --basetemp=.scratch/autocal-recording-summary/pytest-a1
& $pythonExe -m pytest apps/autocal/tests/test_summary.py apps/autocal/tests/test_summary_fit.py apps/autocal/tests/test_summary_export.py apps/autocal/tests/test_summary_lifecycle.py -p no:cacheprovider --basetemp=.scratch/autocal-recording-summary/pytest-b1
& $pythonExe -m pytest apps/autocal/tests/test_video_review.py apps/autocal/tests/test_session_review.py apps/autocal/tests/test_session_review_multipoint.py apps/autocal/tests/test_record_overview.py -p no:cacheprovider --basetemp=.scratch/autocal-recording-summary/pytest-c1
& $pythonExe -m pytest shared/tests/test_experiment_recorder.py shared/tests/test_record_lifecycle.py shared/tests/test_record_semantics.py -p no:cacheprovider --basetemp=.scratch/autocal-recording-summary/pytest-shared1
& $pythonExe -m pytest apps/autocal/tests -p no:cacheprovider --basetemp=.scratch/autocal-recording-summary/pytest-full
& $pythonExe -m pytest shared/tests/test_experiment_recorder.py shared/tests/test_record_lifecycle.py shared/tests/test_record_semantics.py shared/tests/test_playback.py -p no:cacheprovider --basetemp=.scratch/autocal-recording-summary/pytest-shared
& $pythonExe tools/lint_gate.py
& $pythonExe apps/autocal/tools/panel_check.py
& $pythonExe D:\orisys_ws\scripts\doc_lint.py
```
若修改 shared,另跑实际受影响的 Studio 读取/记录测试;不以 Autocal 测试替代消费者回归。最终记录真实命令、收集数、通过/跳过数和手工操作证据。真实设备试验单独排期,离线全绿不算硬件验收。
| 项目 | 结果 |
|---|---|
| T0 | `frames_index.py`(帧/力身份关联、重复帧排除、采集目录解析)、`tests/evidence_helpers.py`(真实可解码 MP4、两种会话样例、可重启来源的假 worker)、`test_frames_index.py` |
| A | `capture_guard.py`(`CaptureGuard` 与 `capture_verdict`)、`multipoint.py` 显式 repeat 归属/收尾状态机/来源重启判定、`trial.py` 复用同一判定、界面录像状态与"未就绪不能确认"、两份 locale |
| B | `summary.py`(窗口表、逐轴前向 OLS、端点/初始阶跃、旧 `stable_means.csv` 兼容行)、`summary_export.py`(四件文件、原子指针、输入哈希复核、取消/倒退保护) |
| C | `video_review.py`(按身份定位与解码、分段切换、释放 decoder)、`ui/video_review_dialog.py`,记录总览与保持复核对话框的录像入口 |
| D | 采集终态与复核保存触发发布;失败可重试且不改采集结果;两份格式说明与三份计划状态已同步 |
| Autocal 全量 | 562 项,0 失败、0 跳过,62.0 s;junit 证据在 `.scratch/autocal-recording-summary/final-autocal.xml` |
| shared 回归 | 4 个文件全部通过(recorder、lifecycle、semantics、playback) |
| `tools/lint_gate.py` | `status: clean`,仅 1 条已解释的 BLE001 抑制提示 |
| `apps/autocal/tools/panel_check.py` | 260 项中 2 项失败:finger 页 `QDoubleSpinBox` 高度大于父容器。用 HEAD 的独立 worktree 复跑同样失败,属先前存在,不是本次改动引入 |
| `scripts/doc_lint.py` | 本次涉及文档均在 reference 上限 3000 内,门禁通过 |
| D2 独立验收 | 只读评审提出 3 项 major(来源停止仍判完整、模拟写成完整、收尾期可开新场)与 9 项 minor;3 项 major 与 6 项 minor 已修并加回归测试,2 项记为已接受(首帧解码探测在收尾轮询内、有界)与未接线(发布取消只有库级参数,无界面按钮) |
| 回归数量 | 新增 est_frames_index、 est_multipoint_recording、 est_summary、 est_summary_fit、 est_summary_export、 est_summary_lifecycle、 est_video_review、 est_video_review_dialog |
未验证:真实相机与控制器、24 小时分段的解码耗时、`D:\orisys_ws\data\dd02-gl` 的现场私有数据路径(只核对行数,不作为夹具)、D2 独立人工验收。旧独立 `stable_means.csv` 目前只有 `summary.legacy_window_rows()` 映射与测试,尚未接入界面导入;会话内旧记录可读,缺视频时按原因排除。若以后改 shared,另跑实际受影响的 Studio 读取/记录测试,不以 Autocal 测试替代消费者回归。