Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,10 +19,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Setup mise
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3.5.1
uses: jdx/mise-action@9e7f7633ff6f6d6048a9418a68d48f288f50eb14 # v4.2.3

- name: Build
run: mise run build
Expand All@@ -35,13 +35,13 @@ jobs:
runs-on: macos-15

steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Setup mise
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3.5.1
uses: jdx/mise-action@9e7f7633ff6f6d6048a9418a68d48f288f50eb14 # v4.2.3

- name: Install xcodegen
run: brew install xcodegen

- name: Build iOS
run: mise run ios:build:dev
run: mise run ios:build:ci
34 changes: 28 additions & 6 deletions Sources/BetterFit/BetterFit.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,6 +36,7 @@ public class BetterFit {
// MARK: - State

private var workoutHistory: [Workout] = []
private let workoutHistoryLock = NSLock()

// MARK: - Initialization

Expand DownExpand Up@@ -67,7 +68,13 @@ public class BetterFit {
private func loadPersistedData() async {
do {
// Load workout history
workoutHistory = try await persistenceService.getWorkouts()
let persistedWorkouts = try await persistenceService.getWorkouts()
withWorkoutHistory { currentWorkouts in
let persistedIds = Set(persistedWorkouts.map(\.id))
currentWorkouts = persistedWorkouts + currentWorkouts.filter {
!persistedIds.contains($0.id)
}
}

// Load user profile
if let profile = try await persistenceService.getUserProfile() {
Expand DownExpand Up@@ -138,7 +145,10 @@ public class BetterFit {
autoTrackingService.stopTracking()

// Record in history
workoutHistory.append(workout)
let history = withWorkoutHistory { currentWorkouts in
currentWorkouts.append(workout)
return currentWorkouts
}

// Persist workout
Task {
Expand DownExpand Up@@ -170,7 +180,7 @@ public class BetterFit {
// Analyze and adapt plan if needed
if let activePlan = planManager.getActivePlan() {
let adaptations = aiAdaptationService.analyzePerformance(
workouts: workoutHistory,
workouts: history,
currentPlan: activePlan
)

Expand All@@ -189,7 +199,7 @@ public class BetterFit {

/// Get workout history
public func getWorkoutHistory() -> [Workout] {
return workoutHistory
withWorkoutHistory { $0 }
}

// MARK: - Personal Records
Expand All@@ -207,7 +217,8 @@ public class BetterFit {
public func getPersonalRecords() -> [PersonalRecordEntry] {
var records: [String: (weight: Double, date: Date)] = [:]

for workout in workoutHistory {
let history = withWorkoutHistory { $0 }
for workout in history {
for workoutExercise in workout.exercises {
let name = workoutExercise.exercise.name
for set in workoutExercise.sets where set.isCompleted {
Expand DownExpand Up@@ -274,13 +285,24 @@ public class BetterFit {

/// Schedule smart notifications
private func scheduleWorkoutNotifications() {
let history = withWorkoutHistory { $0 }
notificationManager.scheduleNotifications(
userProfile: socialManager.getUserProfile(),
workoutHistory: workoutHistory,
workoutHistory: history,
activePlan: planManager.getActivePlan()
)
}

// MARK: - Private Helpers

private func withWorkoutHistory<Result>(
_ operation: (inout [Workout]) -> Result
) -> Result {
workoutHistoryLock.lock()
defer { workoutHistoryLock.unlock() }
return operation(&workoutHistory)
}

// MARK: - Health Integration

/// Process motion data from Watch
Expand Down
8 changes: 8 additions & 0 deletions mise.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,6 +79,14 @@ cd ../.. && bash scripts/update_scheme_env.sh 2>/dev/null || echo "⚠️ No .e
cd Apps/iOS && open BetterFit.xcodeproj
"""

[tasks."ios:build:ci"]
run = """
cd Apps/iOS
xcodegen generate
xcodebuild -project BetterFit.xcodeproj -scheme BetterFit -destination 'generic/platform=iOS Simulator' CODE_SIGNING_ALLOWED=NO build
"""
description = "Build iOS for CI without querying or booting CoreSimulator devices"

[tasks."watch:gen"]
run = "cd Apps/iOS && xcodegen generate"

Expand Down
8 changes: 7 additions & 1 deletion scripts/exercise-video-pipeline/generate.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,6 +168,7 @@ normalize_output () {
# Stage 1 — anchors via fal.ai
# ---------------------------------------------------------------------------

main () {
for entry in "${EXERCISES[@]}"; do
slug="$(slug_for "$entry")"
pose="$(pose_for "$entry")"
Expand DownExpand Up@@ -295,4 +296,9 @@ echo " image model: $FAL_IMAGE_ENDPOINT"
echo " video model (default): $FAL_VIDEO_ENDPOINT"
echo " video overrides: ${FAL_VIDEO_OVERRIDES:-<none>}"
echo " anchors: $ANCHORS_DIR"
echo " videos: $VIDEOS_DIR"
echo " videos: $VIDEOS_DIR"
}

if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
main "$@"
fi
21 changes: 5 additions & 16 deletions scripts/exercise-video-pipeline/test_pipeline.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -37,25 +37,14 @@ for s in generate.sh prompts.sh exercises.sh; do
fi
done

# Source the pipeline functions without running the main loop.
# generate.sh is large — extract just the function definitions and
# the override-lookup helper.
# Source the pipeline functions without running the guarded main loop.
echo "==> sourcing function definitions"
TMPF=$(mktemp)
# Strip the executable blocks (everything from the first 'for' loop on
# Stage 1 onwards is a script body, not a function we want to run).
sed -n '1,/^# Stage 2/p' "$PIPELINE_DIR/generate.sh" > "$TMPF"
# Append a no-op so the last function definition closes cleanly.
cat >> "$TMPF" <<'EOF'
exit 0
EOF
if bash "$TMPF" >/dev/null 2>&1; then
if bash -c "source '$PIPELINE_DIR/generate.sh'" >/dev/null 2>&1; then
ok "function definitions source cleanly"
else
bad "sourcing generated function block"
bash "$TMPF"
bad "sourcing generate.sh"
bash -c "source '$PIPELINE_DIR/generate.sh'"
fi
rm -f "$TMPF"

# Source the smaller files directly.
if bash -c "source '$PIPELINE_DIR/prompts.sh' && source '$PIPELINE_DIR/exercises.sh' && exit 0" 2>/dev/null; then
Expand DownExpand Up@@ -169,4 +158,4 @@ fi
# ---- summary --------------------------------------------------------
echo ""
echo "==> summary: $PASS passed, $FAIL failed"
exit "$FAIL"
exit "$FAIL"
Loading