Skip to content

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
BBYU26 merged 8 commits into
fix/sidecar-pillow-13from
chore/calendar-split-journal
Oct 22, 2026
Merged

BBYU26 merged 8 commits into
fix/sidecar-pillow-13from
chore/calendar-split-journal

Conversation

@BBYU26

@BBYU26 BBYU26 commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #884. C9a-3b-2, the second half of C9a-3b: a "this and following" change now survives PM closing halfway, and PM won't stack another change on a series that an earlier split still overlaps. 3.148.8-alpha. Stacked on #968 (this week's security advisories): the base is fix/sidecar-pillow-13, and there's no closing link while the base isn't main. Still inert for users: release builds refuse every repeating-event write until C9b-1b's dialog.

What it does

Remembers a split while it runs. Before its first write to Google, a "this and following" change is recorded in the encrypted settings store (calendar_split_journal: Google's ids, the plan digest, the original's repeat rule before and after the cut, and its start; never a title or description). The record goes once the change lands or is settled. If PM closes halfway, the next look at that event reads the record against what Google holds now:

  • The change landed (the original holds the cut rule) and had occurrences to move: said once ("occurrences you changed on their own may not have moved… check them in Google Calendar"), then forgotten.
  • The original was never cut and still repeats past the split: it shows twice. PM refuses every change that reaches it and points to Google Calendar. After a restart PM never deletes anything and offers no delete, not even of the duplicate (your Q4 answer, as narrowed by critique 1 H1).
  • The rule was changed in Google since, or nothing overlaps any more: said once, then forgotten.
  • PM can't read Google right now: refuses what it reaches, and keeps the record.

The overlap backstop. Every series read now also lists the parts PM split off it (privateExtendedProperty=pmSplitOf=…). If one still overlaps the original, or PM couldn't list them, "This and following" and "All events" refuse; "This event" stays open. It measures from the occurrence each part was split at, which a new part now carries in a private pmSplitAt note.

Reviews

