Skip to content

fix(web,core): rebase remote promote-all onto series master delta - #2751

Merged
cursor[bot] merged 3 commits into
mainfrom
cursor/fix-remote-promote-delta-52f0
Aug 10, 2026
Merged

fix(web,core): rebase remote promote-all onto series master delta#2751
cursor[bot] merged 3 commits into
mainfrom
cursor/fix-remote-promote-delta-52f0

Conversation

@tyler-dane

@tyler-dane tyler-dane commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Signed-in recurrence promote (scope: "all" after a middle-occurrence SHIFT+ARROW nudge) was forwarding the occurrence’s absolute schedule as the series master DTSTART. Local IndexedDB already rebases via shiftSeriesScheduleByOccurrenceEdit; remote did not.

  • Extracted shared shiftSeriesScheduleByOccurrenceEdit into @core; local replaceSeries imports it
  • Remote replace path rebases occurrence-absolute schedules onto a pre-optimistic series master snapshot when scope === "all"
  • RemoteEventRepository skips IndexedDB fallback for occurrence + scope-all (avoids double-applying the delta)
  • thisAndFollowing keeps absolute remainder DTSTART; local source unchanged

Simplicity

Collapsed all-day delta math onto dayjs.diff(..., "day") and shared promote/assert test helpers. Left resolveRemoteReplaceSchedule as a named helper — it documents the remote vs local ownership split.

Automated validation

  • Unit: remote promote "all" middle timed + all-day → repository schedule is master+delta
  • Unit: remote promote thisAndFollowing keeps absolute schedule
  • Unit: remote scope-all + rules edit still rebases from pre-optimistic master snapshot
  • Unit: local promote still sends absolute schedule (IndexedDB applies delta once)
  • Unit: remote replace does not fall back to local for occurrence scope-all when backend is down
  • Regression: local replaceSeries / nudge→promote suite green
  • Signed-in browser not exercised here (auth/Google not provisioned); remote path covered by mutation + repository unit tests

Independent review

Fresh read-only review found three medium issues; all fixed in follow-up commits:

  1. Remote→local fallback double-applied the delta → skip fallback for occurrence scope-all
  2. Missing master soft-fails to absolute (by design; sync usually back-fills masters)
  3. Optimistic rules edits could pollute cached master before rebase → snapshot master schedule onto mutation variables before onMutate

Test plan

  • bun run test:core -- packages/core/src/util/event/shift-series-schedule-by-occurrence-edit.test.ts
  • bun run test:web -- packages/web/src/events/mutations/useEventMutations.test.tsx packages/web/src/events/repositories/local.event.repository.test.ts packages/web/src/events/repositories/remote.event.repository.test.ts
  • bun run type-check
  • bun run lint
Open in Web Open in Cursor 

cursoragent and others added 3 commits August 10, 2026 22:33
Signed-in promote/scope-all replaces were forwarding an occurrence's
absolute schedule as the series DTSTART. Share the local delta helper in
core and apply it before remote replace when a cached series master exists.

Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
Use dayjs day-unit diffs for all-day rebases and collapse repeated
promote/assert scaffolding in the mutations tests.

Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
…races

Snapshot the series master schedule before optimistic writes, and skip
IndexedDB fallback for rebased occurrence scope-all replaces so the delta
cannot be applied twice.

Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
@tyler-dane
tyler-dane marked this pull request as ready for review August 10, 2026 22:39
@cursor
cursor Bot merged commit 651a3e2 into main Aug 10, 2026
20 checks passed
@cursor
cursor Bot deleted the cursor/fix-remote-promote-delta-52f0 branch August 10, 2026 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants