Watch-side follow-through for the End Workout flow:
- The phone now pushes an authoritative set (in-progress, not-started, and
completed within 24h) instead of the 25 most-recent workouts, and the watch
prunes any workout absent from it. So a Discard/Delete (or a completed run aging
out) drops off the watch, empties its active list, and ends the HKWorkoutSession
— fixing the persistent wrist-raise re-foregrounding. The watch never originates
a workout, so pruning can't lose local data; the 24h grace keeps a just-finished
run on screen. The gate pops if the run you're viewing is pruned.
UX tweaks:
- The in-workout ⋯ is now a pull-down Menu (Add Exercise / End Workout) rather than
an action sheet.
- Starting a split while another workout is still active now prompts to end the
current one(s) — keeping their progress — or run in parallel. Wired into both
start paths (the split picker and "Start This Split"), via a shared
WorkoutDocument.endKeepingProgress() helper.
Claude-Session: https://claude.ai/code/session_01SCv7zvGFcKy47KSTnTLxRe
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.
- Migrate from SwiftData to CoreData with CloudKit sync
- Add core models: Split, Exercise, Workout, WorkoutLog
- Implement tab-based UI: Workout Logs, Splits, Settings
- Add SF Symbols picker for split icons
- Add exercise picker filtered by split with exclusion of added exercises
- Integrate IndieAbout for settings/about section
- Add Yams for YAML exercise definition parsing
- Include starter exercise libraries (bodyweight, Planet Fitness)
- Add Date extensions for formatting (formattedTime, isSameDay)
- Format workout date ranges to show time-only for same-day end dates
- Add build number update script
- Add app icons