Commit Graph

67 Commits

Author SHA1 Message Date
Trey t
3d8cbccc4e Fixes #25 — Long-press lyric words for definition and tense
Tokenize Spanish lyric lines into a flow layout of underlined, long-pressable
words. Long-press (0.35s) opens a sheet with base form, English, part of
speech, and a Tense · person row for verbs. Unknown words silently no-op.
English gloss lines remain untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 09:18:15 -05:00
Trey t
cc6ec70ed9 Update README and app_features to reflect current feature set
README: expanded from the original terse list into categorized sections
covering the six conjugation practice modes, textbook reader, AI chat
and stories, listening/pronunciation, cloze, lyrics, vocab SRS, offline
dictionary, grammar notes/exercises, and CloudKit sync. Architecture
section now documents the dual local/cloud SwiftData stores with the
App Group ID, the widget-schema-must-match requirement, and the
Scripts/textbook extraction pipeline.

app_features.md: added a full Conjuga section (practice modes, verb
reference, grammar, dictionary, sync, widgets, data counts) alongside
the existing ConjuGato and Conjuu ES analyses; added Conjuga as a
first column in the comparison table with rows for the new capability
axes (AI, textbook, speech, offline dictionary, lyrics, CloudKit,
widgets); added a "Conjuga excels at" strengths section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 23:36:15 -05:00
Trey t
d99d88e73c Add CLAUDE.md with project rules
Codifies the rule that Claude must not run git commit or git push
without an explicit request from the user in the current turn.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 23:31:14 -05:00
Trey t
8e1c9b6bf1 Make textbook data self-heal after widget schema wipes
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>
2026-04-21 23:31:14 -05:00
Trey t
d9ddaa4902 Fixes #23 — Add irregularity filter to the Verbs list
The toolbar Filter menu now has two sections:
- Level (existing)
- Irregularity: Any Irregular / Spelling Change / Stem Change /
  Unique Irregular

Filters combine, so "Basic" + "Unique Irregular" narrows to the
foundational ser/ir/haber-class verbs. Categories are derived at load
time from existing IrregularSpan rows using the same spanType ranges
already used by PracticeSessionService (1xx spelling, 2xx stem, 3xx
unique), so no schema or data changes are required.

UI additions:
- Per-row icons (star / arrows / I-beam) show each verb's
  irregularity categories at a glance, tinted by type.
- When any filter is active, a chip bar appears under the search
  field showing the active filters (tap to clear) and the resulting
  verb count.
- Filter toolbar icon fills when any filter is applied.

Data coverage: 614 / 1750 verbs are flagged irregular — 411 spelling,
275 stem-change, 67 unique — consistent with canonical lists from
SpanishDict, Lawless Spanish, and Wikipedia.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 23:29:46 -05:00
Trey t
cdf1e05c4c Fixes #22 — Skip irregular verbs in Full Table practice
randomFullTablePrompt now rejects any (verb, tense) combo where any
form has regularity != "regular" and keeps retrying (40 attempts) until
a fully-regular combo is picked. Full Table practice is meant for
drilling regular conjugation patterns — irregular tables belong in the
Irregularity Drills mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 22:49:46 -05:00
Trey t
455df18dad Stop silent save failures from locking out textbook re-seeds
Two bugs were causing chapters to disappear on every relaunch:

1. seedTextbookData used `try? context.save()` (swallowing errors) and
   returned `inserted > 0`, so a failed save still reported success.
   Callers then bumped UserDefaults textbookDataVersion and subsequent
   launches skipped the re-seed entirely — with no rows on disk.

2. refreshTextbookDataIfNeeded wiped chapters via the batch-delete API
   `context.delete(model: TextbookChapter.self)`, which hits the store
   directly without clearing the context's .unique-id index. Re-inserting
   chapters with the same ids could then throw a unique-constraint error
   on save — also silently eaten by `try?`.

Fixes:
- seedTextbookData now uses do/catch around save(), returns false on
  error, and verifies persistence via fetchCount before returning true.
- refreshTextbookDataIfNeeded fetches and deletes chapters individually
  so the context tracks the deletion cleanly; wipe save is also now
  checked and bails early on failure.
- Bumped textbookDataVersion to 11 so devices poisoned by the previous
  silent-failure path retry on next launch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 22:33:23 -05:00
