cache recent submissions for reminders#88
Conversation
sgeinitz
commented
May 13, 2026
- Cache recent submissions and broaden follow-up audience
- Prompt [y/N] per row in send-follow-up-assessments
- Add 10-minute mtime cache for the three submission CSVs written by
getAllSubmissionsAndEvents. send-quiz-reminder and send-follow-up-question
now skip the Canvas refetch when CSVs from a prior run (often a dry-run
minutes earlier) are still fresh; other callers of
getAllSubmissionsAndEvents are unchanged.
- send-follow-up-question now sends to every student who attempted the
quiz, with intro wording tailored to whether their latest attempt on
the corresponding original question was correct (nice job, slightly
more challenging follow-up) or missed (existing wording).
- Rename _findStudentsWhoMissed to _classifyStudentsByQuestionResult;
the helper now returns {student_id: 'missed' | 'correct'} for every
attempter rather than a list of missed IDs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Real-send mode now previews each feedback message and prompts the instructor to confirm before posting. Default is SKIP — only an exact lowercase 'y' sends, matching the convention already used by send-quiz-reminder / send-follow-up-question. Skipped rows stay at sent_assessment=0 so they can be revisited on a subsequent run. --dry-run is unchanged (previews every row without prompting). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 87436427a4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| max_attempt_per_student = subs_by_q_df.groupby('id')['attempt'].transform('max') | ||
| latest_attempts = subs_by_q_df[subs_by_q_df['attempt'] == max_attempt_per_student] | ||
| q_rows = latest_attempts[latest_attempts['question_id'] == question_id] |
There was a problem hiding this comment.
Classify all attempters before sending follow-up prompts
This change advertises sending follow-ups to every student who attempted the quiz, but the classifier only keeps rows where question_id == selected_qid, so any attempter whose latest attempt lacks that specific question is silently dropped. This happens with question groups/randomized variants (or skipped/omitted question rows), and those students never get a follow-up even though they attempted the quiz.
Useful? React with 👍 / 👎.
| self.all_subs_by_question = pd.read_csv(by_q_csv) | ||
| self.all_subs_and_events = pd.read_csv(events_csv) |
There was a problem hiding this comment.
Fall back to refetch when cached submission CSVs are unreadable
On a cache hit, _tryLoadRecentSubmissions reads CSVs without error handling; if a recent file is truncated/corrupt (for example after an interrupted prior run), pd.read_csv raises and aborts reminder/follow-up flows instead of returning False and refetching from Canvas. Since this helper is now on the hot path for sendQuizReminders, sendFollowUpQuestions, and consolidated reminders, one bad local cache can block sends.
Useful? React with 👍 / 👎.