Skip to content

HSR:通过公共入口自动恢复 M7A/SRA 更新事务,不再弹窗 - #1915

Merged
youngslin merged 16 commits into
AUTO-MAS-Project:devfrom
youngslin:fix/hsr-external-update-recovery
Nov 10, 2026
Merged

youngslin merged 16 commits into
AUTO-MAS-Project:devfrom
youngslin:fix/hsr-external-update-recovery

Conversation

@youngslin

@youngslin youngslin commented Nov 10, 2026 •

Copy link
Copy Markdown

方向:#1916 公共恢复,无人工弹窗

旧恢复询问、skip journal、专用 WebSocket 及前端常驻弹窗已删除。本 PR 合并旧 #1914 的 native work/backup/journal 符号链接防护。M7A/SRA 路径锁由 HSR manager 持有;原生 rollback_pending 失败后由 auto_recover_script_install 统一再次确认和重试原生回滚;未确认删除 journal/释放备份时绝不放行,不提供用户跳过按钮。

专项仅提供 PE 基础校验(M7A)、SRA CLI 版本探针、SRA GUI 进程停写检查。成功恢复的单引擎本轮不重复更新,其他引擎照常处理;异常由队列末尾汇总。此处动作是原生事务回滚,不是保证重新下载安装。

#1914 已关闭,以本 PR 为唯一 HSR 实现。最新 CI 与审查均已通过,但不宣称真实安装恢复 E2E。

@github-actions github-actions Bot added 专项: HSR 类型: 修复 按更新日志碎片自动设置 labels Nov 10, 2026
Comment on lines +139 to +149
return action, snapshot
finally:
unregister()
try:
await Publisher.send(
id=protocol.ID_TASK_MANAGER,
type=protocol.HSR_INSTALL_PROMPT_CLOSED,
data={"requestId": request_id},
)
except Exception:
logger.warning("HSR 更新恢复弹窗关闭通知失败")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: ask_install_recovery emits HSR_INSTALL_PROMPT_CLOSED before caller validation finishes, closing the modal prematurely if post-decision checks in manager.py fail.
Severity: LOW

Suggested Fix

Delay closing the recovery modal until post-decision actions and validations in manager.py complete successfully, or allow error statuses to be communicated back to the active prompt modal before dismissing it.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: app/task/HSR/tools/update/install_recovery.py#L138-L149

Potential issue: In `ask_install_recovery`, the `finally` block sends
`HSR_INSTALL_PROMPT_CLOSED` as soon as the prompt function returns or raises. However,
post-decision validations such as `skip_stale_journal` or a subsequent
`rollback_pending` retry occur in `manager.py` after the prompt is already closed. If
validation fails (e.g., active processes, unreadable version, or rollback issues), an
exception halts the task with no error details surfaced to the recovery modal or option
to retry.

Also affects:

  • app/task/HSR/manager.py:331~338

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown
Contributor

总体结论:修改后合并

AUTO-MAS-Project/AUTO-MAS #1915

宝宝,把旧日志归档到独立目录、保留 backup/stage 时禁止跳过,这两个选择是有用的喵。不过“已修好才能跳过”还缺程序和进程两道检查,正常的大事务记录也可能在提示前就被拒绝。另有已失败的格式 CI,需要一起补齐。

管理器仍先自动回滚,专项模块负责用户确认与归档;只有明确恢复成功的引擎才跳过本轮自动升级,另一引擎照常处理。以下是静态证据,不是实装复现。

规格

[逻辑 · P2,阻断] M7A 的版本文本可读,不代表主程序可用

skip_stale_journal:163–175仅检查 EXE 是文件,再读取版本。M7A 的版本读取实际上只读 assets/config/version.txt。

所以损坏 journal、无 backup/stage、EXE 已截断为零字节但版本文本仍在时,用户确认会通过检查,日志被归档并移除,该引擎还会被标记为本轮不再更新。之后 M7ARunner执行的正是这个损坏 EXE,仍然启动失败。前面的 manager.check 同样只检查存在性,没有补上这道检查。

