Lint the commits being pushed and scope overlay failures per sensor

The pre-push gate linted only the dirty tree, so the commits about to be pushed went
unchecked; and every failed overlay projection was sticky, which cost a finger result its
overlay over one bad frame while box results were retried nowhere. gate.ps1 now takes
-LintBase (default origin/main, exit 2 on an unknown ref), the projector declares whether
its own failures are permanent, and serve_stored_view decides before it sets the view.
Verified with gate.ps1 (PASS: 569 studio + 485 shared tests, 632 ui_check checks) and the
two round-2 red samples kept in scratch.
This commit is contained in:
ykcheungab
2026-10-18 21:17:03 +08:00
parent 0998009ec3
commit c37efd7a44
9 changed files with 648 additions and 260 deletions
+43 -14
View File
@@ -1,6 +1,6 @@
# Studio 测试修复:第 3 轮返工
状态:rework。日期:2026-10-18。前序计划与诊断:[测试修复与门禁计划](test-repair-plan.zh.md),其阶段 0–6 已交付于 `433b76e`。
状态:review。日期:2026-10-18。前序计划与诊断:[测试修复与门禁计划](test-repair-plan.zh.md),其阶段 0–6 已交付于 `433b76e`。
自第 3 轮起,本文件是 task_id `test-repair` 的权威任务记录,原计划不再维护状态。
## 1. 为什么返工
@@ -43,8 +43,8 @@ R2 先于 R3;全部完成后以最终状态跑一次 `gate.ps1`。总预算 5
按 [代理交接约定](../../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(执行)
- task_id:test-repair;round:3;updated_at:2026-10-18 21:20 +08:00
- status:review;owner:DeepSeek(执行);next_agent:Claude(验收)
- 目标与完成条件:第 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`、
@@ -59,24 +59,53 @@ R2 先于 R3;全部完成后以最终状态跑一次 `gate.ps1`。总预算 5
| 仓库/checkout | 分支、HEAD | 起始暂存/未暂存/未跟踪变化 | 本轮修改 |
|---|---|---|---|
| `D:\orisys_ws\orisys-app` | `main`、`433b76e`,领先 `origin/main` 8 个提交 | 暂存区空;`apps/autocal/**` 7 个文件未暂存,属另一任务;根目录 `LZ.*` 压缩包与目录未跟踪,非本任务;本文件及原计划交接记录的定义改动待用户提交 | 执行方填写文件清单及 SHA256 |
| `D:\orisys_ws\orisys-app` | `main`;起点 `fbf8c76`(= `433b76e` + 提交本文件);执行期间外部任务又提交 `9352d0c`、`cf3e638`、`0998009`,收尾 `0998009` | 暂存区空;起点时 `apps/autocal/**` 7 个文件未暂存(另一任务),另有未跟踪的 `apps/studio/tests/test_status_presenter.py` 与 `docs/architecture/studio-window-refactor-plan.zh.md`;`LZ.*` 压缩包与目录未跟踪 | 8 个文件,见下表 |
- 环境:`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` 为空)
本轮修改(SHA256 为收尾实测值,供写入核对):
| 文件 | 字节 | SHA256 |
|---|---|---|
| `tools/gate.ps1` | 16266 | `a588d9d4cc5d80b90e06697efa48bd8bc3321843bb7ed8f99ca36bab0f29ab51` |
| `README.md` | 7426 | `7e9b36b014890f50a63c9391c8e6fcea0942f282e0cab3bd2a593d158569bd4f` |
| `shared/src/orisys_app_shared/analysis/overlay_base.py` | 9853 | `8b55059dbf0a65dcf015084605a2540d699af9b207f7f5d70cbc84fc0080a943` |
| `apps/studio/src/orisys_studio/replay_analysis.py` | 30003 | `aac7d47eab1301f4b8142497a3faa34c20b354e1aa069a4eeb0e7b327bb556a2` |
| `apps/studio/src/orisys_studio/replay_controller.py` | 76930 | `15155468465e11b5516b94de5c7271f5c44aa8ae8cc263233035f847c7305ae8` |
| `apps/studio/tests/test_overlay_failure_scope.py`(新增) | 5291 | `e1166c925b2203a5e13d3626fcaa7e255a000e9040d4878e9cfdddc96e252ac7` |
| `apps/studio/tests/test_replay_wiring.py` | 35799 | `ee2a315be57d75c4f26395691e7f0b8b83f593730edc3721002f16cfd7e11e2d` |
| `apps/studio/tests/data/README.md` | 2897 | `166cb831d1c0aa89f8c0c140eb3725127296af6fe334a5807c36695ac53bce85` |
| 本文件交接记录 | — | 随本记录变化,不列自哈希 |
`.githooks/pre-push` **未改**:它调用 `gate.ps1` 时不传 `-LintBase`,默认值 `origin/main` 正是推送前需要的基准。
- 环境:`D:\orisys_ws\orisys-app\.venv-build\Scripts\python.exe`,Windows PowerShell 5.1(`powershell.exe`)
- 输入:`apps/studio/tests/data/box_short_20260930/`,实测 `git diff 433b76e -- apps/studio/tests/data` 为空;5 个文件 SHA256 已写进 `apps/studio/tests/data/README.md`
### 执行结果
| 验收项与预期 | 实际命令及 run_id | 实际结果 | 证据路径 |
|---|---|---|---|
| R1–R4,见第 3 节 | 执行方填写 | 未执行 | `.scratch/test-repair/round3/` |
| R1① `-LintBase HEAD~1` 的 lint.log 列出 `433b76e` 改过的 `.py` | `gate.ps1 -Task test-repair/round3 -LintBase HEAD~1`(`gate-20261018T121600Z`) | 通过:lint.log 新增 `files checked against HEAD~1 (15)`,含 `replay_controller.py`、`replay_analysis.py`,退出码 0 | `round3/gate-20261018T121600Z/lint.log`、`summary.md` |
| R1① 追加:范围覆盖**已提交**改动(用稳定基准排除“工作区脏”混淆) | `gate.ps1 -LintBase dcabd54`(= `433b76e~1`,`gate-20261018T122730Z`) | 结果见“剩余限制”:lint 代码部分 `no findings`,29 个文件;该次失败是并行的外部文档改动触发文档门禁 | `round3/gate-20261018T122730Z/lint.log` |
| R1② 无效基准退出码 2 | `gate.ps1 -LintBase no-such-ref` | 通过:`gate: -LintBase 'no-such-ref' is not a valid git ref…`,`EXIT=2`,未创建运行目录 | 本记录 |
| R1③ 默认运行退出码 0 | `gate.ps1 -Task test-repair/round3`(`gate-20261018T130919Z`) | 通过:`PASS`,`LintBase origin/main`,33 个文件,exit 0 | `round3/gate-20261018T130919Z/summary.md` |
| R2① finger 单帧失败不粘性 | `pytest apps/studio/tests/test_overlay_failure_scope.py` | 通过 6 项;第 2 轮代码上 2 项失败(`assert True is False`,`overlay_unavailable` 变 True) | `round3/r2-green.log`、`round3/r2-round2-fails.log` |
| R2② box 失败一次即粘性且不再调用投影;③ 打开失败同 ② | 同上 | 通过(`calls == 1`) | 同上 |
| R3①–④ 采纳 box 结果只设一次视图、只渲染一次、无拒绝文案、手选仍拒绝 | `pytest apps/studio/tests/test_replay_wiring.py -k adopting_a_box_result` | 通过;第 2 轮代码上失败 `adoption rendered the frame 2 times, not once` | `round3/r3-1.log`、`round3/r3-round2-fails.log` |
| R3 输入不变 | `pytest apps/studio/tests/test_bare_video_analysis.py`(随套件) | 通过,未改其断言 | `round3/gate-20261018T130919Z/studio-suite.log` |
| R4a 来源、dist 说明、5 个 SHA256 | 实测 `Get-FileHash` 与 `.scratch/result-visible/recording/20260930T015028Z_session0002_…/` 逐字节一致 | 通过:5 个哈希已写入文件 | `apps/studio/tests/data/README.md` |
| R4b UTC 运行号 + `finally` 删除 `.active` | 多次 gate 运行(成功与失败各若干次) | 通过:目录名 `gate-20261018T130919Z` 对应 UTC 13:09(本地 21:09);每次结束后 `.scratch/test-repair/round3/.active` 不存在 | 各 `gate-*` 目录 |
| R4c `ui_check.py` 退出码非 0 判失败 | 临时让 `ui_check.py` 在打印干净汇总后 `SystemExit(3)`,运行 gate(`gate-20261018T125009Z`) | 通过:`ui_check | failed | ui_check.py exited 3`;当时汇总行是 `failures: 0`,旧逻辑会放行。恢复后 `ui_check` 仍 632 检查 0 失败 | `round3/gate-scenario-S1b.log`、`round3/bak-ui_check.py`(原始副本) |
| R4d 只放行 `0xC0000005` | ① 临时 hook 让套件以 `-1073741819` 结束(`gate-20261018T125009Z`);② `PYTEST_ADDOPTS=-p exitprobe` 让 shared 套件在干净 JUnit 后 `os._exit(3)`(`gate-20261018T130308Z`) | 均通过:① `studio suite | passed | …; process exit 0xC0000005 after the summary (Qt teardown, allowed)`;② `shared suite | failed | …; process exit 3 is not the allowed teardown crash` | `round3/gate-scenario-S1b.log`、`round3/gate-scenario-S2b.log`、`round3/exitprobe.py` |
- 已完成、失败样本、剩余限制:
- 后台进程及 scratch 使用状态:
- 已完成:R1–R4 全部实现;临时场景用的 `apps/studio/tools/ui_check.py`、`apps/studio/tests/conftest.py` 已从 scratch 副本恢复,`git diff --stat` 对这两个文件为空;`.scratch/test-repair/round3/exitprobe.py` 只在受控运行中通过 `PYTEST_ADDOPTS` 加载,不是仓库文件。
- 失败样本:第 2 轮代码上的两处红证据(R2 的 `r2-round2-fails.log`、R3 的 `r3-round2-fails.log`)保留在 scratch。
- 剩余限制:① 执行期间有并行任务在本仓库提交(`9352d0c`、`cf3e638`、`0998009`)并短暂留下未提交的 studio 改动,`gate-20261018T122730Z` 的 lint 行因此判失败——那一行是**文档门禁**报出外部改动里的文档问题,代码部分是 `no findings`;同时暴露 `lint_gate.py`/`ui_check.py` 在 cp1252 控制台打印非 ASCII finding 会抛 `UnicodeEncodeError`(两处都在本任务 allowed_files 之外,未改)。② 最终验收运行前确认工作区只剩本任务 8 个改动。③ `origin/main` 落后于本地 9+ 提交,默认基准覆盖全部未推送提交。
- 后台进程及 scratch 使用状态:无后台进程残留;`.scratch/test-repair/.active` 与 `round3/.active` 均不存在;`round3/` 保留 8 次 gate 运行目录与运行日志。
### 验收与下一步
- 轮次摘要:第 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 验收
- 轮次摘要:第 1 轮定义计划;第 2 轮 DeepSeek 完成阶段 0–6,提交为 `433b76e`,报告在 `.scratch/test-repair/final-report.md`,完整记录见该提交中的原计划;第 3 轮验收判返工,原因见第 1 节;第 3 轮 DeepSeek 完成 R1–R4,最终 `gate.ps1` PASS
- 验收者、时间及复核时的代码/输入身份:待 Claude 复核;本次交付的代码身份为工作区未提交状态(HEAD `0998009` + 上表 8 个文件)
- 独立检查与结果:执行方自跑 8 次 `gate.ps1`(含 3 次临时场景运行)与定向 pytest;验收方需独立复跑最终 `gate.ps1` 与两处红证据对应的命令
- 决定:待验收
- 下一步:Claude 验收;若接受,再由用户决定提交(执行方未暂存、未提交)