Skip to content

Let a NOTAM name its runway instead of pointing at it - #36

Merged
RISCfuture merged 1 commit into
navdata/one-schema-one-factoryfrom
navdata/notam-by-identifier
Sep 9, 2026
Merged

Let a NOTAM name its runway instead of pointing at it#36
RISCfuture merged 1 commit into
navdata/one-schema-one-factoryfrom
navdata/notam-by-identifier

Conversation

@RISCfuture

@RISCfuture RISCfuture commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

SwiftData cannot express a relationship between models in two store
configurations, and it does not say so: it quietly pulls the destination
into the configuration instead. Naming the two model sets in the previous
commit proved it — nav data and user data came to seventeen entities
between them where the app persists ten, because NOTAM.runway dragged
Runway in, which dragged Airport, and so on through most of the dataset.
So nav data cannot move to a store of its own while that relationship
stands.

NOTAM now stores the airport record ID and runway designator instead.
That pair is already what identifies a runway here: Runway is unique on
it, RunwayEntity encodes it for App Intents, and the selected-runway
defaults resolve through it. NOTAMStore does the lookup the relationship
used to, in one fetch per airport rather than one per row.

Resolution is fallible on purpose. Magnetic drift renames a runway, and a
renamed runway has to show no NOTAM rather than one written against a
designator that has moved; reapOrphans deletes the entries left naming
nothing, and says how many went.

Both new attributes carry an empty default. SwiftData synthesizes no
value for a new mandatory attribute, so without one the store cannot
migrate in place and the app cannot open at all — a NOTAM predating this
shape arrives holding empty identifiers, names no runway, and is reaped.
For the same reason the pair carries no uniqueness constraint: adding one
to an entity that already has rows is not a change SwiftData can migrate
lightly. NOTAMStore.upsert is the only place a NOTAM is created, and that
is what keeps it to one per runway.

The view model now owns that creation. It held a NOTAM the editor did not
edit otherwise — the badge read zero and the performance numbers ignored
the pilot's entry, which the NOTAM UI tests caught.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01471376Uhug2TYZN8RDFGtq


Stack created with GitHub Stacks CLIGive Feedback 💬

🤖 Generated with Claude Code

https://claude.ai/code/session_01471376Uhug2TYZN8RDFGtq

@RISCfuture
RISCfuture force-pushed the navdata/notam-by-identifier branch 2 times, most recently from 0d299bf to 5fd595f Compare September 8, 2026 08:00
@RISCfuture
RISCfuture force-pushed the navdata/notam-by-identifier branch from 5fd595f to 64758cf Compare September 8, 2026 15:48
@RISCfuture
RISCfuture force-pushed the navdata/notam-by-identifier branch 2 times, most recently from adf7328 to 2ce55a5 Compare September 8, 2026 18:09
SwiftData cannot express a relationship between models in two store
configurations, and it does not say so: it quietly pulls the destination
into the configuration instead. Naming the two model sets in the previous
commit proved it — nav data and user data came to seventeen entities
between them where the app persists ten, because NOTAM.runway dragged
Runway in, which dragged Airport, and so on through most of the dataset.
So nav data cannot move to a store of its own while that relationship
stands.

NOTAM now stores the airport record ID and runway designator instead.
That pair is already what identifies a runway here: Runway is unique on
it, RunwayEntity encodes it for App Intents, and the selected-runway
defaults resolve through it. NOTAMStore does the lookup the relationship
used to, in one fetch per airport rather than one per row.

Resolution is fallible on purpose. Magnetic drift renames a runway, and a
renamed runway has to show no NOTAM rather than one written against a
designator that has moved; reapOrphans deletes the entries left naming
nothing, and says how many went.

Both new attributes carry an empty default. SwiftData synthesizes no
value for a new mandatory attribute, so without one the store cannot
migrate in place and the app cannot open at all — a NOTAM predating this
shape arrives holding empty identifiers, names no runway, and is reaped.
For the same reason the pair carries no uniqueness constraint: adding one
to an entity that already has rows is not a change SwiftData can migrate
lightly. NOTAMStore.upsert is the only place a NOTAM is created, and that
is what keeps it to one per runway.

The view model now owns that creation. It held a NOTAM the editor did not
edit otherwise — the badge read zero and the performance numbers ignored
the pilot's entry, which the NOTAM UI tests caught.

Resolution is fallible on purpose: a renamed runway shows no NOTAM rather
than another runway's. Nothing reaps the orphan it leaves, because every
import clears the NOTAMs outright — a reap could never find one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01471376Uhug2TYZN8RDFGtq
@RISCfuture
RISCfuture force-pushed the navdata/notam-by-identifier branch from 2ce55a5 to 6462bd0 Compare September 9, 2026 06:38
@RISCfuture
RISCfuture merged commit 264a1d0 into main Sep 9, 2026
5 checks passed
@RISCfuture
RISCfuture deleted the navdata/notam-by-identifier branch September 9, 2026 06:40
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