diff --git a/docs/00-ai-start-here.md b/docs/00-ai-start-here.md index ccde0b0..16c0689 100644 --- a/docs/00-ai-start-here.md +++ b/docs/00-ai-start-here.md @@ -45,7 +45,7 @@ SoftBox 软件盒子是一个使用 Go + Gio 开发的 Windows 桌面客户端, ## 当前阶段 -当前项目已完成 Phase 0~2、T-301 与审核整改 `T-604`~`T-609`。Windows 安全路径阻断项、图标缓存资源边界、后台结果回 UI 线程的事件接线、双适配器交互契约与 `VisibleItems` 快照生命周期均已关闭;下一步按 Phase 2 交叉审核顺序落成 modern/win7 `shell.go` 职责拆分任务,其余审核整改与 Phase 1 中央目录预扫描继续串行处理,T-302 暂后置。 +当前项目已完成 Phase 0~2、T-301 与审核整改 `T-604`~`T-609`。Windows 安全路径阻断项、图标缓存资源边界、后台结果回 UI 线程的事件接线、双适配器交互契约与 `VisibleItems` 快照生命周期均已关闭;`T-610` 已落成,下一步执行 modern/win7 `shell.go` 纯职责拆分,其余审核整改与 Phase 1 中央目录预扫描继续串行处理,T-302 暂后置。 优先路径: @@ -53,7 +53,7 @@ SoftBox 软件盒子是一个使用 Go + Gio 开发的 Windows 桌面客户端, 2. 已完成 Phase 1:清单验签、ZIP 安全解压、原子切换回滚原型。 3. 已完成 Phase 2 与 T-301:清单/列表/详情/图标缓存 + 可恢复下载队列。 4. 已完成 T-604:modern/Win7 workspace 与 Gio 版本解析彻底隔离。 -5. 已完成 T-606~T-609:图标缓存资源边界、UI 线程事件接线、双 Gio 适配器交互契约,以及“变更时发布新 backing、同 generation 读取零复制”的 `VisibleItems` 生命周期;下一步落成双端 `shell.go` 职责拆分,再串行处理其余整改与 T-302/T-303、Phase 4-6。 +5. 已完成 T-606~T-609:图标缓存资源边界、UI 线程事件接线、双 Gio 适配器交互契约,以及“变更时发布新 backing、同 generation 读取零复制”的 `VisibleItems` 生命周期;下一步执行已落成的 T-610 双端 `shell.go` 职责拆分,再串行处理其余整改与 T-302/T-303、Phase 4-6。 ## 领取任务规则 diff --git a/docs/06-tasks.md b/docs/06-tasks.md index 6175dcf..7cf9225 100644 --- a/docs/06-tasks.md +++ b/docs/06-tasks.md @@ -59,7 +59,7 @@ Phase 1 安全整改按 `docs/review/phase1-security-review.md` 的交叉复核 #### Phase 2 交叉审核加固 -Phase 2 整改按 `docs/review/phase2-review.md` 的交叉复核定稿顺序串行落成。T-606 已关闭正式图标接入前的并发、读取和内存边界;T-607 建立后台图标结果经 application event 回到 Gio UI goroutine 的线程契约;T-608 为两个隔离 Gio 适配器建立交互契约;T-609 修正 `VisibleItems` 快照生命周期。shell 拆分在前一整改完成并提交后再正式编号。 +Phase 2 整改按 `docs/review/phase2-review.md` 的交叉复核定稿顺序串行落成。T-606 已关闭正式图标接入前的并发、读取和内存边界;T-607 建立后台图标结果经 application event 回到 Gio UI goroutine 的线程契约;T-608 为两个隔离 Gio 适配器建立交互契约;T-609 修正 `VisibleItems` 快照生命周期;T-610 在不改变行为的前提下拆分双端 Gio shell 职责。 | ID | 任务 | 依赖 | 验收要点 | | --- | --- | --- | --- | @@ -67,6 +67,7 @@ Phase 2 整改按 `docs/review/phase2-review.md` 的交叉复核定稿顺序串 | T-607 | 建立图标后台结果的 UI 线程事件投递 | T-606 | 后台 Load/Decode 只发布 application event;有界 relay 请求重绘;UI goroutine drain 后 ApplyIcon;过期结果不回写已删除或已换图标的 app | | T-608 | 建立双 Gio 适配器交互契约 | T-607 | 双端同场景验证 Editor/Clickable 接线、AppID 行身份、详情上下文、500 项 viewport 与控件释放;不重复 ViewModel 纯逻辑 | | T-609 | 修正 VisibleItems 快照生命周期 | T-608 | refilter 构造新 backing array 后替换;旧快照跨 model 更新保持稳定;每帧读取不复制;明确单 owner 与只读约定 | +| T-610 | 拆分双端 Gio shell 职责 | T-609 | 两端按状态/根编排、header/navigation、catalog/list、detail、style 拆为同 package 镜像文件;行为、事件顺序、视觉与 Gio 隔离不变 | ### Phase 3 · 下载与安装 diff --git a/docs/current-state.md b/docs/current-state.md index 1be10d8..f3f8502 100644 --- a/docs/current-state.md +++ b/docs/current-state.md @@ -13,7 +13,7 @@ ## 当前快照 - 日期:2026-07-17 -- 阶段:Phase 2 已完成(T-201~T-204);Phase 3 的 T-301 可恢复下载队列已完成;审核整改 T-604~T-609 已完成,T-302 继续暂后置 +- 阶段:Phase 2 已完成(T-201~T-204);Phase 3 的 T-301 可恢复下载队列已完成;审核整改 T-604~T-609 已完成,T-610 已落成待执行,T-302 继续暂后置 - 技术栈:根 Go 1.25 workspace 只纳入 core/app-modern,`app-win7/go.work` 独立纳入 core/app-win7;版本闸门证明 modern Gio v0.10.1 与 win7 Gio v0.6.0 不交叉解析 - 生产代码:core 已有 Catalog/本地状态/存储、共享 Windows 安全相对路径策略、安全 ZIP 解压/回滚原型、发布稳定只读 generation 的无 IO 软件列表模型、按 key in-flight + 流式有界读取 + 32 MiB/256-key LRU 的可信图标缓存、图标 Load/Decode 事件发布用例、有界 application event relay,以及默认并发 2 的持久可恢复下载队列;modern/win7 主循环已接 relay/Invalidate,AppShell 已实现搜索/分类/视图、惰性列表、详情右栏、图标请求身份与 UI-only ApplyEvent/ApplyIcon - 测试:core 覆盖 Catalog、列表快照 generation/零复制、SemVer/12 状态、本地安装记录、Windows dot-space/设备名/Unicode 折叠路径攻击、ZIP destination 包含性、图标并发/取消/读取边界/LRU、图标事件身份/失败分类/relay 背压与关闭、下载并发/暂停/取消/重试/Range/断连/恢复/事件失败与文件身份替换;两个 app 覆盖 Editor/视图/分类/行/恢复/关闭接线、500 项 viewport、AppID 控件与分类控件生命周期、详情上下文、空状态语义、UI drain 前后、最新/取消/换引用图标结果与平台 stub;安装恢复矩阵保持通过 @@ -21,14 +21,14 @@ - 标准启动路径:`./init.sh` / `./init.ps1`(同步依赖、执行完整 Phase 0 闸门、打印双目标构建命令) - 标准验证路径:`bash scripts/verify_phase0.sh` / `./scripts/verify_phase0.ps1` - 版本管理:git 已初始化,main 分支,远端 origin 为 Gitea `opc/soft_quay`;harness 文档已提交 -- 当前 blocker:无;下一步按 `docs/review/phase2-review.md` 最终顺序落成 modern/win7 `shell.go` 职责拆分任务;Phase 1 中央目录预扫描等继续串行,T-302 继续后置 +- 当前 blocker:无;下一步领取并执行 `T-610`,在各自 Gio package 内按镜像职责拆分 modern/win7 `shell.go`;Phase 1 中央目录预扫描等继续串行,T-302 继续后置 ## 当前目录要点 | 路径 | 状态 | 说明 | | --- | --- | --- | | `docs/` | 已有 | harness coding 文档集(本次初始化完成) | -| `docs/tasks/` | 已有 | Phase 0~2、T-301 与 T-604~T-609 已完成;其余审核整改尚未编号,T-302 暂后置 | +| `docs/tasks/` | 已有 | Phase 0~2、T-301 与 T-604~T-609 已完成;T-610 已落成待执行,其余审核整改尚未编号,T-302 暂后置 | | `scripts/` | 已有 | harness 治理、core 边界、Go 版本检查与 Phase 0 双平台验证入口 | | `core/` | 已建 | Go 1.20 兼容;已有正式 Catalog、本地状态/存储、共享 Windows safepath、列表模型、有界并发图标缓存、图标事件/relay、可恢复下载队列与 Phase 1 安装安全原型 | | `app-modern/` | 已建 | Go 1.25.0 + Gio v0.10.1;Modern AppShell 已接入虚拟列表、详情、图标事件 drain/过期拒绝和内存 ImageOp | @@ -42,7 +42,7 @@ - 已完成:Phase 0 的 `T-001`~`T-004`;Phase 1 的 `T-101`、`T-102`、`T-103`;Phase 2 的 `T-201`~`T-204`;Phase 3 的 `T-301`;审核整改 `T-604`~`T-609`。 - 正在进行:无。 -- 下一个可领取任务:无;先按 `docs/review/phase2-review.md` 最终顺序落成 modern/win7 `shell.go` 职责拆分任务。 +- 下一个可领取任务:`T-610`(依赖 `T-609` 已完成),双端 `shell.go` 纯职责拆分。 ## 当前可运行内容 diff --git a/docs/review/phase2-review.md b/docs/review/phase2-review.md index 9c64cf0..ab62842 100644 --- a/docs/review/phase2-review.md +++ b/docs/review/phase2-review.md @@ -287,4 +287,5 @@ modern/win7 的 `ApplyIcon` 都直接写 `shell.icons` map,Layout 同时读取 - `T-607` 已完成最终处理顺序第 2 项:后台图标 Load/Decode 只发布强类型 application event,有界 FIFO relay 无损背压并请求重绘,由 Gio Frame/UI goroutine drain 后执行 `ApplyEvent`/`ApplyIcon`;最新请求、删除 app、IconRef/DPI 变化和取消都阻断迟到结果回写。core 与双 workspace 定向测试及完整闸门通过。 - `T-608` 已完成最终处理顺序第 3 项:modern/win7 使用除 edition/窗口尺寸外一致的场景矩阵,验证 Editor/Clickable 经 Layout 更新共享 model、重排后 AppID 行身份、详情关闭上下文、500 项 viewport、app/category controls 释放及两类空状态语义;双端定向重复测试与完整闸门通过,生产 `shell.go` 无需修正。 - `T-609` 已完成最终处理顺序第 4 项:`refilter` 在局部新 backing array 完整构造后发布,旧 generation 跨五类公开 model mutation 保持稳定;同 generation 读取共享 backing 且零分配。core 定向重复测试、双 Gio 回归与完整闸门通过,未扩展为并发安全或防御性深拷贝。 -- `shell.go` 拆分和 unsafe cache 诊断尚未编号;下一任务从双端 `shell.go` 职责拆分开始,继续按顺序串行落成。 +- `T-610` 已按最终处理顺序第 5 项落成待执行:仅在各自 `gio` package 内把双端 `shell.go` 拆为状态/根编排、header/navigation、catalog/list、detail、style 镜像职责文件,保留版本差异且不改变行为。 +- unsafe cache 诊断尚未编号;待 T-610 完成、验证并提交后再按顺序串行落成。 diff --git a/docs/tasks/T-610.md b/docs/tasks/T-610.md new file mode 100644 index 0000000..cb6abaf --- /dev/null +++ b/docs/tasks/T-610.md @@ -0,0 +1,82 @@ +--- +id: T-610 +title: 拆分双端 Gio shell 职责 +phase: 2 +deps: [T-609] +status: TODO +created: 2026-07-17 +issue: null +context_ref: null +claim_branch: null +work_branch: null +write_paths: + - docs/tasks/T-610.md + - app-modern/ui/gio/ + - app-win7/ui/gio/ + - docs/routes.md + - docs/04-architecture.md + - docs/05-coding-rules.md + - docs/review/phase2-review.md + - docs/00-ai-start-here.md + - docs/06-tasks.md + - docs/current-state.md +--- + +## 问题 / 背景 + +modern 与 Win7 的 `ui/gio/shell.go` 分别达到 959 行和 880 行,同时承载 `AppShell` 状态与快照生命周期、根布局编排、输入 drain、header/category/view 导航、catalog/list/row/icon、detail 和样式/文案 helper。代码图也把 `Layout`、`layoutContent`、`layoutAppRow`、`layoutDetail` 与 `panel` 识别为同一高耦合热点。继续在单文件中增加下载、设置或授权视图,会扩大冲突范围和两套隔离 Gio 适配器的人工 diff 噪声。 + +双端平行实现是既定架构取舍:modern 锁定 Gio v0.10.1,Win7 锁定 Gio v0.6.0,布局细节和可用 API 存在有意差异。本任务不尝试共享 Gio 控件代码,只在各自现有 `gio` package 内按一致职责拆文件,让后续改动有明确落点。T-608 已提供双端适配器交互契约,T-609 已冻结列表快照生命周期,当前保护面足以约束纯组织性移动。 + +本任务是行为不变的维护性重构,不交付新界面或业务能力,也不借拆分修正视觉、文案、事件时序或模型语义。 + +## 方案 + +1. 在移动前用代码图记录两个 `shell.go` 的声明清单和调用关系,把现有公开/未公开符号作为重构基线;移动后再次核对每个符号恰有一个定义,没有遗漏、复制或意外改名。 +2. 在 modern 与 Win7 的 `ui/gio` package 中采用相同文件职责: + - `shell.go`:保留 `AppShell` 状态、构造、`ApplyIcon`/`SetItems` 生命周期、根 `Layout` 与 `drainInput` 编排。 + - `shell_header.go`:承载 header、category、view/filter 导航和 footer 等顶部/导航职责。 + - `shell_catalog.go`:承载 content/catalog、虚拟列表、app row、icon 与 empty state;行控件状态跟随该职责。 + - `shell_detail.go`:承载 detail 布局及其字段、动作和 fallback/reason helper。 + - `shell_style.go`:承载 palette/theme、panel 绘制、view/status 文案与颜色 helper。 + modern-only 的 `layoutCatalog`、`layoutFooter`、`actionLabel` 等放入对应职责文件,Win7 不为追求文本一致而增加空壳或复制 modern 实现。 +3. 只移动完整声明并收敛各文件 import,保持 package 名、接收者、函数签名、常量值、控件实例、map/list 所有权和调用顺序不变;执行 `gofmt`,不做顺手重命名或逻辑整理。 +4. 冻结根布局与交互不变量: + - 每帧仍先 drain application/UI input,再按原顺序布局 header、content/detail/footer。 + - 搜索、分类、view、行点击、关闭详情、空状态恢复和虚拟列表 viewport 的事件处理顺序不变。 + - `rowControls` 继续按 app ID 保持,删除项/category controls 继续释放;`layout.List.Position` 与 selection/detail 上下文不重置。 + - 图标请求身份、UI goroutine drain、`ApplyEvent`/`ApplyIcon`、过期结果拒绝和 ImageOp 剪枝规则不变。 + - Layout 继续无 IO,所有尺寸、颜色、圆角、间距、控件顺序、可见文案和语义标签不变。 +5. 复用 T-608 适配器契约、T-607 图标事件测试和既有 shell 测试;双端分别重复运行 UI 测试,再执行完整隔离 workspace 构建闸门。测试只在发现现有保护面无法观察拆分不变量时补充,不得为新文件布局复制 ViewModel 纯逻辑测试。 +6. 同步架构、路由和编码规则,记录双端 shell 文件职责、同 package 边界和未来 UI 变更的落点;审核追踪与当前状态在任务完成时更新。 + +## 验收要点 + +- modern 与 Win7 均存在 `shell.go`、`shell_header.go`、`shell_catalog.go`、`shell_detail.go`、`shell_style.go`,职责镜像且仍属于各自 `gio` package;允许版本特有声明只出现在一端。 +- 两个 `shell.go` 只保留 AppShell 状态/生命周期与根编排,不再定义 catalog row/icon、detail 或 panel/style helper;原声明清单中的每个符号在各自 package 内恰有一个定义。 +- `NewAppShell`、`NewTheme`、`Layout`、`SetItems`、`ApplyIcon` 等既有可调用 API、签名和接收者不变;不新增跨 workspace import、共享 Gio package 或兼容 shim。 +- `git diff` 可解释为声明移动、import 收敛和必要文档同步;无颜色/尺寸/文案、控件顺序、事件 drain、列表/selection、图标或快照语义变化。 +- modern Go 1.25.0 与 Win7 Go 1.20.14 下 `go test -count=10 ./ui/gio` 分别通过;T-608 的 Editor/Clickable、AppID、detail context、500 项 viewport、controls lifecycle 和空状态矩阵保持全绿。 +- 双端图标事件/过期拒绝测试保持通过;完整 `./scripts/verify_phase0.ps1` 通过,继续证明 Gio v0.10.1/v0.6.0 隔离及 Windows amd64 双目标可构建。 +- `python scripts/validate_agent_context.py`、`python scripts/validate_harness_governance.py` 与提交前差异检查通过。 + +## 边界(不改什么) + +- 不增加下载、安装、设置、授权或其他新视图,不改变任何可见 UI、交互、可访问文案、窗口尺寸或主题。 +- 不拆分 `AppShell` 为多个状态对象,不重写布局算法,不调整事件处理、列表虚拟化、控件生命周期、图标生命周期或 `VisibleItems` generation 契约。 +- 不提取跨 modern/win7 的 Gio 共享层,不让任一 workspace import 另一端,不升级或统一 Go/Gio 版本。 +- 不修改 core/domain/application、平台层、命令入口、协议或 Schema,不恢复 T-302,不顺带处理 `ErrIconCacheUnsafe` 诊断/quarantine。 +- 不以文件行数为目标制造过度碎片;验收以职责边界和行为不变为准,不设机械最大行数。 +- 不修改、提交或删除用户的 `soft_quay.code-workspace`。 + +## 协作约束 + +- 按仓库当前规则由单 Agent 串行执行,不启动子 Agent。 +- 本任务只允许修改 frontmatter 中的 `write_paths`;若拆分暴露必须改行为才能通过的既有缺陷,停止并记录,不得在 T-610 内扩边修复。 +- T-610 完成、完整验证并提交前,不落成或领取 unsafe cache 诊断、Phase 1 后续整改或 T-302。 + +## 执行记录 + +- 2026-07-17:根据 `docs/review/phase2-review.md` 交叉复核定稿的第五优先级维护项落成任务;现有全局最大任务为 T-609,因此取 T-610,依赖已完成的 T-609。 +- 2026-07-17:代码图确认 modern `shell.go` 为 959 行、29 个声明,Win7 `shell.go` 为 880 行、25 个声明;两端都把状态/根编排、header、catalog/list、detail 和 style 聚合在单文件,主要差异为 modern 独有的 `layoutCatalog`、`layoutFooter` 与 `actionLabel` 等实现。 +- 2026-07-17:冻结为各自 `gio` package 内五文件镜像职责拆分;保留版本特有差异,不共享 Gio 代码、不改变行为,并以 T-607/T-608/T-609 已有事件、适配器和 snapshot 契约作为回归保护面。