Trey t
3c5600f562 Fix textbook section missing on installs that predate bundled JSON
Earlier launches (before cd491bd bundled textbook_data.json) ran
seedTextbookData, got "not bundled — skipping", and still bumped
UserDefaults textbookDataVersion to 9. Subsequent launches then
short-circuited in refreshTextbookDataIfNeeded and never re-seeded,
so ZTEXTBOOKCHAPTER stayed empty and the Course tab hid the section.

- seedTextbookData now returns Bool (true only when chapters inserted).
- Both call sites only write the version key on success, so a missing
  or unparseable bundle no longer locks us out of future retries.
- Bumped textbookDataVersion to 10 to force existing installs to
  re-seed on next launch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 09:39:47 -05:00
Trey T
5f90a01314 Render textbook vocab as paired Spanish→English grid
Previously the chapter reader showed vocab tables as a flat list of OCR
lines — because Vision reads columns top-to-bottom, the Spanish column
appeared as one block followed by the English column, making pairings
illegible.

Now every vocab table renders as a 2-column grid with Spanish on the
left and English on the right. Supporting changes:

- New ocr_all_vocab.swift: bounding-box OCR over all 931 vocab images,
  cluster lines into rows by Y-coordinate, split rows by largest X-gap,
  detect 2- / 3- / 4-column layouts automatically. ~2800 pairs extracted
  this pass vs ~1100 from the old block-alternation heuristic.
- merge_pdf_into_book.py now prefers bounding-box pairs when present,
  falls back to the heuristic, embeds the resulting pairs as
  vocab_table.cards in book.json.
- DataLoader passes cards through to TextbookBlock on seed.
- TextbookChapterView renders cards via SwiftUI Grid (2 cols).
- fix_vocab.py quarantine rule relaxed — only mis-pairs where both
  sides are clearly the same language are removed. "unknown" sides
  stay (bbox pipeline already oriented them correctly).

Textbook card count jumps from 1044 → 3118 active pairs.
textbookDataVersion bumped to 9.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:58:41 -05:00
Trey T
cd491bd695 Bundle textbook JSON so fresh clones build without re-running pipeline
The pbxproj references textbook_data.json and textbook_vocab.json as Copy
Bundle Resources, so xcodebuild fails if they're missing. Committing the
generated output keeps the repo self-sufficient — regenerate via
Conjuga/Scripts/textbook/run_pipeline.sh when content changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:28:45 -05:00
Trey t
df96a9e540 Merge branch 'main' of gitea.treytartt.com:admin/Spanish 2026-04-19 15:23:01 -05:00
Trey t
c73762ab9f Add tappable word lookup to chat bubbles
Assistant messages now render each word as a button. Tap shows a sheet
with base form, English translation, and part of speech. Dictionary
lookup first; falls back to Foundation Models (@Generable ChatWordInfo)
for words not in the local dictionary. Results cached per-session.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:22:59 -05:00
Trey t
f809bc2a1d Fix speech recognition crash from audio format mismatch
Switch audio session to .record-only, use nil tap format so the system
picks a compatible format, and route through AVAudioEngine with a 4096
buffer. Avoids the mDataByteSize(0) assertion seen on some devices.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:22:45 -05:00
Trey T
63dfc5e41a Add textbook reader, exercise grading, stem-change toggle, extraction pipeline
Major changes:
- Textbook UI: chapter list, reader, and interactive exercise view (keyboard
  + Apple Pencil) surfaced under the Course tab. 30 chapters, 251 exercises.
- Stem-change conjugation toggle on Week 4 flashcard decks (E-IE, E-I, O-UE).
  Uses existing VerbForm + IrregularSpan data to render highlighted present
  tense conjugations inline.
- Deterministic on-device answer grader with partial credit (correct / close
  for accent-stripped or single-char-typo / wrong). 11 unit tests cover it.
- SharedModels: TextbookChapter (local), TextbookExerciseAttempt (cloud-
  synced), AnswerGrader helpers. Bumped schema.
- DataLoader: textbook seeder (version 8) + refresh helpers that preserve
  LanGo course decks when textbook data is re-seeded.
- Local extraction pipeline in Conjuga/Scripts/textbook/ — XHTML chapter
  parser, answer-key parser, macOS Vision image OCR + PDF page OCR, merger,
  NSSpellChecker validator, language-aware auto-fixer, and repair pass that
  re-pairs quarantined vocab rows using bounding-box coordinates.