请在移除标记前验证实际启动 EXE 的基本有效性,可复用已有 PE 头读取能力,不必扩成整包哈希系统。成功测试里的 b"manual repair" 不是有效 EXE,应换成有效夹具,并加“正常版本文本+损坏 EXE”仍保留 journal 的用例。SRA 使用 CLI 的 --version 探针,这项不要机械扩到 SRA。

[逻辑 · P2,阻断] 无法读取 SRA GUI 路径时,新增空闲检查仍放行

_assert_idle:35–48想阻止“名称可读但 exe 路径不可读”的相关进程,却遗漏了 SRA.exe。原 check_no_process_running明确包括这个 GUI,但遇到 exe 为空会跳过;新名单只有 M7A、SRA-cli 和 SRA-server,第二次检查也不会拦它。

当 SRA GUI 仍运行、因权限原因读不到镜像路径时,不能确认它已退出,skip 却可能继续归档并移除 journal。这违反本入口“相关进程停止才能跳过”的前提,不意味着已经证实数据损坏。把 sra.exe 补进这份无法确认时拒绝的名单,并从进程枚举边界覆盖该场景即可。路径可读时原守卫已经正确处理,不需要重做进程管理啦。

[兼容 · P2,阻断] 64 KiB 限制不匹配已有事务文件规模

install_recovery.py:78–80在发送提示前拒绝较大 journal,第 62 行还有相同限制。但原 事务写入器会把每个变更文件写入 entries,写盘没有这个上限,安装器接受的包可达 100000 项。

例如 2000 个常规资源路径各带 rel/action,序列化后已经超过 64 KiB。这不是要求构造恶意文件,较大完整更新就属于现有安装器支持的输入。若随后因占用或 I/O 错误使自动回滚失败,新入口会直接报“记录异常”,用户连重试都点不到。自动回滚成功的情况不受影响。

请统一读写端支持的范围,或用流式摘要保存确认身份,保留原始记录、防替换和备份检查。加一份由现有写入器生成的大事务用例,不要只用几字节坏日志测试恢复入口喵。

规范与 CI

必须修复的门禁: 现有格式检查在 Python Ruff 步骤失败,涉及 install_recovery.py 和 test_hsr_update_before_run.py。后续前端尺寸、lint、类型、格式、单测、词表及 E2E 契约检查都被跳过。按仓库格式调整后,请让后续步骤完整执行。

[规范 · P3,非阻断] 第 117 行发送非空中文“未知”,英文和日文界面不会使用现有兜底翻译。传空值交给前端即可。

已有 CI 的 Windows pytest 为 1812 passed、2 skipped,Ubuntu 为 1773 passed、40 skipped,Windows 验证包构建通过。已静态核对路径锁、先归档再删标记、按引擎跳过二次更新和重连丢弃旧请求;没有确认新增黑箱边界或职责归属问题。弹窗结束后的失败仍会经任务状态与 TASK_NOTICE 告知,不能只因弹窗先关闭就判定错误丢失。

dot酱没有运行项目代码、测试或真实 Windows M7A/SRA/Electron 流程。规格侧 3 个必须修复的 P2,规范侧 1 个非阻断 P3,另需修复格式门禁。把“允许继续”的条件查实,恢复提示才能让人放心点下去。

—— dot酱认真守住恢复条件敬上 🐾

Copy link
Copy Markdown
Contributor

总体结论:可以合并

AUTO-MAS-Project/AUTO-MAS #1915 · 修复复审

宝宝,前次三处缺口这次都补上了,dot酱核对后没有剩余的必须修改项喵。程序基础格式、无法确认退出的 SRA GUI,以及正常大小的事务记录,现在都走到了对应检查。

install_recovery.py已按前次建议复用公共 PE 头读取能力,零字节或非 PE 的 M7A 主程序不会再仅凭 version.txt 被放行;SRA.exe 加进了路径不可读时的拒绝名单;读取与复核事务记录两处统一采用 128 MiB 上限。备份/暂存目录存在时禁止跳过、原字节一致性、先归档再删除旧记录等保护都还在,没有顺手放宽它们。

