Skip to content

chore: upstream sync + Admin Service daemon (MEmu self-heal without admin)#16

Open
Coldaine wants to merge 11 commits intomasterfrom
chore/upstream-sync-alas-wrapped
Open

chore: upstream sync + Admin Service daemon (MEmu self-heal without admin)#16
Coldaine wants to merge 11 commits intomasterfrom
chore/upstream-sync-alas-wrapped

Conversation

@Coldaine
Copy link
Owner

@Coldaine Coldaine commented Feb 13, 2026

Summary

Single PR combining:

  1. Upstream sync: Merge latest Zuosizhu/Alas-with-Dashboard (submodule at cda8619) into alas_wrapped — game updates, bug fixes. Preserved 6 local customizations + restored Akashi/template in module/base/template.py.
  2. Admin Service daemon: Optional elevated HTTP service (Windows Task Scheduler) so ALAS can start/kill MEmu without the bot running as Administrator. Token auth, localhost-only. Install once as Admin: alas_wrapped/install_admin_service.bat. See docs/plans/admin_service_architecture.md.
  3. Recovery behavior: On unknown game page when server is up, ALAS always attempts Restart; on 3 consecutive task failures, triggers Restart and continues (no human takeover).
  4. Fixes: uiautomator2 compatibility (connection_attr.py), zh-CN RestartOnUnknownPage help string escape.

Why one PR

Requested: single pull request for upstream sync + admin service implementation instead of separate PRs.

Testing

  • Run ALAS / MCP tools against alas_wrapped after merge.
  • Optional: install Admin Service (run install_admin_service.bat as Admin) and verify bot can restart MEmu without admin.

Coldaine and others added 4 commits February 13, 2026 16:52
- Add AlasAdminService: elevated HTTP daemon (Task Scheduler) for start/kill
- Add AlasAdminClient and platform_windows integration; token auth, cmdline kill
- Recovery: always restart on unknown page when server up; 3-failure triggers restart and continue
- Fix uiautomator2 compatibility (set_new_command_timeout, logger) in connection_attr
- Fix zh-CN RestartOnUnknownPage help string escape
- Doc: docs/plans/admin_service_architecture.md; install_admin_service.bat

Co-authored-by: Cursor <cursoragent@cursor.com>
- Synced module/, assets/, campaign/, config templates, deploy/, doc/, submodule/, webapp/
- Preserved our customizations: logger (debug), webui patch (py37 subprocess), app (patch call), device/method/utils (u2.init guard), minitouch (_Service fallback), device/connection (AdbClient monkey patch)
- No submodule pointer change (already at latest)

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…tomization)

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI review requested due to automatic review settings February 13, 2026 23:50
@qodo-free-for-open-source-projects

Review Summary by Qodo

Merge upstream Alas-with-Dashboard with Operation Siren implementation and coalition event updates

✨ Enhancement 🐞 Bug fix 📝 Documentation

Grey Divider

Walkthroughs

Description
• **Major upstream sync**: Merged latest Zuosizhu/Alas-with-Dashboard (cda8619c) into alas_wrapped
  to incorporate game updates and upstream bug fixes
• **Operation Siren complete implementation**: Refactored operation_siren.py with 20+ methods for
  daily missions, port operations, shop management, voucher handling, and meowfficer farming
• **Loop refactoring across modules**: Replaced for _ in self.loop() patterns with explicit `while
  1 loops and added skip_first_screenshot parameters throughout OS handlers (strategic.py`,
  action_point.py, storage.py, mission.py, map_event.py, map_order.py, port.py,
  enemy_searching.py, os_status.py) for improved screenshot control
• **Coalition event updates**: Removed FASHION event (coalition_20260122) support and updated to
  FROSTFALL/DAL events with new area-based difficulty modes (area1-normal through area6-hard)
• **Campaign loading refactor**: Changed load_campaign() to use instance variables instead of
  returning new instances for better lifecycle management
• **Asset and UI improvements**: Added QUIT_RECONFIRM button asset for exercise quit confirmation,
  updated tactical reward button JP coordinates, added siren platform handler
• **Configuration updates**: Updated deploy templates with new executable paths, removed
  RestartOnUnknownPage option, updated coalition mode defaults and options
• **Internationalization updates**: Updated i18n strings (en-US, zh-CN, zh-TW, ja-JP) for coalition
  task names and mode options
• **Preserved local customizations**: Maintained 6 key customizations in logger, webui, device
  methods, and restored template.py with Akashi merchant threshold and channel fix
Diagram
flowchart LR
  upstream["Upstream Alas<br/>cda8619c"] -- "Merge content<br/>module, assets,<br/>campaign, deploy" --> alas["alas_wrapped<br/>codebase"]
  alas -- "Refactor loops<br/>add skip_first_screenshot" --> handlers["OS Handlers<br/>strategic, action_point,<br/>storage, mission, etc."]
  alas -- "Remove FASHION<br/>Add FROSTFALL/DAL" --> coalition["Coalition<br/>Event Updates"]
  alas -- "Implement 20+ methods<br/>daily, port, shop" --> siren["Operation Siren<br/>Complete"]
  alas -- "Update config<br/>paths, modes, i18n" --> config["Configuration<br/>& Localization"]
  customizations["Local Customizations<br/>logger, webui, device"] -- "Preserve & restore" --> alas
Loading

Grey Divider

File Changes

1. alas_wrapped/module/os/operation_siren.py ✨ Enhancement +891/-34

Complete Operation Siren task implementation with all gameplay features

• Completely refactored from a simple class inheritance structure to a full implementation with 20+
 methods for Operation Siren tasks
• Added comprehensive methods for daily missions, port operations, shop management, voucher
 handling, and meowfficer farming
• Implemented complex task scheduling including cross-month operations, abyssal/obscure clearing,
 stronghold battles, and month boss encounters
• Added helper methods for action point management, fleet coordination, and task delay calculations

alas_wrapped/module/os/operation_siren.py