- UI test target (ConjugaUITests) with three tests: end-to-end textbook
  flow, all-chapters screenshot audit, and stem-change toggle verification.

Generated textbook content (textbook_data.json, textbook_vocab.json) and
third-party source files are gitignored — re-run Scripts/textbook/run_pipeline.sh
locally to regenerate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:12:55 -05:00
Trey t
5ba76a947b Bump courseDataVersion to 7 after merging Gitea course data updates
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:41:55 -05:00
Trey t
bb596b19bd Merge branch 'main' of gitea.treytartt.com:admin/Spanish 2026-04-16 08:40:17 -05:00
Trey t
47a7871c38 Add 13 new grammar notes with 1010 exercises from video extraction
Scraped a 4h Spanish fundamentals YouTube video (transcript + OCR on
14810 frames), extracted structured content across 52 chapters, and
generated fill-in-the-blank quizzes for every grammar topic.

- 13 new GrammarNote entries (articles, possessives, demonstratives,
  greetings, poder, al/del, prepositional pronouns, irregular yo,
  stem-changing, stressed possessives, present/future perfect, present
  indicative conjugation)
- 1010 generated exercises across all 36 grammar notes (new + existing)
- Fix tense guide parser to handle unnumbered *Usages* blocks
- Rewrite 6 broken tense guide bodies (imperative, subj pluperfect,
  subj future) with numbered usage format
