Daily audio: pause generation when the last lesson wasn't engaged with#643
Merged
Conversation
Avoids piling up unheard lessons. 'Engaged' = completed or listened past the halfway point (DailyAudioLesson.is_engaged). - Nightly cron skips a user whose most recent lesson isn't engaged (paused), before doing any LLM work. - get_todays_lesson_for_user(include_paused=True) returns that waiting lesson flagged `paused` for the app to show, instead of nothing. Generation callers use the default (today-only) so a paused older lesson never blocks on-demand creation (change-topic / first day). - get_daily_audio_status surfaces a waiting paused lesson as 'ready' so the nav dot still nudges the learner back. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
ArchLens - No architecturally relevant changes to the existing views |
- is_engaged: fall back to 'started it' when duration_seconds is missing, rather than pausing a user forever on a data anomaly. ENGAGEMENT_THRESHOLD constant replaces the inline 0.5. - Single source of truth: DailyAudioLesson.waiting_paused_for(user, language_id) used by the endpoint, get_daily_audio_status, and the cron (gate + dry-run) — removes the duplicated 'latest and not is_engaged' checks (and the learned_language.id vs learned_language_id drift). - Cron uses a cheap today_lesson_exists() scalar query instead of building a full lesson response just to test existence — also avoids mislabeling a stale (audio-missing) today lesson as 'paused'. - Remove now-dead find_latest_for_user (zero callers; near-duplicate of latest_for_language with divergent ordering). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
mircealungu
added a commit
that referenced
this pull request
May 29, 2026
…dule) (#645) * Daily audio: first-class DailyAudioSubscription (config, on/off, schedule) Introduces a per-(user, language) DailyAudioSubscription as the source of truth for WHAT to generate and WHEN, replacing the daily_audio_lesson_type_<lang> / _suggestion_<lang> UserPreference rows. Builds on #643's engagement pause — reuses DailyAudioLesson.is_engaged / waiting_paused_for rather than duplicating it; the subscription owns config only (type, subject, enabled, schedule). - New table + model + backfill tool from the legacy preference keys. - Cron is subscription-driven: skips disabled subs and non-scheduled days, then applies #643's today-exists + engagement-pause gates as before. - save_user_preferences mirrors the legacy keys into the subscription so currently-deployed clients keep working (turning off = empty type). - get_todays_lesson adds subscription_status (not_subscribed|active|off) and next_lesson_date alongside #643's `paused` flag. - set_daily_subscription_enabled endpoint for the turn-off toggle. - weekday_mask groundwork for Mon/Wed/Fri schedules (only 'daily' active now). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Daily audio: address code-review findings - Mirror (#2): key on type OR suggestion keys so a suggestion-only save still syncs the subscription; resolve the language with find (not find_or_create, which committed mid-request — #5); cap raw_suggestion at 128. - next_lesson_date (#3): only promise a date when today's lesson already exists; return None otherwise so the UI can offer an explicit "generate now" instead of a date the cron may not honor (cron miss / first day / timezone). - Align suggestion length to 128 (#4): subscription + daily_audio_lesson columns widened, input capped at 128 (was 80/100/255). - Remove unused DailyAudioSubscription.find_or_create (#6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Daily audio: dedicated configure endpoints; mark legacy compat for removal - GET /daily_subscription returns the current (user, learned_language) config from DailyAudioSubscription, replacing the legacy preference-key read path. - POST /configure_daily_subscription upserts type/subject directly into the subscription, replacing the daily-audio path of /save_user_preferences. - Mark the legacy daily-audio block + mirror in save_user_preferences for removal once the deployed clients are on the new endpoint (~2026-06-05). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Daily audio: explicit language on subscription + today's-lesson endpoints Race fix: when the learner switches language quickly, the server's user.learned_language can lag the UI and reads/writes hit the wrong language. get_todays_lesson, daily_subscription (GET/POST), and set_daily_subscription_enabled now take an explicit `language` query/form param (with a fallback to user.learned_language for clients not yet updated). The generator's get_todays_lesson_for_user and _subscription_fields plumb the Language through. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stops the nightly job piling up unheard lessons: if a learner doesn't get at least halfway through their most recent lesson, daily generation pauses until they come back and listen.
"Engaged" = completed, or
pause_position ≥ 50%of duration —DailyAudioLesson.is_engaged.Changes
tools/generate_daily_audio_lessons.py): per user, before any LLM work — skip if today's lesson already exists (exists), or if the most recent lesson isn't engaged (paused). Dry-run reports the paused count.get_todays_lesson_for_user(include_paused=True): when there's no lesson today and the latest wasn't engaged, returns that waiting lesson flaggedpausedso the app shows it rather than triggering a new generation. Default stays today-only, soprepare_lesson_generationand on-demand creation (change-topic / first day) are unaffected.get_daily_audio_status: a waiting paused lesson reports asready, so the nav dot keeps nudging the learner back to it.is_engaged+latest_for_language(user, language_id).Notes
is_engaged; easy to tune.Test
Expect a user whose last lesson is <50% listened to report
paused.🤖 Generated with Claude Code