63 lines
6.0 KiB
Markdown
63 lines
6.0 KiB
Markdown
---
|
||||
|
|
id: T-617
|
|||
|
|
title: 自更新事务恢复与健康门禁加固
|
|||
|
|
phase: 4
|
|||
|
|
deps: [T-403]
|
|||
|
|
status: TODO
|
|||
|
|
created: 2026-07-19
|
|||
|
|
issue: null
|
|||
|
|
context_ref: null
|
|||
|
|
claim_branch: null
|
|||
|
|
work_branch: null
|
|||
|
|
write_paths:
|
|||
|
|
- docs/tasks/T-617.md
|
|||
|
|
- core/updater/updater.go
|
|||
|
|
- core/updater/recovery.go
|
|||
|
|
- core/updater/updater_test.go
|
|||
|
|
- app-modern/cmd/softbox/update_health_test.go
|
|||
|
|
- app-win7/cmd/softbox/update_health_test.go
|
|||
|
|
- docs/review/phase4-review.md
|
|||
|
|
- docs/api.md
|
|||
|
|
- docs/04-architecture.md
|
|||
|
|
- docs/06-tasks.md
|
|||
|
|
- docs/00-ai-start-here.md
|
|||
|
|
- docs/current-state.md
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 问题 / 背景
|
|||
|
|
|
|||
|
|
`docs/review/phase4-review.md` 的 O1/O4 确认 T-403 的自更新状态机保留了 backup、从不强杀进程,Windows 真机锁/杀毒/断电仍由 T-601 验证;但无头自动测试未覆盖 journal、rename、目录同步、清理失败和 `staging_activated`/`launched`/`committed` 的中断恢复,也没有双端主程序内部 health flag 的参数拒绝测试。
|
|||
|
|
|
|||
|
|
进一步复核发现一个必须修复的恢复一致性问题:`prepared` transaction 写入后,`current(app) → backups/<request-id>` 的 rename 可能已成功,但其目录同步失败。此时当前代码返回 `failBeforeActivation`,磁盘实际为“target 缺失、backup 存在、phase=prepared”;下次 `recoverLayout` 却把 `prepared` 一律当作未移动而只删除 journal,旧 app 不会恢复。这是可用性/恢复缺陷,不能仅靠 T-601 真机验证或测试补充掩盖。
|
|||
|
|
|
|||
|
|
## 方案
|
|||
|
|
|
|||
|
|
1. 收紧 `core/updater` 的 `prepared` 恢复语义:只根据受限布局内经 `Lstat` 验证的 target/backup 实际状态决定收敛。target 存在且 backup 不存在时才可删除 prepared journal;target 缺失且 backup 存在时必须先恢复 backup;任何其他组合 fail closed 并保留 journal/材料。首次 backup rename 返回错误时,`Update` 必须尝试同一受限恢复路径;恢复不能安全完成时保留原始错误、`ErrRecoveryRequired`、journal 与 backup,绝不删除 data/licenses 或强杀进程。
|
|||
|
|
2. 扩展 `core/updater/updater_test.go`,优先复用既有 `DirectorySyncer` 注入点和受控临时目录,不为测试引入通用生产文件系统抽象。覆盖 backup rename 后 sync 失败的即时/下次恢复、健康超时后 rollback 被结构性阻塞并在条件解除后 Recover、prepared/target_backed_up/staging_activated/launched/committed 的中断状态、transaction 写入/目录同步/cleanup 失败的错误链和可恢复性。对无法在无头环境稳定模拟的 Windows EXE 锁,只验证相同 fail-closed 状态机,不宣称替代 T-601。
|
|||
|
|
3. 两个 `cmd/softbox` 新增镜像的 `update_health_test.go`,验证非内部 flag 不被消费、health flag 缺 request ID 或含多余参数时返回已处理错误;不伪造 `os.Executable`、目录 sync 或成功 health 确认。
|
|||
|
|
4. 更新 Phase 4 审核结论、架构/API 的自更新恢复表述和项目快照:明确 prepared rename+sync 不一致已由本任务修复;保持“可信自更新包下载/验签/版本选择/UI 触发、真实 Windows 故障注入尚未装配”的边界。
|
|||
|
|
|
|||
|
|
## 验收要点
|
|||
|
|
|
|||
|
|
- 任何 `prepared` journal 都不会在 target 缺失且 managed backup 存在时被直接删除;成功恢复后旧 `app/SoftBox.exe` 回到 target,失败时保留 journal/backup 并让 `errors.Is(err, ErrRecoveryRequired)` 成立。backup rename 后 directory sync 失败不再使旧 app 失去受控恢复路径。
|
|||
|
|
- 对 prepared、target_backed_up、staging_activated、launched、committed 五个可持久化 phase,测试构造合法受限布局并证明 Recover 只会恢复旧 app 或完成已确认的新 app;不安全/矛盾布局 fail closed,不触碰 `data/`、`licenses/` 或受管根外路径。
|
|||
|
|
- health timeout 后 rollback 被阻塞时,返回同时保留 health 原因与恢复原因,保留 journal/backup;解除阻塞并再次 Recover 后状态可预测收敛。transaction/rename/sync/cleanup 的可注入失败均保留可检查错误链;不能在无头测试稳定触发的 Windows 文件锁仅记录为 T-601 真机项。
|
|||
|
|
- modern 与 Win7 的内部 health CLI 参数拒绝测试一致;Gio Layout 无 I/O,core 继续保持 Go 1.20 且不 import Gio、Windows API 或第三方文件系统抽象。
|
|||
|
|
- `go -C core vet ./...`、`go -C core test -count=10 ./updater`、`go -C core test -count=1 ./...`、两个 app 的 `cmd/softbox` 全包测试、双端 Windows amd64 主程序/Updater 构建、`./scripts/verify_phase0.ps1`、`python scripts/validate_agent_context.py`、`python scripts/validate_harness_governance.py` 与 `git diff --check` 全部通过。真实 Windows 锁、杀毒和断电不在本任务完成声明中。
|
|||
|
|
|
|||
|
|
## 边界(不改什么)
|
|||
|
|
|
|||
|
|
- 不实现可信自更新 Catalog/package 下载、签名、SHA-256、版本选择、自动触发、Updater UI、命名管道、强杀、MSI、服务或注册表;不把未验证 staging 变成可执行来源。
|
|||
|
|
- 不把 Windows 文件锁、杀毒软件、UAC/签名发布或物理断电的真机结论移入单元测试;它们仍归 T-601/T-603。
|
|||
|
|
- 不改子软件 install/update 事务、Catalog/下载/授权协议、Gio/Go 工具链、data/licenses 语义或平台公开接口;不为方便失败注入引入泛化生产文件系统 mock 层。
|
|||
|
|
|
|||
|
|
## 协作约束
|
|||
|
|
|
|||
|
|
- 当前项目为单 Agent 串行模式;当前 Agent 独占全部 `write_paths`,自行完成规格、恢复状态机审查、测试、验证和提交,不启动子 Agent。
|
|||
|
|
- 先提交本任务规格及路线图/快照/审核修正;领取后将本文件改为 `DOING`,填写当前 HEAD `context_ref` 与 `work_branch: agent/codex/T-617`,再运行基线和实现。
|
|||
|
|
- T-501 仅在本任务 `DONE`、完整验证和实现提交后正式落成;不得把 O2/O5 的可信 Catalog、下载消费、授权或发布源装配夹带入本任务。
|
|||
|
|
|
|||
|
|
## 执行记录
|
|||
|
|
|
|||
|
|
- 2026-07-19:正式落成。根据 Phase 4 审核 O1/O4 及补充状态机复核,冻结“prepared rename 后 sync 失败必须恢复/保留、五 phase Recover、故障错误链与双端 health flag 参数拒绝”的最小整改闭环;真实 Windows 锁与发布侧装配继续后置。
|