Skip to content

feat(equipment): 新增meta演习装备配置 - #1304

Merged
longer-sausage merged 1 commit into
wess09:devfrom
longer-sausage:dev
Oct 22, 2026
Merged

longer-sausage merged 1 commit into
wess09:devfrom
longer-sausage:dev

Conversation

@longer-sausage

@longer-sausage longer-sausage commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

📋 许可确认

  • 我已仔细阅读并同意 GPL-3.0 开源协议 中的所有条款,并理解我的贡献将受到该协议的约束
  • 我确认我提交的代码不会侵犯任何第三方的知识产权

💯 代码质量确认

  • 我已执行静态类型检查,确保代码不含基本类型错误:
    • 后端:uv run ruff check . --select E9,F63,F7,F82 --ignore F821,F722
    • 前端:npm run typecheck --prefix frontend
  • 对于难以解决的必要类型忽略标记,我已添加注释说明原因
  • 涉及游戏交互的代码遵循状态循环模式(截图-检查循环),未使用"点击-等待-休眠"模式
  • 新增/修改的 UI 模板图像基于固定的 1280×720 分辨率截图
  • 若修改了 module/config/argument/ 下的 YAML 源文件,已运行 uv run -m module.config.config_updater 并提交生成产物
  • 若修改了游戏逻辑,已在真实模拟器实例上运行验证(游戏逻辑无自动化测试)

🔍 变更类型 (勾选所有适用项)

  • 🐛 Bug 修复 (修复一个问题)
  • ✨ 新功能 (添加新功能)
  • 🔄 重构 (不改变功能的代码调整)
  • 📝 文档更新
  • 🔧 配置变更
  • 🎨 代码风格优化
  • 💅 样式调整 (UI/UX 外观变化)
  • 🚀 性能提升
  • ✅ 测试相关
  • 🌐 国际化/本地化
  • 🔗 依赖更新
  • 🗺️ 活动/地图数据 (campaign/)
  • 🖼️ 资源图像 (assets/)
  • 🔌 MCP 工具相关 (mcp_server_sse.py)
  • 🔄 其他...

📄 PR 描述

🔗 相关 Issue

📸 修改效果截图

🛠️ 实现复杂度

  • 简单 (小改动,影响有限)
  • 中等 (需要一些技术考量)
  • 复杂 (涉及多个组件或系统)

📋 实现细节 (可选)

🧪 测试步骤 (可选)

Sourcery 总结

为演习和 META 战斗引入可配置的战前换装与战后恢复流程,并完善相关配置、资源、文档和测试。

新功能:

  • 新增可按舰队站位配置的战前装备应用与战后装备恢复功能,支持演习及 META 信标/协助任务。

错误修复:

  • 确保装备配置校验失败、装备保存失败或 META 页面切换异常时,不会错误清除待恢复状态。

改进:

  • 将装备配置处理整合到通用战斗流程中,并复用统一的装备码接口与整编页面操作。
  • 优化 META 战斗装备恢复流程,支持在普通信标、协助和档案页面之间安全切换。

构建:

  • 新增装备配置相关的任务参数、配置生成逻辑及多语言配置项。

文档:

  • 补充战斗、装备管理及 META 模块中有关装备配置与恢复流程的用户文档和维护文档。

测试:

  • 新增装备配置、演习换装及 META 装备恢复的离线回归测试。

杂项:

  • 新增整编页面的站位、重组和保存按钮资源,并移除演习专用的装备处理模块。
Original summary in English

Sourcery 总结

为演习和 META 战斗引入可配置的战前换装与可靠的战后装备恢复流程。

新功能:

  • 为演习和 META 战斗新增按舰队站位配置的战前换装与战后恢复功能。

问题修复:

  • 防止装备配置校验、装备应用或页面切换失败时错误清除待恢复状态。

功能增强:

  • 将装备方案处理整合到通用战斗流程,并支持 META 在普通信标、协助和档案页面之间安全恢复装备。
  • 移除演习专用装备处理逻辑,改用通用装备码配置接口。

构建:

  • 新增 Equipment 任务配置、参数生成产物及多语言配置项。

文档:

  • 补充战斗、装备管理和 META 模块的配置、恢复流程及维护说明。

测试:

  • 新增装备配置、演习换装和 META 装备恢复的离线回归测试。

杂项:

  • 新增整编页面舰队站位、重组和保存按钮资源。
Original summary in English

Sourcery 摘要

为演习和 META 战斗引入可配置的装备预设,并确保战斗结束后能安全恢复装备。

新功能:

  • 为演习和 META 信标战斗添加按舰队位置配置的战前与战后装备预设。

错误修复:

  • 当验证、应用、保存、页面导航或 META 入口转换失败时,保留待处理的装备恢复操作。

增强功能:

  • 将装备预设处理整合到共享战斗流程中,并支持在信标、协助和档案页面之间可靠地恢复 META 装备。

构建:

  • 添加装备任务配置、生成的配置值、任务关联和本地化标签。

文档:

  • 记录装备预设配置、战斗流程集成以及 META 装备恢复行为。

测试:

  • 添加离线回归测试,覆盖装备验证、演习装备流程和 META 装备恢复。

杂项:

  • 添加舰队重组资源,并移除演习专用的装备处理程序,改用共享实现。
Original summary in English

Sourcery 摘要

为演习和 META 战斗引入可配置且可可靠恢复的战前与战后装备方案。

新功能:

  • 为演习和 META 信标及协助战斗新增按舰队站位配置的战前装备应用与战后恢复。

错误修复:

  • 在装备配置、装备应用、保存或 META 页面切换失败时保留待恢复状态,避免装备未恢复却被错误清除。

改进:

  • 将任务换装流程整合到通用战斗处理,并支持在普通信标、协助和档案页面之间安全完成 META 装备恢复。
  • 移除演习专用装备处理,统一复用装备码配置与舰队整编流程。

构建:

  • 新增 Equipment 任务配置、生成配置项、任务关联及多语言配置。

文档:

  • 补充战斗、装备管理和 META 模块的装备配置、恢复流程及维护说明。

测试:

  • 新增装备配置、演习换装和 META 装备恢复的离线回归测试。

杂项:

  • 新增舰队站位、整编保存及 META 模拟入口资源。
Original summary in English

Summary by Sourcery

为演习和 META 战斗引入可配置且可可靠恢复的战前与战后装备方案。

New Features:

  • 为演习和 META 信标及协助战斗新增按舰队站位配置的战前装备应用与战后恢复。

Bug Fixes:

  • 在装备配置、装备应用、保存或 META 页面切换失败时保留待恢复状态,避免装备未恢复却被错误清除。

Enhancements:

  • 将任务换装流程整合到通用战斗处理,并支持在普通信标、协助和档案页面之间安全完成 META 装备恢复。
  • 移除演习专用装备处理,统一复用装备码配置与舰队整编流程。

Build:

  • 新增 Equipment 任务配置、生成配置项、任务关联及多语言配置。

Documentation:

  • 补充战斗、装备管理和 META 模块的装备配置、恢复流程及维护说明。

Tests:

  • 新增装备配置、演习换装和 META 装备恢复的离线回归测试。

Chores:

  • 新增舰队站位、整编保存及 META 模拟入口资源。

