Files
workouts/project.yml
T
rzen 936a585ece Seed starter splits deterministically with immutable clone-on-edit seeds
Starter splits ship as byte-canonical SplitDocument JSON with fixed
ULIDs (Workouts/Resources/StarterSplits, regenerated by
Scripts/generate_starter_splits.swift) and auto-seed after connect into
a verifiably empty container, re-checked after a settle delay — wrong
guesses are harmless because identical bytes make same-path conflicts
empty and tombstones reap resurrected seeds. Seeds are immutable:
SyncEngine.save(split:) forks an edited seed to a fresh ULID and
soft-deletes the original, whose stub is exempt from pruning
(IndieSync 0.3.0 prune(exempting:)) and vetoes resurrection forever;
split views resolve by id through a redirect map to follow the swap.
Add Starter Splits in Settings restores deleted seeds by lifting the
veto stub and rewriting the bundle bytes.

Also fixes ingestFromWatch bypassing the tombstone veto (a phone-deleted
workout resurrected when a stale watch resent it) and reaps a live file
immediately when its tombstone arrives.

SplitDetailView also picks up the category-grouped exercise sections
from the exercise-category work.
2026-07-06 01:16:05 -04:00

146 lines
4.6 KiB
YAML

name: Workouts
options:
bundleIdPrefix: dev.rzen.indie
deploymentTarget:
iOS: "26.0"
watchOS: "26.0"
xcodeVersion: "26.0"
defaultConfig: Debug
settings:
base:
SWIFT_VERSION: "6.0"
DEVELOPMENT_TEAM: ${APPLE_TEAM_ID}
MARKETING_VERSION: "2.1"
CURRENT_PROJECT_VERSION: "1"
ENABLE_USER_SCRIPT_SANDBOXING: "NO"
packages:
IndieAbout:
url: https://git.rzen.dev/rzen/indie-about.git
from: "0.2.2"
IndieSync:
url: https://git.rzen.dev/rzen/indie-sync.git
from: "0.3.0"
Yams:
url: https://github.com/jpsim/Yams
from: "6.0.0"
targets:
# ---- iOS app (owns iCloud Drive sync; embeds the watch app) ----------------
Workouts:
type: application
platform: iOS
sources:
- path: Shared
- path: Workouts
excludes:
- "Resources/Info-*.plist"
- "Resources/*.entitlements"
- path: CHANGELOG.md
buildPhase: resources
type: file
- path: README.md
buildPhase: resources
type: file
- path: LICENSE.md
buildPhase: resources
type: file
dependencies:
- package: IndieAbout
- package: IndieSync
- package: Yams
- target: Workouts Watch App
postBuildScripts:
- script: '"${SRCROOT}/../indie-skills/skills/app-versioning/scripts/update_build_info.sh"'
name: Update Build Info
shell: /bin/sh
basedOnDependencyAnalysis: false
inputFiles:
- $(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)
- $(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Info.plist
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.Workouts
INFOPLIST_FILE: Workouts/Resources/Info-iOS.plist
CODE_SIGN_ENTITLEMENTS: Workouts/Resources/Workouts-iOS.entitlements
GENERATE_INFOPLIST_FILE: false
SWIFT_STRICT_CONCURRENCY: complete
IPHONEOS_DEPLOYMENT_TARGET: "26.0"
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor
TARGETED_DEVICE_FAMILY: "1"
DEVELOPMENT_ASSET_PATHS: "\"Workouts/Preview Content\""
scheme:
testTargets:
- WorkoutsTests
# ---- unit tests (domain model / codec, against the iOS app target) --------
WorkoutsTests:
type: bundle.unit-test
platform: iOS
sources:
- WorkoutsTests
dependencies:
- target: Workouts
- package: IndieSync
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.WorkoutsTests
GENERATE_INFOPLIST_FILE: true
SWIFT_STRICT_CONCURRENCY: complete
# ---- watchOS app (no iCloud; syncs through the phone via WatchConnectivity) -
Workouts Watch App:
type: application
platform: watchOS
sources:
- path: Shared
- path: Workouts Watch App
excludes:
- "Resources/Info-*.plist"
- "Resources/*.entitlements"
dependencies:
- package: IndieSync
- target: Workouts Watch Widget
embed: true
postBuildScripts:
- script: '"${SRCROOT}/../indie-skills/skills/app-versioning/scripts/update_build_info.sh"'
name: Update Build Info
shell: /bin/sh
basedOnDependencyAnalysis: false
inputFiles:
- $(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)
- $(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Info.plist
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.Workouts.watchkitapp
INFOPLIST_FILE: "Workouts Watch App/Resources/Info-watchOS.plist"
CODE_SIGN_ENTITLEMENTS: "Workouts Watch App/Resources/Workouts-watchOS.entitlements"
GENERATE_INFOPLIST_FILE: false
SWIFT_STRICT_CONCURRENCY: complete
WATCHOS_DEPLOYMENT_TARGET: "26.0"
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor
TARGETED_DEVICE_FAMILY: "4"
DEVELOPMENT_ASSET_PATHS: "\"Workouts Watch App/Preview Content\""
scheme:
testTargets: []
# ---- watchOS widget extension (a launcher complication for the watch face) --
Workouts Watch Widget:
type: app-extension
platform: watchOS
sources:
- path: Workouts Watch Widget
excludes:
- "Resources/Info-*.plist"
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.Workouts.watchkitapp.widget
INFOPLIST_FILE: "Workouts Watch Widget/Resources/Info-WatchWidget.plist"
GENERATE_INFOPLIST_FILE: false
SWIFT_STRICT_CONCURRENCY: complete
WATCHOS_DEPLOYMENT_TARGET: "26.0"
TARGETED_DEVICE_FAMILY: "4"