Series: moving a session moves the ones after it, keeping the pattern (#730 L6) #804

Closed
opened 2026-09-24 05:22:07 +00:00 by claude-bot · 0 comments
Collaborator

Owner, 2026-09-24 (lane 4 survey, #730 L6). The owner rescheduled a session in their own recurring game, and it now falls after the series' next session. "If I reschedule a session, it will automatically move the following sessions … (doesn't shift the pattern)."

Today

materialize_session_series (app/tasks/reminder_tasks.py ~7182) creates every occurrence up to 28 days ahead (SERIES_MATERIALIZE_WINDOW_DAYS), all as confirmed, keyed uniquely on (series_id, series_occurrence_date). Rescheduling one session (session_service reschedule, ~458) moves only that session, so it can land on or past its successors.

The rule

When a series session is moved, walk the series' later sessions in date order:

  • Each one must sit on a regular day of the series that is at least half an interval after the session before it.
  • If a session already satisfies that, stop. Everything after it is untouched.
  • Otherwise, move it to the first regular day that does. The pattern's days never change, only which session sits on which slot.

Example, every other Monday, with sessions on 5 Oct, 19 Oct and 2 Nov:

  • Move 5 Oct to Thursday 8 Oct. Nothing else moves, because 19 Oct is 11 days later, which is more than half of 14.
  • Move 5 Oct to Thursday 22 Oct instead. 19 Oct goes to 2 Nov, and 2 Nov goes to 16 Nov.

A session that moves under this rule:

  • has its answers re-asked, like any move (L6);
  • tells its people, with the usual notice;
  • keeps its identity: its number (D86), notes and title.

Where the walk stops without moving anything. Every series session is created confirmed, so "confirmed" marks nothing special. What does mark something is a session the GM has already moved by hand: its time no longer matches its occurrence slot. The walk also stops at a session detached from the series, or one that is cancelled or played. The walk never rearranges a session somebody deliberately placed. If the ripple would need to move past such a session, stop, and say so on the move form, so the GM can move it too. This is the conservative reading; confirm it with the owner when it's built.

What it needs

  • The vacated slot must not be refilled. The materialiser's rolling window would recreate 19 Oct an hour later. The series needs a record of occurrence dates that are skipped or taken, or the materialiser must skip any occurrence date earlier than a session that already occupies a later slot. Choose the simpler of the two, and test it against the hourly run.
  • The GM's move form says what else will move before they save, for example: "Two later sessions move with it: 19 Oct → 2 Nov, 2 Nov → 16 Nov." Nothing moves silently.
  • Tests at the service level:
    • the walk and its stop;
    • a move that needs no ripple;
    • a move into the half-interval gap;
    • the materialiser not refilling the vacated slot;
    • a hand-moved, detached, cancelled or played session stopping the walk.

Built in lane 4's scheduling server PR (#730), alongside L6's re-ask and L7's pencilled-in → vote.

🤖 Generated with Claude Code

**Owner, 2026-09-24 (lane 4 survey, #730 L6).** The owner rescheduled a session in their own recurring game, and it now falls *after* the series' next session. "If I reschedule a session, it will automatically move the following sessions … (doesn't shift the pattern)." ## Today `materialize_session_series` (`app/tasks/reminder_tasks.py` ~7182) creates every occurrence up to 28 days ahead (`SERIES_MATERIALIZE_WINDOW_DAYS`), all as `confirmed`, keyed uniquely on `(series_id, series_occurrence_date)`. Rescheduling one session (`session_service` reschedule, ~458) moves only that session, so it can land on or past its successors. ## The rule When a series session is moved, walk the series' later sessions in date order: - Each one must sit on a **regular day of the series** that is **at least half an interval after** the session before it. - If a session already satisfies that, stop. Everything after it is untouched. - Otherwise, move it to the first regular day that does. The pattern's days never change, only which session sits on which slot. Example, every other Monday, with sessions on 5 Oct, 19 Oct and 2 Nov: - Move 5 Oct to Thursday 8 Oct. Nothing else moves, because 19 Oct is 11 days later, which is more than half of 14. - Move 5 Oct to Thursday 22 Oct instead. 19 Oct goes to 2 Nov, and 2 Nov goes to 16 Nov. A session that moves under this rule: - has its answers **re-asked**, like any move (L6); - tells its people, with the usual notice; - **keeps its identity**: its number (D86), notes and title. **Where the walk stops without moving anything.** Every series session is created `confirmed`, so "confirmed" marks nothing special. What does mark something is a session the GM has **already moved by hand**: its time no longer matches its occurrence slot. The walk also stops at a session **detached from the series**, or one that is **cancelled or played**. The walk never rearranges a session somebody deliberately placed. If the ripple would need to move past such a session, stop, and say so on the move form, so the GM can move it too. This is the conservative reading; confirm it with the owner when it's built. ## What it needs - **The vacated slot must not be refilled.** The materialiser's rolling window would recreate 19 Oct an hour later. The series needs a record of occurrence dates that are skipped or taken, or the materialiser must skip any occurrence date earlier than a session that already occupies a later slot. Choose the simpler of the two, and test it against the hourly run. - The GM's move form says what else will move before they save, for example: "Two later sessions move with it: 19 Oct → 2 Nov, 2 Nov → 16 Nov." Nothing moves silently. - Tests at the service level: - the walk and its stop; - a move that needs no ripple; - a move into the half-interval gap; - the materialiser not refilling the vacated slot; - a hand-moved, detached, cancelled or played session stopping the walk. Built in lane 4's scheduling server PR (#730), alongside L6's re-ask and L7's pencilled-in → vote. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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#804
No description provided.