Reported with screenshots: a dozen records lifted out of wsjtx_log.adi into a new
.adi imported as "0 imported, 0 ignored, 0 total". The parser only emitted
records after <EOH>, and a hand-assembled file has no header — so the whole file
was read as header text and thrown away. The count says the file was empty; there
is nothing on screen to suggest a missing tag, which is why this was reported as
"import does nothing".
An <eor> is proof that a record ended, header or no header. Fields are now
collected always and DISCARDED at <eoh> — that tag is exactly the statement
"everything before this was the header", so real headers stay out of the data
just as reliably, and a headerless file keeps its first record instead of losing
it to the same rule.
An existing test asserted the old behaviour. It encoded a defensible reading of
the spec, but the file it rejects is one operators really make and the rejection
is silent, so the test is rewritten with the evidence that changed it rather than
deleted.
writeRecord gained a fourth `allow map[string]bool` argument in the export
field-picker change; the round-trip test still called it with three. Pass nil
(no field filtering — the historical behaviour).
Global "Export to ADIF" gains a third option "Choose fields…" next to the
standard-only and full-OpsLog choices, and right-clicking selected QSOs adds
"Export selected — choose fields…". The picker separates official ADIF 3.1.7
fields (grouped by category) from OpsLog/non-standard tags actually present in
the log (discovered via DistinctExtraKeys over extras_json), with All/None per
group and reset-to-defaults; the selection is persisted per user.
Backend: adif.Exporter gains a Fields allow-set that gates every promoted and
extras field in writeRecord; app.go ExportADIF/ExportADIFFiltered/
ExportADIFSelected take a fields []string param, plus new ADIFExtraFields.
Backend (Go 1.25 / Wails v2):
- QSO storage on SQLite (modernc) with embedded migrations (0001..0005)
- Streaming ADIF import (batch insert) + WorkedBefore per callsign and DXCC
- Callsign lookup with QRZ.com + HamQTH providers (primary/failsafe routing)
and SQLite-backed TTL cache
- DXCC resolver from cty.dat (auto-download, longest-prefix-match)
- Multi-profile operator identities (home/portable/SOTA/contest) — every
QSO stamps MY_* from the active profile
- CAT control via OmniRig COM on a single OS-locked goroutine, with
bidirectional sync (freq/mode/band/split/VFOs) and Rig1/Rig2 hot-swap
- Settings store (key/value), CAT debug log at %APPDATA%/HamLog/cat.log
Frontend (React 18 + TypeScript + Tailwind v4 + shadcn-style):
- Single-row entry strip with CAT-aware band/mode/freq, RST, Start/End
UTC, per-field locks (band/mode/freq/start/end) for backdated QSOs
- Topbar: live freq (MHz.kHz.Hz dotted), live UTC, band/mode/SPLIT badges,
CAT pill with rig selector and clickable Azimuth pill (rotor TODO)
- Settings tree: Profiles (Log4OM-style manager), Station Information
(edits the active profile), unified Callsign Lookup with Test buttons,
Bands/Modes lists, CAT
- Worked-before matrix (band × mode × class) with new-DXCC highlighting
- ADIF import from menu + Maintenance > Refresh cty.dat
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>