Files
soft_quay/docs/tasks/T-615.md

63 lines
6.3 KiB
Markdown
Raw Permalink 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.
---
id: T-615
title: 保留安装输出 I/O 根因并统一磁盘满诊断
phase: 3
deps: [T-303]
status: DONE
created: 2026-07-19
issue: null
context_ref: d1603c52b6c2df645db11a808ced9a3cc8b3e764
claim_branch: null
work_branch: agent/codex/T-615
write_paths:
- docs/tasks/T-615.md
- core/installer/
- core/application/install/
- docs/api.md
- docs/04-architecture.md
- docs/00-ai-start-here.md
- docs/06-tasks.md
- docs/current-state.md
---
## 问题 / 背景
T-303 的磁盘预检只能 fail-fast,不能消除“查询后被其他进程占满”的窗口。当前 `Extractor.extractPlan` 将 `io.Copy` 的所有失败包成 `ErrArchiveCorrupt`,并以 `%v` 丢弃原始 error chain;staging 写入的 ENOSPC 因而可能被错误映射为 `zip_corrupt`。此外,staging 清理使用忽略错误的 `os.RemoveAll`:旧 `current` 因尚未进入 switch 而安全,但未清理的 staging 会让后续安装缺少明确的恢复语义。
这不是包信任边界绕过,但违反 T-303 的稳定失败码与可由 `errors.Is` 识别根因的诊断契约。`docs/review/phase3-review.md` 的交叉复核将其裁定为 P1;必须在 T-401 装配真实运行状态/启动能力之前关闭。
## 方案
1. 在 `core/installer` 区分 ZIP 输入(打开、读取、CRC/关闭)失败与 staging 输出(目录/文件创建、写入、sync、close)失败。前者继续归入 `ErrArchiveCorrupt`;后者使用稳定的 staging-output sentinel,并保留底层 OS 错误的 `errors.Is` 链。不得把目标写入错误伪装为“read ZIP”。
2. 将 extraction 失败后的 staging 清理由“忽略 `RemoveAll` 错误”改为受控、可观察的 managed staging 清理。若主失败与清理失败并存,返回能同时被 `errors.Is` 识别的错误;下一次 `Recover` 必须只在已验证 app layout 内收敛残留 staging,或 fail closed 并给出确定的恢复错误,不能静默覆盖 `current`。
3. 在 `core/application/install` 为平台提供的、可测试的 `StorageFailureClassifier` 注入边界;它只判断已保留的底层 I/O 错误是否为磁盘满,core 不 import Windows API。`InstallServiceConfig` 必须显式要求该依赖;可识别的预检、write、sync、close 磁盘满均映射为 `disk_full`,其他 staging 输出 I/O 仍映射 `install_failed`,ZIP/CRC 输入错误仍映射 `zip_corrupt`。
4. 同步 `docs/api.md`/架构中的失败语义,并以内部可注入的 file-operation/failure seam 补齐测试:输入 CRC 损坏、staging write/sync/close 的 ENOSPC、普通输出 I/O、清理失败和后续恢复。测试必须证明原始根因保留、错误码准确、已有 `current`/`installed-app.json` 不变、首次安装不产生可执行 `current`。
## 验收要点
- ZIP/CRC 输入失败仍有 `ErrArchiveCorrupt` 和 `zip_corrupt`;staging 输出写入失败不携带该 sentinel,且原始输出错误可由 `errors.Is` 识别。
- fake `StorageFailureClassifier` 证明预检、write、sync、close 任一可识别 ENOSPC 都返回 `FailureCodeDiskFull`;无法识别的输出 I/O 返回 `FailureCodeInstallFailed`,不泄漏原始错误给 UI 合约。
- 清理失败不被吞掉;主 extraction 错误和 cleanup 错误均可由 `errors.Is` 检测。后续 `Recover` 只处理已验证的 managed staging,不能影响 `current`、`data/` 或 `licenses/`。
- 更新失败时旧 `current` 与旧 `installed-app.json` 字节保持不变;首次失败不留下 executable `current`。所有新增构造路径都必须显式提供 disk、target-state 与 storage-failure classifier,不能静默降级。
- `go -C core vet ./...`、`go -C core test -count=1 ./...`、`go -C core test -count=10 ./installer ./application/install`、`./scripts/verify_phase0.ps1`、`python scripts/validate_agent_context.py` 与 `python scripts/validate_harness_governance.py` 全部通过;执行记录写明结果。
## 边界(不改什么)
- 不修改 Catalog、package、app manifest、installed-app 或下载任务 Schema,不改变 T-302 的同句柄验证、staging/switch/rollback 顺序。
- 不实现 Toolhelp、运行状态复查、等待退出、强杀、启动程序、Gio 安装编排或下载完成文件消费;O1 进入 T-401,O3 留给后续下载→安装生产编排任务。
- 不在 core import Windows API、Gio、SQLite 或第三方依赖;不以当前 OS errno 常量取代平台分类接口。
- 不做物理断电、杀毒软件或文件锁真机故障注入(T-601)。
## 协作约束
- 当前项目为单 Agent 串行模式;当前 Agent 独占全部 `write_paths`,自行完成设计、安全复核、测试和提交,不启动子 Agent。
- 先提交本任务规格及路线图/架构/状态文档;领取后将本文件改为 `DOING`,填写当前 HEAD `context_ref` 与 `work_branch: agent/codex/T-615`,再运行基线和实现。
- T-401 仅在本任务 `DONE`、验证和实现提交后再正式落成;其规格必须消费 T-303 的 `TargetStateChecker`,并实现切换临界区的最后一次运行状态复查。
## 执行记录
- 2026-07-19:正式落成。根据 Phase 3 交叉复核冻结输出 I/O/ZIP 输入的错误分界、可注入磁盘满分类、清理失败恢复语义及 T-401/O1 与后续编排/O3 的边界。
- 2026-07-19:领取任务,基于 `d1603c52b6c2df645db11a808ced9a3cc8b3e764` 在 `agent/codex/T-615` 执行;先运行基线验证,再实现与复核。
- 2026-07-19:完成。`Extractor` 以内部 file-operation seam 区分 ZIP 输入与 staging 创建/write/sync/close 输出,新增可保留原始错误链的 `ErrStagingOutput`;清理失败以 `ErrStagingCleanup` 与主失败共同返回。无 journal 的残留 staging 仅在通过 app layout 校验后由 Recover 删除,不影响 current、installed-app、data 或 licenses。`InstallService` 强制注入 `StorageFailureClassifier`,只对 `ErrStagingOutput` 中的平台可识别磁盘满返回 `disk_full`,其他输出 I/O 返回 `install_failed`。
- 2026-07-19:验证通过:基线 `./init.ps1`;`go -C core vet ./...`;`go -C core test -count=1 ./...`;`go -C core test -count=10 ./installer ./application/install`;`./scripts/verify_phase0.ps1`;`python scripts/validate_agent_context.py`;`python scripts/validate_harness_governance.py`。新增写/sync/close ENOSPC、普通输出 I/O、CRC 分界、清理失败及后续恢复测试。