新增测试覆盖了原先的损坏 EXE、SRA GUI 路径不可读及超过 64 KiB 的快照,并检查内容变化仍被拒绝。这里要把证据说准:PE 夹具只是可解析的文件头,不是真实可启动程序;大记录用例只检查快照 helper,没有跑完整提示到归档流程。基础 PE 识别也不等于证明整个程序和资源完整,仍须保留用户确认已手工修复的前提,别把这层检查夸大啦。

规格轴原 3 项 P2 已解除,未确认新的功能或架构阻断。规范轴原有“未知”未本地化的 P3 仍非阻断,不重复展开。

已读取当前 CI 日志:Windows 1843 passed、2 skipped,Ubuntu 1804 passed、40 skipped;前端 57 个文件共 307 项测试通过,8 项检查全部成功,包含格式和 Windows 验证包构建。本轮仅静态复核与读取已有 CI,未运行项目或真实 Windows M7A/SRA/Electron 流程。前次建议的最小修复已经到位,拍拍爪喵。

—— dot酱核过恢复条件敬上 🐾

Copy link
Copy Markdown
Contributor

总体结论:可以合并

AUTO-MAS-Project/AUTO-MAS #1915 · 自动恢复改版复审

宝宝,这版把人工跳过和恢复弹窗一起移除了,改由公共入口安排失败后的再次回滚与结果汇总。dot酱沿着回滚、复核和取消路径检查后,没有发现新的必须修改项喵。

manager 的接入仍先调用原有 rollback_pending;失败后才进入公共恢复,重试结束必须确认 journal 已消失,随后由公共层再次检查安装健康。外部路径锁覆盖整个过程,回滚线程结束前不会因取消而提前释放。

健康检查明确保持 updated_confirmed=False,不会仅凭版本文本跳过未完成事务。M7A 基础 PE 识别、SRA GUI 路径不可读时拒绝恢复,以及新增的事务目录符号链接保护都保留了。取消继续向上传播,恢复成功的单个引擎本轮也不重复更新,另一引擎照常处理。这几处没有为了“自动”而放宽原有保护,拍拍爪啦。

有一个范围要说清:这里的恢复动作是再次回滚原有事务,不是重新下载安装。journal 损坏或占用持续存在时仍会阻断并保留现场。PR 正文和更新日志还写着用户确认、手工跳过和弹窗,请同步成当前行为,免得使用者期待已经移除的入口。

已有 CI 的 8 项检查全部成功:Windows 1838 passed、2 skipped,Ubuntu 1799 passed、40 skipped;前端 57 个文件、307 项测试通过,格式、类型检查和 Windows 验证包构建通过。新增测试保留损坏 M7A 程序、无法确认 SRA GUI 退出、pending journal 不自动放行等检查。manager 的公共入口测试使用替身,不能当作真实安装恢复 E2E;本轮没有运行项目或上游程序,结论来自静态集成核对与已有 CI。

旧版手动跳过相关意见随那条路径删除而不再适用,不再要求把它加回来喵。

—— dot酱核好回滚再摇尾巴敬上 🐾