2. alas_wrapped/module/exercise/assets.py ✨ Enhancement +1/-0

Add exercise quit confirmation button asset

• Added new button asset QUIT_RECONFIRM with multi-region support (cn, en, jp, tw)
• Defines clickable area and visual properties for exercise quit confirmation dialog

alas_wrapped/module/exercise/assets.py


3. alas_wrapped/module/coalition/ui.py ✨ Enhancement +31/-69

Remove FASHION coalition event support and refactor fleet handling

• Removed support for coalition_20260122 (FASHION event) from mode switching and fleet
 configuration
• Renamed coalition_set_fleet() to coalition_ensure_fleet() and removed return value logic
• Simplified handle_fleet_preparation() by removing fleet switch return value and consolidating
 error checks
• Removed FASHION event entries from entrance, difficulty, and battle count dictionaries

alas_wrapped/module/coalition/ui.py


View more (43)
4. alas_wrapped/module/tactical/assets.py 🐞 Bug fix +1/-1

Fix tactical reward button JP region coordinates

• Updated REWARD_2 button's JP region button coordinates from (399, 415, 520, 450) to `(383,
 404, 503, 444)`
• Aligns JP button area with other regions for consistency

alas_wrapped/module/tactical/assets.py


5. alas_wrapped/module/os_handler/strategic.py ✨ Enhancement +74/-32

Refactor strategic search loops and add screenshot control parameters

• Replaced for _ in self.loop() patterns with explicit while 1 loops and skip_first_screenshot
 parameter handling
• Added Timer import and refactored timeout handling in _strategy_search_scroll_appear() method
• Reordered conditional checks in strategic search option setting for better logic flow
• Added skip_first_screenshot parameters to multiple methods for improved screenshot control

alas_wrapped/module/os_handler/strategic.py


6. alas_wrapped/module/os_handler/action_point.py ✨ Enhancement +56/-23

Refactor action point loops and add screenshot control parameters

• Replaced for _ in self.loop() patterns with explicit while 1 loops throughout the file
• Added skip_first_screenshot parameter to 8+ methods for better screenshot control
• Refactored action_point_set_button() to use explicit loop counter instead of timeout
• Improved action_point_get_buy_remain() with explicit Timer usage and better timeout handling

alas_wrapped/module/os_handler/action_point.py


7. alas_wrapped/module/os_handler/storage.py ✨ Enhancement +52/-13

Refactor storage handler loops and add screenshot parameters

• Replaced for _ in self.loop() patterns with explicit while 1 loops in 6+ methods
• Added skip_first_screenshot parameter to storage-related methods for improved control
• Refactored storage item checkout and logger usage methods with better loop handling

alas_wrapped/module/os_handler/storage.py


8. alas_wrapped/module/base/template.py 🐞 Bug fix +6/-25

Clean up template matching debug code and simplify implementation

• Removed debug logging comments and simplified _safe_match_template() channel mismatch handling
• Removed targeted Akashi debugging code that captured near-miss template matches
• Simplified match_luma() method by removing conditional image shape checks
• Reverted match_result() and match_multi() to use standard cv2.matchTemplate() instead of
 _safe_match_template()

alas_wrapped/module/base/template.py


9. alas_wrapped/module/coalition/coalition.py ✨ Enhancement +8/-29

Remove FASHION event and raid-event conflict handling

• Removed coalition_20260122 (FASHION event) support from get_event_pt() method
• Removed _coalition_has_oil_icon property that checked for FASHION event
• Removed UI navigation code for servers without oil icon display
• Removed disable_event_on_raid() method that disabled event tasks during raids
• Removed commented-out code for oil checking in coalition execution

alas_wrapped/module/coalition/coalition.py


10. alas_wrapped/module/os/globe_operation.py ✨ Enhancement +35/-15

Refactor globe operation loops and add screenshot control

• Replaced for _ in self.loop() patterns with explicit while 1 loops in 4+ methods
• Added skip_first_screenshot parameter to ensure_no_zone_pinned(), os_map_goto_globe(), and
 globe_enter() methods
• Simplified zone_select_execute() to use ui_click() helper instead of manual loop
• Improved screenshot control throughout globe operation methods

alas_wrapped/module/os/globe_operation.py


11. alas_wrapped/module/os/map.py ✨ Enhancement +18/-8

Refactor OS map loops and use QUIT_RECONFIRM asset

• Added import for QUIT_RECONFIRM from exercise assets
• Replaced for _ in self.loop() with explicit while 1 loops in os_auto_search_daemon() and
 interrupt_auto_search()
• Changed handle_combat_quit_reconfirm() call to appear_then_click(QUIT_RECONFIRM, ...) for
 consistency
• Added skip_first_screenshot parameter to auto search methods

alas_wrapped/module/os/map.py


12. alas_wrapped/module/campaign/os_run.py ✨ Enhancement +37/-29

Refactor campaign loading to use instance variables

• Refactored load_campaign() to use instance variables campaign and campaign_loaded instead of
 returning new instances
• Changed method signature from load_campaign(cls=OperationSiren) to load_campaign() with no
 parameters
• Updated all task methods to call load_campaign() once and reuse self.campaign instance
• Improved campaign instance lifecycle management across multiple task executions

alas_wrapped/module/campaign/os_run.py


13. alas_wrapped/module/os_handler/mission.py ✨ Enhancement +29/-7

Refactor mission handler loops and add screenshot parameters

• Replaced for _ in self.loop() patterns with explicit while 1 loops in 4+ methods
• Added skip_first_screenshot parameter to os_mission_enter() and os_mission_quit() methods
• Improved screenshot control in mission checkout and overview acceptance methods

alas_wrapped/module/os_handler/mission.py


14. alas_wrapped/module/campaign/campaign_event.py ✨ Enhancement +9/-37

Remove gems farming reset method and raid-event conflict handling

• Removed _reset_gems_farming() method and inlined its logic into _disable_tasks()
• Removed disable_event_on_raid() method that handled event-raid conflicts
• Changed log message from "disable old raid event tasks" to "disable old event tasks"
• Simplified event disabling logic by removing raid-specific handling

alas_wrapped/module/campaign/campaign_event.py


15. alas_wrapped/module/os/fleet.py ✨ Enhancement +21/-5

Refactor fleet loops and use QUIT_RECONFIRM asset

• Added import for QUIT_RECONFIRM from exercise assets
• Replaced for _ in self.loop() patterns with explicit while 1 loops in 3+ methods
• Changed handle_combat_quit_reconfirm() call to appear_then_click(QUIT_RECONFIRM, ...) for
 consistency
• Added skip_first_screenshot parameter to boss_leave() method

alas_wrapped/module/os/fleet.py


16. alas_wrapped/module/os/map_fleet_selector.py ✨ Enhancement +30/-8

Add screenshot control parameters to fleet selector methods

• Added skip_first_screenshot parameter to 4 methods: open(), close(), click(), and
 ensure_to_be()
• Replaced for _ in main.loop() patterns with explicit while 1 loops
• Improved screenshot control throughout fleet selector operations

alas_wrapped/module/os/map_fleet_selector.py


17. alas_wrapped/module/os_handler/map_event.py ✨ Enhancement +56/-4

Add siren platform handler and refactor map event loops

• Added new handle_siren_platform() method to handle siren platform notices after map entry
• Replaced for _ in self.loop() patterns with explicit while 1 loops in 2+ methods
• Added skip_first_screenshot parameter to ensure_no_map_event() and os_auto_search_quit()
 methods

alas_wrapped/module/os_handler/map_event.py


18. alas_wrapped/module/os_handler/map_order.py ✨ Enhancement +23/-8

Refactor map order loops and add screenshot control parameters

• Replaced for _ in self.loop() patterns with explicit while 1 loops in 4+ methods
• Added skip_first_screenshot parameter to order_enter(), order_execute(), and
 wait_until_order_finished() methods
• Improved screenshot control and loop handling throughout map order operations

alas_wrapped/module/os_handler/map_order.py


19. alas_wrapped/module/ui/page.py ✨ Enhancement +4/-9

Update coalition page routing and remove FASHION event

• Changed coalition page destination from page_campaign_menu to page_campaign in multiple
 comments
• Updated active coalition page from FASHION event to FROSTFALL event
• Removed FASHION-specific coalition page configuration

alas_wrapped/module/ui/page.py


20. alas_wrapped/module/os/map_operation.py ✨ Enhancement +18/-4

Refactor map operation loops and add screenshot parameters

• Replaced for _ in self.loop() patterns with explicit while 1 loops in 2+ methods
• Added skip_first_screenshot parameter to zone_init() and map_exit() methods
• Improved screenshot control and loop handling in map operation methods

alas_wrapped/module/os/map_operation.py


21. alas_wrapped/module/os_handler/port.py ✨ Enhancement +15/-3

Refactor port handler loops and use explicit imports

• Changed import from wildcard from module.os_handler.assets import * to explicit imports
• Replaced for _ in self.loop() patterns with explicit while 1 loops in 2+ methods
• Added skip_first_screenshot parameter handling to port mission and dock repair methods

alas_wrapped/module/os_handler/port.py


22. alas_wrapped/module/ui/ui.py ✨ Enhancement +6/-7

Update coalition UI handling for DAL event

• Commented out NEONCITY fleet preparation exit handling
• Uncommented and enabled DAL difficulty exit handling for coalition_20251120
• Removed FASHION event reuse of NEONCITY preparation exit

alas_wrapped/module/ui/ui.py


23. alas_wrapped/module/os_handler/enemy_searching.py ✨ Enhancement +16/-5
 Refactor enemy searching loops and add screenshot control

alas_wrapped/module/os_handler/enemy_searching.py


24. alas_wrapped/module/config/config_generated.py ⚙️ Configuration changes +1/-2

Update error config and coalition mode defaults

• Removed Error_RestartOnUnknownPage = True configuration option
• Updated Coalition_Mode default from 'hard' to 'area1-normal' with expanded mode options
• Changed coalition mode options to include area-specific and difficulty variants

alas_wrapped/module/config/config_generated.py


25. alas_wrapped/module/os_handler/os_status.py ✨ Enhancement +9/-4

Refactor yellow coins retrieval with explicit loop control

• Added import for module.os_handler.assets wildcard
• Refactored get_yellow_coins() method to use explicit while True loop instead of self.loop()
• Added skip_first_screenshot parameter (default True) to control initial screenshot behavior
• Changed screenshot logic to call self.device.screenshot() conditionally based on
 skip_first_screenshot flag

alas_wrapped/module/os_handler/os_status.py


26. alas_wrapped/module/exercise/combat.py ✨ Enhancement +3/-1

Update combat quit reconfirm handling with direct click

• Added explicit import of QUIT from module.combat.combat
• Replaced self.handle_combat_quit_reconfirm() call with `self.appear_then_click(QUIT_RECONFIRM,
 offset=(20, 20), interval=5)`
• Added self.interval_reset(QUIT) call after the click operation

alas_wrapped/module/exercise/combat.py


27. alas_wrapped/module/config/argument/args.json ⚙️ Configuration changes +78/-71

Update config options for events and coalition modes

• Removed RestartOnUnknownPage configuration option from Error settings
• Updated Coalition event options: replaced event_20220526_cn with event_20251218_cn across
 multiple server regions
• Changed Coalition mode options from easy, normal, hard, sp to area-based modes (area1-normal
 through area6-hard)
• Updated Coalition default mode value from hard or sp to area1-normal
• Removed coalition_20260122 event option, keeping only coalition_20251120

alas_wrapped/module/config/argument/args.json


28. alas_wrapped/module/config/i18n/en-US.json 📝 Documentation +22/-19

Update i18n strings for coalition and configuration changes

• Moved Coalition task name from "Light & Shadow Fashion Shoot" to "DATE A LANE" and repositioned
 it after Hospital
• Moved CoalitionSp task name from "Light & Shadow Fashion Shoot SP" to "Neon City Investigator
 SP" and repositioned it after RaidDaily
• Removed RestartOnUnknownPage configuration help text
• Removed coalition_20260122 event label
• Updated Coalition Mode options from easy, normal, hard, sp to area1-normal through
 area6-hard
• Simplified OpponentTrial help text by removing detailed explanation
• Updated OpponentChooseMode help text to be empty

alas_wrapped/module/config/i18n/en-US.json


29. alas_wrapped/module/config/i18n/zh-TW.json 📝 Documentation +20/-17

Update Traditional Chinese i18n for coalition changes

• Moved Coalition task name from "光影風尚-拍攝進行時" to "極地風暴" and repositioned after Hospital
• Moved CoalitionSp task name from "光影風尚-拍攝進行時SP" to "極地風暴每日SP" and repositioned after RaidDaily
• Removed RestartOnUnknownPage configuration help text
• Removed coalition_20260122 event label
• Updated Coalition Mode options from easy, normal, hard, sp to area1-normal through
 area6-hard

alas_wrapped/module/config/i18n/zh-TW.json


30. alas_wrapped/module/config/i18n/zh-CN.json 📝 Documentation +20/-17

Update Simplified Chinese i18n for coalition changes

• Moved Coalition task name from "光影风尚-拍摄进行时" to "DATE A LANE" and repositioned after Hospital
• Moved CoalitionSp task name from "光影风尚-拍摄进行时SP" to "迷彩都市的寻踪者SP" and repositioned after RaidDaily
• Removed RestartOnUnknownPage configuration help text
• Removed coalition_20260122 event label
• Updated Coalition Mode options from easy, normal, hard, sp to area1-normal through
 area6-hard

alas_wrapped/module/config/i18n/zh-CN.json


31. alas_wrapped/module/config/i18n/ja-JP.json 📝 Documentation +20/-17

Update Japanese i18n for coalition changes

• Moved Coalition task name from "特集写真-撮影進行中" to "ネオンシティの探索者" and repositioned after Hospital
• Moved CoalitionSp task name from "特集写真-撮影進行中SP" to "ネオンシティの探索者SP" and repositioned after
 RaidDaily
• Removed RestartOnUnknownPage configuration help text
• Removed coalition_20260122 event label
• Updated Coalition Mode options from easy, normal, hard, sp to area1-normal through
 area6-hard

alas_wrapped/module/config/i18n/ja-JP.json


32. alas_wrapped/config/deploy.template.yaml ⚙️ Configuration changes +10/-12

Update deploy template executable paths and settings

• Changed GitExecutable from git (system PATH) to ./toolkit/Git/mingw64/bin/git.exe with
 updated comments
• Changed AutoUpdate from false to true with updated rationale comments
• Changed PythonExecutable from ./.venv/Scripts/python.exe to ./toolkit/python.exe with
 updated comments
• Changed InstallDependencies from false to true with updated rationale comments
• Changed AdbExecutable from adb (system PATH) to
 ./toolkit/Lib/site-packages/adbutils/binaries/adb.exe with updated comments

alas_wrapped/config/deploy.template.yaml


33. alas_wrapped/deploy/Windows/template.yaml ⚙️ Configuration changes +8/-11

Update Windows deploy template paths and settings

• Changed AutoUpdate from false to true with updated comment rationale
• Changed PythonExecutable from ./.venv/Scripts/python.exe to ./toolkit/python.exe with
 updated comments
• Changed InstallDependencies from false to true with updated comment rationale
• Changed AdbExecutable from adb (system PATH) to
 ./toolkit/Lib/site-packages/adbutils/binaries/adb.exe with updated comments

alas_wrapped/deploy/Windows/template.yaml


34. alas_wrapped/module/config/argument/task.yaml ⚙️ Configuration changes +12/-12

Reorder coalition tasks in task configuration

• Moved Coalition task configuration from Event section (before Event) to after Hospital
• Moved CoalitionSp task configuration from EventDaily section (before EventA) to after RaidDaily

alas_wrapped/module/config/argument/task.yaml


35. alas_wrapped/config/template.json ⚙️ Configuration changes +2/-2

Update coalition mode defaults in config template

• Changed Coalition Mode default value from hard to area1-normal in Event section
• Changed Coalition Mode default value from sp to area1-normal in EventDaily section

alas_wrapped/config/template.json


36. CHANGELOG.md 📝 Documentation +2/-1

Document upstream sync in changelog

• Updated unreleased version date from 2026-02-08 to 2026-02-13
• Added new entry documenting upstream sync of Zuosizhu/Alas-with-Dashboard (cda8619c) with details
 on merged content and preserved customizations

CHANGELOG.md


37. alas_wrapped/module/config/argument/menu.json ⚙️ Configuration changes +3/-3

Reorder coalition tasks in menu configuration

• Moved Coalition task from position before Event to after Hospital in Event menu
• Moved CoalitionSp task from first position to after RaidDaily in EventDaily menu

alas_wrapped/module/config/argument/menu.json


38. alas_wrapped/module/config/argument/argument.yaml ⚙️ Configuration changes +2/-3

Update coalition mode options and remove restart config

• Removed RestartOnUnknownPage: true configuration line from Error section
• Changed Coalition Mode default value from hard to area1-normal
• Updated Coalition Mode options from [ easy, normal, hard, sp ] to `[ area1-normal, area1-hard,
 area2-normal, area2-hard, area3-normal, area3-hard, area4-normal, area4-hard, area5-normal,
 area5-hard, area6-normal, area6-hard ]`

alas_wrapped/module/config/argument/argument.yaml


39. alas_wrapped/campaign/Readme.md Additional files +0/-2

...

alas_wrapped/campaign/Readme.md


40. alas_wrapped/module/coalition/assets.py Additional files +0/-11

...

alas_wrapped/module/coalition/assets.py


41. alas_wrapped/module/combat/assets.py Additional files +0/-1

...

alas_wrapped/module/combat/assets.py


42. alas_wrapped/module/combat/combat.py Additional files +0/-9

...

alas_wrapped/module/combat/combat.py


43. alas_wrapped/module/config/config_updater.py Additional files +0/-2

...

alas_wrapped/module/config/config_updater.py


44. alas_wrapped/module/exercise/exercise.py Additional files +0/-10

...

alas_wrapped/module/exercise/exercise.py


45. alas_wrapped/module/exercise/opponent.py Additional files +0/-19

...

alas_wrapped/module/exercise/opponent.py


46. alas_wrapped/module/raid/run.py Additional files +0/-1

...

alas_wrapped/module/raid/run.py


Grey Divider

Qodo Logo

Co-authored-by: Cursor <cursoragent@cursor.com>
@Coldaine Coldaine changed the title chore: merge upstream_alas into alas_wrapped (Zuosizhu cda8619c) chore: upstream sync + Admin Service daemon (MEmu self-heal without admin) Feb 13, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Syncs alas_wrapped with the latest upstream ALAS snapshot to pick up new game content and upstream fixes, while updating several automation flows (notably OpSi and coalition/event handling) to match upstream behavior.

Changes:

  • Updated OpSi (Operation Siren) handlers and workflows (strategic search, storage, missions, port, map operations) with new loop/screenshot patterns and additional map-event handling.
  • Refreshed coalition/event configuration and UI logic (mode options, task/menu ordering, i18n strings, and removed older coalition event assets/entries).
  • Updated combat/exercise quit reconfirm handling and various generated/config template files to align with upstream.

Reviewed changes

Copilot reviewed 54 out of 55 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
alas_wrapped/module/ui/ui.py Updates “additional UI” handlers (notably coalition-related exits).
alas_wrapped/module/ui/page.py Adjusts coalition page wiring/comments and event page destinations.
alas_wrapped/module/tactical/assets.py Updates button metadata for tactical rewards.
alas_wrapped/module/raid/run.py Removes raid-specific event disabling call in run loop.
alas_wrapped/module/os_handler/strategic.py Refactors strategic search flow; adds skip_first_screenshot plumbing and timer-based waits.
alas_wrapped/module/os_handler/storage.py Refactors storage actions; adds skip_first_screenshot parameters and loop rewrites.
alas_wrapped/module/os_handler/port.py Narrows asset imports and refactors port mission/dock loops with skip_first_screenshot.
alas_wrapped/module/os_handler/os_status.py Adds skip_first_screenshot to yellow coin OCR retrieval.
alas_wrapped/module/os_handler/mission.py Refactors OS mission enter/quit/accept loops and screenshot cadence.
alas_wrapped/module/os_handler/map_order.py Refactors map order navigation loops and timers.
alas_wrapped/module/os_handler/map_event.py Adds siren platform handling and refactors map-event ensure/quit loops.
alas_wrapped/module/os_handler/enemy_searching.py Refactors OS map button wait logic with explicit timeout timer.
alas_wrapped/module/os_handler/action_point.py Refactors AP flows with skip_first_screenshot; adjusts selection/buy remain logic.
alas_wrapped/module/os/operation_siren.py Replaces mixin-based OperationSiren with a single, expanded OSMap-derived implementation.
alas_wrapped/module/os/map_operation.py Adds skip_first_screenshot to zone init and map exit flow.
alas_wrapped/module/os/map_fleet_selector.py Adds skip_first_screenshot support to fleet selector open/close/click/ensure.
alas_wrapped/module/os/map.py Refactors auto-search daemon/interrupt flows; changes quit reconfirm handling; adjusts rescan gating.
alas_wrapped/module/os/globe_operation.py Refactors globe navigation helpers to use ui_click and skip_first_screenshot.
alas_wrapped/module/os/fleet.py Refactors walking/boss-leave loops and quit reconfirm handling.
alas_wrapped/module/exercise/opponent.py Removes explanatory docstring/comments around opponent ordering/priority.
alas_wrapped/module/exercise/exercise.py Simplifies opponent sort logic/comments for leftmost mode.
alas_wrapped/module/exercise/combat.py Switches quit reconfirm handling to explicit button click + interval reset.
alas_wrapped/module/exercise/assets.py Adds QUIT_RECONFIRM button asset for exercise (now used beyond exercise too).
alas_wrapped/module/config/i18n/zh-TW.json Updates coalition naming/mode options; removes RestartOnUnknownPage strings.
alas_wrapped/module/config/i18n/zh-CN.json Updates coalition naming/mode options; removes RestartOnUnknownPage strings.
alas_wrapped/module/config/i18n/ja-JP.json Updates coalition naming/mode options; removes RestartOnUnknownPage strings.
alas_wrapped/module/config/i18n/en-US.json Updates coalition naming/mode options; clears some exercise help text; removes RestartOnUnknownPage strings.
alas_wrapped/module/config/config_updater.py Removes auto-enabling MeowfficerFarming when Hazard1Leveling is enabled.
alas_wrapped/module/config/config_generated.py Updates generated defaults (coalition mode); removes RestartOnUnknownPage default.
alas_wrapped/module/config/argument/task.yaml Reorders Coalition/CoalitionSp task groups under Event/EventDaily.
alas_wrapped/module/config/argument/menu.json Reorders menu task lists (Coalition and CoalitionSp positioning).
alas_wrapped/module/config/argument/argument.yaml Updates coalition mode options; removes RestartOnUnknownPage argument.
alas_wrapped/module/config/argument/args.json Updates coalition mode options/event lists; removes RestartOnUnknownPage UI arg.
alas_wrapped/module/combat/combat.py Removes handle_combat_quit_reconfirm() helper.
alas_wrapped/module/combat/assets.py Removes QUIT_RECONFIRM button from combat assets.
alas_wrapped/module/coalition/ui.py Removes “FASHION” coalition support; updates DAL stage mapping and fleet handling flow.
alas_wrapped/module/coalition/coalition.py Removes “FASHION” PT OCR/oil-icon special casing; adjusts stop-condition usage and run loop.
alas_wrapped/module/coalition/assets.py Removes “FASHION” coalition button assets.
alas_wrapped/module/campaign/os_run.py Refactors OS campaign loader into cached self.campaign with campaign_loaded guard.
alas_wrapped/module/campaign/campaign_event.py Inlines GemsFarming reset logic; removes disable_event_on_raid() helper.
alas_wrapped/module/base/template.py Changes template matching internals (channel coercion helper exists but is no longer used in several methods).
alas_wrapped/deploy/Windows/template.yaml Reverts deploy template defaults to upstream (AutoUpdate/deps/toolkit paths).
alas_wrapped/config/template.json Updates default coalition mode in config template.
alas_wrapped/config/deploy.template.yaml Reverts deploy template defaults to upstream (git/python/adb paths and update flags).
alas_wrapped/campaign/Readme.md Removes older event rows (including 2026-01-22 entries).
alas_wrapped/assets/jp/tactical/REWARD_2.BUTTON.png Adds/updates JP tactical reward button image artifact.
CHANGELOG.md Adds upstream sync entry and updates Unreleased date.
Comments suppressed due to low confidence (2)

alas_wrapped/module/base/template.py:284

  • match_result() now calls cv2.matchTemplate(image, self.image, ...) directly. There are call sites that pass grayscale images (e.g., rgb2gray(self.device.image) in storage code), which will crash OpenCV when the template is RGB. Use _safe_match_template() here (or otherwise coerce channels) to keep behavior consistent with match() and avoid runtime errors.
        res = cv2.matchTemplate(image, self.image, cv2.TM_CCOEFF_NORMED)
        _, sim, _, point = cv2.minMaxLoc(res)
        # print(self.file, sim)

        button = self._point_to_button(point, image=image, name=name)
        return sim, button

alas_wrapped/module/os_handler/map_order.py:84

  • confirm_timer is constructed but never started/reset before confirm_timer.reached() is checked. In Timer, reached() returns True when the timer hasn't been started yet, so order_execute() can immediately return True as soon as self.is_in_map() is true (even if the order wasn't executed). Initialize it with .start() (or call .reset() before the loop) and reset it appropriately when leaving the map.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if len(image.shape) == 3:
image = rgb2luma(image)
res = cv2.matchTemplate(image, self.image_luma, cv2.TM_CCOEFF_NORMED)
res = cv2.matchTemplate(image, self.image, cv2.TM_CCOEFF_NORMED)
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

match_luma()'s non-GIF branch is doing cv2.matchTemplate(image, self.image, ...) without converting image to luma and without using the precomputed self.image_luma. This makes luma matching incorrect (and may also hit channel-type mismatches depending on caller). Use rgb2luma(image) and match against self.image_luma (consistent with match_luma_result() and Button.match_luma()).

Suggested change
res = cv2.matchTemplate(image, self.image, cv2.TM_CCOEFF_NORMED)
image = rgb2luma(image)
res = cv2.matchTemplate(image, self.image_luma, cv2.TM_CCOEFF_NORMED)

Copilot uses AI. Check for mistakes.
Comment on lines 311 to 322
raw = image
if self.is_gif:
result = []
for template in self.image:
# 2026-01-25 Fix: Use _safe_match_template to handle channel mismatch
res = self._safe_match_template(image, template)
res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
res = np.array(np.where(res > similarity)).T[:, ::-1].tolist()
result += res
result = np.array(result)
else:
# 2026-01-25 Fix: Use _safe_match_template to handle channel mismatch
res = self._safe_match_template(image, self.image)
result = np.array(np.where(res > similarity)).T[:, ::-1]
result = cv2.matchTemplate(image, self.image, cv2.TM_CCOEFF_NORMED)
result = np.array(np.where(result > similarity)).T[:, ::-1]

Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

match_multi() now uses cv2.matchTemplate(image, template, ...) directly for both GIF and non-GIF templates. This will raise an OpenCV error when image is grayscale but the template is RGB (there are in-repo usages like Template.match_multi(rgb2gray(...))). Consider switching these calls back to _safe_match_template() (or explicitly convert image/template channels) to prevent crashes.

Copilot uses AI. Check for mistakes.
@@ -99,7 +99,6 @@ class GeneratedConfig:
Error_SaveError = True
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Error_RestartOnUnknownPage was removed from GeneratedConfig, but it is still referenced at runtime (e.g., alas_wrapped/alas.py checks self.config.Error_RestartOnUnknownPage). This will raise AttributeError when that error path executes, and it also contradicts the current CHANGELOG entry claiming the flag exists. Either restore the generated config field (and its argument/i18n wiring) or remove/guard the runtime usage and update documentation accordingly.

Suggested change
Error_SaveError = True
Error_SaveError = True
Error_RestartOnUnknownPage = True

Copilot uses AI. Check for mistakes.
@qodo-free-for-open-source-projects

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. match_luma() skips shape check 📘 Rule violation ⛯ Reliability
Description
match_luma() now calls rgb2luma(image) without checking image shape, and then matches against
self.image instead of self.image_luma, which can break on already-luma/grayscale inputs and
cause incorrect matching. This violates the requirement to explicitly handle edge cases at potential
failure points.
Code

alas_wrapped/module/base/template.py[246]

+            res = cv2.matchTemplate(image, self.image, cv2.TM_CCOEFF_NORMED)
Evidence
PR Compliance ID 3 requires explicit handling of edge cases and failure points. The modified
match_luma() implementation unconditionally converts image via rgb2luma(image) (no shape
guard) and then uses cv2.matchTemplate(image, self.image, ...) in the non-gif path, increasing the
chance of runtime errors or incorrect behavior for boundary inputs (e.g., grayscale arrays).

Rule 3: Generic: Robust Error Handling and Edge Case Management
alas_wrapped/module/base/template.py[233-246]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`match_luma()` no longer guards for grayscale vs RGB inputs and matches against `self.image` rather than the intended luma template, which can cause runtime errors or incorrect template matching.

## Issue Context
Compliance requires edge cases (e.g., null/empty/boundary values and format differences) be explicitly handled at failure points.

## Fix Focus Areas
- alas_wrapped/module/base/template.py[233-249]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Windows deploy template diverges settings 📘 Rule violation ⛯ Reliability
Description
alas_wrapped/deploy/Windows/template.yaml now enables AutoUpdate/InstallDependencies and
switches PythonExecutable/AdbExecutable/GitExecutable away from the documented required
values. This can cause inconsistent or broken Windows deployments compared to the documented
UV-managed runtime configuration.
Code

alas_wrapped/deploy/Windows/template.yaml[R21-48]

    # [Other] Use false to when connected to an untrusted network
    SSLVerify: true
    # Update Alas at startup
-    # [UV-managed] Use false — we manage updates via git, not ALAS
-    # [Original] Use true
-    AutoUpdate: false
+    # [In most cases] Use true
+    AutoUpdate: true

  Python:
    # Filepath of python executable `python.exe`
-    # [UV-managed] Use './.venv/Scripts/python.exe'
    # [Easy installer] Use './toolkit/python.exe'
-    # [Other] Use your own python
-    PythonExecutable: './.venv/Scripts/python.exe'
+    # [Other] Use you own python, and its version should be 3.7.6 64bit
+    PythonExecutable: './toolkit/python.exe'
    # URL of pypi mirror
    # [CN user] Use 'https://pypi.tuna.tsinghua.edu.cn/simple' for faster and more stable download
    # [Other] Use null
    PypiMirror: null
    # Install dependencies at startup
-    # [UV-managed] Use false — UV manages deps outside of ALAS
-    # [Original] Use true
-    InstallDependencies: false
+    # [In most cases] Use true
+    InstallDependencies: true
    # Path to requirements.txt
    # [In most cases] Use 'requirements.txt'
    # [In AidLux] Use './deploy/AidLux/{version}/requirements.txt', version is default to 0.92
    RequirementsFile: 'requirements.txt'

  Adb:
    # Filepath of ADB executable `adb.exe`
-    # [UV-managed] Use 'adb' (system PATH) or './.venv/Lib/site-packages/adbutils/binaries/adb.exe'
    # [Easy installer] Use './toolkit/Lib/site-packages/adbutils/binaries/adb.exe'
-    AdbExecutable: 'adb'
+    # [Other] Use you own latest ADB, but not the ADB in your emulator
+    AdbExecutable: './toolkit/Lib/site-packages/adbutils/binaries/adb.exe'
Evidence
PR Compliance ID 12 requires the documented executable paths and settings for the deployment YAML.
The Windows template sets GitExecutable to a toolkit path, sets AutoUpdate to true, sets
PythonExecutable to ./toolkit/python.exe, sets InstallDependencies to true, and sets
AdbExecutable to a toolkit path—diverging from the required values.

CLAUDE.md
alas_wrapped/deploy/Windows/template.yaml[11-15]
alas_wrapped/deploy/Windows/template.yaml[23-26]
alas_wrapped/deploy/Windows/template.yaml[27-38]
alas_wrapped/deploy/Windows/template.yaml[44-48]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Windows deployment template diverges from the documented required deployment YAML settings.

## Issue Context
The repository standard requires:
- `Python.PythonExecutable: ./.venv/Scripts/python.exe`
- `Python.InstallDependencies: false`
- `Git.GitExecutable: git`
- `Git.AutoUpdate: false`
- `Adb.AdbExecutable: adb`

## Fix Focus Areas
- alas_wrapped/deploy/Windows/template.yaml[11-48]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. match_multi channel crash 🐞 Bug ✓ Correctness
Description
Template.match_multi() now calls cv2.matchTemplate() directly, which will raise an OpenCV error
when passed a grayscale (2D) image against RGB templates. OS storage flows explicitly convert
screenshots to grayscale before calling match_multi(), making this a likely runtime crash.
Code

alas_wrapped/module/base/template.py[R315-321]

+                res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
                res = np.array(np.where(res > similarity)).T[:, ::-1].tolist()
                result += res
            result = np.array(result)
        else:
-            # 2026-01-25 Fix: Use _safe_match_template to handle channel mismatch
-            res = self._safe_match_template(image, self.image)
-            result = np.array(np.where(res > similarity)).T[:, ::-1]
+            result = cv2.matchTemplate(image, self.image, cv2.TM_CCOEFF_NORMED)
+            result = np.array(np.where(result > similarity)).T[:, ::-1]
Evidence
match_multi() no longer uses _safe_match_template() (channel coercion), but OS storage code
passes rgb2gray(self.device.image) into match_multi(). Since templates are loaded as RGB by
load_image(), the Gray/RGB mismatch can crash OpenCV template matching.

alas_wrapped/module/base/template.py[295-327]
alas_wrapped/module/base/template.py[118-140]
alas_wrapped/module/os_handler/storage.py[124-167]
alas_wrapped/module/base/utils.py[522-544]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`Template.match_multi()` uses `cv2.matchTemplate()` directly. When callers pass grayscale (2D) images and templates are RGB (3D), OpenCV template matching can throw an exception.

### Issue Context
OS storage flows convert screenshots to grayscale (`rgb2gray(...)`) and then call `TEMPLATE_*.match_multi(image, ...)`. The Template class already contains `_safe_match_template()` to coerce channels, but `match_multi()` bypasses it.

### Fix Focus Areas
- alas_wrapped/module/base/template.py[118-164]
- alas_wrapped/module/base/template.py[295-327]
- alas_wrapped/module/os_handler/storage.py[124-167]
- alas_wrapped/module/base/utils.py[522-544]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

if len(image.shape) == 3:
image = rgb2luma(image)
res = cv2.matchTemplate(image, self.image_luma, cv2.TM_CCOEFF_NORMED)
res = cv2.matchTemplate(image, self.image, cv2.TM_CCOEFF_NORMED)

Choose a reason for hiding this comment

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

Action required

1. match_luma() skips shape check 📘 Rule violation ⛯ Reliability

match_luma() now calls rgb2luma(image) without checking image shape, and then matches against
self.image instead of self.image_luma, which can break on already-luma/grayscale inputs and
cause incorrect matching. This violates the requirement to explicitly handle edge cases at potential
failure points.
Agent Prompt
## Issue description
`match_luma()` no longer guards for grayscale vs RGB inputs and matches against `self.image` rather than the intended luma template, which can cause runtime errors or incorrect template matching.

## Issue Context
Compliance requires edge cases (e.g., null/empty/boundary values and format differences) be explicitly handled at failure points.

## Fix Focus Areas
- alas_wrapped/module/base/template.py[233-249]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 21 to +48
# [Other] Use false to when connected to an untrusted network
SSLVerify: true
# Update Alas at startup
# [UV-managed] Use false — we manage updates via git, not ALAS
# [Original] Use true
AutoUpdate: false
# [In most cases] Use true
AutoUpdate: true

Python:
# Filepath of python executable `python.exe`
# [UV-managed] Use './.venv/Scripts/python.exe'
# [Easy installer] Use './toolkit/python.exe'
# [Other] Use your own python
PythonExecutable: './.venv/Scripts/python.exe'
# [Other] Use you own python, and its version should be 3.7.6 64bit
PythonExecutable: './toolkit/python.exe'
# URL of pypi mirror
# [CN user] Use 'https://pypi.tuna.tsinghua.edu.cn/simple' for faster and more stable download
# [Other] Use null
PypiMirror: null
# Install dependencies at startup
# [UV-managed] Use false — UV manages deps outside of ALAS
# [Original] Use true
InstallDependencies: false
# [In most cases] Use true
InstallDependencies: true
# Path to requirements.txt
# [In most cases] Use 'requirements.txt'
# [In AidLux] Use './deploy/AidLux/{version}/requirements.txt', version is default to 0.92
RequirementsFile: 'requirements.txt'

Adb:
# Filepath of ADB executable `adb.exe`
# [UV-managed] Use 'adb' (system PATH) or './.venv/Lib/site-packages/adbutils/binaries/adb.exe'
# [Easy installer] Use './toolkit/Lib/site-packages/adbutils/binaries/adb.exe'
AdbExecutable: 'adb'
# [Other] Use you own latest ADB, but not the ADB in your emulator
AdbExecutable: './toolkit/Lib/site-packages/adbutils/binaries/adb.exe'

Choose a reason for hiding this comment

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

Action required

2. Windows deploy template diverges settings 📘 Rule violation ⛯ Reliability

alas_wrapped/deploy/Windows/template.yaml now enables AutoUpdate/InstallDependencies and
switches PythonExecutable/AdbExecutable/GitExecutable away from the documented required
values. This can cause inconsistent or broken Windows deployments compared to the documented
UV-managed runtime configuration.
Agent Prompt
## Issue description
The Windows deployment template diverges from the documented required deployment YAML settings.

## Issue Context
The repository standard requires:
- `Python.PythonExecutable: ./.venv/Scripts/python.exe`
- `Python.InstallDependencies: false`
- `Git.GitExecutable: git`
- `Git.AutoUpdate: false`
- `Adb.AdbExecutable: adb`

## Fix Focus Areas
- alas_wrapped/deploy/Windows/template.yaml[11-48]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +315 to +321
res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
res = np.array(np.where(res > similarity)).T[:, ::-1].tolist()
result += res
result = np.array(result)
else:
# 2026-01-25 Fix: Use _safe_match_template to handle channel mismatch
res = self._safe_match_template(image, self.image)
result = np.array(np.where(res > similarity)).T[:, ::-1]
result = cv2.matchTemplate(image, self.image, cv2.TM_CCOEFF_NORMED)
result = np.array(np.where(result > similarity)).T[:, ::-1]

Choose a reason for hiding this comment

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

Action required

3. Match_multi channel crash 🐞 Bug ✓ Correctness

Template.match_multi() now calls cv2.matchTemplate() directly, which will raise an OpenCV error
when passed a grayscale (2D) image against RGB templates. OS storage flows explicitly convert
screenshots to grayscale before calling match_multi(), making this a likely runtime crash.
Agent Prompt
### Issue description
`Template.match_multi()` uses `cv2.matchTemplate()` directly. When callers pass grayscale (2D) images and templates are RGB (3D), OpenCV template matching can throw an exception.

### Issue Context
OS storage flows convert screenshots to grayscale (`rgb2gray(...)`) and then call `TEMPLATE_*.match_multi(image, ...)`. The Template class already contains `_safe_match_template()` to coerce channels, but `match_multi()` bypasses it.

### Fix Focus Areas
- alas_wrapped/module/base/template.py[118-164]
- alas_wrapped/module/base/template.py[295-327]
- alas_wrapped/module/os_handler/storage.py[124-167]
- alas_wrapped/module/base/utils.py[522-544]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d9dc915270

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if len(image.shape) == 3:
image = rgb2luma(image)
res = cv2.matchTemplate(image, self.image_luma, cv2.TM_CCOEFF_NORMED)
res = cv2.matchTemplate(image, self.image, cv2.TM_CCOEFF_NORMED)

Choose a reason for hiding this comment

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

P2 Badge Match non-GIF luma templates against luma data

The non-GIF branch of Template.match_luma now calls cv2.matchTemplate(image, self.image, ...), which bypasses luma conversion and stops using self.image_luma. This regresses match_luma into normal image matching and can fail at runtime when callers provide grayscale input (channel mismatch), while also making detections more sensitive to color variation than intended for luma matching.

Useful? React with 👍 / 👎.

Coldaine and others added 6 commits February 13, 2026 18:07
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- validate screenshot benchmark outputs and fail invalid/black frames\n- only recommend screenshot methods from valid results\n- add dated benchmark findings doc (2026-02-13)\n- add root helper script to tail latest PatrickCustom log
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