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>
This commit is contained in:
@@ -246,3 +246,135 @@ Status legend: [x] fixed+tested, [~] partially addressed, [ ] open/needs input
|
||||
popover's heading (", id #8") and the pending-proposal's own
|
||||
on-map label (`? #8 G8 5:4`) both show it while there's still a
|
||||
screenshot up to check it against by eye.
|
||||
|
||||
## Windows build (packaging/windows) -- real progress, not yet a clean pass
|
||||
|
||||
Booted the actual dockur/windows build VM and drove it live (VNC) to find
|
||||
out what's really failing, rather than guessing from the README's own
|
||||
"UNTESTED end to end" note. Three real, separate bugs found and fixed,
|
||||
each confirmed live against the real VM, not just read off a diff:
|
||||
|
||||
- [x] The build watcher was never actually installed at all, despite
|
||||
`install_progress.log` claiming every provisioning step succeeded.
|
||||
`C:\OEM` (dockur's `/oem` staging dir) doesn't reliably persist past
|
||||
Windows Setup finishing -- exactly what the (already-uncommitted,
|
||||
now committed) `install.bat`/`watch_build.bat` fix diagnosed, just
|
||||
never verified against a real run before now. A 2-day-old
|
||||
`BUILD_REQUEST` had been sitting unclaimed the whole time. Manually
|
||||
re-applied the fix's logic live once (copied the corrected files to
|
||||
`C:\FenigmaBuild`, registered the Startup-folder entry) and
|
||||
confirmed on a full container restart that the watcher now
|
||||
auto-starts on login and picks up a pending request with zero
|
||||
manual intervention -- the actual fix, not just my live patch, is
|
||||
what's doing that.
|
||||
- [x] `pip install pytesseract` fails outright: MSYS2's mingw64 Python
|
||||
enforces PEP 668 ("externally-managed-environment"), which
|
||||
`install.bat` never accounted for. Needs `--break-system-packages`.
|
||||
- [x] `import fenigma.app` fails with `ModuleNotFoundError: No module
|
||||
named 'cv2'` even after `pacman -S mingw-w64-x86_64-opencv`
|
||||
succeeds -- that package is the C++ library only. The actual
|
||||
Python bindings are a SEPARATE package, `mingw-w64-x86_64-
|
||||
python-opencv`, that `install.bat`'s dependency list simply never
|
||||
included. (`pip install opencv-python-headless` as a fallback
|
||||
doesn't work either and shouldn't be relied on: MSYS2's mingw64
|
||||
Python uses a different ABI than PyPI's Windows wheels
|
||||
-- `cp314-mingw_x86_64_msvcrt_gnu` vs `win_amd64` -- so pip can
|
||||
never use a prebuilt wheel there, only build from source, which
|
||||
then needs a full separate native toolchain -ninja/cmake/gcc- this
|
||||
VM doesn't have either.)
|
||||
|
||||
All three are one-line fixes once known. `install.bat`'s pacman package
|
||||
list and pip install line need these applied for a from-scratch VM to
|
||||
provision correctly (currently they're only proven fixed live on this
|
||||
session's VM, not yet folded back into the committed `install.bat` --
|
||||
do that before relying on a fresh `./build_windows.sh` run from
|
||||
scratch).
|
||||
|
||||
With all three fixed, `import fenigma.app` succeeds and a real build
|
||||
attempt got all the way through source copy, sanity check, dist-tree
|
||||
assembly, and WiX harvest+compile (`candle.exe`) -- further than this
|
||||
pipeline has ever gotten. Two more issues surfaced right at the finish
|
||||
line:
|
||||
- [x] `product.wxs`'s `Version` needs strict WiX `x.x.x.x` numeric
|
||||
form -- a `0.1.0-test` version string (my own test invocation,
|
||||
not `build_windows.sh`'s real default) fails `candle.exe` with
|
||||
CNDL0108/CNDL0010. Not a real bug, just don't pass a version with
|
||||
a suffix.
|
||||
- [ ] `light.exe` (final MSI linking) did not finish within 15 minutes
|
||||
on this VM (4 CPU / 8GB RAM) before the RAM-conscious auto-
|
||||
shutdown killed it -- process was genuinely active (343MB
|
||||
working set, not hung on a dialog), just slow, likely from the
|
||||
~1GB+ bulk-copied mingw64 runtime (see README's own "dist tree is
|
||||
fat, not lean" note) combined with this VM's disk/CPU being
|
||||
shared with the host. Needs either a longer timeout on a retry,
|
||||
or the dist-tree-trimming work the README already flags as a
|
||||
known follow-up (tracing the real DLL/typelib closure instead of
|
||||
bulk-copying all of mingw64) to make `light.exe` have less to
|
||||
compress in the first place.
|
||||
|
||||
## OCR: new fire-support-request grammar gaps (from real user-pasted messages)
|
||||
|
||||
- [x] A "taking fire" report's reporting unit ("Infantry#11 taking
|
||||
fire!...") was being added as a hostile Target, not a friendly
|
||||
Ally -- see the id-scheme entry above for the "no Friendly/Hostile
|
||||
prefix word exists in this grammar" root cause and the fix
|
||||
(`_TAKING_FIRE_RE`, `force_ally`, and splitting the shell/deadline
|
||||
into a synthetic StrikeRequest even for the no-offset "on our
|
||||
position" case, which previously kept them on the entity itself --
|
||||
fine when it was wrongly a Target, silently lost once correctly an
|
||||
Ally, since Ally tuples carry no shell/deadline fields at all). 4
|
||||
existing tests updated, all still passing plus the rest of the
|
||||
suite (51 total).
|
||||
|
||||
- [ ] A multi-shell sequential request ("Requesting TEAR Shell first,
|
||||
then HE Shell, at bearing...") only captures the FIRST shell
|
||||
(TEAR) -- "then HE Shell" is silently dropped, no way currently to
|
||||
record "use this shell, then that one." Real scope question before
|
||||
fixing: does the board/firing-panel data model even have a place
|
||||
to put a second shell for one strike request, or does this need a
|
||||
new field/shape entirely?
|
||||
- [ ] "Answer by 10:30:00" isn't recognized as a deadline at all --
|
||||
`_TAKING_FIRE_TIME_RE`/`_REQUESTED_BEFORE_RE` only know "before/by
|
||||
\<time\>" and "Requested before - \<time\> -" phrasing. A third
|
||||
deadline grammar to add.
|
||||
- [ ] A same-message "Important: ... Answer by \<time\>" follow-up line
|
||||
gets misread as a brand new named entity header (the last-resort
|
||||
bare-`<name>:` fallback rule matches "Important:"), creating a
|
||||
bogus `Target#Important` carrying that deadline as its own
|
||||
`requested_time`. Real false-positive in the header-detection
|
||||
fallback, needs either an exclusion list (blocklist "Important"
|
||||
and similar prose lead-ins) or a stricter bare-header shape.
|
||||
Confirmed live against the user's real pasted message (with an
|
||||
assumed `Infantry#N taking fire!` header line prepended, since
|
||||
their paste seems to have been cropped before it -- worth
|
||||
double-checking against the actual full in-game message).
|
||||
|
||||
- [x] "\<Type\>#\<id\> Destroyed" kill-feed parsing already exists and
|
||||
already marks the matching Target dead (`parse_destroyed`,
|
||||
`_merge_targets`'s own destroyed-handling block in app.py) --
|
||||
confirmed working end-to-end against a real 9-entry kill-feed
|
||||
paste, including multi-word types ("Enemy Mechanized Infantry#2
|
||||
Destroyed" correctly resolved to INFANTRY_MECHANIZED). This was
|
||||
already-existing, working functionality, not something needing to
|
||||
be built.
|
||||
One real gap found in the same test: "Enemy Field Gun#1 Destroyed"
|
||||
silently dropped. Two bugs stacked, both fixed:
|
||||
- [x] "Field Gun" is just the game's own alt name for plain
|
||||
Artillery (confirmed by the user directly) -- not a missing
|
||||
unit type needing a new enum member/icon after all. Added to
|
||||
`_TYPE_WORD_ALIASES` next to AmmoCache/CoastalBattery.
|
||||
- [x] Even with that alias, it still didn't resolve: `_ALLY_PREFIX_RE`
|
||||
only ever stripped a leading "Friendly"/"Hostile" word, never
|
||||
"Enemy" -- so `squash_multiword_ids`'s "EnemyFieldGun#1"
|
||||
token got alias-looked-up and fuzzy-matched as a WHOLE
|
||||
("EnemyFieldGun" vs "Artillery", nowhere close), not just its
|
||||
"FieldGun" part. "Enemy Mechanized Infantry#2" only ever
|
||||
worked by fuzzy-match ACCIDENT (a long, distinctive type
|
||||
string still clears the ratio threshold with "Enemy" stuck
|
||||
to the front; a short, unrelated one like Artillery doesn't).
|
||||
`_ALLY_PREFIX_RE` now strips "Enemy" too, with a lookahead
|
||||
requiring something after it -- a BARE "Enemy#N" is
|
||||
`TargetType.ENEMY` itself (its own value IS "Enemy"),
|
||||
stripping unconditionally would've left an empty type_word
|
||||
and broken every ad-hoc "Enemy#N Destroyed" report instead.
|
||||
3 new regression tests, all passing (54 total).
|
||||
|
||||
Reference in New Issue
Block a user