4 Commits

Author SHA1 Message Date
rzen 208fa73f3d Make the iCloud gate patient and branded
Stop giving up on a slow iCloud container: a freshly enabled iCloud Drive
that reports nil while still provisioning is now polled patiently for up
to ~10 minutes instead of failing fast to the "unavailable" screen. A nil
ubiquity token (not signed into iCloud at all) still fails immediately,
and the connecting screen reveals an escape hatch at 28s for users who'd
rather jump to setup than keep waiting.

The connecting and iCloud-required screens are now branded — a purple
gradient with teal accents — and the spinner becomes a custom comet-arc
ConnectingIndicator around an iCloud glyph. Connecting copy escalates
with the wait so a slow first connect reads as steady progress.

Claude-Session: https://claude.ai/code/session_01SCv7zvGFcKy47KSTnTLxRe
2026-06-21 14:37:30 -04:00
rzen 180f07e23c Reflect watch-forwarded workout progress on the phone immediately
ingestFromWatch now upserts the SwiftData cache directly after writing the file,
instead of relying on the NSMetadataQuery observer — a same-process file
overwrite doesn't reliably emit a modified event, so watch progress never reached
open iPhone screens. iCloud Drive stays the source of truth (file written first);
the observer re-applies idempotently if it fires.

Claude-Session: https://claude.ai/code/session_018gg69MaUetDNzWzBXisfMV
2026-06-19 17:17:14 -04:00
rzen 31583c27c7 Add os.Logger diagnostics to SyncEngine.connect() 2026-06-19 14:49:06 -04:00
rzen 85d0eaddbb Workouts 2.0: re-base persistence on iCloud Drive documents
Replace Core Data + NSPersistentCloudKitContainer + App-Group store +
WatchConnectivity dictionary sync with the QuickRabbit iCloud-documents
architecture:

- iCloud Drive JSON documents are the sole source of truth (one file per
  aggregate: Splits/<ULID>.json, Workouts/YYYY/MM/<ULID>.json), with a
  rebuildable SwiftData cache populated only by an NSMetadataQuery observer
  and a connect-time reconcile. Soft-delete tombstones; hard iCloud gate.
- Shared model layer (ULID, Codable *Documents + stateless mappers, @Model
  cache entities, SwiftData container) compiled into both targets.
- New iPhone<->Watch bridge over WatchConnectivity keyed by ULIDs; the phone
  is the sole writer of iCloud Drive, the watch round-trips documents.
- AppServices DI + iCloud-required root gate; Swift 6 strict concurrency.
- Starter splits generated on demand from the bundled YAML catalogs.
- Migrate to XcodeGen (project.yml), iOS 26 / watchOS 26; CloudDocuments
  entitlement (drop CloudKit/App Group/aps-environment).
- Duration stored as Int seconds (was a Date epoch hack); fix workout
  end-on-create, undismissable delete dialog, toolbar-hiding nav stacks,
  and the Settings placeholder.
- Add README/CHANGELOG/LICENSE, .gitignore, refreshed REQUIREMENTS, and the
  Scripts/ TestFlight pipeline (release.sh + ASC API scripts).

MARKETING_VERSION 2.0.
2026-06-19 14:25:27 -04:00