Files
orisys-app/docs/test-repair-rework.zh.md
T
ykcheungab fbf8c76bb5 为测试修复加入第 3 轮返工任务
验收 433b76e 时发现门禁不 lint 已提交改动、叠加底图失败范围过大且回退无测试,故定义返工项。文档门禁 clean。
2026-10-18 20:04:26 +08:00

83 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Studio 测试修复:第 3 轮返工
状态:rework。日期:2026-10-18。前序计划与诊断:[测试修复与门禁计划](test-repair-plan.zh.md),其阶段 0–6 已交付于 `433b76e`。
自第 3 轮起,本文件是 task_id `test-repair` 的权威任务记录,原计划不再维护状态。
## 1. 为什么返工
验收方(Claude)读了 `433b76e` 的实际差异,未在 Windows 上复跑。第 2 轮的测试修复大体成立,但以下问题会让门禁或产品行为与声明不符:
| # | 问题 | 证据 | 后果 |
|---|---|---|---|
| R1 | 推送前的门禁不 lint 已提交的改动 | `gate.ps1` 调用 `tools/lint_gate.py` 时不带 `--base`;`lint_gate.py` 第 87–89 行只在给了基准时比较 `base...HEAD`,否则只看暂存与未暂存差异 | pre-push 时要推送的提交从不被检查,反而会检查其他任务未提交的 autocal 文件 |
| R2 | 叠加底图的粘性失败范围过大 | `replay_analysis.py` 的 `overlay_base()` 在 `project()` 第一次返回 `None` 时就置 `_overlay_failed`;`overlay_base.py` 的 finger 投影在单帧 `unrolled is None` 或任何异常时都返回 `None` | 一帧坏图就让 finger 结果在整个会话里失去叠加视图,超出本任务只处理 box 的范围 |
| R3 | 新回退逻辑没有测试,采纳时还会闪出拒绝文案 | 测试中没有引用 `overlay_unavailable`;`serve_stored_view()` 先按 `ARROW_STITCHED` 渲染一次,失败后改 `ARROW_PURE` 再渲染一次 | 回退坏了门禁仍是绿的;操作员会短暂看到“采集画面不可用” |
| R4 | 门禁与测试数据的小问题 | 见第 3 节 R4 | 证据不完整,或门禁结论偏宽 |
## 2. 规则
沿用原计划第 2 节全部规则:scratch、固定解释器、不暂存不提交、不改 autocal、不得通过删除或放宽断言、加 skip 或 xfail 让测试变绿。
scratch 仍为 `orisys-app/.scratch/test-repair/`,本轮运行放在 `round3/` 下;开始时写 `.active`,结束后删除。
## 3. 返工项
| 项 | 要求 | 验收 | 估时 |
|---|---|---|---|
| R1 lint 基准 | `gate.ps1` 新增 `-LintBase` 参数,默认 `origin/main`,传给 `lint_gate.py --base`。先用 `git rev-parse --verify` 校验,无效时退出码 2,不得静默退回只看工作区。`summary.md` 写明 lint 基准和被检查的文件数。pre-push 钩子用默认值;README“合并门禁”一节补一句参数说明 | ① `gate.ps1 -LintBase HEAD~1` 的 `lint.log` 列出 `433b76e` 改过的 `.py` 文件,例如 `replay_controller.py`;② `-LintBase no-such-ref` 退出码 2;③ 默认运行退出码 0 | 1 h |
| R2 失败范围 | 只有“再试也不会成功”的失败才粘性:投影器打开失败,或 box 投影失败(第 2 轮实测每帧都失败)。finger 投影单帧返回 `None` 只影响该帧,下一帧照常尝试。建议由 `OverlayBaseProjector` 按传感器声明失败是否永久,`AnalysisSession` 据此决定;不得按异常文本判断 | 新增不依赖 SDK 的单元测试,用替身投影器:① finger 式投影首帧 `None`、次帧成功 → 次帧拿到底图,`overlay_unavailable` 为假;② box 式投影失败一次 → `overlay_unavailable` 为真,之后不再调用投影;③ 打开失败 → 同 ②。记录 ① 在第 2 轮代码上失败的证据 | 1.5 h |
| R3 回退测试 | `serve_stored_view()` 在设置视图之前就确定该结果能否画叠加,只设置一次视图、只渲染一次。新增测试:用 `tests/data/box_short_20260930` 走真实分析流程采纳 box 结果,断言 ① 最终视图为 `ARROW_PURE`;② 采纳过程中面板从未显示 `panels.arrow_capture_unavailable`;③ `render_frame` 只调用一次;④ 之后手动选 `ARROW_STITCHED` 仍显示拒绝及原因 | 新测试的 ② 或 ③ 在第 2 轮代码上失败、修后通过;`test_bare_video_analysis.py` 现有断言不变且通过 | 1.5 h |
| R4 小修 | a. `tests/data/README.md` 的来源改为实际来源 `.scratch/result-visible/`,注明 `dist/` 原件已不可用、无法逐字节比对,并列出 5 个文件的 SHA256;b. `gate.ps1` 结束时在 `finally` 中删除 `.active`,运行号改用 UTC 时间;c. `ui_check.py` 退出码非 0 时判失败;d. pytest 退出码非 0 而 JUnit 无失败时,只放行 `0xC0000005`(`-1073741819`)并在汇总中写明,其他非 0 退出码判失败 | a 的哈希与实际文件一致;b–d 各用一次临时构造的场景验证(例如临时让 `ui_check.py` 以退出码 3 结束),验证后恢复,并用 `git diff` 确认无残留 | 1 h |
R2 先于 R3;全部完成后以最终状态跑一次 `gate.ps1`。总预算 5 h,超出 50%(7.5 h)按约定标 blocked。
## 4. 需用户决定(本轮不执行)
1. **box 叠加画面的断言。** `test_bare_video_analysis.py` 原断言“箭头画在采集画面上”,第 2 轮改为断言“面板拒绝”。这样产品缺陷在门禁里显示为通过,修好后也不会有测试提醒。选项 A:保持现状,另开任务修复 box 底图重建,先查明为何分析 pass 换阈值重试能成功而投影器不能(建议)。选项 B:恢复原断言并加 `xfail(strict=True)`,需要用户对原计划第 2 节“不得加 xfail”破例。执行方不得自行选择。
2. **深度图非零。** `test_replay_wiring.py` 把“深度恒为零”改为“有非零值”(实测 8926/133225)。需用户确认这段录像上 box 链路返回深度场是预期行为。
## 5. 不在本轮内
计时测试改为确定性测试,包括诊断实测 65.5 fps 高于假相机 30 fps 的原因:负载只会让测得帧率变低,这更像计数问题。另有:把 `test_a_low_camera_rate_is_recorded_as_a_negotiation` 中不依赖计时的断言拆回门禁;为 `timing` 测试提供单独的运行入口;autocal 测试树;Gitea runner。
## 交接记录
按 [代理交接约定](../../docs/platform/agent-handoff.zh.md) 维护;只保留当前状态和每轮一行摘要。
- task_id:test-repair;round:3;updated_at:2026-10-18 19:55 +08:00
- status:rework;owner:Claude(定义与验收);next_agent:DeepSeek(执行)
- 目标与完成条件:第 3 节 R1–R4 的验收列全部满足,最终 `gate.ps1` 退出码 0
- 范围:allowed_files 为 `tools/gate.ps1`、`.githooks/pre-push`、`README.md`(合并门禁一节)、
`apps/studio/src/orisys_studio/replay_analysis.py`、`apps/studio/src/orisys_studio/replay_controller.py`、
`shared/src/orisys_app_shared/analysis/overlay_base.py`、`apps/studio/tests/` 下新增或修改的测试、
`apps/studio/tests/data/README.md`、本文件交接记录。排除:`apps/autocal/**`、`orisys-sdk`、
`test_bare_video_analysis.py` 的现有断言、放宽 `tools/skip_budget.txt` 或填写 `tools/known_failures.txt`、第 4 节两项
- 停止条件:交接约定默认条件;需要改 `orisys-sdk` 或 `apps/autocal` 时停止并询问;时间预算 5 h
- 影响面:`overlay_base.py` 属于 shared,当前唯一消费者是 `replay_analysis.py`;lint 默认基准改变后,推送前检查覆盖全部未推送提交
- 授权:用户 2026-10-18 19:46 要求“写成给 DeepSeek 的后续任务”;执行需用户在 DeepSeek 会话中发出启动指令;不暂存、不提交、不推送
### 基准与输入
| 仓库/checkout | 分支、HEAD | 起始暂存/未暂存/未跟踪变化 | 本轮修改 |
|---|---|---|---|
| `D:\orisys_ws\orisys-app` | `main`、`433b76e`,领先 `origin/main` 8 个提交 | 暂存区空;`apps/autocal/**` 7 个文件未暂存,属另一任务;根目录 `LZ.*` 压缩包与目录未跟踪,非本任务;本文件及原计划交接记录的定义改动待用户提交 | 执行方填写文件清单及 SHA256 |
- 环境:`D:\orisys_ws\orisys-app\.venv-build\Scripts\python.exe`,Windows PowerShell 5.1
- 输入:`apps/studio/tests/data/box_short_20260930/`,须与 `433b76e` 一致(`git diff 433b76e -- apps/studio/tests/data` 为空)
### 执行结果
| 验收项与预期 | 实际命令及 run_id | 实际结果 | 证据路径 |
|---|---|---|---|
| R1–R4,见第 3 节 | 执行方填写 | 未执行 | `.scratch/test-repair/round3/` |
- 已完成、失败样本、剩余限制:
- 后台进程及 scratch 使用状态:
### 验收与下一步
- 轮次摘要:第 1 轮定义计划;第 2 轮 DeepSeek 完成阶段 0–6,提交为 `433b76e`,报告在 `.scratch/test-repair/final-report.md`,完整记录见该提交中的原计划;第 3 轮验收判返工,原因见第 1 节
- 验收者、时间及复核时的代码/输入身份:Claude,2026-10-18 19:40 +08:00,`433b76e`
- 独立检查与结果:只读审查 38 个文件的实际差异,以及 `lint_gate.py`、`overlay_base.py` 的相关代码。**未独立复跑** `gate.ps1` 与两套测试,因为验收方当时只有 Linux shell,没有该 Windows 解释器;第 2 轮自报的测试数字仍属未验证,第 3 轮验收时复跑
- 决定:返工;依据原计划第 4 节阶段 4(门禁须检查改动文件)与第 2 节(不扩大到 box 以外的行为变化)
- 下一步:用户提交本文件后,在 DeepSeek 会话中发出启动指令;完成后标 review,交回 Claude 验收