Repository navigation
Cancelled and moved single changes ring where the views show them (PR 7a) - #117
Merged
Merged
Conversation
… 7a, 209, 214)
The reminders expanded every series on its own and applied none of its
single changes. A cancelled occurrence kept ringing at its slot (Google keeps
every deleted occurrence as such a row, so with PR 7 every deleted
occurrence of a new series would have rung), and a moved one rang twice: at
its old slot through the series and at its new time through its own row,
on CalDAV, Google and Exchange alike.
Now every `{series}::rid::{slot}` row takes its slot out of its series before
it expands (override_slots, without_overridden_slots), as the views drop it
(expandAll): matched exactly on a timed series, by the day it names on a
series of days. A slot that does not read is left alone. A cancelled row
still rings nowhere; a whole cancelled series stays silent.
eventOccurrences.json: five rows the reminders differed on now agree and move
to AGREEING; the contract runner folds the slots the same way. A direct test
through event_triggers. Red: without the fold, both fail.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… by its day (215) EWS reports an occurrence's OriginalStart as midnight in the mailbox's zone. The series' own exceptions were already re-anchored to the local midnight of that day, but the override id kept the raw instant. Read by the day it is nearest to, as the views and now the reminders read an all-day slot, it named the neighbouring day wherever the mailbox's zone lies more than twelve hours from the device's (a New York mailbox in Tokyo, or a UTC-midnight series in Auckland's summer): the views hid that day already, and the fold of #117 would have silenced its reminder. - adapter-ews: override_slot mints the id from the anchored instant on an all-day series; names_override lets writing find the exception by either spelling, so an id minted before still resolves. - Cache generation 7 re-reads every account once, so cached rows carry the new ids. A colour set on an all-day Exchange single change is lost once. - The contract table's header and the TODO note no longer say the reminders apply no single changes; Exchange never rang twice for a moved occurrence (its series already listed the slot), so the claim names CalDAV and Google. - ews.md documents the slot. Red: with the raw slot in the id, the new test fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ne (216) The anchored slot of 215 is this device's local midnight. What that changed: - adapter-ews delete_series_occurrence reads the server's slot of an all-day series as the read anchors it before it compares. Deleting, cancelling or moving one day failed beyond six hours from the mailbox's zone (for plain occurrences before 215 too); a move left a duplicate. The target itself is never re-read, so a midnight east of UTC+12 keeps its day. - The events token names the device's zone besides the zone translation, so a device that moved reads the folder again and its ids, starts and exceptions follow. names_override stays exact: a slot from another zone is refused, never read as a guessed day. - cal-core plan_repairs: a row bound to one occurrence follows its override when that is minted again, and is never promoted to the series, which recoloured every other occurrence. Helps CalDAV and Google remints too. - host-core SoundPrefs: a single change without a sound of its own rings with its series' (the key the desktop writes). - TODO and ews.md say so. Red: each of the four is caught when sabotaged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… zone (217) An all-day Exchange item's instants are midnights in its own zone. The 12-hour sample that recovered the day reads a midnight east of UTC+12 as the day before, and the delete of 216 trusted it: in an Auckland mailbox in New Zealand's summer, deleting one day of a daily all-day series deleted the next. Now: - adapter-ews all_day_zone: the item's start zone, read as its series' zone is (read_series_zone), UTC for a series made without one. all_day_anchor reads the day in it; only where Exchange names no zone Aperio can read is the day sampled. The start, the exceptions, single changes' rows and their id slot all read it. - delete_series_occurrence compares the server's slot as read in the series' zone, so a neighbour, a whole day away, never comes within the tolerance. Without a zone it compares the raw instants, as before 216, and aborts rather than trust a sampled day. - cal-core plan_repairs reads an all-day start's day twelve hours into it, so a row signed in Berlin finds its day after the device moved to New York instead of missing it or taking the day before. - The misplaced test doc comment is back on its test; DESIGN §14.4 and the sound module name the series fallback; ews.md and TODO describe 217. Red: the anchor ignoring the zone, the delete comparing raw instants, the delete sampling the day, and the repair reading the UTC date are each caught. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed zone - adapter-ews all_day_anchor samples the day twelve hours into it in the zone Exchange names, not by its exact date there. After Aperio's own write of an Outlook all-day item (UTC midnights, no zone) Exchange keeps the old zone's midnights and labels them UTC (live round 3, T2): read by the exact date, the item jumped back a day right after its drag and its reminders rang a day early. The sample holds for a label up to twelve hours off and for any offset the zone has, Auckland's summer included. - An exception's before copy, read through a shape without zones, takes its series' zone as its row does (WriteTarget::series_zone); read without one, an untouched all-day slot counted as moved and a rename wrote it back. - cal-core starts_the_same reads an all-day day 13:45 into the instant: its own day for any zone in (-10:15, +13:45], so New Zealand's summer, the Chatham Islands and London keep their days across zones and at every change of clocks; twelve hours in, New Zealand's summer named the day before and its first summer day shared a key with the last winter day. - Docs: the repair's doc comment, TODO (the London item is fixed), ews.md. Red: the exact date, the before copy without its series' zone, and repairs read twelve hours in are each caught. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…midnight - adapter-ews all_day_anchor samples 13:45 into the day, the window cal-core's anchor repair reads days in: exact for a midnight the named zone gives, and the intended day for a relabelled item from any zone in (-10:15, +13:45]. Twelve hours still read an Auckland item dragged in New Zealand's summer as the day before. - A device zone that skips midnight that day gets the first hour after it, as the doc said and as the views place the day, not the raw instant. - The new repair test's comment names Berlin's January midnight right. - TODO names the window, and the open phone-only per-occurrence sound key that a re-minted id loses. Red: twelve hours in, the Auckland relabel is read a day early. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The delete path's comment and the relabelled-item test's doc name the sample 13:45 into the day, as the code reads it since the fifth check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR 7a of the arc "exceptions when splitting a series": cancelled and moved single changes now ring where the views show them (decisions 209 and 214).
Why
The reminders (
host-core, used by both desktop and phone) expanded every series on its own and applied none of its single changes ({series}::rid::{slot}rows). The views drop a series' occurrence wherever such a row stands in for it (expandAll). The contract table recorded the difference assurfacesDifferon five rows.to_event).What changes
override_slotscollects, per series, the slots its override rows stand in for. Cancelled and moved rows both count, and the slot is read withcal_core::split_override_id.without_overridden_slotsadds those slots to the series' exceptions before it expands. The expansion then matches them as it matches its own exceptions: exactly on a timed series, and by the day they name on a series of days (decision 95).Contract
shared/contracts/eventOccurrences.json: five rows now agree and lose their own reminders answer:a-moved-occurrence-stands-in-for-its-slota-cancelled-occurrence-removes-its-slota-moved-occurrence-of-a-zoned-series-after-the-changean-override-slot-in-another-spellingan-override-listed-before-its-seriesThey move from
DIFFERINGtoAGREEINGin the Rust contract, and the contract runner folds the slots the same way. The TS anti-silence list names the two override rows it did not name yet.Tests
a_single_change_takes_its_slot_out_of_the_seriesruns throughevent_triggerswith a weekly series, a cancelled occurrence, and a moved occurrence whose slot is spelled with an offset. Only the series' other occurrences and the moved one at its new time ring.every_row_holds_for_the_remindersboth fail.cargo test --workspace, tsc desktop and mobile, eslint, bridges, and vitest (2377) pass.First check (90dd625)
Three finders, two skeptics per finding, and a completeness critic. One finding mattered, plus doc corrections:
Exchange all-day single changes (decision 215).
OriginalStartas midnight in the mailbox's zone. The series' exceptions were already re-anchored to the local midnight of that day, but the override id kept the raw instant.override_slot). Writing finds the exception by either spelling (names_override), so an older id still resolves.Doc corrections.
ews.mddocuments the slot.Runs:
quickAddOfferCalendarfile (9 failures), which passes alone 10/10. This round changed no TypeScript, and the existing task covers that flake.Second check (6a6a16c)
The anchored slot is this device's local midnight. Six findings followed from that, and decision 216 fixes them:
delete_series_occurrencenow reads the server's slot as the read anchors it before it compares. Before, deleting, cancelling or moving a day failed beyond six hours from the mailbox's zone, and a move left a duplicate. Plain occurrences had the same failure before 215. The target is never re-read, so a midnight east of UTC+12 keeps its day.names_overridestays exact: a slot from another zone is refused, never read as a guessed day.cal_core::plan_repairs, a row bound to one occurrence follows its override when that override is minted again. It is never promoted to the series, which used to recolour every other occurrence. This also covers CalDAV and Google remints.Red proofs: each of the four is caught when sabotaged.
Runs: all gates pass, including vitest 2377 in both runs.
Third check (f36b11a)
Four findings were confirmed. They all came from the 12-hour sample, which reads a midnight east of UTC+12 as the day before, so decision 217 replaces the guess:
all_day_zonetakes the item's start zone, read the way its series' zone is read, and UTC for a series made without one.all_day_anchorreads the day in that zone. The start, the exceptions, single changes' rows and their id slot all go through it. Only where Exchange names no readable zone is the day still sampled.delete_series_occurrencecompares the server's slot as read in the series' zone, so a neighbour, a whole day away, never comes within the tolerance. With 216, deleting one day of a daily all-day series in an Auckland mailbox in New Zealand's summer deleted the next day. Without a zone, the raw instants are compared, as before 216, and the delete aborts rather than trust a sampled day.plan_repairsreads an all-day start's day twelve hours into it. A row signed in Berlin now finds its day after the device moved to New York, instead of missing it or taking the day before.Red proofs:
Each one fails.
Runs: all gates pass, including vitest 2377 in both runs.
Fourth check (c05e3b5)
Five findings were confirmed, and all are fixed:
all_day_anchorsamples the day twelve hours into it in the zone Exchange names, instead of taking its exact date there.WriteTarget::series_zone). Before, an untouched all-day slot counted as moved, and a rename wrote it back.cal_core::starts_the_samereads an all-day day 13:45 into the instant. That gives every zone in (−10:15, +13:45] its own day: New Zealand's summer, the Chatham Islands and London keep their days across zones and at every change of clocks. Read twelve hours in, New Zealand's summer named the day before, and its first summer day shared a key with the last winter day.ews.mdare updated.Red proofs: each of these is caught:
Runs: all gates pass, including vitest 2377 in both runs.
Fifth check (08a544a)
One doc typo was confirmed and fixed: a repair test's comment gave the wrong time for Berlin's January midnight. Two split findings were taken as well:
all_day_anchornow samples 13:45 into the day, the window cal-core's anchor repair reads days in. That is exact for a midnight the named zone gives, and the intended day for a relabelled item from any zone in (−10:15, +13:45]. Twelve hours still read an Auckland item dragged in New Zealand's summer as the day before. Red proof: at twelve hours, the Auckland relabel test fails.Noted in TODO, not changed: only the phone stores a sound for one occurrence, under that occurrence's id. A re-minted id loses that sound.
Runs: all gates pass.
Sixth check (2593a71)
No code findings. Two comments still said "twelve hours"; both now say 13:45, as the code reads.
Docs
TODO: a PR 7a entry, and the contract note that lists where the surfaces differ is corrected.
🤖 Generated with Claude Code