Summary by CodeRabbit

  • 新功能
    • 演习、META 信标和信标协助新增可选的自动装备方案:可分别设置战前与战后装备,并选择应用前是否清空装备。
    • 任务结束后会按配置恢复装备;档案战斗不应用此功能。
  • 文档
    • 补充装备方案的配置方式、适用范围及任务中的装备处理说明。

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1b750a34-e614-4d13-878b-8dbec3f7dfd4
📥 Commits

Reviewing files that changed from the base of the PR and between de8119b and a9e4bdb.

⛔ Files ignored due to path filters: 11
  • assets/cn/equipment/FLEET_POSITION_DOWN.png is excluded by !**/*.png
  • assets/cn/equipment/FLEET_POSITION_FLAGSHIP.png is excluded by !**/*.png
  • assets/cn/equipment/FLEET_POSITION_HEAD.png is excluded by !**/*.png
  • assets/cn/equipment/FLEET_POSITION_MIDDLE.png is excluded by !**/*.png
  • assets/cn/equipment/FLEET_POSITION_TAIL.png is excluded by !**/*.png
  • assets/cn/equipment/FLEET_POSITION_UP.png is excluded by !**/*.png
  • assets/cn/equipment/FLEET_REORGANIZE.png is excluded by !**/*.png
  • assets/cn/equipment/FLEET_SAVE.png is excluded by !**/*.png
  • assets/cn/os_ash/ASH_SIMULATE.png is excluded by !**/*.png
  • tests/fixtures/meta_equipment/simulate.png is excluded by !**/*.png
  • tests/fixtures/meta_equipment/simulate_confirm.png is excluded by !**/*.png
📒 Files selected for processing: 25
  • config/template.json
  • docs/modules/combat.md
  • docs/modules/game/misc.md
  • docs/modules/game/retire-equipment.md
  • docs/modules/os/auxiliary.md
  • module/combat/combat.py
  • module/config/argument/args.json
  • module/config/argument/argument.yaml
  • module/config/argument/task.yaml
  • module/config/config_generated.py
  • module/config/i18n/en-US.json
  • module/config/i18n/ja-JP.json
  • module/config/i18n/zh-CN.json
  • module/config/i18n/zh-MIAO.json
  • module/config/i18n/zh-TW.json
  • module/equipment/assets.py
  • module/equipment/equipment_config.py
  • module/exercise/combat.py
  • module/exercise/equipment.py
  • module/exercise/exercise.py
  • module/os_ash/ash.py
  • module/os_ash/assets.py
  • module/os_ash/meta.py
  • tests/test_equipment_config.py
  • tests/test_meta_beacon.py
💤 Files with no reviewable changes: 1
  • module/exercise/equipment.py

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

📝 Walkthrough

新增任务装备方案配置和通用处理器。Combat 与演习流程会在战前应用方案,并在任务结束时处理装备恢复。META 流程会复用战斗实例,并通过可用入口执行战后恢复。

Changes: 任务装备方案

Layer / File(s) Summary
装备方案配置与界面标记
config/template.json, module/config/argument/*, module/config/config_generated.py, module/config/i18n/*, module/equipment/assets.py
Exercise、OpsiAshBeacon 和 OpsiAshAssist 新增默认关闭的装备方案配置。配置包含清空选项和各舰队位置的 before、after 字段。新增相应翻译及界面标记。
装备方案校验与应用
module/equipment/equipment_config.py, tests/test_equipment_config.py, docs/modules/game/retire-equipment.md
新增 EquipmentConfigHandler,负责解析配置、校验装备码、清空和应用装备,并管理待恢复标志。测试覆盖配置校验、操作顺序和失败后的状态。
战斗准备与演习交接
module/combat/combat.py, module/exercise/*, tests/test_equipment_config.py, docs/modules/combat.md, docs/modules/game/misc.md
Combat 在战斗准备时处理战前装备方案。演习复用 Combat 的准备流程,并在符合条件时执行战后处理。演习专用的 ExerciseEquipment 类及其调用被移除。
META 战后装备恢复
module/os_ash/*, module/os_ash/meta.py, tests/test_meta_beacon.py, docs/modules/os/auxiliary.md
META 战斗复用 AshCombat 实例,并新增战后装备恢复流程。流程根据页面状态选择恢复入口;到达准备页面后恢复装备,再返回相应页面。档案战斗不启用装备方案。测试覆盖入口切换、超时及待恢复状态。

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant 任务流程
  participant Combat
  participant EquipmentConfigHandler
  participant 装备界面
  任务流程->>Combat: 进入战斗准备
  Combat->>EquipmentConfigHandler: 调用战前装备处理
  EquipmentConfigHandler->>装备界面: 清空或应用 before 装备码
  装备界面->>EquipmentConfigHandler: 保存整编结果
  EquipmentConfigHandler->>Combat: 设置待恢复标志
  Combat->>任务流程: 继续战斗准备
  任务流程->>EquipmentConfigHandler: 任务结束时调用战后处理
  EquipmentConfigHandler->>装备界面: 应用 after 装备码并保存
  装备界面->>EquipmentConfigHandler: 返回保存结果
  EquipmentConfigHandler->>任务流程: 清除待恢复标志
Loading

Suggested reviewers: wess09, beatrice-betty

Merge Risk: ⚪ Minimal · up to a9e4b

No actionable issue remains identified in the equipment preset and restoration changes; the PR is mergeable after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 37.08% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 89 functions across 11 files. (13 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed 标题准确概括了本次变更的主要内容:为演习和 META 作战新增装备配置。标题简洁、具体,并与变更范围一致。
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 37.08% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 89 functions across 11 files. (13 skipped: 13 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

CI 检查报告

检查结果

检查 结果 耗时
Post PR report ➖ unknown -

导入冒烟测试

  • 结果:✅
  • 扫描模块:621(通过 618,已知失败 3,意外失败 0,过期白名单 0)

@sourcery-ai

sourcery-ai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

审阅者指南

本 PR 将装备码方案处理整合进通用 Combat 流程,为演习和 META 信标/协助任务增加按舰队站位的战前换装与可靠战后恢复,并通过配置生成、识别资源、文档及离线回归测试完整支持该功能。

战前装备应用与恢复时序图

sequenceDiagram
    participant Combat
    participant EquipmentConfigHandler
    participant FleetPage
    participant EquipmentCode
    participant Battle

    Combat->>EquipmentConfigHandler: handle_battle_preparation()
    EquipmentConfigHandler->>EquipmentConfigHandler: equipment_config
    EquipmentConfigHandler->>FleetPage: ensure_reorganize()
    FleetPage-->>EquipmentConfigHandler: FLEET_SAVE visible
    EquipmentConfigHandler->>EquipmentCode: _equipment_config_clear()
    EquipmentConfigHandler->>EquipmentCode: _equipment_config_apply(code)
    EquipmentConfigHandler->>FleetPage: ensure_save()
    EquipmentConfigHandler-->>Combat: equipment_handle_before_flag = true
    Combat->>Battle: click BATTLE_PREPARATION
    Note over Combat,Battle: After combat, the task re-enters preparation
    Combat->>EquipmentConfigHandler: equipment_handle_after()
    EquipmentConfigHandler->>FleetPage: ensure_reorganize()
    EquipmentConfigHandler->>EquipmentCode: _equipment_config_clear()
    EquipmentConfigHandler->>EquipmentCode: _equipment_config_apply(after)
    EquipmentConfigHandler->>FleetPage: ensure_save()
    EquipmentConfigHandler-->>Combat: equipment_handle_before_flag = false
Loading

META 在不同入口页面间恢复装备的时序图

sequenceDiagram
    participant Meta
    participant AshCombat
    participant MetaPage
    participant BattlePreparation
    participant EquipmentConfigHandler

    Meta->>AshCombat: combat()
    AshCombat-->>Meta: equipment_handle_before_flag = true
    Meta->>Meta: handle_ash_equipment_after()
    alt dossier page is active
        Meta->>MetaPage: click ASH_QUIT
    else beacon page shows simulation entry
        Meta->>MetaPage: click ASH_SIMULATE
        Meta->>MetaPage: handle_popup_confirm()
    else assist entry is available
        Meta->>MetaPage: click BEACON_MY
    end
    MetaPage-->>Meta: BATTLE_PREPARATION visible
    Meta->>EquipmentConfigHandler: equipment_handle_after()
    EquipmentConfigHandler-->>Meta: restoration completed
    Meta->>MetaPage: return to beacon or assist page
Loading

装备任务配置实体关系图

erDiagram
    TASK ||--o| EQUIPMENT_CONFIG : enables
    EQUIPMENT_CONFIG ||--o{ FLEET_POSITION : defines
    FLEET_POSITION ||--o| EQUIPMENT_PRESET : before
    FLEET_POSITION ||--o| EQUIPMENT_PRESET : after

    TASK {
        boolean Equipment_Enable
        boolean Equipment_ClearBeforeApply
    }
    EQUIPMENT_CONFIG {
        yaml Config
    }
    FLEET_POSITION {
        string position
    }
    EQUIPMENT_PRESET {
        string equipment_code
    }
Loading

文件变更

变更 详情 文件
将按舰队站位的战前/战后装备方案实现为通用战斗能力,并接入演习与 META 流程。
  • 新增 YAML 装备方案解析、装备码预检、整编页面导航及保存确认。
  • 支持可选的战前清空、逐站位应用,以及战后恢复/卸装;仅在保存成功后更新待恢复状态。
  • 将演习从专用装备处理迁移到共享 Combat 流程,连续出击只换装一次并在任务结束恢复。
module/equipment/equipment_config.py
module/combat/combat.py
module/exercise/combat.py
module/exercise/exercise.py
module/exercise/equipment.py
完善 META 信标与协助任务的装备恢复和页面切换状态机。
  • 复用同一 AshCombat 实例跨战斗保存待恢复状态,档案战斗禁用普通信标装备方案。
  • 支持在普通信标、协助和档案页面之间选择可用入口,并通过模拟战斗入口进入编队恢复装备。
  • 在任务切换、自动攻击挂起、奖励结算和异常导航场景保留待恢复标志,恢复失败不误报成功。
module/os_ash/meta.py
module/os_ash/ash.py
module/os_ash/assets.py
新增 Equipment 任务配置、任务关联、生成配置与多语言界面定义。
  • 增加 Enable、ClearBeforeApply 及六个舰队站位的 before/after 装备码配置。
  • 将 Equipment 关联到演习、META 信标和协助任务,并提交生成配置产物与本地化标签。
module/config/argument/argument.yaml
module/config/argument/args.json
module/config/argument/task.yaml
module/config/config_generated.py
module/config/template.json
module/config/i18n/en-US.json
module/config/i18n/ja-JP.json
module/config/i18n/zh-CN.json
module/config/i18n/zh-MIAO.json
module/config/i18n/zh-TW.json
补充整编、舰队站位及 META 模拟入口的识别资源。
  • 新增六个舰队站位、整编保存按钮和 META 模拟战斗按钮资源,并注册多语言坐标/模板定义。
module/equipment/assets.py
assets/cn/equipment/FLEET_POSITION_DOWN.png
assets/cn/equipment/FLEET_POSITION_FLAGSHIP.png
assets/cn/equipment/FLEET_POSITION_HEAD.png
assets/cn/equipment/FLEET_POSITION_MIDDLE.png
assets/cn/equipment/FLEET_POSITION_TAIL.png
assets/cn/equipment/FLEET_POSITION_UP.png
assets/cn/equipment/FLEET_REORGANIZE.png
assets/cn/equipment/FLEET_SAVE.png
assets/cn/os_ash/ASH_SIMULATE.png
tests/fixtures/meta_equipment/simulate.png
tests/fixtures/meta_equipment/simulate_confirm.png
记录共享战斗装备处理、META 页面恢复约定,并增加离线回归覆盖。
  • 更新战斗、装备管理、演习和 META 维护文档,明确配置校验、控制方式、状态标志和页面恢复语义。
  • 增加配置预检、接口兼容、换装失败、演习换装及 META 多入口恢复测试。
docs/modules/combat.md
docs/modules/game/misc.md
docs/modules/game/retire-equipment.md
docs/modules/os/auxiliary.md
tests/test_equipment_config.py
tests/test_meta_beacon.py

提示与命令

与 Sourcery 互动

  • 触发新一轮审阅: 在拉取请求中评论 @sourcery-ai review。
  • 继续讨论: 直接回复 Sourcery 的审阅评论。
  • 根据审阅评论创建 GitHub issue: 回复审阅评论,请 Sourcery 根据该评论创建 issue。你也可以在审阅评论中回复 @sourcery-ai issue 来创建 issue。
  • 生成拉取请求标题: 在拉取请求标题的任意位置写入 @sourcery-ai,即可随时生成标题。你也可以在拉取请求中评论 @sourcery-ai title,随时(重新)生成标题。
  • 生成拉取请求摘要: 在拉取请求正文中你希望摘要出现的位置写入 @sourcery-ai summary,即可随时生成 PR 摘要。你也可以在拉取请求中评论 @sourcery-ai summary,随时(重新)生成摘要。
  • 生成审阅者指南: 在拉取请求中评论 @sourcery-ai guide,即可随时(重新)生成审阅者指南。
  • 解决所有 Sourcery 评论: 在拉取请求中评论 @sourcery-ai resolve,即可解决所有 Sourcery 评论。如果你已处理完所有评论且不想再看到它们,这个命令会很有用。
  • 撤销所有 Sourcery 审阅: 在拉取请求中评论 @sourcery-ai dismiss,即可撤销所有现有的 Sourcery 审阅。如果你想从新一轮审阅开始,这个命令尤其有用——别忘了评论 @sourcery-ai review 来触发新一轮审阅!

自定义你的体验

访问你的控制面板以:

  • 启用或禁用审阅功能,例如 Sourcery 生成的拉取请求摘要、审阅者指南等。
  • 更改审阅语言。
  • 添加、删除或编辑自定义审阅说明。
  • 调整其他审阅设置。

获取帮助

Original review guide in English

Reviewer's Guide

本 PR 将装备码方案处理整合进通用 Combat 流程,为演习和 META 信标/协助任务增加按舰队站位的战前换装与可靠战后恢复,并通过配置生成、识别资源、文档及离线回归测试完整支持该功能。

Sequence diagram for pre-battle equipment application and restoration

sequenceDiagram
    participant Combat
    participant EquipmentConfigHandler
    participant FleetPage
    participant EquipmentCode
    participant Battle

    Combat->>EquipmentConfigHandler: handle_battle_preparation()
    EquipmentConfigHandler->>EquipmentConfigHandler: equipment_config
    EquipmentConfigHandler->>FleetPage: ensure_reorganize()
    FleetPage-->>EquipmentConfigHandler: FLEET_SAVE visible
    EquipmentConfigHandler->>EquipmentCode: _equipment_config_clear()
    EquipmentConfigHandler->>EquipmentCode: _equipment_config_apply(code)
    EquipmentConfigHandler->>FleetPage: ensure_save()
    EquipmentConfigHandler-->>Combat: equipment_handle_before_flag = true
    Combat->>Battle: click BATTLE_PREPARATION
    Note over Combat,Battle: After combat, the task re-enters preparation
    Combat->>EquipmentConfigHandler: equipment_handle_after()
    EquipmentConfigHandler->>FleetPage: ensure_reorganize()
    EquipmentConfigHandler->>EquipmentCode: _equipment_config_clear()
    EquipmentConfigHandler->>EquipmentCode: _equipment_config_apply(after)
    EquipmentConfigHandler->>FleetPage: ensure_save()
    EquipmentConfigHandler-->>Combat: equipment_handle_before_flag = false
Loading

Sequence diagram for META equipment restoration across entry pages

sequenceDiagram
    participant Meta
    participant AshCombat
    participant MetaPage
    participant BattlePreparation
    participant EquipmentConfigHandler

    Meta->>AshCombat: combat()
    AshCombat-->>Meta: equipment_handle_before_flag = true
    Meta->>Meta: handle_ash_equipment_after()
    alt dossier page is active
        Meta->>MetaPage: click ASH_QUIT
    else beacon page shows simulation entry
        Meta->>MetaPage: click ASH_SIMULATE
        Meta->>MetaPage: handle_popup_confirm()
    else assist entry is available
        Meta->>MetaPage: click BEACON_MY
    end
    MetaPage-->>Meta: BATTLE_PREPARATION visible
    Meta->>EquipmentConfigHandler: equipment_handle_after()
    EquipmentConfigHandler-->>Meta: restoration completed
    Meta->>MetaPage: return to beacon or assist page
Loading

Entity relationship diagram for equipment task configuration

erDiagram
    TASK ||--o| EQUIPMENT_CONFIG : enables
    EQUIPMENT_CONFIG ||--o{ FLEET_POSITION : defines
    FLEET_POSITION ||--o| EQUIPMENT_PRESET : before
    FLEET_POSITION ||--o| EQUIPMENT_PRESET : after

    TASK {
        boolean Equipment_Enable
        boolean Equipment_ClearBeforeApply
    }
    EQUIPMENT_CONFIG {
        yaml Config
    }
    FLEET_POSITION {
        string position
    }
    EQUIPMENT_PRESET {
        string equipment_code
    }
Loading

File-Level Changes

Change Details Files
将按舰队站位的战前/战后装备方案实现为通用战斗能力,并接入演习与 META 流程。
  • 新增 YAML 装备方案解析、装备码预检、整编页面导航及保存确认。
  • 支持可选的战前清空、逐站位应用,以及战后恢复/卸装;仅在保存成功后更新待恢复状态。
  • 将演习从专用装备处理迁移到共享 Combat 流程,连续出击只换装一次并在任务结束恢复。
module/equipment/equipment_config.py
module/combat/combat.py
module/exercise/combat.py
module/exercise/exercise.py
module/exercise/equipment.py
完善 META 信标与协助任务的装备恢复和页面切换状态机。
  • 复用同一 AshCombat 实例跨战斗保存待恢复状态,档案战斗禁用普通信标装备方案。
  • 支持在普通信标、协助和档案页面之间选择可用入口,并通过模拟战斗入口进入编队恢复装备。
  • 在任务切换、自动攻击挂起、奖励结算和异常导航场景保留待恢复标志,恢复失败不误报成功。
module/os_ash/meta.py
module/os_ash/ash.py
module/os_ash/assets.py
新增 Equipment 任务配置、任务关联、生成配置与多语言界面定义。
  • 增加 Enable、ClearBeforeApply 及六个舰队站位的 before/after 装备码配置。
  • 将 Equipment 关联到演习、META 信标和协助任务,并提交生成配置产物与本地化标签。
module/config/argument/argument.yaml
module/config/argument/args.json
module/config/argument/task.yaml
module/config/config_generated.py
module/config/template.json
module/config/i18n/en-US.json
module/config/i18n/ja-JP.json
module/config/i18n/zh-CN.json
module/config/i18n/zh-MIAO.json
module/config/i18n/zh-TW.json
补充整编、舰队站位及 META 模拟入口的识别资源。
  • 新增六个舰队站位、整编保存按钮和 META 模拟战斗按钮资源,并注册多语言坐标/模板定义。
module/equipment/assets.py
assets/cn/equipment/FLEET_POSITION_DOWN.png
assets/cn/equipment/FLEET_POSITION_FLAGSHIP.png
assets/cn/equipment/FLEET_POSITION_HEAD.png
assets/cn/equipment/FLEET_POSITION_MIDDLE.png
assets/cn/equipment/FLEET_POSITION_TAIL.png
assets/cn/equipment/FLEET_POSITION_UP.png
assets/cn/equipment/FLEET_REORGANIZE.png
assets/cn/equipment/FLEET_SAVE.png
assets/cn/os_ash/ASH_SIMULATE.png
tests/fixtures/meta_equipment/simulate.png
tests/fixtures/meta_equipment/simulate_confirm.png
记录共享战斗装备处理、META 页面恢复约定,并增加离线回归覆盖。
  • 更新战斗、装备管理、演习和 META 维护文档,明确配置校验、控制方式、状态标志和页面恢复语义。
  • 增加配置预检、接口兼容、换装失败、演习换装及 META 多入口恢复测试。
docs/modules/combat.md
docs/modules/game/misc.md
docs/modules/game/retire-equipment.md
docs/modules/os/auxiliary.md
tests/test_equipment_config.py
tests/test_meta_beacon.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@Beatrice-betty Beatrice-betty changed the title feat(equipment): 新增装备配置 feat(equipment): 新增meta演习装备配置 Oct 21, 2026
@longer-sausage
longer-sausage marked this pull request as ready for review October 22, 2026 14:51

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

嘿——我发现了 7 个问题

给 AI 智能体的提示
请处理此代码审查中的评论:

## 单条评论

### 评论 1
<location path="module/equipment/equipment_config.py" line_range="139-140" />
<code_context>
+        logger.hr('战前装备配置', level=2)
+        self.ensure_reorganize()
+
+        if self.config.Equipment_ClearBeforeApply:
+            if not self.equipment_clear():
+                raise RequestHumanTakeover('清空装备失败')
+
</code_context>
<issue_to_address>
**舰队装备仍处于部分变更状态**

如果清空、应用或保存操作在之前已有位置发生变更后失败,`equipment_handle_before()` 会在设置 `_equipment_handle_before_flag` 之前抛出异常,因此恢复流程会跳过后续方案,舰队最终处于已清空或只装备了一部分的状态。

请在首次修改舰队之前设置待恢复标志,并且只有在恢复成功后才清除该标志。

另请检查 `module/equipment/equipment_config.py:143-153`。
</issue_to_address>

### 评论 2
<location path="module/os_ash/meta.py" line_range="825" />
<code_context>
                 if self._meta_category == 'beacon':
                     self._reset_assist_request_state()
+                    if self.ash_combat.equipment_handle_before_flag and not self._check_beacon_point():
+                        self.handle_ash_equipment_after()
                 if not self._meta_category in self._meta_receive:
                     self._meta_receive.append(self._meta_category)
</code_context>
<issue_to_address>
**META 恢复流程被放弃**

当装备恢复流程找不到可用的准备方案条目,或在超时前无法进入准备页面时,`handle_ash_equipment_after()` 会返回 `False`,但 META 调用方仍会继续完成任务、停止、切换或安排后续任务;下一个任务会因被丢弃的 `ash_combat` 实例而丢失待恢复标志,导致舰队仍处于临时配置。

当 `handle_ash_equipment_after()` 返回 `False` 时,请确保每个调用方都会停止,或以其他方式保留可重试的恢复状态。

另请检查 `module/os_ash/meta.py:342`、`module/os_ash/meta.py:350`、`module/os_ash/meta.py:443`、`module/os_ash/meta.py:454`、`module/os_ash/meta.py:999`。
</issue_to_address>

### 评论 3
<location path="module/exercise/exercise.py" line_range="346-348" />
<code_context>
                 break

-        # self.equipment_take_off_when_finished()
+        if self.equipment_config_enabled and self.equipment_handle_before_flag:
+            self._choose_opponent(0)
+            self.equipment_handle_after()
+            self.ui_back(EXERCISE_CHECK)

</code_context>
<issue_to_address>
**练习被中断时会跳过恢复**

如果在应用战前配置后练习循环被中断,`_exercise_once()` 中发生异常或收到任务停止信号,会导致 `run()` 在到达装备清理代码块之前退出。练习中的舰队会继续使用战前配置,而下一个任务实例没有持久化的待恢复标志来触发恢复。

请通过 `finally` 或中断处理程序执行恢复流程,同时保留原始停止信号。
</issue_to_address>

### 评论 4
<location path="module/os_ash/meta.py" line_range="182-186" />
<code_context>
+            else:
+                self.device.screenshot()
+
+            if self.appear(BATTLE_PREPARATION, offset=(30, 30)):
+                if self.ash_combat.is_dossier:
+                    if self.appear(BATTLE_PREPARATION, offset=(30, 30), interval=2):
+                        self.device.click(BACK_ARROW)
+                    continue
+                break
+            if timeout.reached():
</code_context>
<issue_to_address>
**档案恢复流程会卡住**

如果恢复流程从档案战斗准备页面开始,而点击返回后仍未离开该页面,档案分支会在检查 `timeout` 之前执行 `continue`,因此 `handle_ash_equipment_after()` 永远不会返回超时结果,META 恢复流程会无限循环。

请在档案分支继续执行之前检查超时。
</issue_to_address>

### 评论 5
<location path="tests/test_meta_beacon.py" line_range="15" />
<code_context>

+import module.config.server as server
+
+server.server = 'cn'
+
+from module.base.base import ModuleBase
</code_context>
<issue_to_address>
**测试会泄漏 CN 服务器设置**

当测试套件同时导入此模块和依赖其他服务器设置的测试时,该模块会在导入时修改共享的 `module.config.server.server` 值,却从不恢复它。因此,之后导入的测试会使用 CN 特定的服务器行为,并可能因测试顺序而通过或失败。

请在需要 CN 行为的测试中设置并恢复服务器值,或使用 teardown 恢复其原有值。
</issue_to_address>

### 评论 6
<location path="tests/test_equipment_config.py" line_range="214-218" />
<code_context>
+
+    def test_preparation_gets_new_frame_after_equipping_then_starts_once(self):
+        handler = make_handler(clear=False, cls=Combat)
+        handler.appear = Mock(return_value=True)
+        self.assertTrue(handler.handle_battle_preparation())
+        handler.device.click.assert_not_called()
+        self.assertTrue(handler.handle_battle_preparation())
+        handler.device.click.assert_called_once_with(BATTLE_PREPARATION)
+        handler._code_apply.assert_called_once_with(code=BEFORE_CODE)
+
</code_context>
<issue_to_address>
**没有验证是否获取了新截图**

如果准备循环在应用装备后不再刷新截图,那么在 `test_preparation_gets_new_frame_after_equipping_then_starts_once` 中,`appear` 始终返回 `True`,且测试直接调用了两次 `handle_battle_preparation()`。即使准备循环在装备完成后、下次检查前不再获取新截图,这两个断言仍会通过。

请使用依赖帧内容的外观检测结果来运行准备循环,并断言在下次准备检查之前已经截取了新图。
</issue_to_address>

### 评论 7
<location path="tests/test_equipment_config.py" line_range="57-61" />
<code_context>
+        handler.config.EquipmentCode_Config = yaml.safe_dump({'source': None, 'target': None})
+        handler._code_export = Mock(return_value=BEFORE_CODE)
+        self.assertTrue(handler.code_clear(name='source'))
+        self.assertEqual(yaml.safe_load(handler.config.EquipmentCode_Config)['source'], BEFORE_CODE)
+        self.assertEqual(handler.last_code, BEFORE_CODE)
+        self.assertTrue(handler.code_apply(name='target'))
+        handler._code_apply.assert_called_with(code=BEFORE_CODE)
+        self.assertIsNone(handler.last_code)
+
+    def test_invalid_codes_are_rejected_before_navigation_or_clearing(self):
</code_context>
<issue_to_address>
**没有断言装备是否已清空**

如果 `code_clear()` 跳过应用 `code=None`,却仍返回成功,那么在 `test_combat_named_code_backup_and_transfer_keep_original_behavior` 中,`_code_apply` 默认返回 `True`,但测试从未断言 `code_clear()` 是否以 `code=None` 调用了它。如果 `code_clear()` 仅备份代码却没有清空舰船,仍然报告成功,之后的转移调用会满足 `assert_called_with(code=BEFORE_CODE)`,测试也会通过。

除了之后的转移调用外,还请断言清空时 `_code_apply` 收到了 `code=None`。
</issue_to_address>

Sourcery 对开源项目免费——如果您喜欢我们的审查,欢迎分享 ✨
Original comment in English

Hey - I've found 7 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="module/equipment/equipment_config.py" line_range="139-140" />
<code_context>
+        logger.hr('战前装备配置', level=2)
+        self.ensure_reorganize()
+
+        if self.config.Equipment_ClearBeforeApply:
+            if not self.equipment_clear():
+                raise RequestHumanTakeover('清空装备失败')
+
</code_context>
<issue_to_address>
**Fleet remains partly changed**

When a clear, apply, or save operation fails after an earlier position has been changed, `equipment_handle_before()` raises before setting `_equipment_handle_before_flag`, so the recovery path skips the after-plan and the fleet remains cleared or partially equipped.

Set the pending-restore flag before the first fleet mutation and clear it only after restoration succeeds.

Also at `module/equipment/equipment_config.py:143-153`.
</issue_to_address>

### Comment 2
<location path="module/os_ash/meta.py" line_range="825" />
<code_context>
                 if self._meta_category == 'beacon':
                     self._reset_assist_request_state()
+                    if self.ash_combat.equipment_handle_before_flag and not self._check_beacon_point():
+                        self.handle_ash_equipment_after()
                 if not self._meta_category in self._meta_receive:
                     self._meta_receive.append(self._meta_category)
</code_context>
<issue_to_address>
**META recovery is abandoned**

When equipment recovery cannot find a usable preparation entry or reach the preparation page before timeout, `handle_ash_equipment_after()` returns `False`, but the META callers continue task completion, stopping, switching, or scheduling; the next task loses the pending flag on the discarded `ash_combat` instance, leaving the fleet in the temporary loadout.

Make every caller stop or otherwise preserve retryable restoration state when `handle_ash_equipment_after()` returns `False`.

Also at `module/os_ash/meta.py:342`, `module/os_ash/meta.py:350`, `module/os_ash/meta.py:443`, `module/os_ash/meta.py:454`, `module/os_ash/meta.py:999`.
</issue_to_address>

### Comment 3
<location path="module/exercise/exercise.py" line_range="346-348" />
<code_context>
                 break

-        # self.equipment_take_off_when_finished()
+        if self.equipment_config_enabled and self.equipment_handle_before_flag:
+            self._choose_opponent(0)
+            self.equipment_handle_after()
+            self.ui_back(EXERCISE_CHECK)

</code_context>
<issue_to_address>
**Interrupted exercise skips restoration**

When the exercise loop is interrupted after the before-configuration has been applied, an exception or task-stop signal during `_exercise_once()` exits `run()` before it reaches the equipment cleanup block. The exercise’s fleet remains on the before-configuration, and the next task instance has no persisted pending flag to trigger restoration.

Run the restoration path from a `finally` or interruption handler while preserving the original stop signal.
</issue_to_address>

### Comment 4
<location path="module/os_ash/meta.py" line_range="182-186" />
<code_context>
+            else:
+                self.device.screenshot()
+
+            if self.appear(BATTLE_PREPARATION, offset=(30, 30)):
+                if self.ash_combat.is_dossier:
+                    if self.appear(BATTLE_PREPARATION, offset=(30, 30), interval=2):
+                        self.device.click(BACK_ARROW)
+                    continue
+                break
+            if timeout.reached():
</code_context>
<issue_to_address>
**Dossier recovery hangs**

When recovery starts on dossier battle preparation and the back click does not leave that page, the dossier branch continues before checking `timeout`, so `handle_ash_equipment_after()` never reaches its timeout return and META recovery loops indefinitely.

Check the timeout before continuing the dossier branch.
</issue_to_address>

### Comment 5
<location path="tests/test_meta_beacon.py" line_range="15" />
<code_context>

+import module.config.server as server
+
+server.server = 'cn'
+
+from module.base.base import ModuleBase
</code_context>
<issue_to_address>
**Tests leak the CN server setting**

When the test suite imports this module alongside tests that depend on another server setting, the module assigns the shared `module.config.server.server` value at import time and never restores it, so tests imported afterward run with CN-specific server behavior and can pass or fail depending on test order.

Set and restore the server value within the tests that require CN behavior, or use a teardown that restores its previous value.
</issue_to_address>

### Comment 6
<location path="tests/test_equipment_config.py" line_range="214-218" />
<code_context>
+
+    def test_preparation_gets_new_frame_after_equipping_then_starts_once(self):
+        handler = make_handler(clear=False, cls=Combat)
+        handler.appear = Mock(return_value=True)
+        self.assertTrue(handler.handle_battle_preparation())
+        handler.device.click.assert_not_called()
+        self.assertTrue(handler.handle_battle_preparation())
+        handler.device.click.assert_called_once_with(BATTLE_PREPARATION)
+        handler._code_apply.assert_called_once_with(code=BEFORE_CODE)
+
</code_context>
<issue_to_address>
**Fresh screenshot is never verified**

When the preparation loop no longer refreshes the screenshot after equipment is applied, in `test_preparation_gets_new_frame_after_equipping_then_starts_once`, `appear` always returns `True` and the test calls `handle_battle_preparation()` twice directly. Both assertions pass even if the preparation loop stops taking a fresh screenshot between equipping and the next check.

Exercise the preparation loop with frame-sensitive appearance results and assert that a screenshot is taken before the next preparation check.
</issue_to_address>

### Comment 7
<location path="tests/test_equipment_config.py" line_range="57-61" />
<code_context>
+        handler.config.EquipmentCode_Config = yaml.safe_dump({'source': None, 'target': None})
+        handler._code_export = Mock(return_value=BEFORE_CODE)
+        self.assertTrue(handler.code_clear(name='source'))
+        self.assertEqual(yaml.safe_load(handler.config.EquipmentCode_Config)['source'], BEFORE_CODE)
+        self.assertEqual(handler.last_code, BEFORE_CODE)
+        self.assertTrue(handler.code_apply(name='target'))
+        handler._code_apply.assert_called_with(code=BEFORE_CODE)
+        self.assertIsNone(handler.last_code)
+
+    def test_invalid_codes_are_rejected_before_navigation_or_clearing(self):
</code_context>
<issue_to_address>
**Equipment clearing is not asserted**

When `code_clear()` skips applying `code=None` but still returns success, in `test_combat_named_code_backup_and_transfer_keep_original_behavior`, `_code_apply` returns `True` by default, but the test never asserts that `code_clear()` calls it with `code=None`. If `code_clear()` reports success after backing up the code without clearing the ship, the later transfer call satisfies `assert_called_with(code=BEFORE_CODE)` and the test passes.

Assert that `_code_apply` receives `code=None` during clearing, in addition to the later transfer call.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment on lines +139 to +140
if self.config.Equipment_ClearBeforeApply:
if not self.equipment_clear():

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 中 · 舰队装备仍处于部分变更状态

如果清空、应用或保存操作在之前已有位置发生变更后失败,equipment_handle_before() 会在设置 _equipment_handle_before_flag 之前抛出异常,因此恢复流程会跳过后续方案,舰队最终处于已清空或只装备了一部分的状态。

请在首次修改舰队之前设置待恢复标志,并且只有在恢复成功后才清除该标志。

另请检查 module/equipment/equipment_config.py:143-153。

给 AI 智能体的提示
在 `module/equipment/equipment_config.py` 第 139-140 行:

**舰队装备仍处于部分变更状态**

如果清空、应用或保存操作在之前已有位置发生变更后失败,`equipment_handle_before()` 会在设置 `_equipment_handle_before_flag` 之前抛出异常,因此恢复流程会跳过后续方案,舰队最终处于已清空或只装备了一部分的状态。

请在首次修改舰队之前设置待恢复标志,并且只有在恢复成功后才清除该标志。

另请检查 `module/equipment/equipment_config.py:143-153`。
Original comment in English

🟡 Medium · Fleet remains partly changed

When a clear, apply, or save operation fails after an earlier position has been changed, equipment_handle_before() raises before setting _equipment_handle_before_flag, so the recovery path skips the after-plan and the fleet remains cleared or partially equipped.

Set the pending-restore flag before the first fleet mutation and clear it only after restoration succeeds.

Also at module/equipment/equipment_config.py:143-153.

Prompt for AI agents
In `module/equipment/equipment_config.py` at lines 139-140:

**Fleet remains partly changed**

When a clear, apply, or save operation fails after an earlier position has been changed, `equipment_handle_before()` raises before setting `_equipment_handle_before_flag`, so the recovery path skips the after-plan and the fleet remains cleared or partially equipped.

Set the pending-restore flag before the first fleet mutation and clear it only after restoration succeeds.

Also at `module/equipment/equipment_config.py:143-153`.

Comment thread module/os_ash/meta.py
logger.info("当前服务器暂不支持档案信标和一刀模式,请联系开发者")
self._ensure_meta_page()
self._attack_meta()
self.handle_ash_equipment_after()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 高 · META 恢复流程被放弃

当装备恢复流程找不到可用的准备方案条目,或在超时前无法进入准备页面时,handle_ash_equipment_after() 会返回 False,但 META 调用方仍会继续完成任务、停止、切换或安排后续任务;下一个任务会因被丢弃的 ash_combat 实例而丢失待恢复标志,导致舰队仍处于临时配置。

当 handle_ash_equipment_after() 返回 False 时,请确保每个调用方都会停止,或以其他方式保留可重试的恢复状态。

另请检查 module/os_ash/meta.py:342、module/os_ash/meta.py:350、module/os_ash/meta.py:443、module/os_ash/meta.py:454、module/os_ash/meta.py:999。

给 AI 智能体的提示
在 `module/os_ash/meta.py` 第 825 行:

**META 恢复流程被放弃**

当装备恢复流程找不到可用的准备方案条目,或在超时前无法进入准备页面时,`handle_ash_equipment_after()` 会返回 `False`,但 META 调用方仍会继续完成任务、停止、切换或安排后续任务;下一个任务会因被丢弃的 `ash_combat` 实例而丢失待恢复标志,导致舰队仍处于临时配置。

当 `handle_ash_equipment_after()` 返回 `False` 时,请确保每个调用方都会停止,或以其他方式保留可重试的恢复状态。

另请检查 `module/os_ash/meta.py:342`、`module/os_ash/meta.py:350`、`module/os_ash/meta.py:443`、`module/os_ash/meta.py:454`、`module/os_ash/meta.py:999`。
Original comment in English

🟠 High · META recovery is abandoned

When equipment recovery cannot find a usable preparation entry or reach the preparation page before timeout, handle_ash_equipment_after() returns False, but the META callers continue task completion, stopping, switching, or scheduling; the next task loses the pending flag on the discarded ash_combat instance, leaving the fleet in the temporary loadout.

Make every caller stop or otherwise preserve retryable restoration state when handle_ash_equipment_after() returns False.

Also at module/os_ash/meta.py:342, module/os_ash/meta.py:350, module/os_ash/meta.py:443, module/os_ash/meta.py:454, module/os_ash/meta.py:999.

Prompt for AI agents
In `module/os_ash/meta.py` at line 825:

**META recovery is abandoned**

When equipment recovery cannot find a usable preparation entry or reach the preparation page before timeout, `handle_ash_equipment_after()` returns `False`, but the META callers continue task completion, stopping, switching, or scheduling; the next task loses the pending flag on the discarded `ash_combat` instance, leaving the fleet in the temporary loadout.

Make every caller stop or otherwise preserve retryable restoration state when `handle_ash_equipment_after()` returns `False`.

Also at `module/os_ash/meta.py:342`, `module/os_ash/meta.py:350`, `module/os_ash/meta.py:443`, `module/os_ash/meta.py:454`, `module/os_ash/meta.py:999`.

Comment on lines +346 to +348
if self.equipment_config_enabled and self.equipment_handle_before_flag:
self._choose_opponent(0)
self.equipment_handle_after()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 中 · 练习被中断时会跳过恢复

如果在应用战前配置后练习循环被中断,_exercise_once() 中发生异常或收到任务停止信号,会导致 run() 在到达装备清理代码块之前退出。练习中的舰队会继续使用战前配置,而下一个任务实例没有持久化的待恢复标志来触发恢复。

请通过 finally 或中断处理程序执行恢复流程,同时保留原始停止信号。

给 AI 智能体的提示
在 `module/exercise/exercise.py` 第 346-348 行:

**练习被中断时会跳过恢复**

如果在应用战前配置后练习循环被中断,`_exercise_once()` 中发生异常或收到任务停止信号,会导致 `run()` 在到达装备清理代码块之前退出。练习中的舰队会继续使用战前配置,而下一个任务实例没有持久化的待恢复标志来触发恢复。

请通过 `finally` 或中断处理程序执行恢复流程,同时保留原始停止信号。
Original comment in English

🟡 Medium · Interrupted exercise skips restoration

When the exercise loop is interrupted after the before-configuration has been applied, an exception or task-stop signal during _exercise_once() exits run() before it reaches the equipment cleanup block. The exercise’s fleet remains on the before-configuration, and the next task instance has no persisted pending flag to trigger restoration.

Run the restoration path from a finally or interruption handler while preserving the original stop signal.

Prompt for AI agents
In `module/exercise/exercise.py` at lines 346-348:

**Interrupted exercise skips restoration**

When the exercise loop is interrupted after the before-configuration has been applied, an exception or task-stop signal during `_exercise_once()` exits `run()` before it reaches the equipment cleanup block. The exercise’s fleet remains on the before-configuration, and the next task instance has no persisted pending flag to trigger restoration.

Run the restoration path from a `finally` or interruption handler while preserving the original stop signal.

Comment thread module/os_ash/meta.py
Comment on lines +182 to +186
if self.appear(BATTLE_PREPARATION, offset=(30, 30)):
if self.ash_combat.is_dossier:
if self.appear(BATTLE_PREPARATION, offset=(30, 30), interval=2):
self.device.click(BACK_ARROW)
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 中 · 档案恢复流程会卡住

如果恢复流程从档案战斗准备页面开始,而点击返回后仍未离开该页面,档案分支会在检查 timeout 之前执行 continue,因此 handle_ash_equipment_after() 永远不会返回超时结果,META 恢复流程会无限循环。

请在档案分支继续执行之前检查超时。

给 AI 智能体的提示
在 `module/os_ash/meta.py` 第 182-186 行:

**档案恢复流程会卡住**

如果恢复流程从档案战斗准备页面开始,而点击返回后仍未离开该页面,档案分支会在检查 `timeout` 之前执行 `continue`,因此 `handle_ash_equipment_after()` 永远不会返回超时结果,META 恢复流程会无限循环。

请在档案分支继续执行之前检查超时。
Original comment in English

🟡 Medium · Dossier recovery hangs

When recovery starts on dossier battle preparation and the back click does not leave that page, the dossier branch continues before checking timeout, so handle_ash_equipment_after() never reaches its timeout return and META recovery loops indefinitely.

Check the timeout before continuing the dossier branch.

Prompt for AI agents
In `module/os_ash/meta.py` at lines 182-186:

**Dossier recovery hangs**

When recovery starts on dossier battle preparation and the back click does not leave that page, the dossier branch continues before checking `timeout`, so `handle_ash_equipment_after()` never reaches its timeout return and META recovery loops indefinitely.

Check the timeout before continuing the dossier branch.

Comment thread tests/test_meta_beacon.py

import module.config.server as server

server.server = 'cn'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 中 · 测试会泄漏 CN 服务器设置

当测试套件同时导入此模块和依赖其他服务器设置的测试时,该模块会在导入时修改共享的 module.config.server.server 值,却从不恢复它。因此,之后导入的测试会使用 CN 特定的服务器行为,并可能因测试顺序而通过或失败。

请在需要 CN 行为的测试中设置并恢复服务器值,或使用 teardown 恢复其原有值。

给 AI 智能体的提示
在 `tests/test_meta_beacon.py` 第 15 行:

**测试会泄漏 CN 服务器设置**

当测试套件同时导入此模块和依赖其他服务器设置的测试时,该模块会在导入时修改共享的 `module.config.server.server` 值,却从不恢复它。因此,之后导入的测试会使用 CN 特定的服务器行为,并可能因测试顺序而通过或失败。

请在需要 CN 行为的测试中设置并恢复服务器值,或使用 teardown 恢复其原有值。
Original comment in English

🟡 Medium · Tests leak the CN server setting

When the test suite imports this module alongside tests that depend on another server setting, the module assigns the shared module.config.server.server value at import time and never restores it, so tests imported afterward run with CN-specific server behavior and can pass or fail depending on test order.

Set and restore the server value within the tests that require CN behavior, or use a teardown that restores its previous value.

Prompt for AI agents
In `tests/test_meta_beacon.py` at line 15:

**Tests leak the CN server setting**

When the test suite imports this module alongside tests that depend on another server setting, the module assigns the shared `module.config.server.server` value at import time and never restores it, so tests imported afterward run with CN-specific server behavior and can pass or fail depending on test order.

Set and restore the server value within the tests that require CN behavior, or use a teardown that restores its previous value.

Comment on lines +214 to +218
handler.appear = Mock(return_value=True)
self.assertTrue(handler.handle_battle_preparation())
handler.device.click.assert_not_called()
self.assertTrue(handler.handle_battle_preparation())
handler.device.click.assert_called_once_with(BATTLE_PREPARATION)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 中 · 没有验证是否获取了新截图

如果准备循环在应用装备后不再刷新截图,那么在 test_preparation_gets_new_frame_after_equipping_then_starts_once 中,appear 始终返回 True,且测试直接调用了两次 handle_battle_preparation()。即使准备循环在装备完成后、下次检查前不再获取新截图,这两个断言仍会通过。

请使用依赖帧内容的外观检测结果来运行准备循环,并断言在下次准备检查之前已经截取了新图。

给 AI 智能体的提示
在 `tests/test_equipment_config.py` 第 214-218 行:

**没有验证是否获取了新截图**

如果准备循环在应用装备后不再刷新截图,那么在 `test_preparation_gets_new_frame_after_equipping_then_starts_once` 中,`appear` 始终返回 `True`,且测试直接调用了两次 `handle_battle_preparation()`。即使准备循环在装备完成后、下次检查前不再获取新截图,这两个断言仍会通过。

请使用依赖帧内容的外观检测结果来运行准备循环,并断言在下次准备检查之前已经截取了新图。
Original comment in English

🟡 Medium · Fresh screenshot is never verified

When the preparation loop no longer refreshes the screenshot after equipment is applied, in test_preparation_gets_new_frame_after_equipping_then_starts_once, appear always returns True and the test calls handle_battle_preparation() twice directly. Both assertions pass even if the preparation loop stops taking a fresh screenshot between equipping and the next check.

Exercise the preparation loop with frame-sensitive appearance results and assert that a screenshot is taken before the next preparation check.

Prompt for AI agents
In `tests/test_equipment_config.py` at lines 214-218:

**Fresh screenshot is never verified**

When the preparation loop no longer refreshes the screenshot after equipment is applied, in `test_preparation_gets_new_frame_after_equipping_then_starts_once`, `appear` always returns `True` and the test calls `handle_battle_preparation()` twice directly. Both assertions pass even if the preparation loop stops taking a fresh screenshot between equipping and the next check.

Exercise the preparation loop with frame-sensitive appearance results and assert that a screenshot is taken before the next preparation check.

Comment on lines +57 to +61
self.assertEqual(yaml.safe_load(handler.config.EquipmentCode_Config)['source'], BEFORE_CODE)
self.assertEqual(handler.last_code, BEFORE_CODE)
self.assertTrue(handler.code_apply(name='target'))
handler._code_apply.assert_called_with(code=BEFORE_CODE)
self.assertIsNone(handler.last_code)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 中 · 没有断言装备是否已清空

如果 code_clear() 跳过应用 code=None,却仍返回成功,那么在 test_combat_named_code_backup_and_transfer_keep_original_behavior 中,_code_apply 默认返回 True,但测试从未断言 code_clear() 是否以 code=None 调用了它。如果 code_clear() 仅备份代码却没有清空舰船,仍然报告成功,之后的转移调用会满足 assert_called_with(code=BEFORE_CODE),测试也会通过。

除了之后的转移调用外,还请断言清空时 _code_apply 收到了 code=None。

给 AI 智能体的提示
在 `tests/test_equipment_config.py` 第 57-61 行:

**没有断言装备是否已清空**

如果 `code_clear()` 跳过应用 `code=None`,却仍返回成功,那么在 `test_combat_named_code_backup_and_transfer_keep_original_behavior` 中,`_code_apply` 默认返回 `True`,但测试从未断言 `code_clear()` 是否以 `code=None` 调用了它。如果 `code_clear()` 仅备份代码却没有清空舰船,仍然报告成功,之后的转移调用会满足 `assert_called_with(code=BEFORE_CODE)`,测试也会通过。

除了之后的转移调用外,还请断言清空时 `_code_apply` 收到了 `code=None`。
Original comment in English

🟡 Medium · Equipment clearing is not asserted

When code_clear() skips applying code=None but still returns success, in test_combat_named_code_backup_and_transfer_keep_original_behavior, _code_apply returns True by default, but the test never asserts that code_clear() calls it with code=None. If code_clear() reports success after backing up the code without clearing the ship, the later transfer call satisfies assert_called_with(code=BEFORE_CODE) and the test passes.

Assert that _code_apply receives code=None during clearing, in addition to the later transfer call.

Prompt for AI agents
In `tests/test_equipment_config.py` at lines 57-61:

**Equipment clearing is not asserted**

When `code_clear()` skips applying `code=None` but still returns success, in `test_combat_named_code_backup_and_transfer_keep_original_behavior`, `_code_apply` returns `True` by default, but the test never asserts that `code_clear()` calls it with `code=None`. If `code_clear()` reports success after backing up the code without clearing the ship, the later transfer call satisfies `assert_called_with(code=BEFORE_CODE)` and the test passes.

Assert that `_code_apply` receives `code=None` during clearing, in addition to the later transfer call.

@longer-sausage
longer-sausage merged commit 36559d2 into wess09:dev Oct 22, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant