Build 3 — Chain workouts, mid-session add-set, watch HR resilience

Chain multiple workouts into a single session, add another set mid-flow when a planned exercise needs more, repeat-previous now cascades to every uncompleted set, watch HR transport switches to a queued protocol with HealthKit fallback at save time, and a Watch link diagnostics view ships in Settings.

← All changes

Additions

  • Chain workouts. From WorkoutDetailView, queue multiple templates into one session. Warm-up blocks of every template after the first are filtered out so the warm-up isn’t repeated. One HKWorkoutSession, one Strava upload, one summary.
  • Mid-session add-set. Once the planned sets for an exercise are complete, the runner offers an “add another set” affordance; the new SetLog is seeded from the last set’s actuals. The SessionSummary and the “SET N OF M” caption both render the extras correctly.
  • Repeat-previous cascade. Tapping the “Repeat previous ↖” ghost now propagates the previous set’s reps / weight / duration to every uncompleted set in the same exercise (reusing the existing applyRepsToRemainingSets / applyWeightToRemainingSets / applyDurationToRemainingSets propagators).
  • Drill into an exercise from a workout preview. WorkoutDetailView’s exercise rows now tap into ExerciseDetailView (with the existing “Search on YouTube” fallback) so you can scout an exercise before starting.
  • Band preset on WeightStepper. Empty weight cells in EditWorkoutView get a “Band” chip that opens the same Light / Medium / Heavy BandPicker grid the runner uses. No schema or decode changes — Weight.band(String) was already wired end-to-end.

Watch HR resilience

  • HealthKit fallback at save time. The phone now queries HealthKit for HR samples in the workout window and merges them with the live-streamed buffer (dedupe by timestamp), so dropped WCSession messages no longer leave the HKWorkout without a BPM timeline.
  • Queued HR transport. The watch switched from sendMessageData / updateApplicationContext (last-write-wins) to transferUserInfo (queued, ordered, no overwrite) — short reachability drops no longer eat samples.
  • Watch link diagnostics. New WatchLinkDiagnostics service: structured event ring buffer + os.Logger mirror + per-session JSON snapshot. Settings → Diagnostics → Watch link log shows reachability, HR streaming, transport, workout, and save events with category filters and a plain-text Share export.

Tests

Coverage for addSet, previousValues out-of-range fallback, and chained-template synthesis.