Skip to content

Forget a selected airport the new dataset no longer carries - #45

Merged
RISCfuture merged 3 commits into
mainfrom
navdata/prune-selected-airport
Sep 9, 2026
Merged

Forget a selected airport the new dataset no longer carries#45
RISCfuture merged 3 commits into
mainfrom
navdata/prune-selected-airport

Conversation

@RISCfuture

Copy link
Copy Markdown
Contributor

The problem

A leg's airport is remembered in the app group as a bare record ID (Defaults[.takeoffAirport] / .landingAirport, Defaults.swift:129-136), and the nav-data store is replaced wholesale each cycle. Nothing reconciled the two.

That assumption is now known to be false. FAA site numbers are not stable across cycles: in the 2026-09-03 cycle the FAA corrected FAA LID 18AL (LOUISVILLE STAGEFIELD AHP) from site 03329.19 to 00329.19 — a long-standing digit transposition — and it has not been re-published. Airports are also simply retired.

When the selected record vanishes, RunwayPerformanceService throws airportNotFound and the pilot is told:

Takeoff and landing numbers couldn't be calculated — That airport isn't in the database. Check the identifier, or reload airport data in SF50 TOLD.

Neither remedy can work. The identifier was written by the app, not typed; and reloading airport data is precisely what removed the record, so every future cycle fails the same way. The selection lives in the app-group suite — the one extensions can read — so this surfaces in the widget and in Siri, where there is no way to reselect. In-app UI is unaffected; it falls back to "Choose Airport".

The fix

install(generation:) now forgets a selection the incoming dataset cannot resolve, along with the runway chosen on it. Both install paths — the prebuilt download and the property-list import — already converge here, so one call site covers both.

The check deliberately does not use the view model's container. As the comment there notes, that container still reads the generation being replaced until the app reopens its store, so a fetch through it would find the stale airport and clear nothing. It opens the generation just installed instead, with the same in-memory guard makeImportContainer uses so tests, previews and screenshot runs keep reading the container they were given. A failed fetch reads as "present", so nothing is cleared on the strength of an error.

Operation gains clearSelection(), beside the accessors that already read the selection.

Verification

  • xcodebuild build, scheme SF50 TOLD on iPhone 17 Pro (as CI): BUILD SUCCEEDED
  • SF50 Shared Unit Tests plan: 419 tests in 50 suites + 15 in 3 suites, all passed
  • SwiftLint --strict with CI's fetched parent config: 0 violations in 383 files
  • swift-format --strict with CI's config: clean

Notes for review

No tests added. clearSelection() is wiring, and the prune sits in the app target where nothing currently tests NavDataLoaderViewModel — covering it would mean new scaffolding rather than extending existing coverage. Happy to add one if you'd rather.

Based on the stack tip (navdata/prefer-prebuilt-store) so it lands last without disturbing the ordering of #35#44. It arguably belongs in #39, where install(generation:) is introduced, but folding it there means rebasing everything above it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QZ3UWydnavm3g9Gs62Xirb

@RISCfuture
RISCfuture force-pushed the navdata/prefer-prebuilt-store branch from 7d36d45 to 576d8eb Compare September 9, 2026 06:39
An error occurred while trying to automatically change base from navdata/prefer-prebuilt-store to navdata/publish-store September 9, 2026 06:40
@RISCfuture
RISCfuture force-pushed the navdata/prefer-prebuilt-store branch from 576d8eb to 015df8a Compare September 9, 2026 15:20
@RISCfuture
RISCfuture changed the base branch from navdata/prefer-prebuilt-store to main September 9, 2026 15:20
@RISCfuture
RISCfuture force-pushed the navdata/prune-selected-airport branch from 7c930a8 to 015df8a Compare September 9, 2026 15:21
A leg's airport is remembered in the app group as a record ID, and the FAA
retires airports between cycles and occasionally corrects the site number
identifying one. Installing a dataset that lacks the record left the selection
in place, where the widget and Siri resolved it, failed, and suggested
reloading the data that had just removed it — advice that could not work,
since no later cycle restores the record either.

Installing now forgets a selection the incoming generation cannot resolve,
along with the runway chosen on it. The check reads the generation just
installed rather than the container the views still hold, which points at the
dataset being replaced.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QZ3UWydnavm3g9Gs62Xirb
@RISCfuture
RISCfuture force-pushed the navdata/prune-selected-airport branch from 015df8a to 594b907 Compare September 9, 2026 15:30
RISCfuture and others added 2 commits September 9, 2026 08:33
The view takes `\.modelContext` from the environment without naming the
module that defines it, which MemberImportVisibility reports as a warning
today and will reject outright.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01471376Uhug2TYZN8RDFGtq
Installing a generation forgets a selected airport the incoming dataset cannot
resolve, and leaves alone one it still carries. Only the first half is visible in
a failure a pilot would report, so a prune that fired on every install would look
like a fix while quietly costing the airport chosen for the flight.

The check opens the generation being installed rather than the container the
views hold, and that path is only taken for a store on disk — a view model given
an in-memory container reads back the container it was handed. So the tests hand
it a file-backed store and write the incoming dataset into the app group, where
an install looks for it, carrying one airport and not the other. Each leg is
asserted in both directions, so neither a prune that never fires nor one that
always fires passes.

`clearSelectionsMissing(fromGeneration:)` becomes internal, which is what the
tests drive; the entry point above it is a download.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vch7d69o8AYxDmprJ7syCR
@RISCfuture
RISCfuture merged commit 645cb78 into main Sep 9, 2026
5 checks passed
@RISCfuture
RISCfuture deleted the navdata/prune-selected-airport branch September 9, 2026 19:45
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