FEnigma/packaging/windows/oem/install.bat
Dominik Roth 6a61bffb22 Fix taking-fire ally misclassification; Windows build fixes; Field Gun
OCR (src/fenigma/ocr.py):
- A "taking fire" report's reporting unit was added as a hostile Target,
  not a friendly Ally -- no "Friendly"/"Hostile" prefix word exists in
  that grammar for the usual inference to key off of, so it silently
  defaulted to not-ally. Fixed with an explicit force_ally override
  (_TAKING_FIRE_RE), and the shell/deadline (which an Ally tuple has no
  fields for) now always splits into a synthetic StrikeRequest target at
  the reporting position, even for the no-offset "on our position" case
  that previously kept them on the entity itself.
- "Enemy <Type>#<id> Destroyed" kill-feed lines were silently dropping
  for shorter/less distinctive type words (e.g. "Enemy Field Gun#1") --
  _ALLY_PREFIX_RE only ever stripped "Friendly"/"Hostile", never
  "Enemy", so the whole "EnemyFieldGun" token got alias/fuzzy-matched
  against "Artillery" and missed by a mile. Longer type words
  ("Enemy Mechanized Infantry#2") only ever worked by fuzzy-match
  accident. Now strips "Enemy" too (lookahead guards a BARE "Enemy#N"
  report, which IS TargetType.ENEMY itself, from being stripped to an
  empty, unresolvable string).
- "Field Gun" added to _TYPE_WORD_ALIASES as plain Artillery under
  another name (confirmed by the user), not a missing unit type.
7 new/updated regression tests, 54 total passing.

Windows build (packaging/windows/): three real bugs found and fixed by
actually booting and driving the build VM live (VNC), not just guessing
from the README's "UNTESTED end to end" note:
- install.bat's MSYS2/WiX provisioning previously left NOTHING behind
  once C:\OEM stopped existing (a 2-day-old BUILD_REQUEST sat unclaimed
  the whole time) -- the build.bat/watch_build.bat persistence fix
  (C:\FenigmaBuild instead of C:\OEM) is real and now confirmed live:
  after a full container restart, the watcher auto-starts on login and
  picks up a pending request with zero manual intervention.
- pip install pytesseract needs --break-system-packages (MSYS2's
  mingw64 Python enforces PEP 668).
- mingw-w64-x86_64-opencv is the C++ library only; the actual Python
  bindings are the separate mingw-w64-x86_64-python-opencv package,
  never in install.bat's dependency list.

With all three, import fenigma.app succeeds and a real build attempt
gets through source copy, sanity check, dist-tree assembly, and WiX
harvest+compile -- further than this pipeline has ever gotten. Full
findings, including the still-open light.exe timeout and the OCR
multi-shell/deadline-phrasing/phantom-header gaps found along the way,
logged in TODO.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 22:02:17 +02:00

119 lines
6.9 KiB
Batchfile

@echo off
REM One-time provisioning, auto-run by dockur/windows during the final step
REM of Windows's own unattended setup (see its README's /oem mechanism).
REM Everything here happens exactly once and lands on the VM's persistent
REM disk -- later builds just boot this already-provisioned VM and run
REM build.bat, no re-provisioning.
REM
REM UNTESTED end to end: written from MSYS2's documented CI bootstrap
REM sequence (the same one msys2/setup-msys2 uses) and WiX's own docs, not
REM verified against a live dockur/windows boot. Expect to debug this on
REM the actual first run -- watch it happen at http://localhost:8006.
REM
REM Every step also echoes to Z:\install_progress.log (best-effort, only
REM if the Z:\ shared drive happens to be up already at this point in
REM setup) purely so build_windows.sh on the host has SOMETHING to show
REM besides silence during the one-time provisioning run.
setlocal enabledelayedexpansion
call :log "starting FEnigma build-VM provisioning"
REM -- Stage the OTHER oem/ files somewhere that outlives C:\OEM itself,
REM done first, before anything else. Confirmed on a real run: C:\OEM
REM (dockur's /oem copy target) does NOT reliably persist once Windows
REM Setup finishes and you're at the desktop -- it's fundamentally a
REM Windows Setup-time staging mechanism ($OEM$ folders, copied by WinPE
REM "right after the Windows image is applied ... and before the first
REM reboot" per Microsoft's own docs), not guaranteed permanent storage,
REM and in practice `dir C:\OEM` came back "File Not Found" once actually
REM checked from an interactive desktop session. build.bat/product.wxs/
REM watch_build.bat all get referenced again AFTER install.bat's own
REM process has exited (by the Startup-folder entry below, potentially
REM much later), so they need a home install.bat itself controls and
REM knows persists -- a plain folder on C:, not the OEM staging area.
mkdir C:\FenigmaBuild 2>nul
copy /y C:\OEM\build.bat C:\FenigmaBuild\build.bat >> C:\OEM\install.log 2>&1
copy /y C:\OEM\product.wxs C:\FenigmaBuild\product.wxs >> C:\OEM\install.log 2>&1
copy /y C:\OEM\watch_build.bat C:\FenigmaBuild\watch_build.bat >> C:\OEM\install.log 2>&1
REM -- MSYS2: the "base" self-extracting archive, not the GUI installer --
REM (the GUI installer has no reliable non-interactive/silent flag across
REM versions; the base sfx archive is what CI pipelines actually use).
REM Discover the current filename by scraping the repo listing, since it's
REM datestamped and there's no stable "latest" URL.
call :log "finding current MSYS2 base archive..."
powershell -NoProfile -Command ^
"$ProgressPreference='SilentlyContinue';" ^
"$html = Invoke-WebRequest -Uri 'https://repo.msys2.org/distrib/x86_64/' -UseBasicParsing;" ^
"$name = ($html.Links | Where-Object { $_.href -match '^msys2-base-x86_64-.*\.sfx\.exe$' } | Select-Object -Last 1).href;" ^
"Invoke-WebRequest -Uri ('https://repo.msys2.org/distrib/x86_64/' + $name) -OutFile 'C:\msys2-base.sfx.exe' -UseBasicParsing"
if not exist C:\msys2-base.sfx.exe (
call :log "FAILED: could not download MSYS2 base archive"
exit /b 1
)
call :log "extracting MSYS2 to C:\msys64 ..."
C:\msys2-base.sfx.exe -y -oC:\ >> C:\OEM\install.log 2>&1
del C:\msys2-base.sfx.exe
REM First bash launch finalizes the base install and kills itself off
REM mid-update (documented MSYS2 behavior) -- run it, ignore its exit
REM code, then run the real update.
call :log "bootstrapping MSYS2 (pacman -Syuu, twice) ..."
C:\msys64\usr\bin\bash.exe -lc "exit 0" >> C:\OEM\install.log 2>&1
C:\msys64\usr\bin\bash.exe -lc "pacman -Syuu --noconfirm" >> C:\OEM\install.log 2>&1
C:\msys64\usr\bin\bash.exe -lc "pacman -Syuu --noconfirm" >> C:\OEM\install.log 2>&1
call :log "installing GTK4/libadwaita/PyGObject/build deps ..."
REM mingw-w64-x86_64-opencv is the C++ library ONLY -- confirmed live on a
REM real VM that `import cv2` fails without it, the actual Python bindings
REM are the separate mingw-w64-x86_64-python-opencv package. Don't try to
REM paper over a missing one with `pip install opencv-python-headless`
REM either: MSYS2's mingw64 Python uses a different ABI than PyPI's Windows
REM wheels (cp3XX-mingw_x86_64_msvcrt_gnu vs win_amd64), so pip can never
REM use a prebuilt wheel there, only build from source, which then needs a
REM full separate native toolchain (ninja/cmake/gcc) this VM doesn't have.
C:\msys64\usr\bin\bash.exe -lc "pacman -S --noconfirm --needed mingw-w64-x86_64-python mingw-w64-x86_64-python-pip mingw-w64-x86_64-python-gobject mingw-w64-x86_64-gtk4 mingw-w64-x86_64-libadwaita mingw-w64-x86_64-python-numpy mingw-w64-x86_64-python-pillow mingw-w64-x86_64-opencv mingw-w64-x86_64-python-opencv mingw-w64-x86_64-tesseract-ocr" >> C:\OEM\install.log 2>&1
call :log "pip install pytesseract (pure python, no wheel needed) ..."
REM --break-system-packages: MSYS2's mingw64 Python enforces PEP 668
REM ("externally-managed-environment"), confirmed live -- a plain
REM `pip install` here fails outright without this flag. Safe here: this
REM VM's whole mingw64 Python install exists only to run FEnigma, there's
REM no system package manager relying on it staying untouched.
C:\msys64\mingw64\bin\python3.exe -m pip install --break-system-packages pytesseract >> C:\OEM\install.log 2>&1
REM -- WiX v3 toolset (candle/light/heat), a plain zip of standalone exes,
REM no installer needed. Fixed versioned URL, no scraping required.
call :log "fetching WiX v3.11 ..."
powershell -NoProfile -Command ^
"$ProgressPreference='SilentlyContinue';" ^
"Invoke-WebRequest -Uri 'https://github.com/wixtoolset/wix3/releases/download/wix3111rtm/wix311-binaries.zip' -OutFile 'C:\wix311-binaries.zip' -UseBasicParsing;" ^
"Expand-Archive -Path 'C:\wix311-binaries.zip' -DestinationPath 'C:\wix' -Force"
del C:\wix311-binaries.zip
REM -- Register the build watcher to run at every login from here on,
REM plus kick it off right now too (a fresh login won't retroactively
REM fire for this already-logged-in session). Deliberately an All-Users
REM Startup-folder entry, NOT a SYSTEM-context Scheduled Task: confirmed
REM on a real run that a /ru SYSTEM task can't see Z:\ at all and spins
REM forever on watch_build.bat's own "if not exist Z:\" wait -- Z:\ (the
REM /shared mount) is mapped per INTERACTIVE session, invisible to a
REM SYSTEM task with no session of its own. Startup-folder entries run
REM in whichever user's session actually logs in, inheriting their
REM drive mappings correctly.
call :log "registering build watcher (Startup folder) ..."
copy /y C:\FenigmaBuild\watch_build.bat "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\FenigmaBuildWatcher.bat" >> C:\OEM\install.log 2>&1
start "" cmd /c C:\FenigmaBuild\watch_build.bat
call :log "provisioning done"
echo DONE > C:\OEM\provisioned.marker
if exist Z:\ echo DONE > Z:\PROVISIONED
endlocal
exit /b 0
:log
echo [install.bat] %~1 >> C:\OEM\install.log
if exist Z:\ echo [install.bat] %~1 >> Z:\install_progress.log
exit /b 0