Make Apple Health workout recording watch-only

The phone no longer writes estimated Health workouts: the watch, which
runs the live session, is the sole recorder. Replaces WorkoutHealthWriter
with a WorkoutHealthDeleter that only removes a legacy phone-estimate
workout when its record is deleted here, drops the MET calorie table and
the phone's write/read Health scopes, and keeps phoneEstimate decodable
for existing documents.

Claude-Session: https://claude.ai/code/session_01HJDQQDA9QdP8zByg43H5v3
This commit is contained in:
2026-07-08 07:56:19 -04:00
parent 06fa52345b
commit a4ed4df756
9 changed files with 102 additions and 261 deletions
+7 -18
View File
@@ -35,9 +35,8 @@ enum LoadType: Int, CaseIterable, Codable, Sendable {
}
}
/// The kind of training a split represents used to tag the Apple Health workout
/// so it lands in the right category (and credits the rings correctly), and to pick
/// a MET value when the phone has to estimate calories without watch sensor data.
/// The kind of training a split represents used to tag the watch's Apple Health
/// workout so it lands in the right category (and credits the rings correctly).
/// Persisted as its raw `Int` on `SplitDocument`; the `HKWorkoutActivityType`
/// mapping lives in `Shared/HealthKit/HealthKitMapping.swift` to keep this enum
/// HealthKit-free.
@@ -70,23 +69,13 @@ enum WorkoutActivityType: Int, CaseIterable, Codable, Sendable {
case .cycling: "figure.outdoor.cycle"
}
}
/// Metabolic-equivalent value used only for the phone-side calorie estimate
/// (`kcal MET × bodyweightKg × hours`) when no watch metrics are available.
var met: Double {
switch self {
case .traditionalStrength: 5.0
case .functionalStrength: 4.0
case .hiit: 8.0
case .coreTraining: 4.0
case .cardio: 7.0
case .cycling: 7.5
}
}
}
/// Where a workout's health metrics came from: real watch sensors, or a phone-side
/// estimate written when no watch session ran. Persisted in `WorkoutMetrics`.
/// Where a workout's health metrics came from: real watch sensors, or for records
/// written by app versions up to 2.x a phone-side MET estimate made when no watch
/// session ran. The phone no longer writes estimates (recording is watch-only), but
/// `phoneEstimate` is retained so legacy documents on disk still decode. Persisted in
/// `WorkoutMetrics`.
enum MetricSource: String, Codable, Sendable {
case watch
case phoneEstimate