From 66d9eff2f984990a5368fbc2536dd4cc8a84140f Mon Sep 17 00:00:00 2001 From: iamdoubz <> Date: Tue, 7 Jul 2026 13:02:14 -0500 Subject: [PATCH] feat(storage): persist requested language at meeting creation (T8.7, M4.2) --- src-tauri/src/storage/mod.rs | 68 ++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/storage/mod.rs b/src-tauri/src/storage/mod.rs index a3e1764..2e2e075 100644 --- a/src-tauri/src/storage/mod.rs +++ b/src-tauri/src/storage/mod.rs @@ -42,6 +42,12 @@ pub struct NewMeeting { /// re-rendering notes.md on reprocess/resume reapplies the same /// section structure instead of losing it. pub template_id: Option, + /// Transcription language requested at recording start (T8.7, FR-TRX-4): + /// `None` means auto-detect. Recorded immediately (not just at + /// `finalize_meeting`) so a crash-recovered `recovering` meeting still + /// knows what was asked for; `finalize_meeting`'s `language` overwrites + /// this with whatever whisper.cpp actually resolved/detected. + pub language: Option, } /// `list_meetings` filters (Phase 8, FR-SEARCH-2). All fields are ANDed @@ -703,8 +709,8 @@ impl Store for SqliteStore { let audio_path = folder.join("audio.wav"); let now = now_unix(); sqlx::query( - "INSERT INTO meetings (id, title, started_at, folder_path, audio_path, status, calendar_event_id, template_id, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, 'recording', ?, ?, ?, ?)", + "INSERT INTO meetings (id, title, started_at, folder_path, audio_path, status, calendar_event_id, template_id, language, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, 'recording', ?, ?, ?, ?, ?)", ) .bind(&id) .bind(&m.title) @@ -713,6 +719,7 @@ impl Store for SqliteStore { .bind(audio_path.display().to_string()) .bind(&m.calendar_event_id) .bind(&m.template_id) + .bind(&m.language) .bind(now) .bind(now) .execute(&self.pool) @@ -1785,6 +1792,60 @@ mod tests { } } + /// T8.7/FR-TRX-4: the language requested at `create_meeting` is visible + /// immediately (not just after `finalize_meeting`) — a crash-recovered + /// `recovering` meeting still knows what was asked for. + #[tokio::test] + async fn create_meeting_persists_the_requested_language_immediately() { + let store = SqliteStore::connect_in_memory().await.unwrap(); + let id = store + .create_meeting(NewMeeting { + title: "Reunión semanal".to_string(), + calendar_event_id: None, + template_id: None, + language: Some("es".to_string()), + }) + .await + .unwrap(); + let meeting = store.get_meeting(&id).await.unwrap(); + assert_eq!(meeting.language.as_deref(), Some("es")); + } + + /// `finalize_meeting` overwrites whatever `create_meeting` stored with + /// the language whisper.cpp actually resolved/detected (T8.7, FR-TRX-4) + /// — e.g. "auto" mode's detected result, or an English-only model's + /// forced "en". + #[tokio::test] + async fn finalize_meeting_overwrites_the_requested_language_with_the_resolved_one() { + let store = SqliteStore::connect_in_memory().await.unwrap(); + let id = store + .create_meeting(NewMeeting { + title: "Auto-detect meeting".to_string(), + calendar_event_id: None, + template_id: None, + language: None, // requested "auto" + }) + .await + .unwrap(); + store + .finalize_meeting( + &id, + FinalizeMeeting { + segments: Vec::new(), + speakers: Vec::new(), + duration_secs: 42, + recorded: false, + language: Some("fr".to_string()), // what auto-detect resolved to + backend_used: Some("cpu".to_string()), + model_used: Some("small-q5_1".to_string()), + }, + ) + .await + .unwrap(); + let meeting = store.get_meeting(&id).await.unwrap(); + assert_eq!(meeting.language.as_deref(), Some("fr")); + } + #[tokio::test] async fn rename_meeting_updates_the_title() { let store = SqliteStore::connect_in_memory().await.unwrap(); @@ -1793,6 +1854,7 @@ mod tests { title: "Untitled meeting".to_string(), calendar_event_id: None, template_id: None, + language: None, }) .await .unwrap(); @@ -1818,6 +1880,7 @@ mod tests { title: "Untitled meeting".to_string(), calendar_event_id: None, template_id: None, + language: None, }) .await .unwrap(); @@ -1862,6 +1925,7 @@ mod tests { title: "Untitled meeting".to_string(), calendar_event_id: None, template_id: None, + language: None, }) .await .unwrap();