Root cause of the repeatedly-disappearing textbook: both widget timeline
providers were opening the shared local SwiftData store with a schema
that omitted TextbookChapter. On each widget refresh SwiftData
destructively migrated the store to match the widget's narrower schema,
dropping the ZTEXTBOOKCHAPTER rows (and sometimes the table itself).
The app then re-created an empty table on next open, but
refreshTextbookDataIfNeeded skipped re-seeding because the UserDefaults
version flag was already current — leaving the store empty indefinitely.
Three changes:
1. Widgets (CombinedWidget, WordOfDayWidget): added TextbookChapter to
both schema arrays so they match the main app. Widget refreshes will
no longer drop the entity.
2. DataLoader.refreshTextbookDataIfNeeded: trigger now considers BOTH
the version flag and the actual on-disk row count. If rows are
missing for any reason (past wipes, future subset-schema openers,
corruption), the next launch re-seeds. Eliminates the class of bug
where a version flag lies about what's really in the store.
3. StoreInspector: reports ZTEXTBOOKCHAPTER row count alongside the
other entities so we can confirm state from logs.
Bumped textbookDataVersion to 12 so devices that were stuck in the
silent-failure state re-seed on next launch regardless of prior flag
value.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>