Files
orisys-app/docs/architecture/studio-window-refactor-plan.zh.md
T
ykcheungab 70b4341fd0 更新 Studio 主窗口重构的 S3 交接计划
核对已接线阶段与当前回放行为,明确并行标定任务的文件边界。文档门禁通过,本轮未执行代码重构或回归测试。
2026-10-19 17:23:36 +08:00

190 lines
13 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 主窗口分步重构计划
目的:plan。范围:`apps/studio/src/orisys_studio/app_window.py` 及其直接调用方。
当前架构由 [Studio 架构](studio-architecture.md) 维护;本文件是唯一实施进度记录。
## 目标与约束
主窗口保留组件装配、跨功能信号连接、窗口几何及明确的关闭顺序。
按职责迁移现有实现,不增加产品功能、依赖、线程或全局状态容器。
会话、回放、布局、显示偏好和记录状态继续由现有控制器持有。
显示层只读取状态;录制与标定采样继续消费采集线程的数据,不依赖刷新频率。
启动、停止、暂停、异常处理、信号顺序及懒加载时机均属于行为保持边界。
关闭时保留预览关闭、采集回调解绑、分析取消与等待、采集和录制收尾、3D 释放的顺序。
测试和工具确实使用的旧入口可以暂留,但每一步必须说明保留原因并更新真实调用方。
不提交、不切换分支;保留所有已有修改,不将并行功能开发混入重构。
## 顺序与验收
每步都先检查调用方及相关测试,完成后更新本计划和架构文档。
任务顺序为 S0 → S1 → S2 → S3 → S4 → S5 → S6;每一步均可独立审查。
### S0:基线与计划
- [x] 记录 HEAD、索引和已有修改,建立独立 scratch 证据目录。
- [x] 在改动前运行状态显示与主窗口相关测试。
基线:2026-10-18,`orisys-app` 的 `main`,HEAD `433b76e`。
源码为 3,181 行;`StudioMainWindow` 有 212 个方法,含属性访问器。
原架构文档的 2,309 行及“拆分已完成”属于历史状态。
### S1:状态显示
- [x] 新建 `status_presenter.py`,接收显示事实与目标控件,不接收整个窗口。
- [x] 迁移 phase、来源摘要、标定摘要、有效性及录制统计的格式化与显示。
- [x] 保留 `_record_stats` 注入入口,保证已有截图工具和 UI 检查仍有效。
涉及主窗口、新 Presenter 和定向测试。验收:实时视图不显示回放标题;分析结果保持自己的
传感器身份;未知、无标定、部分轴标定仍可区分;录制关闭中不显示完成,丢失计数完整。
验证:状态 Presenter 独立测试、`test_ui_smoke`、`test_replay_wiring` 和现有 UI 检查。
### S2:界面构建
- [x] 准备 `ui/window_ui.py` 和 `ui/window_menus.py`,先以独立窗口验证。
- [x] 接入 `ui/window_ui.py` 的控件和布局构建,保持控件身份、顺序及 parent。
- [x] 迁移菜单和 QAction 创建;由窗口显式连接功能操作。
- [x] 迁移对应文字与主题更新,保留必要属性兼容入口。
依赖 S1。涉及主窗口、UI 模块及实际调用方;面板构建和菜单构建分两批验收。
验证:`test_ui_elements`、`test_view_layout`、`test_sensor_switch_window`、主题与语言检查。
3D 仍在原时机创建,启动恢复顺序及保存的布局不变。
### S3:实时标定交互
- [ ] 提取 `live_calibration.py` 的选择保存、解析、确认及提交请求。
- [ ] 文件身份和匹配规则复用 `CalibrationService`;对话框通过窄接口访问。
- [ ] 设备确认、记录版本及采样仍走现有记录通道。
依赖 S2。验证:`test_live_calibration_dialog`、`test_calibration_service` 及确认事件测试。
导出不等于应用,应用请求不等于设备确认,序列号不匹配的处理不变。
### S4:分析配置
- [ ] 提取 `analysis_setup.py` 的对话框、裸视频工作目录和分析服务构造。
- [ ] 迁移按录制目录保存的完整分析选择,保持接受、取消、重算来源及缓存语义。
- [ ] `ReplayController` 继续负责执行、取消、缓存及结果选择,不吸收配置逻辑。
依赖 S3 的标定选择接口。验证:`test_bare_video_analysis`、`test_analysis_progress`、
`test_replay_wiring`、`test_recording_recalibration`;保留录制 chain、标定/设备确认、
显式禁用标定、空载窗口及实际参考帧 ID/时间,取消或失败保留上一完整结果。
### S5:运行协调与预览
- [ ] 先提取 `preview_controller.py`,负责设备和预览定时器生命周期。
- [ ] 再提取 `activity_coordinator.py`,统一按钮和快捷键的运行、暂停、停止规则。
- [ ] worker 操作通过 `SessionController`;关闭流程继续在窗口显式排列。
依赖 S4。两批分别验证 `test_session_controller`、`test_pause_controls`、
`test_transport_review` 和连接中停止、断开、异常、重复关闭场景。
普通停止保持非阻塞,退出等待资源结束;预览与采集不能争用相机。
### S6:显示入口与兼容桥收尾
- [ ] 将 2D/3D 的共同交付协调归入现有 `FrameView`,调用方显式传入显示上下文。
- [ ] 更新测试和工具为真实控制器接口,删除已无调用方的窗口转发。
- [ ] 核对依赖方向、无循环、线程归属和文档现状;运行完整门禁。
依赖 S5。验证:`test_shared_depth_scale`、`test_scene3d_frame_views`、回放定位与
显示设置重绘测试。2D/3D 使用同一帧;实时不覆盖回放;重绘不启动新分析。
结束条件是主窗口只承担约定职责,且所有相关检查通过,不以行数作为唯一标准。
## 历史验证摘要
以下是旧批次证据,不是当前 HEAD 的复验。详细原计划快照保存在本轮 scratch 的
`plan-before.md`;原始日志路径若不可用,应注明证据缺失。
| 批次 | 实施与结果 | 原始证据(相对应用仓库) |
|---|---|---|
| S1,2026-10-18 | 状态迁出;前后定向 125 passed,独立 19 passed,最终 Studio 550 passed/19 skipped;首次门禁 Studio 两项失败保留,隔离通过不能解释原因 | `.scratch/studio-window-refactor/20261018-200221/`;`gate-20261018T120931Z/summary.md` |
| S2 准备,2026-10-19 | main a0c13c1;只新增模块及测试,主窗口字节不变;13 passed,lint 通过 | `.scratch/studio-window-refactor/20261019-094111/final.xml` |
| S2 接线,2026-10-19 | main c6c16df;3070→2894 行;10 控件、35 菜单/action 同对象,18 业务回调留窗口;46→49 passed | `.scratch/studio-window-refactor/20261019-095028/` |
S2 串行门禁:lint 通过,UI 632 checks/0 failures;shared 461 passed、15 failed、
18 skipped、3 deselected,涉及映射缺失及模型尺寸;Studio 垃圾回收时访问冲突,无 JUnit。
扩展 UI 131 passed/1 failed,为分析停止后的即时状态断言。旧/新窗口隔离均 4 passed;
旧窗口全套对照无进展后中断。不可据此归因。汇总:
`.scratch/studio-window-refactor/gate-20261019T015301Z/`。
S1 首次 shared 467 passed、18 skipped、3 deselected,UI 632/0;另有关闭后的
`asset_rejected` 异步回调,S5 须复核。S1/S2 临时反转条件的回归能发现错误,已恢复源码。
均为 Windows/Python 3.10.19/offscreen;未验证真实设备、可见桌面或硬件 GL。
未放宽断言或基线。S2 的非迁移方法 AST 一致是当时证据,后续功能提交不受其约束。
## 当前交接:仅执行 S3
- task_id:`studio-window-refactor`;round:2;updated_at:2026-10-19,Asia/Hong_Kong。
- status:ready;owner:Codex(交出后停止写入);next_agent:DeepSeek 执行方。
- 用户要求“check existing plan and prepare to handoff to deepseek”;本轮只更新交接。
先前分步重构授权继续有效;转发启动指令后执行 S3,完成交付 review。
S4–S6 留下一轮,不因 S1/S2 结构完成而声称全量验收通过。
### 基准与输入
| 仓库 | 分支与 HEAD | 起始状态/本轮修改 |
|---|---|---|
| `D:\orisys_ws\orisys-app` | dev;9d4563e9292469e9df500a7acab6d26489810455 | 索引空;finger sensor.json 已有未暂存修改;本轮仅此计划 |
| `D:\orisys_ws` | master;9201914cbe335b6862058212af0bc2614f2b4792 | 场加权计划有其他任务修改;设备包、mph、dragon-q6a 无关未跟踪;本轮不改根仓库 |
当前主窗口 2899 行、213 个方法(含属性访问器);WindowUi/WindowMenus 已接线,
live_calibration.py/analysis_setup.py 尚不存在。当前源码包含后续回放修复,不能回退旧窗口。
本轮工作目录为应用仓库;解释器 `D:\orisys_ws\orisys-app\.venv-build\Scripts\python.exe`。
源码、配置、测试与依赖声明 SHA256 见
[baseline-sha256.json](../../.scratch/studio-window-refactor/handoff-20261019-171832/baseline-sha256.json);
本轮计划哈希见同目录 `delivery-sha256.json`,不把哈希写回被哈希文件。
同 checkout 无需补丁;跨 checkout 须提供差异、新文件及上述基准。无须原始视频或硬件。
### 范围、依赖与停止条件
allowed_files:`apps/studio/src/orisys_studio/app_window.py`、新增 `live_calibration.py`,
必要的 `shell_ports.py`;相关实时标定测试及新增单元测试;本计划与 `studio-architecture.md`。
其他阶段、SDK、shared、配置、Autocal 和功能变更均不在本轮范围。
迁移 live choice 的读取/保存、默认路径、解析、导出后选择和确认/提交请求。
复用同一 prefs 与保存入口,避免第二份状态;服务仍负责文件身份和匹配。
注入显式控件、回调或窄接口,不传整个窗口或使用任意属性代理。
先保留实际被 SensorDialog、运行入口、回放配置和测试调用的窗口桥;列出调用者与保留原因。
测试 monkeypatch 的转发仍须生效,不能复制旧实现来满足测试。
采集线程确认继续只写 RecordingCoordinator/SessionController,不操作 Qt;
GUI drain 在原时机执行。导出不应用,请求不当作确认;角色 default/file/none、
缺失文件、序列号检查、提示文字及 worker 请求参数均保持当前行为。
[场加权标定任务](../../../docs/workflow/field-weighted-calibration-plan.zh.md) 当前 working,
涉及 calibration_service.py、video_analysis_dialog.py、replay_controller.py 和 shared。
本轮把它们作为只读依赖;不改接口、不覆盖其工作。若接手时其变化影响提取或验证,
先核对该任务的交接记录与文件所有权,停止交叠部分;不得根据旧哈希恢复它们。
需要修改重叠文件或改变功能时请求决定,独立准备可继续。
默认遵循交接约定的三次失败停止规则;未设时间预算。没有提交、推送或硬件授权。
### 执行与验收
DeepSeek 先运行下方相同测试建立当前基线,再分“选择/解析”和“确认/请求”两批提取。
每批检查调用方与差异、跑相同回归,补窄接口独立测试;完成更新架构现状,运行门禁。
结果应保持旧行为、减少窗口业务逻辑、无循环依赖及新线程。独立验收方复跑关键证据。
历史全量失败不自动豁免;本轮失败记录实际退出码、归因证据与剩余项,不降标准。
```powershell
# 工作目录 D:\orisys_ws\orisys-app;每次替换为唯一 run_id
& ./.venv-build/Scripts/python.exe -m pytest apps/studio/tests/test_live_calibration_dialog.py apps/studio/tests/test_calibration_service.py apps/studio/tests/test_model_calibration_ui.py apps/studio/tests/test_recording_recalibration.py apps/studio/tests/test_bare_video_analysis.py apps/studio/tests/test_window_surfaces.py -p no:cacheprovider --basetemp=.scratch/studio-window-refactor/pytest-<run_id> --junitxml=.scratch/studio-window-refactor/<run_id>.xml
& ./.venv-build/Scripts/python.exe -m pytest apps/studio/tests/test_ui_smoke.py -k calibration -p no:cacheprovider --basetemp=.scratch/studio-window-refactor/pytest-confirm-<run_id>
& ./.venv-build/Scripts/python.exe tools/lint_gate.py
powershell -NoProfile -ExecutionPolicy Bypass -File tools/gate.ps1 -Task studio-window-refactor -LintBase HEAD -Serial
# 工作目录 D:\orisys_ws
& ./orisys-app/.venv-build/Scripts/python.exe scripts/doc_lint.py --files orisys-app/docs/architecture/studio-window-refactor-plan.zh.md orisys-app/docs/architecture/studio-architecture.md
```
| 本轮验收项 | 实际命令与结果 | 证据 |
|---|---|---|
| 当前阶段/调用方 | 只读检索与 Python AST 计数;S1/S2 已接线、S3 未实施 | 当前源码及 baseline-sha256.json |
| 文档检查 | `scripts/doc_lint.py --files orisys-app/docs/architecture/studio-window-refactor-plan.zh.md`;退出码 0 | 本轮 scratch/doc-lint.log |
| 文档大小 | `scripts/doc_count.py orisys-app/docs/architecture/studio-window-refactor-plan.zh.md`;预算内 | 本轮 scratch/doc-count.log |
| 代码回归/全量门禁 | 本轮未执行,只整理交接;上方是未来命令 | 不复用历史结果冒充当前通过 |
轮次摘要:1,S0–S2 实施及历史限制见上;2,核对现状并准备 S3 交接,未改生产代码。
验收者、独立复跑和决定尚未发生。下一步由 DeepSeek 核对现场、将 owner/status 更新为
DeepSeek/working,完成后交 review;验收方决定 done/rework,不能自行宣称接受。
本轮无后台进程;证据保留在 `.scratch/studio-window-refactor/handoff-20261019-171832/`,
检查结束移除任务 .active,不清理日志。缺失 scratch 材料明确标记,不依赖它继续写入。