# v6.3.12 热更新最终提交修复

本版本针对“更新文件全部下载成功，但退出后仍然是旧版本”的问题重构本地替换阶段。

## 根因

v6.3.10/v6.3.11 的增量更新虽然只下载少量变化文件，但替换器在覆盖前会递归备份整个 Portable 程序目录。
Portable 中包含 `_internal`、runtime、CLI/Node 等大量文件，任意长路径、文件占用、权限或安全软件拦截都可能让整个备份失败并回滚，因此服务端可以看到所有更新文件 HTTP 200，但客户端最后仍保持旧版本。

## 修复

- 回退快照只备份本次 stage 中真正发生变化的文件，不再递归备份整个客户端目录。
- 非 EXE 文件先更新，主 EXE 使用同目录临时文件替换，`VERSION.txt` 永远最后提交。
- 只有全部程序文件和主 EXE 成功后才把 VERSION.txt 改成目标版本。
- 主 EXE 被安全软件短暂占用时最多等待 30 秒，并在第 5 次尝试后清理同名旧进程。
- 外部替换器优先使用 DETACHED_PROCESS + CREATE_BREAKAWAY_FROM_JOB，降低主程序退出时替换器被一起终止的概率。
- 新增“启动握手 + 用户确认应用”双标记：替换器不会再在提示框停留 20 秒后自行强杀客户端；只有用户点击确定后才关闭整个旧客户端进程树并开始覆盖。
- 新增 `data/update_apply_pending.json`，能识别“替换器启动后被系统静默终止”的情况并停止重复下载。
- `data/update_last.log` 继续记录阶段日志；失败文件增加明确错误码：
  - `parent_process_not_exit`
  - `payload_copy_failed`
  - `main_exe_replace_failed`
  - `version_commit_failed`
  - `staging_directory_missing`
  - `rollback_snapshot_missing`
- 替换失败时只恢复本次变更文件，不再回滚整个 Portable。

## 兼容

继续兼容 v6.3.9 服务端的 `delta+range` 更新协议和打包工具 v1.5.5 生成的 Portable ZIP。
