Reconcile starter seeds on connect and add restore + duplicate cleanup

Seeding now covers existing installs, not just empty containers: after the
same settle delay as auto-seed, connect() branches to reconcileSeeds(),
driven by a pure tested planner — upgrade an older seed revision in place
(safe: clone-on-edit guarantees no user content at seed ULIDs), skip
up-to-date/quarantined files, respect delete-veto stubs, and write missing
seeds unless a same-name legacy split exists. Settings gains Restore
Starter Splits (the one deliberate veto lift, writing current bundle
bytes) and a dev duplicate-cleanup tool backed by a fail-closed scanner.
The HealthKit estimate now follows the clone redirect when resolving a
workout's split.

Claude-Session: https://claude.ai/code/session_01LEoff8bXGBS83tK1c55Mf7
This commit is contained in:
2026-07-06 16:29:59 -04:00
parent 2c1e4759ae
commit 7586edd878
10 changed files with 1344 additions and 152 deletions
+8 -2
View File
@@ -172,9 +172,15 @@ final class WorkoutHealthWriter {
}
}
/// The split's configured activity type, following the seed clone-on-edit
/// redirect (the estimate can run seconds to hours after the workout, so the
/// split may have forked in between). Generic strength when the split is gone.
private func activityType(for doc: WorkoutDocument) -> WorkoutActivityType {
if let splitID = doc.splitID, let split = CacheMapper.fetchSplit(id: splitID, in: context) {
return split.activityTypeEnum
if let splitID = doc.splitID {
let resolved = syncEngine?.currentSplitID(for: splitID) ?? splitID
if let split = CacheMapper.fetchSplit(id: resolved, in: context) {
return split.activityTypeEnum
}
}
return .traditionalStrength
}