Retention: a failed run's clock still restarts on any write to the session #798

Closed
opened 2026-09-24 02:49:21 +00:00 by claude-bot · 2 comments
Collaborator

A smaller version of #791, which the #791 fix deliberately left alone.

#791 moved retention's anchor for processed sessions to the write-once audio_processed_at. A session whose processing has only ever failed has no such stamp, and still counts from sessions.updated_at (app/retention.py, audio_retention_anchor). updated_at moves on any write to the row. That includes the erasure note run_member_erasure adds when it deletes a member's WAV from a failed session, as well as a title edit, an RSVP-driven touch, and so on. So erasing a member from a failed session restarts its audio clock, which is the same "a privacy control causes more to be kept" shape as #791.

Fix: a write-once "audio received" stamp, written where the bot's upload is accepted (routers/bot.py, the audio handoff), and backfilled from updated_at for existing failed rows so nothing changes on upgrade day. Retention's failed-run branch then anchors on it. It's the same pattern as #791's migration and its tests (test_audio_processed_at_migration.py, the preview/sweep agreement seeds).

Low urgency: only failed runs, which are rare and which a GM is usually about to retry. Not a lane item. File under the retention work (#778/#791).

🤖 Generated with Claude Code

A smaller version of #791, which the #791 fix deliberately left alone. #791 moved retention's anchor for *processed* sessions to the write-once `audio_processed_at`. A session whose processing has **only ever failed** has no such stamp, and still counts from `sessions.updated_at` (`app/retention.py`, `audio_retention_anchor`). `updated_at` moves on **any** write to the row. That includes the erasure note `run_member_erasure` adds when it deletes a member's WAV from a failed session, as well as a title edit, an RSVP-driven touch, and so on. So erasing a member from a failed session restarts its audio clock, which is the same "a privacy control causes more to be kept" shape as #791. **Fix:** a write-once "audio received" stamp, written where the bot's upload is accepted (`routers/bot.py`, the audio handoff), and backfilled from `updated_at` for existing failed rows so nothing changes on upgrade day. Retention's failed-run branch then anchors on it. It's the same pattern as #791's migration and its tests (`test_audio_processed_at_migration.py`, the preview/sweep agreement seeds). Low urgency: only failed runs, which are rare and which a GM is usually about to retry. Not a lane item. File under the retention work (#778/#791). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Collaborator

Picking this up (1 Oct), on fix/798-audio-received-at, as the issue lays out: a write-once sessions.audio_received_at set where the bot's upload is accepted, backfilled from updated_at for today's unprocessed rows, and retention anchoring on audio_processed_at, then audio_received_at, then updated_at as the last fallback. One migration on the current head (11d4e5f6a7b8). Additive to the bot API, so no contract bump.

Picking this up (1 Oct), on `fix/798-audio-received-at`, as the issue lays out: a write-once `sessions.audio_received_at` set where the bot's upload is accepted, backfilled from `updated_at` for today's unprocessed rows, and retention anchoring on `audio_processed_at`, then `audio_received_at`, then `updated_at` as the last fallback. One migration on the current head (`11d4e5f6a7b8`). Additive to the bot API, so no contract bump.
Author
Collaborator

Done in #992, merged 1 Oct (main 58701c2c).

  • sessions.audio_received_at: written once where the bot's upload is accepted; a re-upload or a retry doesn't move it.
  • audio_retention_anchor (the one place the anchor is computed; the preview and the sweep both use it) takes audio_processed_at, then for a failed run audio_received_at, with updated_at only as the last fallback.
  • Migration a798c0d1e2f3 on 11d4e5f6a7b8, backfilling from updated_at for exactly the rows that counted from it before, so nothing moves on upgrade day.
  • Tests cover the regression (a member erase, and a title edit, on a failed session leave its deadline alone), the write-once stamp, and the migration up, down and as the single head.

No follow-ups.

Done in #992, merged 1 Oct (main 58701c2c). - `sessions.audio_received_at`: written once where the bot's upload is accepted; a re-upload or a retry doesn't move it. - `audio_retention_anchor` (the one place the anchor is computed; the preview and the sweep both use it) takes `audio_processed_at`, then for a failed run `audio_received_at`, with `updated_at` only as the last fallback. - Migration `a798c0d1e2f3` on `11d4e5f6a7b8`, backfilling from `updated_at` for exactly the rows that counted from it before, so nothing moves on upgrade day. - Tests cover the regression (a member erase, and a title edit, on a failed session leave its deadline alone), the write-once stamp, and the migration up, down and as the single head. No follow-ups.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/Quest-Board#798
No description provided.