Seven rounds, each finding checked by a skeptic, every fix pinned by a test checked by mutation. They found:

  • a "shows twice" reading made from the repeat rule alone (the original's occurrences could have been deleted one by one in Google);
  • the original's exceptions left unread on one side;
  • two unrelated writes hiding a record;
  • the order of the "this change is running" mark;
  • three wrong readings of the overlap (an extra date earlier on the split day, a part moved later that day, a part moved to a later day), settled by measuring from the split occurrence itself.

One low limit kept (in the design doc): if the split occurrence had itself already been moved on its own, and nothing of the original follows it in the window, a crash mid-split reads "changed" rather than "shows twice". Counting it would refuse forever after a clean split that left it behind, which is worse. PM deletes nothing either way.

Checks

The full just check passes at the tip: 2,094 Rust tests and 2,005 frontend tests, plus clippy, fences and audits.

Live test (optional, once merged, dev build)

Probe R2 in the "C9a probes" section of docs/calendar-live-tests-2026-10-10.md, run after W4. It confirms Google accepts the parts filter. If Following/All refuse with "PM couldn't check for a part it split off", Google rejected it: tell me.

Moved 21-10-2026: the dependency advisories now live in #968

The certificate fix that sat here (4dda153, 20-10) moved into #968, together with this week's Pillow advisories, and this PR now stacks on it. It is renumbered 3.148.8-alpha, and its own changes are unchanged (range-diff: every commit identical apart from its version lines). The full just check passes on the rebased branch (c676088), including deny and pip-audit.

🤖 Generated with Claude Code

Copilot AI balanced review requested due to automatic review settings October 18, 2026 20:55
@BBYU26 BBYU26 added enhancement New feature or request rust Pull requests that update rust code labels Oct 18, 2026
@BBYU26 BBYU26 self-assigned this Oct 18, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

BBYU26 and others added 8 commits October 21, 2026 16:18
…an earlier split still overlaps → 3.148.7-alpha (C9a-3b-2 of #884)

A "this and following" change is now recorded in the settings store before
its first write (calendar_split_journal: Google's ids, the plan digest, the
original's rule before and after the cut, its start) and forgotten once it
lands or settles. A record no held split stands for (PM restarted) is read
against Google's copies by meaning: a proven duplicate refuses what it reaches
but lets "All events" delete on the new part through; a landed or changed one
is said once and forgotten; one PM can't read refuses until it can.

Every series read now also lists the parts PM split off it
(privateExtendedProperty=pmSplitOf); one that still overlaps the original
refuses every scope past "this event" (scope-M4), as does a listing PM
couldn't read.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…riginal's occurrences; one claim doesn't hide a record

Review round 1 of C9a-3b-2, and the decided Q4 (DECISIONS 18-10): a proven
duplicate only refuses, its words pointing to Google Calendar; no "All
events" delete is let through. A Twice reading also needs the original
still repeating from the split on, read off its occurrences as the backstop
reads them (the planned series' parts, or a window listing of the original);
otherwise it is said once as changed. A record is skipped as a running
change's only while both its series are claimed.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… mark running splits explicitly

Review round 2 of C9a-3b-2. Reading the original from its new part now lists
its exceptions and cross-checks them as gather does, so an occurrence changed
on its own and left on it never counts as the rule repeating. A record is a
running change's only while that send or settle has marked it in
CalendarEditState.splitting; two unrelated writes holding both series no
longer hide it.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ice needs whole exceptions on both sides

Review round 3 of C9a-3b-2. The running mark now goes on before the send
writes its record and before a settle takes its split out of the held ones,
so no look meets a record with neither. Read from the original itself, a
twice reading also needs its exceptions listed whole, as from the new part.
Tests pin both marks and their removal, and both unread cases.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 4 of C9a-3b-2: an extra date earlier on the split day stays on a
cut original, and comparing days read it as overlapping the new part,
refusing every change past this occurrence on a split that finished cleanly.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ences, by day

Review round 5 of C9a-3b-2: comparing instants missed an uncut original's
occurrence on the split day when the new part was retimed later that day,
and still read an extra date as overlapping when the part moved earlier.
Back to days, with the original's extra dates (RDATE) left out beside its
stored exceptions; parts_overlap takes the master.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rt was split at

Review round 6 of C9a-3b-2: measured from the new part's start, a part moved
to a later day hid an uncut original whose last occurrence in the window was
the split occurrence itself (a yearly event, the last of a COUNT). A new part
now carries a private pmSplitAt note (with PM's other notes, ignored in every
comparison), and an original overlaps while it has a live occurrence at or
after that point. A cut ends it before, wherever the part moved; an extra date
kept earlier that day is before it. Parts without the note fall back to their
start. The RDATE exclusion is no longer needed and goes.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Renumbered above #968's 3.148.7-alpha now that this PR sits on it; the dependency commit it carried is in #968.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@BBYU26 BBYU26 changed the title chore(calendar): remember a split while it runs, and refuse a series an earlier split still overlaps → 3.148.7-alpha (C9a-3b-2 of #884) 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) Oct 21, 2026
@BBYU26
BBYU26 changed the base branch from main to fix/sidecar-pillow-13 October 21, 2026 15:37
@BBYU26
BBYU26 force-pushed the chore/calendar-split-journal branch from 4dda153 to c676088 Compare October 21, 2026 15:37
BBYU26 added a commit that referenced this pull request Oct 21, 2026
Renumbered above #959's new 3.148.8-alpha now that the stack sits on #968.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@BBYU26
BBYU26 added this pull request to stack #975 October 22, 2026 02:51
@BBYU26
BBYU26 merged commit 83afc17 into main Oct 22, 2026
17 checks passed
@BBYU26
BBYU26 deleted the chore/calendar-split-journal branch October 22, 2026 03:23
BBYU26 added a commit that referenced this pull request Oct 22, 2026
…3.148.9-alpha (C9b-1a of #884) (#960)

* chore(calendar): the repeating-event dialog's parts, not yet shown → 3.148.8-alpha (C9b-1a of #884)

The "which occurrences?" dialog for a repeating event is built and
tested but not mounted: the pure rules and words (saveChoices.ts), the
SaveChoicesDialog, the store's choices, scoped writes and settling in
useEventWrites, and settle buttons on WriteNotices. Repeating events
stay read-only and release builds still refuse scoped writes.

Backend: a one-off Google has turned into a series is read-only with
its own reason (BecameRepeating) on every path; a delete's choices that
meet a changed occurrence land Google's copy; every orphan's words are
said; a settle that leaves the change held answers PartialSplit with a
note, so its buttons stay; one release gate for a missing choice,
pinned by a source test; no jargon in what rows show.

The one visible change: the became-repeating reason's wording.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(calendar): a save always names its event; refusals in the dialog are announced; notices wrap only with settle buttons

Review round 1 of C9b-1a: saveEdit's title is required, so a partial
notice can't read "(no title)"; the choices dialog's refusal, which arrives
after it opened, is a live region whatever its tone; only a notice with settle
buttons wraps them under its words, so other notices look as before; a settle
with no answer keeps its notice's own offers (now tested); and the What's New
line no longer says the event was made in PM.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(calendar): a settle Google turned away says the change was put back

Review round 2 of C9b-1a: PM's own claim now reaches a settle as a held change
with a note, so a plain busy answer only comes from Google refusing Finish's
next step, after which PM took the new part back. Its words said PM was still
changing the event; they now say it was put back as it was.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: 3.148.9-alpha, after the advisories PR #968

Renumbered above #959's new 3.148.8-alpha now that the stack sits on #968.

Part of #884

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants