feat(62): iOS background refresh — BGAppRefreshTask + bounded sync#41
Merged
Conversation
Four failing tests for BackgroundRefreshCoordinator.performBackgroundRefresh(): (a) triggers one sync and returns true on success (b) returns false when provider times out (c) completes within budget even when provider blocks (d) returns false without calling sync when unpaired BackgroundRefreshCoordinator does not exist yet — all four tests fail with "cannot find 'BackgroundRefreshCoordinator' in scope". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add BackgroundRefreshCoordinator: races one FizzySyncProvider.triggerSync() cycle against a configurable time budget (25 s production, 0.1 s tests) using TaskGroup. Returns true on success, false when unpaired or timed out. iOS-only wiring in FenixKanbanApp via .backgroundTask(.appRefresh(…)) scene modifier. Reschedules on each task completion and on every scenePhase → background transition. submitBackgroundRefreshRequest() is nonisolated static to avoid Swift 6 actor-isolation warnings from the backgroundTask closure. Info-Partial.plist: add BGTaskSchedulerPermittedIdentifiers + UIBackgroundModes += fetch (iOS only — macOS build verified clean: no UIBackgroundModes entries, no BGTaskSchedulerPermittedIdentifiers key). Add docs/runbooks/background-refresh-verification.md: LLDB simulation recipe, prerequisites (Background App Refresh on, Low Power Mode off, not force-quit), macOS plist-leak verification steps, Xcode 27 beta note for Susanoo. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Guard scenePhase-driven scheduler activation + BGTaskScheduler submits behind the XCTest env check (same detection PersistenceController uses). A 300s scheduler tick firing inside a long CI test phase races the suites — matches the 302s runner crash on this PR's CI run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # FenixKanban/FenixKanbanApp.swift
The 300s Task.sleep spy outlived suite teardown on starved CI runners (watchdog crash-restart, zero failing tests, 4 burned runs). The spy now blocks on a continuation released by the coordinator's cancelAll. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds iOS background refresh so the board is fresh when the Captain opens FK on iPhone.
BackgroundRefreshCoordinator— races oneFizzySyncProvider.triggerSync()cycle against a configurable time budget (25 s production) using TaskGroup; returns true on success, false when unpaired or timed out. Never throws.BGAppRefreshTask(com.bluefenixproductions.FenixKanban.fizzy-refresh) intoFenixKanbanAppvia.backgroundTask(.appRefresh(…))scene modifier (iOS-only,#if os(iOS)gated). Reschedules on each task completion and on scenePhase → background.Info-Partial.plist: addBGTaskSchedulerPermittedIdentifiers+UIBackgroundModes += fetch. macOS build verified clean: emptyUIBackgroundModes, noBGTaskSchedulerPermittedIdentifierskey.docs/runbooks/background-refresh-verification.md: LLDB simulation recipe, prerequisites, macOS plist-leak verification steps, Xcode 27 beta note for Susanoo.Test plan:
BackgroundRefreshTests.swift(all GREEN): (a) triggers one sync + returns true, (b) returns false on timeout, (c) completes within budget when provider blocks, (d) returns false when unpaired.generic/platform=macOS, no signing): BUILD SUCCEEDED, zero errors/warnings in new code.docs/runbooks/background-refresh-verification.md.Mission: #28 · Status log: #62
🤖 Generated with Claude Code