diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a64bb6b..742dfa9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,11 +8,17 @@ on: jobs: test: - runs-on: macos-15 + # Needs macOS 26 host: Xcode 26's `actool` invokes AVFCore-backed + # `ibtoold` for `.icon` asset compilation, which dyld-fails on macOS 15 + # because of missing CoreMedia symbols (e.g. `_kFigCaptionRegionDisplayAlign_Before`). + # `swift build` and `swift test` worked on `macos-15` once xcode-select + # pointed at Xcode 26.3, but the app's asset catalog needs the OS frameworks. + runs-on: macos-26 steps: - uses: actions/checkout@v4 - name: Select Xcode - run: sudo xcode-select -s /Applications/Xcode_16.app + # mlx-audio-swift requires swift-tools-version:6.2 (Xcode 26). + run: sudo xcode-select -s /Applications/Xcode_26.3.app - name: Build core run: swift build - name: Test core @@ -20,8 +26,8 @@ jobs: - name: Build app run: | xcodebuild \ - -project TranscriberApp/TranscriberApp.xcodeproj \ - -scheme TranscriberApp \ + -project TranscriberApp/Scribe.xcodeproj \ + -scheme Scribe \ -configuration Debug \ -destination 'platform=macOS' \ build \ diff --git a/Sources/TranscriberCore/Calendar/CalendarWatcher.swift b/Sources/TranscriberCore/Calendar/CalendarWatcher.swift index ccc503a..793378e 100644 --- a/Sources/TranscriberCore/Calendar/CalendarWatcher.swift +++ b/Sources/TranscriberCore/Calendar/CalendarWatcher.swift @@ -68,9 +68,18 @@ public actor CalendarWatcher { } } - public func stop() { - pollTask?.cancel() + /// Cancels the poll loop and awaits its termination. The previous sync + /// variant returned before the in-flight `refreshNow()` had finished, so + /// `stop()` could complete and a stale poll iteration would still bump + /// the lookup callout afterward — visible on slower hardware as a + /// flaky `testStopCancelsPollLoop`. By awaiting `task.value` here, any + /// in-progress refresh is allowed to drain before `stop()` returns and + /// no further polls can happen for this watcher instance. + public func stop() async { + let task = pollTask pollTask = nil + task?.cancel() + await task?.value } /// Forces an immediate refresh outside the regular cadence. Called on