Repository navigation
Calendar editing: create, change and delete your Google events from PM #884
Description
What this is
Edit your calendars from PM instead of switching to Google Calendar: create, change, move and delete events, including repeating events and events with guests, on any Google calendar you can write to. Decided 2026-10-09; this replaces the card's earlier scope of "PM-owned projected events only".
Decisions (Bobby, 2026-10-09)
- Google is the source of truth. PM writes through to Google and trusts its reply. PM never keeps its own copy of an edit.
- Online only for now. Editing offline and resolving conflicting changes are a separate, later card. Until then PM still detects a conflicting change and never overwrites it.
- Full functionality. Choose the calendar, repeating events (this event / this and following / all events), guests, drag to move, click-and-drag to create: what Google Calendar's own editor does. Each deliberate cut gets written down.
- Permission:
calendar.events, turned on per Google account ("Enable editing"). Calendars shared with you are editable where you have write access. Subscribed and ICS calendars stay read-only. - No "Edit in Google" link as a stopgap.
- AI editing your calendar is its own later Stage-4 card; nothing in this epic lets a model reach the write path.
Safety rules every layer keeps
- Every edit is a diff against a fresh copy from Google, and PM checks the event's version before sending only the fields you changed (and sends that version with the write). If the event changed elsewhere, that's a conflict and PM never silently overwrites it.
- PM's local mirror is shortened on purpose and is never used to build a write.
- A background sync can't undo a save you just made.
- Only PM's main window can call the write commands.
Prerequisite fixes (merged 2026-10-09)
- Disconnecting Google Calendar or Drive revokes a grant the other service (or backup) still uses #883 (PR fix(connectors): a Google disconnect no longer cuts off another service that still uses the account → 3.139.8-alpha #885) Disconnecting Google Calendar or Drive revokes a grant the other service (or backup) still uses
- Advanced-Protection Google accounts: backup and a second service sign in through the wrong project #886 (PR fix(connectors): Advanced-Protection Google accounts sign in through their own project everywhere → 3.139.9-alpha #889) Advanced-Protection Google accounts: backup and a second service sign in through the wrong project
- Clearing the Microsoft client ID leaves Outlook calendar accounts behind, failing every sync #887 (PR fix(connectors): clearing the Microsoft client also signs out Outlook calendars → 3.139.10-alpha #890) Clearing the Microsoft client ID leaves Outlook calendar accounts behind
- Calendar keys page the grid behind open dialogs, and Escape in a picker closes its dialog too #888 (PR fix(calendar): keys and swipes stand down behind dialogs, and a picker's Escape stays in the picker → 3.139.11-alpha #891) Calendar keys page the grid behind open dialogs, and Escape in a picker closes its dialog too
Build plan after the fixes
About 23 layers. In order: Enable editing per account (C1), the mirror and pure write core (C2–C3), write commands and fences (C4), the single-event editor (C5–C6), repeating events including "this and following" (C7–C9), create (C10), repeat rules (C11), guests with Send / Don't send (C12), notifications, colours and labels (C13; labels were cut from it on 2026-10-19 and have their own Backlog card), invitations and RSVP (C14), drag to move and resize (C15–C16), click-and-drag to create (C17), Meet, Duplicate and change calendar (C18), rich-text descriptions (C19), and birthday and Gmail events (C20). Each layer is live-tested on a dev build against a copy of the data folder and a dedicated test calendar.
Delivery
A stacked series of PRs. They merge into main in reviewed batches (the first, the prerequisite fixes, on 2026-10-09); no release is cut until the whole stack is done and has been tested on a dev build. As of 22-10-2026 the last release is still v3.130.10-alpha (2026-08-29).
Decided 2026-10-09 (Bobby took every recommendation on the plan's open questions): Outlook editing is its own card, "Outlook calendar editing (phase 2)", because there is no Outlook account to test against. Focus time, out of office and Find a time are a card until a Workspace account turns up. Touch dragging stays off in v1. Calendar settings and sharing, attachments, search beyond the mirror and .ics import, and dragging milestones each have their own Backlog card.
Cards added since: "Check repeating events against Google Calendar, then match it" (17-10), "Google Calendar event labels: show and change them" (cut from C13, 19-10), "Declined events still nudge" (found while specifying C14, 20-10), "Adding guests to someone else's event" (C14, question 4) and "Check creating events against Google Calendar, then match it" (C10's Google checks, G1 to G6). The specs for C to F name a few more, each made with its PR.
Layers
-
C1 Turn on editing per Google account: PR feat(calendar): turn on editing per Google account → 3.140.0-alpha #894 (merged 2026-10-10)
-
C2 The mirror records what editing needs (v57): PR chore(calendar): the mirror records what editing needs (v57) → 3.140.1-alpha #896 (merged 2026-10-10)
-
C3 Pure write core for single events: PR chore(calendar): pure write core for single events → 3.140.2-alpha #897 (merged 2026-10-10)
-
C4 Write commands, Google I/O and fences: PR feat(calendar): write commands, private Google I/O and fences → 3.141.0-alpha #898 (merged 2026-10-10)
-
C5 Editor building blocks and draft logic: PR chore(calendar): editor building blocks and draft logic → 3.141.1-alpha #899 (merged 2026-10-10)
-
C6a Delete single events, with an Undo the backend holds: PR feat(calendar): delete single events, with an Undo the backend holds → 3.142.0-alpha #900 (merged 2026-10-10)
-
C6b Edit single events, and the read-only copy rewrite: PR feat(calendar): edit single events, and the read-only copy rewrite → 3.143.0-alpha #901 (merged 2026-10-10)
-
C7 Recurrence core, and iCal series that say how they repeat: PR feat(calendar): the recurrence core, and iCal series that say how they repeat (3.144.0-alpha, C7 of #884) #902 (merged 2026-10-10)
-
C8a Series maths for moving a repeating event (inert): PR chore(calendar): series maths for moving a repeating event → 3.147.5-alpha (C8a of #884) #922 (merged 2026-10-16)
-
C8b Series planners and their reconcile (inert): PR chore(calendar): series planners and their reconcile → 3.147.6-alpha (C8b of #884) #923 (merged 2026-10-16)
-
C8c A weekly series' day may cross into the next week (inert; Bobby's F6 answer, "every Sunday" dragged to Monday becomes "every Monday"): PR fix(calendar): a weekly series' day may cross into the next week → 3.147.8-alpha #926 (merged 2026-10-17)
C9 (edit, delete and split repeating events) is six PRs (decided 2026-10-17, C9a-3 split in two the same day; design in the local docs):
- C9a-1 The series executor, sending a change step by step and reading every answer, with no I/O (inert): PR chore(calendar): the series executor, a machine with no I/O → 3.148.1-alpha (C9a-1 of #884) #931 (merged 2026-10-17)
- C9a-2 Series reads: the series as opened, the choices to offer, the exceptions listing and its cross-check: PR chore(calendar): series reads, and the choices a change offers → 3.148.3-alpha (C9a-2 of #884) #953 (merged 2026-10-18)
- C9a-3a Series writes without a new series: "This event" and "All events" saves and deletes, and the "This and following" delete: PR chore(calendar): series writes without a new series → 3.148.4-alpha (C9a-3a of #884) #954 (merged 2026-10-18)
- C9a-3b "This and following" edits (a new series), half-finished splits and settling them: two PRs; C9a-3b-1 is PR chore(calendar): "this and following" edits, and settling one PM couldn't finish → 3.148.6-alpha (C9a-3b-1 of #884) #958 (merged 2026-10-18), C9a-3b-2 (the journal row and the overlap backstop) is PR chore(calendar): remember a split while it runs, and refuse a series an earlier split still overlaps → 3.148.8-alpha (C9a-3b-2 of #884) #959 (merged 2026-10-22)
- C9b-1 The This / This and following / All events dialog (repeating events become editable here): two PRs; C9b-1a (the dialog's parts, not yet shown) is PR chore(calendar): the repeating-event dialog's parts, not yet shown → 3.148.9-alpha (C9b-1a of #884) #960 (merged 2026-10-22), C9b-1b (repeating events become editable) is PR feat(calendar): change repeating events, create events, repeat rules and guests → 3.155.0-alpha (C9b-1b + C10–C12 of #884) #961 (merged 2026-10-22)
- C9b-2 The "Repeats ..." line, and moving a milestone after a split: PR feat(calendar): the popover says how an event repeats, and a split offers to move its milestones → 3.152.0-alpha (C9b-2) #965 (merged 2026-10-22)
C10 (creating events) is three PRs (decided 2026-10-18; spec in the local docs):
- C10a The create command and its safeguards, dev builds only: PR chore(calendar): the create command and its safeguards, dev builds only → 3.149.1-alpha (C10a) #962 (merged 2026-10-22)
- C10b Create events from the full editor: "+ New event" or press c, on the last-used calendar, with Google's default length: PR feat(calendar): create events in your Google calendars → 3.150.0-alpha (C10b) #963 (merged 2026-10-22)
- C10c Quick create (Shift+C), and the new event shows on the calendar as you type: PR feat(calendar): quick create, and the new event shows on the calendar as you type → 3.151.0-alpha (C10c) #964 (merged 2026-10-22)
C11 (repeat rules: new events can repeat, and changing how an event repeats) is four PRs (decided 2026-10-18; spec in the local docs):
- C11a Repeat rules in words and on the wire, and the backend can create a repeating event (nothing sends one yet): PR chore(calendar): repeat rules in words and on the wire, and the backend can create a repeating event → 3.152.1-alpha (C11a) #966 (merged 2026-10-22)
- C11b New events can repeat: the Repeat row in the editor and quick create, presets and Custom: PR feat(calendar): new events can repeat → 3.153.0-alpha (C11b) #967 (merged 2026-10-22)
- C11c The planners take a new rule or "Does not repeat" (inert until C11d): PR chore(calendar): the repeating-event planners take a new rule, not yet sent → 3.153.1-alpha (C11c of #884) #969 (merged 2026-10-22)
- C11d Changing how an event repeats, all-day/timed and zone switches for every occurrence, and "Does not repeat" (dev builds until probe P-R2): PR feat(calendar): change how an event repeats → 3.154.0-alpha (C11d of #884) #970 (merged 2026-10-22)
C12 (guests, and Send / Don't send) is four PRs (decided 2026-10-19; spec in the local docs):
- C12a Guests and update emails on the backend (inert): PR chore(calendar): guests and update emails on the backend, not yet shown → 3.154.1-alpha (C12a of #884) #971 (merged 2026-10-22)
- C12b The guest list and the update-email question, not yet shown: PR chore(calendar): the guest list and the update-email question, not yet shown → 3.154.2-alpha (C12b of #884) #972 (merged 2026-10-22)
- C12c Edit events you organise with guests, and choose whether Google emails them: PR feat(calendar): edit events with guests, and choose whether Google emails them → 3.155.0-alpha (C12c of #884) #973 (merged 2026-10-22)
- C12d New events can have guests: in PR A below
#968 (that week's dependency security advisories: Pillow 13, certifi and the certificate crates, with Python 3.11 or newer) merged first, and everything through C12c merged on 2026-10-22 (3.155.0-alpha).
The rest, regrouped (decided 2026-10-22)
Bobby asked for fewer PRs to save time and tokens, so the 24 PRs the C12-C20 specs planned become 7, one per feature a user would name. The specs are unchanged; each PR still builds layer by layer, then gets one version bump, one review loop and one full check.
- A: C12d + C13: new events can have guests; notifications and colour in both editors (Google's event labels were cut from C13 and go to their own Backlog card): PR feat(calendar): guests on new events, and notifications and colour in the editor → 3.156.0-alpha (C12d + C13 of #884) #976 (open, 2026-10-22)
- B: C14a-c: reply to invitations from the popover; your own notifications, colour and busy/free on events you're invited to; shared fields when the organiser allows: PR feat(calendar): reply to invitations, and change your own settings on events you're invited to → 3.157.0-alpha (C14a-c of #884) #977 (open, 2026-10-23)
- C: C15-C17: drag to move and resize in Week, Day and Month; Undo after a save; click or drag on the grid to create: PR feat(calendar): drag events to move and resize them, Undo after a save, click or drag to create → 3.158.0-alpha (C15-C17 of #884) #999 (open, 2026-10-28)
- D: C18: Google Meet on events you organise and on new events; Duplicate; move an event to another calendar
- E: C19: descriptions show Google's formatting, and can be formatted in PM
- F: C20: birthdays and Gmail events where Google allows; ask a calendar's owner for edit access; the final help sweep
- G: C14d: Remove from my calendar, at the top of the stack so it stays a leaf: run live test L-I4 before merging it
A to C are stacked on #998 (that week's Dependabot batch, 3.155.1-alpha; it also builds the Linux rpm in its own step, labelled 3.155.1+alpha, because the newer Tauri CLI refuses the - in -alpha there). Merge order: #998, #976, #977, #999. D starts from main after that.
Decided 2026-10-17 (Bobby took every recommendation): a change to who can see a repeating event pre-selects nothing and keeps Save off until you pick "This and following" or "All events"; a linked milestone dated on or after a split is offered a move to the new part each time; the new part gets no Meet link, and the dialog says so; no Undo after saving a repeating event in C9 (it comes with drag's Undo, C16); and the Google checks for C9a join the Backlog card "Check repeating events against Google Calendar, then match it".
Fixes from the first live test (2026-10-10), before C8
Bobby's live test of C1–C7 on a dev build found these. Decided the same day: event colours fill the card the way Google does, a "prepare ahead" you've cleared stays cleared when the event moves, and PM checks Google about every 30 seconds while its window is on screen.
- F1 The editor's end can't come before its start, and descriptions keep their line breaks: PR fix(calendar): the editor's end can't come before its start, and descriptions keep their lines → 3.144.2-alpha #904 (merged 2026-10-10)
- F2 Timed events that cross midnight fill the time grid instead of the all-day strip: PR fix(calendar): timed events that cross midnight fill the time grid → 3.144.3-alpha #905 (merged 2026-10-10)
- F3 Changes made in Google show in PM within about 30 seconds: PR feat(calendar): changes made in Google show in PM within about 30 seconds → 3.145.0-alpha #906 (merged 2026-10-10)
- F4 Event colours from Google, filled solid: PR feat(calendar): event colours from Google → 3.146.0-alpha #916 (merged 2026-10-10)
- F5 Ctrl+Z undoes a delete, and a pending delete's Undo survives a reload: PR feat(calendar): Ctrl+Z undoes a delete, and a pending delete's Undo survives a reload → 3.147.0-alpha #917 (merged 2026-10-10)
- F6 A cleared "prepare ahead" stays cleared when its event moves: PR fix(flags): a cleared "prepare ahead" stays cleared when its event moves → 3.147.2-alpha #920 (merged 2026-10-14)
- Found in the second live test: a dev build on a data copy made real scheduled backups; it no longer does: PR fix(backup): a dev build on a data copy makes no scheduled backups → 3.147.4-alpha #921 (merged 2026-10-15)
Live tests owed (22-10-2026)
No live-test results are recorded since the second live test (2026-10-15). The steps are in the local docs/calendar-live-tests-2026-10-10.md: sections 1 to 3, which now hold a part for each merged layer (C9b-1b, C10a to C10c, C9b-2, C11a, C11b, C11d, C12a, C12c). Two matter most:
- P-R2: until it's recorded, release builds refuse "Does not repeat" on a repeating event.
- P-R1 (an all-day repeating event with no time zone): it was C11b's merge blocker, and C11b merged on 22-10 with no result recorded, so release builds already create these.
PR A's, PR B's and PR C's parts are written and wait for those PRs. For PR C, LD1 matters most: it checks that WebKitGTK keeps the pointer on the calendar while dragging, and if it doesn't, every drag is put back. #998 adds one: install the release rpm over your current one on Fedora (rpm -q pm should show the +alpha label).
The Google Calendar checks live on Backlog cards: repeating events (L-R11, the C9a probes, P-R1 to P-R6) on "Check repeating events against Google Calendar, then match it", and creating events (the create spec's G1 to G6, not the guest probes of the same names in the live-tests doc) on "Check creating events against Google Calendar, then match it". The four prerequisite fixes' live tests are in the descriptions of #885, #889, #890 and #891, still unticked.
Out of scope
- Apple calendars stay read-only (CalDAV/EventKit is its own card, "Apple Calendar / Contacts (CalDAV / EventKit)", Stage 4 since the 2026-07-15 reorg).
- No offline queue and no push relay in this epic.
The earlier prerequisite list here (a durable write queue, an incremental mirror first, keeping recurring series locally) isn't needed for an online write-through, so it moves to the offline card. "Calendar — PM correspondence" (deadline projection) now comes after this and reuses its write core.
Activity
fix(connectors): a Google disconnect no longer cuts off another servi…
fix(connectors): Advanced-Protection Google accounts sign in through …
fix(connectors): clearing the Microsoft client also signs out Outlook…
fix(calendar): keys and swipes stand down behind dialogs, and a picke…
fix(scripts): the calendar write fence's test and gate pass the scrip…
feat(calendar): the recurrence core, and iCal series that say how the…
feat(calendar): turn on editing per Google account → 3.140.0-alpha (#894
chore(calendar): the mirror records what editing needs (v57) → 3.140.…
chore(calendar): pure write core for single events → 3.140.2-alpha (#897
feat(calendar): write commands, private Google I/O and fences → 3.141…
chore(calendar): editor building blocks and draft logic → 3.141.1-alp…
101 remaining items
fix(calendar): review round 2 of PR B (#884)
feat(calendar): new events can have guests (C12d of #884)
feat(calendar): saves can carry notifications and colour; a Google la…
feat(calendar): change notifications and colour in the editor (C13b of …
chore(calendar): version 3.156.0-alpha and What's New for guests on n…
fix(calendar): review round 1 of PR A (#884)
chore(calendar): replying to invitations on the backend (C14a of #884)
fix(calendar): review round 2 of PR A (#884)
feat(calendar): reply to invitations from the popover (C14b of #884)
fix(calendar): 3.155.0's What's New no longer says a Busy or Free cha…
feat(calendar): change your own settings on events you are invited to…
fix(calendar): the ghost-state test waits for its effect after Check …
chore(calendar): version 3.157.0-alpha and What's New for invitations (…
fix(calendar): review round 1 of PR B (#884)
fix(calendar): review round 2 of PR B (#884)