2026-07-19 21:27:26 +08:00
|
|
|
|
---
|
|
|
|
|
|
id: T-402
|
|
|
|
|
|
title: 子软件更新编排与自然退出等待
|
|
|
|
|
|
phase: 4
|
|
|
|
|
|
deps: [T-401]
|
2026-07-19 21:39:33 +08:00
|
|
|
|
status: DONE
|
2026-07-19 21:27:26 +08:00
|
|
|
|
created: 2026-07-19
|
|
|
|
|
|
issue: null
|
2026-07-19 21:39:33 +08:00
|
|
|
|
context_ref: fda52a57ca0d4c449e206c163864bdd3e354cbaf
|
2026-07-19 21:27:26 +08:00
|
|
|
|
claim_branch: null
|
2026-07-19 21:39:33 +08:00
|
|
|
|
work_branch: agent/codex/T-402
|
2026-07-19 21:27:26 +08:00
|
|
|
|
write_paths:
|
|
|
|
|
|
- docs/tasks/T-402.md
|
|
|
|
|
|
- core/application/update/
|
|
|
|
|
|
- app-modern/platform/windows/
|
|
|
|
|
|
- app-win7/platform/windows/
|
|
|
|
|
|
- docs/api.md
|
|
|
|
|
|
- docs/04-architecture.md
|
|
|
|
|
|
- docs/00-ai-start-here.md
|
|
|
|
|
|
- docs/current-state.md
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 问题 / 背景
|
|
|
|
|
|
|
|
|
|
|
|
T-401 已提供精确 entrypoint 的 Toolhelp 运行状态和 `InstallService` 在 staging 前、`current → backup` 临界区的 fail-closed 复查,但没有“可更新识别 → 请求用户关闭 → 有限等待自然退出 → 重新安装”的应用编排。直接调用安装器时,调用方既无法区分用户取消、等待超时和检测不可用,也无法证明更新过程中不会强杀进程或把未可信下载事件当作安装请求。
|
|
|
|
|
|
|
|
|
|
|
|
现有 production cmd 仍没有可信 Catalog、许可证和 completed-download 消费来源,Gio shell 也没有更新确认交互。因此本任务必须建立可测试的纯 core 更新 use case 与双端自然退出等待能力,但不能伪称已具备端到端 UI/下载/授权闭环。
|
|
|
|
|
|
|
|
|
|
|
|
## 方案
|
|
|
|
|
|
|
|
|
|
|
|
1. 新建纯 Go 1.20 的 `core/application/update`。更新请求只组合既有、已由外层从可信 Catalog 选择的 `install.InstallRequest`;use case 先通过本地受控记录/`current` 读取已装版本和旧 entrypoint,拒绝缺少启动元数据、不存在的安装、同版本/降级 Catalog 选择和不安全布局。它不接受 UI 提供的 EXE、路径、参数或未验证的 app/version/hash。
|
|
|
|
|
|
2. `UpdateService` 显式注入记录解析、精确 `TargetStateChecker`、关闭确认器、自然退出等待器和 `InstallRunner`。仅当旧 entrypoint 已运行时才请求关闭确认;拒绝确认则不改变磁盘。确认后等待器以配置的正且有上限的 timeout 等待自然退出,context 取消、超时、快照错误分别保留稳定结果和错误链。绝不调用 kill/TerminateProcess、脚本、Shell 或任意 IPC;`prepare_update/ready` 命名管道仍是 V1.1。
|
|
|
|
|
|
3. 退出成功后才调用现有 `InstallService`;安装器仍在 staging 前和 switch 临界区复查,以覆盖等待结束后的重新启动竞态。更新 service 不直接改 `current`、`backup`、journal、`data/` 或 `licenses/`,也不吞掉底层 `InstallError`。失败时旧 current/installed record 的可启动性由已验证的 Switcher rollback 保证。
|
|
|
|
|
|
4. 双端 `platform/windows` 扩展 T-401 的相同 public contract,提供可取消、固定短间隔的 Toolhelp 轮询等待器。等待器只查询该精确完整 entrypoint;检测错误 fail closed,达到 deadline 返回稳定超时,不把快照失败、取消或相同 basename 误报为退出。非 Windows stub 返回明确不支持错误。测试以 clock/snapshot seam 覆盖首次已退出、运行后退出、取消、超时、检测失败和同名不同路径。
|
|
|
|
|
|
5. 协议/架构文档固定更新结果码、确认/等待顺序以及“外层可信 Catalog/下载来源尚未装配”的事实。两个 cmd/Gio 本任务不注入 allow-all 授权、不会在 Layout 等待/检查进程,也不临时接入假的更新按钮;将来 adapter 只能在后台提交 app ID 与已验证选择,再以安全事件反馈结果。
|
|
|
|
|
|
|
|
|
|
|
|
## 验收要点
|
|
|
|
|
|
|
|
|
|
|
|
- `UpdateService` 只接受严格的可信 install selection,确认本地记录版本低于 Catalog 目标;未安装、旧 v1 缺启动元数据、版本相同/降级、不安全 current 均 fail closed,且不会调用确认、等待或安装。
|
|
|
|
|
|
- 运行中目标仅在确认后等待正常退出;拒绝、context 取消、超时、Toolhelp 检测失败都不调用安装器、不改 current/record,不强杀。退出后安装器收到原始可信 selection,并由其两次复查阻断退出后的重新启动竞态。
|
|
|
|
|
|
- 安装器成功时返回 app ID/新版本;安装失败保持其可 `errors.Is` 的 `InstallError`/稳定失败码,旧版本仍可通过受控 launch 路径验证。测试覆盖成功、确认拒绝、wait 各失败、重启竞态、install failure/rollback,以及 `data/`、`licenses/` 字节不变。
|
|
|
|
|
|
- 两个 `platform/windows` public contract 一致;Windows Toolhelp wait 编译,非 Windows stub 明确报不支持,snapshot/clock seam 覆盖路径碰撞与所有等待终态。没有 Gio Layout I/O、Windows API 或第三方依赖进入 core。
|
|
|
|
|
|
- `go -C core vet ./...`、`go -C core test -count=1 ./...`、`go -C core test -count=10 ./application/update ./application/install ./installer`、两端 Windows amd64 构建、`./scripts/verify_phase0.ps1`、`python scripts/validate_agent_context.py`、`python scripts/validate_harness_governance.py` 全部通过;执行记录写明 production cmd 尚未具备可信 Catalog/许可证/download 消费装配。
|
|
|
|
|
|
|
|
|
|
|
|
## 边界(不改什么)
|
|
|
|
|
|
|
|
|
|
|
|
- 不实现 completed download 的生产消费、下载任务删除/保留协议、Catalog fetch、许可证策略或 allow-all 授权;继续由后续可信外层装配和 T-501~T-503 处理。
|
|
|
|
|
|
- 不实现强杀、等待窗口/进度 UI、命名管道 `prepare_update/ready`、保存提示 IPC、自动重启子软件、文件锁/杀毒/断电真机结论;T-601 仍负责 Windows 环境验证。
|
|
|
|
|
|
- 不改 ZIP、签名、安装 transaction 格式或 `InstallService` 的已有安全验证;不实现 SoftBox 自身更新、Updater EXE、`data/`/`licenses/` 迁移(T-403)。
|
|
|
|
|
|
- 不升级 Gio/Go 工具链、不把 Gio/Windows API/SQLite 依赖引入 core,不开放任意 app path、EXE、参数、shell command 或 URL。
|
|
|
|
|
|
|
|
|
|
|
|
## 协作约束
|
|
|
|
|
|
|
|
|
|
|
|
- 当前项目为单 Agent 串行模式;当前 Agent 独占全部 `write_paths`,自行完成规格、实现、测试和提交,不启动子 Agent。
|
|
|
|
|
|
- 先提交本任务规格和项目快照;领取后将本文件改为 `DOING`,填写当前 HEAD 的 `context_ref` 与 `work_branch: agent/codex/T-402`,再重新记录基线和实现。
|
|
|
|
|
|
- T-403 仅在本任务 `DONE`、完整验证和实现提交后正式落成。若 production cmd 仍缺可信 Catalog/许可证/download 消费源,必须保持这一非闭环事实,不能用测试 fake 伪装生产可用。
|
|
|
|
|
|
|
|
|
|
|
|
## 执行记录
|
|
|
|
|
|
|
|
|
|
|
|
- 2026-07-19:正式落成。以 T-401 的完整路径运行检测和 Switcher 临界区复查为基础,冻结“确认关闭→有限自然退出等待→委托可信安装器→二次运行复查”的更新顺序;明确下载/授权生产装配、命名管道、强杀和 T-601 真机验证不在本任务。
|
2026-07-19 21:39:33 +08:00
|
|
|
|
- 2026-07-19:领取任务,基于 `fda52a57ca0d4c449e206c163864bdd3e354cbaf` 在 `agent/codex/T-402` 执行;T-401 基线与正式任务文档校验已通过,再实现更新编排。
|
|
|
|
|
|
- 2026-07-19:完成。新增纯 core `application/update`,以受控本地记录验证严格更新版本,在运行中经关闭确认和有限自然退出等待后才委托原始可信 install request;安装器保留 staging 前与 switch 临界区复查,所有安装错误链可观察。双端 `platform/windows` 增加可取消的完整路径自然退出轮询与非 Windows fail-closed stub。production cmd 没有可信 Catalog/许可证/completed-download 消费和关闭确认 UI,故未注入 fake 或 allow-all 闭环。验证通过:`go -C core vet ./...`、`go -C core test -count=1 ./...`、`go -C core test -count=10 ./application/update ./application/install ./installer`、双端 Windows amd64 构建与 Linux stub test 编译、`./scripts/verify_phase0.ps1`、`python scripts/validate_agent_context.py`、`python scripts/validate_harness_governance.py`。
|