- Bump courseDataVersion 5→6 with TenseGuide refresh on upgrade
- Add docs/spanish-fundamentals/ with raw transcripts, polished notes,
  structured JSON, and exercise data

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:40:05 -05:00
b17fb49d49 Merge pull request 'Add English translations to exceptional yo forms' (#20) from issue/19-exceptional-yo-english into main
Reviewed-on: #20
2026-04-16 08:03:35 -05:00
Trey T
5b69f3b630 Fixes #19 — Add English translations to exceptional yo form flashcards
Cards now show "tengo — I have" instead of just "tengo", so learners
see the English meaning alongside the Spanish yo form. Bumps course
data version to 6 to trigger re-seed on next launch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:02:40 -05:00
Trey t
ff4f906128 Fix crash from zero-length audio buffers in speech recognition
Guard against empty audio buffers before appending to speech
recognition request — AVAudioBuffer asserts non-zero data size.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 19:00:51 -05:00
23ff9d66de Merge pull request 'Expand grammar exercises to 100 sentences each' (#18) from feature/expand-grammar-exercises into main 2026-04-13 18:55:56 -05:00
Trey t
b48e935231 Expand grammar exercises to 100 sentences each, pick 10 random per session
- Ser vs Estar: 100 sentences
- Por vs Para: 100 sentences
- Preterite vs Imperfect: 100 sentences
- Subjunctive Triggers: 100 sentences
- Personal A: 100 sentences

Each session randomly selects 10 from the pool for variety.

Closes #15

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 18:55:36 -05:00
924090190f Merge pull request 'Add Done button to grammar exercise score screen' (#17) from fix/grammar-exercise-back-button into main 2026-04-13 18:49:37 -05:00
Trey t
945b2ff1f3 Add Done button to grammar exercise score screen
Fixes stuck state after completing grammar exercises — adds a
dismiss button on the results screen.

Closes #14

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 18:49:18 -05:00
77932f802a Merge pull request 'Fix listening practice crash on Start Speaking' (#16) from fix/listening-crash into main 2026-04-13 18:45:28 -05:00
Trey t
5944f263cd Fix listening practice crash when tapping Start Speaking
Wrap startRecording in do/catch so audio setup failures don't crash.
Validate recording format has channels before installTap. Use
DispatchQueue.main.async instead of Task{@MainActor} in recognition
callback to avoid dispatch queue assertions.

Closes #13

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 18:45:05 -05:00
Trey t
a3318adf5e Use ViewThatFits for study time and activity cards layout
Side by side on iPad, stacked vertically on iPhone. Fixes
calendar grid overflowing on narrow screens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:28:02 -05:00
Trey t
a3807faf2d Fix speech authorization crash on device from dispatch queue assertion
Request authorization off main queue and marshal callback result back
via DispatchQueue.main.async. Check current status first to avoid
unnecessary system prompt if already authorized or denied.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:19:03 -05:00
93ab7b3e16 Merge pull request 'Add 6 new practice features, offline dictionary, and feature reference' (#12) from newStuff into main 2026-04-13 16:13:15 -05:00
Trey t
a663bc03cd Add 6 new practice features, offline dictionary, and feature reference
New features:
- Offline Dictionary: reverse index of 175K verb forms + 200 common
  words, cached to disk, powers instant word lookups in Stories
- Vocab SRS Review: spaced repetition for course vocabulary cards
  with due count badge and Again/Hard/Good/Easy rating
- Cloze Practice: fill-in-the-blank using SentenceQuizEngine with
  distractor generation from vocabulary pool
- Grammar Exercises: interactive quizzes for 5 grammar topics
  (ser/estar, por/para, preterite/imperfect, subjunctive, personal a)
  with "Practice This" button on grammar note detail
- Listening Practice: listen-and-type + pronunciation check modes
  using Speech framework with word-by-word match scoring
- Conversational Practice: AI chat partner via Foundation Models
  with 10 scenario types, saved to cloud container

Other changes:
- Add Conversation model to SharedModels and cloud container
- Add Info.plist keys for speech recognition and microphone
- Skip speech auth on simulator to prevent crash
- Fix preparing data screen to only show during seed/migration
- Extract courseDataVersion to static property on DataLoader
- Add "How Features Work" reference page in Settings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:12:36 -05:00
b13f58ec81 Merge pull request 'Add AI-generated short stories with tappable words' (#11) from feature/short-stories into main 2026-04-13 11:32:19 -05:00
Trey t
451866e988 Add AI-generated short stories with tappable words and comprehension quiz
Generate one-paragraph Spanish stories on-device using Foundation Models,
matched to user's level and enabled tenses. Every word is tappable —
pre-annotated words show instantly, others get a quick on-device AI
lookup with caching. English translation hidden by default behind a
toggle. Comprehension quiz with 3 multiple-choice questions. Stories
saved to cloud container for sync and persistence across resets.

Closes #9

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:31:58 -05:00
0848675016 Merge pull request 'Add irregular verbs reference guides' (#10) from feature/common-irregular-verbs into main 2026-04-13 10:56:49 -05:00
Trey t
79c4c6e290 Add irregular verbs reference guides to grammar section
Add two grammar notes under new "Irregular Verbs" category:
- Most Common Irregular Verbs: 15 essential verbs with present
  and preterite forms plus example sentences
- Types of Irregular Verbs: spelling changes, stem changes, and
  unique irregulars with patterns and examples

Closes #5

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:56:34 -05:00
ee8a0c478f Merge pull request 'Fix lyrics wiped on schema reset' (#8) from fix/lyrics-data-loss into main 2026-04-13 10:27:39 -05:00
Trey t
282cd1b3a3 Fix lyrics wiped on schema reset by moving SavedSong to cloud container
SavedSong was in the local container alongside reference data, so it
got deleted whenever localStoreResetVersion was bumped. Move it to the
cloud container (CloudKit-synced) so saved songs persist across schema
changes. Update lyrics views to use cloudModelContextProvider.

Closes #4

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:27:21 -05:00
24cc05389e Merge pull request 'Highlight main tenses with Essential badges and focus mode' (#7) from feature/main-tenses-highlight into main 2026-04-13 10:08:02 -05:00
Trey t
40d436ad9c Highlight main tenses with Essential badges and focus mode
Mark 6 core tenses (presente, pretérito, imperfecto, futuro,
subjuntivo presente, imperativo) as essential. Add "Common Tenses"
quick action in Practice to drill only these. Show "Essential"
badge on core tenses in Guide > Tenses list.

Closes #3

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:07:46 -05:00
e1b1910c06 Merge pull request 'Add background study timer' (#6) from feature/background-study-timer into main 2026-04-13 09:45:07 -05:00
Trey t
473eb271cc Add background study timer tracking foreground time per day
Track how long users spend studying by timing foreground sessions.
StudyTimerService starts on app active, stops on background, and
accumulates seconds into DailyLog.studySeconds (CloudKit-synced).
Dashboard shows today/total study time with a 7-day bar chart.

Closes #1

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 09:44:44 -05:00
Trey t
877e699c56 Add Spanish Suffixes grammar guide with card-based content layout
Add comprehensive suffix reference (diminutives, augmentatives, verb
endings, noun/adjective-forming, adverbs, pejoratives) as grammar note
#21 under Word Building category.

Refactor grammar detail rendering to group paragraphs with their
examples into visual cards, replacing the flat wall-of-text layout.
Suffix entries get pill-styled labels with compact inline examples.
Bump courseDataVersion to 5.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:31:30 -05:00
Trey t
d372a5c77f Add checkpoint exams with cumulative vocabulary review per course
Checkpoint exams appear after each week in the course view, testing
all words from week 1 through the current week within the same course.
Users can choose 25, 50, or 100 questions with even distribution
across weeks. Results are tracked separately from weekly tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:45:25 -05:00
Trey t
a1dc17bf00 Add per-form English translations to verb conjugation table
New EnglishConjugator in SharedModels constructs English translations
by combining the verb's infinitive with person pronouns and tense
auxiliaries (e.g., abatir conditional yo → "I would knock down").
Covers all 20 tense IDs, handles 60+ irregular English verbs,
multi-word verbs, 3rd person rules, gerund and participle formation.

VerbDetailView shows the English below each conjugated form, plus a
legend explaining red = irregular conjugation. 42 tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:44:17 -05:00
Trey t
c58313496e Avoid showing the same verb back-to-back in practice
fetchDueCard now accepts the last-shown verb ID and prefers a
different verb from the due queue. Falls back to the same verb
only when it's the sole due card.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:27:29 -05:00
Trey t
636193fae1 Fix lyrics navigation, translation line alignment, and store reset
Navigation: present search as a sheet from library (avoids nested
NavigationStack), use view-based NavigationLink for song rows (fixes
double-push from duplicate navigationDestination).

Translation: Apple Translation inserts a blank line after every
translated line. Strip all blanks from the EN output, then re-insert
them at the same positions where the original ES has blanks. Result
is 1:1 line pairing between Spanish and English.

Store reset: revert localStoreResetVersion bump — adding SavedSong
is a lightweight SwiftData migration, no store nuke needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:08:32 -05:00
Trey t
faef20e5b8 Add Lyrics practice: search, translate, and read Spanish song lyrics
New feature in the Practice tab that lets users search for Spanish songs
by artist + title, fetch lyrics from LRCLIB (free, no API key), pull
album art from iTunes Search API, auto-translate to English via Apple's
on-device Translation framework, and save for offline reading.

Components:
- SavedSong SwiftData model (local container, no CloudKit sync)
- LyricsSearchService actor (LRCLIB + iTunes Search, concurrent)
- LyricsSearchView (artist/song fields, result list with album art)
- LyricsConfirmationView (lyrics preview, auto-translation, save)
- LyricsLibraryView (saved songs list, swipe to delete)
- LyricsReaderView (Spanish lines with English subtitles)
- Practice tab integration (Lyrics button with NavigationLink)
- localStoreResetVersion bumped to 3 for schema migration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:44:40 -05:00
Trey t
5fa1cc3921 Filter phonetic glosses from Complete the Sentence quiz
Examples shorter than 4 words (like pronunciation guides
"discutir(dees-koo-teer)") are now rejected by both
isBlankResolvable and buildQuestion. The engine only picks real
multi-word sentences for the quiz prompt.

Every card already has at least one real sentence alongside its
phonetic entries, so no data regeneration is needed — the filter
alone fixes the issue.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:22:28 -05:00
Trey t
a51d2abd47 Defer AVSpeechSynthesisVoice init to first speak() call
AVSpeechSynthesisVoice(language:) triggers a malloc double-free on
iOS 26 simulators when deserializing voice metadata during app launch.
Move voice resolution from init() to first speak() so the framework
call happens after the app is fully initialized.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 20:52:56 -05:00
Trey t
2a062cf484 Bump courseDataVersion to 4 for sentence gap-fill re-seed
Existing installs will delete and re-seed all VocabCard/CourseDeck data
on next launch, picking up the ~6,300 new example sentences and blank
fields added for the Complete the Sentence quiz type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 20:47:31 -05:00
Trey t
02e8d5141a Complete the Sentence: fill sentences for final batches 26-29
290 cards: Intermediate III tail (48), Advanced I (95), Advanced II
(147). All 8 courses now have complete sentence coverage for the
Complete the Sentence quiz type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 20:43:49 -05:00