Every write sampled ZoneId.systemDefault() and stamped it into EVENT_TIMEZONE, so the column was real but only ever held the device's zone: an event synced from elsewhere could be read in its zone, never authored in one. Give EventForm a nullable `timezone`, where null keeps meaning "the device zone at save time" — so every existing call site behaves exactly as before — and a non-null value pins the event to a zone it then tracks across DST. toWriteTimes resolves the form's zone ahead of the device's; toEditForm pins only when the stored zone differs from the device's, and prefills such an event in its own zone so the form shows the wall-clock the event actually means. Two provider-contract bugs fall out of this: - Editing the time of a foreign-zone event rewrote EVENT_TIMEZONE to the device's. The instants stayed right, so nothing looked wrong, but the event silently stopped tracking its zone and would drift an hour at the next DST boundary. Only the timesChanged gate spared title-only edits. - A zone change with an untouched wall-clock is still a time change (the same 09:00 elsewhere is a different instant), so it now trips timesChanged and rewrites DTSTART instead of being dropped. All-day events keep carrying no zone at all: they're date-anchored, and the UTC midnights they normalise to are an anchor rather than a location. TimeZoneCatalog is pure JVM so the search ranking and DST-aware offsets stay plain JUnit tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Documentation map
Where to look for what:
| Document | What it is |
|---|---|
ARCHITECTURE.md |
Orientation tour: principles, layers, navigation, recurring-write / conflict / reminder pipelines, testing |
../CHANGELOG.md |
Release history (Keep a Changelog, SemVer) |
../.planning/ROADMAP.md |
Living roadmap: shipped milestones, current scope, idea backlog |
../.planning/PROJECT.md |
What the project is, stack, naming, infrastructure |
../.planning/REQUIREMENTS.md |
Requirement checklist per milestone |
../.planning/STATE.md |
Snapshot of where development currently stands |
superpowers/specs/ |
The original design spec (2026-06-08) — historical record, not updated |
superpowers/plans/ |
Per-milestone implementation plans with task checklists — historical record of how each slice was built, including provider lessons learned |
../fastlane/metadata/android/ |
Store metadata (single source of truth): descriptions, title, icon, screenshots (DE + EN). Harvested directly by the official F-Droid repo; transformed into the self-hosted repo layout at release time by ../scripts/fastlane_to_fdroid_localized.sh |
../fdroid-metadata/ |
App-level F-Droid control file (*.yml: Categories, License, links) for the self-hosted repo's fdroid update |
fdroid-official/ |
Draft recipe + notes for publishing to the official F-Droid repo (reproducible build + developer-signed binary) |
Conventions: plans and specs under superpowers/ are point-in-time
artifacts of the agentic workflow that built each milestone — they get
status updates but are never rewritten. The .planning/ files are living
documents and should stay current.