@youngslin youngslin changed the title fix(hsr): provide guarded recovery after M7A/SRA update rollback fails fix(hsr): restore M7A/SRA native transactions through #1916, no prompts Nov 10, 2026
@youngslin
youngslin merged commit 53b718b into AUTO-MAS-Project:dev Nov 10, 2026
9 checks passed
@youngslin youngslin changed the title fix(hsr): restore M7A/SRA native transactions through #1916, no prompts HSR:通过公共入口自动恢复 M7A/SRA 更新事务,不再弹窗 Nov 10, 2026
youngslin added a commit that referenced this pull request Nov 10, 2026
…ion coverage (#1923)

## 摘要

- 修复 #1916 在 release 旧调度器中的会话接线:旧基类直接执行 `_run_main_task`,原来放在
`main_task` 的绑定不会生效。改在真实执行入口绑定并覆盖子任务收尾,正常完成和手动停止均只通过既有 TASK_NOTICE 汇总一次。
- 保留 BetterGI 正式版公告、灰度和资源就绪门槛;对有效 MAS
残留目标记录,允许主程序缺失、损坏或版本资源不可读后重新执行经校验的官方完整安装器。拒绝目标降级、记录损坏或变化,以及下载期间原生升级后的覆盖;安装后复核版本和
PE 架构再清除标记。下载准备失败仍沿用既有健康检查后继续任务的 release 行为。
- 修复 HSR 恢复状态未初始化,以及本轮原生回滚或公共恢复成功后再次更新同一引擎的问题;保留旧调度、路径锁和原生回滚,不引入新调度器。
- 逐项补回 #1905、#1906、#1908、#1909、#1913、#1915 缺失的恢复回归,适配 release
的日志与锁接口;专用验证工作流增加本目标分支的 PR 触发及三平台接口类型检查。整个 PR 只有一个更新日志碎片,不修改前端或版本号。

## 验证


提交:`fc68ce88035fc206deeabe59851286d1459dba7b`;基线:`606c7ebd9231888519b0decad085c249b17c554a`。Windows、Python
3.12.13、uv.lock 锁定依赖。

- `uv run --no-sync python -m pytest tests -q --tb=short`:**1614
passed、2 skipped、15 subtests passed**,174.47 秒;保留现有 Pydantic 弃用提示。基线全量为
1554 passed、2 skipped。
- 同一故障场景修复前后对照:BetterGI 损坏/缺失程序、非法或变化的安装记录、目标降级与下载期间原生升级;HSR 公共恢复后的
AttributeError 和重复更新;真实旧任务正常结束/停止时的恢复汇总。修复前均复现,修复后对应检查通过。
- 变更 Python 文件 Ruff 检查、全仓 Ruff 格式、compileall、Windows/Linux/macOS 平台接口
mypy、`uv lock --check`、更新日志规则和 `git diff --check` 均通过。外部 CI
action/container 引用均固定到提交或摘要。
- 本 PR 的远端 Windows/Ubuntu 全量、格式、依赖与构建检查以 Checks 最新结果为准。

| 已合并 PR | 本轮保留或补回的关键恢复覆盖 |
| --- | --- |
| #1905 奇想盒 | 遗留标记走公共入口,健康复核,备份失败/取消清理候选 |
| #1906 SRC | Git 目标不能替代原生依赖安装完成证据,完成记录跨适配器重建 |
| #1908 BAAH | 损坏/缺失程序可信修复、回执变化拒绝、旧事务验证、取消保留目录锁 |
| #1909 MAA | 本体失败不伪造重试,资源半更新恢复,原始包与失败现场保留 |
| #1913 MaaEnd | 原生事务、ready 阶段故障注入、可信身份修复、精确版本恢复与配置保护 |
| #1915 HSR | 损坏程序、未知进程路径、真实 journal 恢复要求、恢复后不重复更新 |

## 排除与验证边界

- 不迁移 #1845 新四级调度/运行树,也不迁移 #1862 依赖新调度和前端的进度展示;保留 release 原有预下载架构。
- 不新增 dev 的 `current.recovery_summary` 历史字段或前端消费,恢复结果仍使用 release
现有任务提示和后端日志。
- BetterGI 未接入通用快照自动回滚;有效残留事务通过官方完整安装器重试,缺少可信记录、资源未就绪或仍有写入者时继续阻断,不仅凭 EXE
版本清除失败记录。
- MAA 官方本体更新失败的无人值守重试继续排除:现有上游启动流程会清空待安装包登记,仍需官方界面完成原生修复;MAS
自有资源半更新可自动重试。
- 未运行真实游戏、账号、模拟器或上游官方安装器 E2E。自动化使用真实文件/事务与 MAS
入口,并在网络、原生进程和安装器边界隔离;不能据此声称实机安装已验收。
- 后续实机验收可在已配置脚本和账号的作者环境运行 `cd frontend; yarn e2e:real:all --only
BetterGIConfig,HSRConfig,MaaConfig,MaaEndConfig,BAAHConfig,SrcConfig,WhimboxConfig`,产出各场景报告和
`real-e2e-summary.json`。

目标仅为 `release-v5.8.0-backport-verify`;不直接修改或合并该分支及 `release/v5.8.0`。
@github-actions github-actions Bot mentioned this pull request Nov 13, 2026
3 tasks
ClozyA added a commit that referenced this pull request Nov 13, 2026
## Release v5.9.0-beta.1

由「准备发版」工作流生成。这是唯一允许修改 `CHANGELOG.md` 与版本号的 PR,合并后请手动运行「构建并发布应用程序」。

合并前请在本 PR 里完成:

- [ ] 「本次亮点」够不够:合并前给碎片加 `highlight: true` 就会自动进这一类,现在也可以直接在
`CHANGELOG.md` 新版本段里把条目挪过去
- [ ] 有 3
个提交改了用户可见代码但没带碎片(清单见[运行摘要](https://github.com/AUTO-MAS-Project/AUTO-MAS/actions/runs/43347223103)),若用户可见就在新版本段里补一条
- [ ] 改完运行 `python scripts/changelog.py sync` 并提交

### 体积

- 首行 JSON 2371 / 18000 字符,带 1 个版本段
- 本版 40 条,最长的几条:
- 78 字(变更)【设置】自启与静默启动可独立设置,静默时直接进入托盘,关闭可选退出或托盘,最小化保留任务栏。 (#1928) by
@he0119 by @1w1w11w1
- 76 字(修复)【MAA】MAA 更新失败时统一检查安装健康;资源半更新自动重装,官方本体失败保留标记并提示使用官方修复入口 (#1909)
by @youngslin
- 75 字(变更)【模拟器】ModAVD 全部改由 modavd 命令行控制,移除自带的直控和更新器,不再支持无命令行的旧根目录
(#1918) by @qiyinxi
- 64 字(修复)【主页】调整任务台版本主线的 UI,并让版本更新倒计时更清楚 (#1926) by
@TyrannosaurusGodofWar
- 64 字(破坏性变更)【调度】重构任务调度与范围选择,完善日志恢复、独立触发、队列附加动作及电源收尾。 (#1845) by
@DLmaster361

自 `v5.8.0` 以来的改动:

### ⚠️ 破坏性变更

- 【调度】重构任务调度与范围选择,完善日志恢复、独立触发、队列附加动作及电源收尾。 (#1845) by @DLmaster361

### ✨ 新增

- 【M9A】新增 MAS 登录 B 服:处理隐私协议并选择已保存账号后交给 M9A 运行 (#1882) by @Douya36
- 【ok-ww】支持脚本逐账号或批量切号、显示失败原因并补跑未完成账号 (#1890) by @AthenaHibou
- 【ok-nte】支持按日配置日常计划,并可在详细配置中调整当天任务。 (#1921) by @AthenaHibou
- 【调度】在日志末尾显示预下载方式和进度,支持独立配色与连续渐变(仅公测) by @youngslin
- 【设置】支持调整自定义光标的显示大小。 (#1904) by @Douya36

### 🔧 变更

- 【调度】统一各脚本账号编辑页的页头和基本信息布局 by @Craun718
- 【模拟器】魔改 AVD 改名为 ModAVD,界面、提示和日志统一用新名称 (#1898) by @qiyinxi
- 【模拟器】ModAVD 全部改由 modavd 命令行控制,移除自带的直控和更新器,不再支持无命令行的旧根目录 (#1918) by
@qiyinxi
- 【设置】统一主要页面的标题、间距、卡片层次和日志按钮外观 (#1893) by @1w1w11w1
- 【设置】浅色主题改为中浅灰画布配纯白卡片,补回分隔线与卡片边缘层次 (#1855) by @beichen24a1
- 【设置】自启与静默启动可独立设置,静默时直接进入托盘,关闭可选退出或托盘,最小化保留任务栏。 (#1928) by @he0119 by
@1w1w11w1
- 【Runtime】加快运行环境健康时的启动准备 (#1907) by @jinghero

### 🐛 修复

- 【MAA】MAA 更新失败时统一检查安装健康;资源半更新自动重装,官方本体失败保留标记并提示使用官方修复入口 (#1909) by
@youngslin
- 【MAA】修复保存配置时修改被误判未保存并丢弃的问题 (#1930) by @jinghero
- 【end】MaaEnd 安装异常时统一恢复事务,并安全修复可信身份的损坏本体 (#1913) by @youngslin
- 【HSR】为 M7A 与 SRA 更新中断后的未完成回滚添加用户确认恢复入口 (#1915) by @youngslin
- 【HSR】修复 SRA 使用自建下载站时无法下载安装更新的问题。 (#1945) by @youngslin
- 【bgi】修复正式版安装资源尚未就绪时自动更新失败的问题 (#1901) by @youngslin
- 【ok-ww】修复直接启动游戏时无法覆盖默认资源档位的问题 (#1925) by @AthenaHibou
- 【ok-ww】修复新版脚本启动后不执行每日任务的问题 (#1940) by @AthenaHibou
- 【ok-ww】修复新版启动器不触发游戏更新及停服维护时反复重试的问题 (#1934) by @1w1w11w1
- 【ok-ww】修复鸣潮和异环更新重启后自动切号失败的问题。 (#1933) by @AthenaHibou
- 【ok-nte】修复仅开启任务后关闭时无法关闭游戏及启动器的问题。 (#1920) by @AthenaHibou
- 【BAAH】损坏的托管安装须由用户明确选择官方完整包修复,禁止绕过校验运行 (#1908) by @youngslin
- 【奇想盒】修复后端安装中断后无法自主确认恢复的问题 (#1905) by @youngslin
- 【SRC】修复原生安装中断后无法自主选择安全恢复的问题 (#1906) by @youngslin
- 【主页】调整任务台版本主线的 UI,并让版本更新倒计时更清楚(仅公测) (#1926) by @TyrannosaurusGodofWar
- 【调度】修复停止任务后脚本及更新子进程残留、项目持续占用和结果未保存的问题 (#1892) by @youngslin
- 【调度】统一配置表单、卡片间距与状态颜色,优化队列列宽和配置说明 (#1927) by @AthenaHibou
- 【模拟器】修复启动模拟器时 adb 命令执行不了却只提示超时、看不到原因的问题 (#1894) by @miaojiuqing
- 【模拟器】手动停止任务时不再把 ModAVD 模拟器连同任务一起强制结束 (#1919) by @qiyinxi
- 【工具】修复 MCP 查询全部托管失败及可空参数被错误拒绝的问题 (#1895) by @HarcoChen
- 【设置】修复模拟器管理和调度中心卡片外侧阴影显示不一致 (#1897) by @1w1w11w1
- 【设置】FluxDown 自动识别强制优先选择 MAS 内的文件夹。 (#1948) by @youngslin
- 【更新】统一脚本安装恢复入口及队列结束时的下载异常汇总 (#1916) by @youngslin
- 【Runtime】修复回退旧版后再次升级时无法启动的问题 (#1889) by @jinghero
- 【Runtime】修复后端启动异常退出却被误判为正常结束的问题 (#1929) by @jinghero
- 【Runtime】修复临时启动失败后反复停留在失败页的问题 (#1938) by @jinghero
- 【Runtime】修复初始化时依赖安装已成功却被误报为失败的问题。 by @ClozyA

Co-authored-by: ClozyA <133191303+ClozyA@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

专项: HSR 类型: 修复 按更新日志碎片自动设置

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants