Before step_fetch, scan all downloads/ subdirs and move any mod that
comparison.json now assigns to a different group. Matching uses steam_id
(via meta.cpp publishedid) first, normalized name as fallback.
Stale junctions in arma_dir are removed before the folder move so
step_link can re-create them pointing to the new location.
- New arma_modlist_tools/migrator.py: migrate_mod_groups()
- run.py: step_migrate(), --skip-migrate flag, wired into dispatch loop
- gui/app.py: step_migrate inserted as Step 3/5 between compare and fetch
- gui/locales.py: add step3/4/5 names (en + vi), renumber old 3->4, 4->5
- test_suite.py: 7 new migrator tests (158 total, 0 failed)
When launched via pythonw.exe (no console), sys.stdout/stderr are None.
Accessing .encoding on None raised AttributeError, caught by the GUI's
pipeline import guard and shown as 'Failed to load pipeline'. Added
None check before the encoding check in fix_console_encoding(), added
a test, and documented the pitfall in CLAUDE.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three issues caused the Logs view to appear blank during a real pipeline run:
1. `from run import step_fetch, step_link` was outside the worker's
try/except/finally. An import failure silently killed the thread,
leaving _pipeline_done uncalled and the Run button stuck disabled
forever. Now wrapped in its own try/except that posts the error to
the log and resets the UI.
2. `build_server_index` makes N sequential HTTP requests (one per mod
folder's meta.cpp) with no output during the scan. Added an optional
`progress_fn(current, total, name)` callback; step_fetch wires it to
print progress every 25 folders so the log never goes silent.
3. No immediate feedback after clicking Start — the log was blank until
the worker thread started printing. Now posts a "Pipeline started"
banner from the main thread before the worker launches.
parser.py and update_mods.py were missing
'from __future__ import annotations', causing a TypeError on
Python < 3.10 when the X | Y union syntax is evaluated at runtime.
All other modules already had the import.
Also lowers MIN_PYTHON from 3.11 to 3.9 -- the toolchain does not
use any Python 3.10/3.11-specific stdlib features beyond the union
annotation syntax which is now handled by the future import.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pipeline: parse HTML presets, compare modlists, download from Caddy
file server, create junctions/symlinks to Arma 3 Server directory.
Includes update/sync flows, missing-mod reporting, OS compat layer,
shared config, dep checker, comprehensive test suite (71 tests).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>