Skip to content

feat(ios): add background and long-running sync Shortcuts - #370

Draft
devnoname120 wants to merge 2 commits into
OpenStrap:mainfrom
devnoname120:feat/ios-sync-shortcut
Draft

devnoname120 wants to merge 2 commits into
OpenStrap:mainfrom
devnoname120:feat/ios-sync-shortcut

Conversation

@devnoname120

@devnoname120 devnoname120 commented Sep 13, 2026

Copy link
Copy Markdown

Purpose

Expose explicit band-sync actions for Shortcuts and personal automations without requiring the Edge interface to open. These provide additional synchronization opportunities; they do not guarantee that iOS will run or finish every scheduled invocation.

Changes

  • Sync Data starts real BLE synchronization through the existing commit-before-ACK persistence path. Its 25-second native deadline includes waiting for Flutter readiness. Open Edge and Sync provides an interactive alternative.
  • Ignore Connectivity Errors, disabled by default, returns a successful Skipped: result only for Bluetooth unavailable or the paired band being unreachable. Missing pairing, denied permission, unfinished accessory setup, storage, startup, and other failures still produce errors. This option does not suppress independent iOS/Shortcuts notifications or system progress UI.
  • Retain one headless-capable Flutter engine, wait for an explicit Dart readiness handshake, and correlate requests and replies. Overlapping requests respect existing BLE ownership. Cancellation ignores late replies, preserves committed data, and does not disconnect an independent app-owned session.
  • Sync Data (Long Running) uses LongRunningIntent and CancellableIntent on iOS 27 with Xcode 27 or later. It reports saved-batch progress without inventing a percentage and has an application-imposed ten-minute ceiling, not a guaranteed runtime grant. The ordinary action supports iOS 16 and later; the application deployment target is unchanged.
  • Add regression coverage, the separate ShortcutIntents system-invocation test scheme, and guides/IOS_SHORTCUTS.md.

Results distinguish completed transfer, partial progress, an existing request, and skipped connectivity failures. Starting asynchronous work is not reported as completed synchronization.

Separate commits

Commit Scope
b53cdc2 Bounded Shortcuts, shared sync infrastructure, selective error suppression, tests, and documentation.
d99a630 Long-running intent, progress/cancellation, and additional tests/documentation.

Long-running support is deliberately isolated so it can be moved to a separate stacked PR. It depends on the shared infrastructure in the first commit.

Recorded validation

Check Result
Selected Dart regression tests 99 passed.
Targeted Dart analysis No issues found.
iOS 27 native tests 13 passed.
iOS 27 AppIntentsTesting system-invocation tests 4 passed.
iOS 26.5 native compatibility tests 9 passed; 4 iOS-27-only tests skipped.
Signed physical-device Release build Built, installed, and launched on an iPhone 16 Pro Max running iOS 27.

System-invocation tests cover background execution, relaunch after termination without opening a window, the foreground fallback, and long-running invocation. Clean-simulator integration tests reach the real Flutter bridge and expect a missing-pairing error; they do not establish successful Bluetooth transfer.

Physical-device installation used ignored local identity overrides to keep the existing installation and App Group separate. Those overrides are not included in these commits.

Remaining device validation

Keeping this PR in draft until real-band and unattended-automation testing is complete:

  • Verify incremental synchronization and a larger backlog on a paired WHOOP.
  • Verify connectivity-error suppression, cancellation/timeout recovery, and overlapping UI/Shortcut requests with the real band.
  • Test scheduled personal automations while locked and after force-quitting Edge, separately from Bluetooth state restoration.

The device installation check did not pair a band or invoke synchronization.

Summary by Sourcery

Expose reliable, bounded iOS Shortcut synchronization for paired bands, including optional long-running execution on iOS 27, while preserving truthful results and shared BLE ownership.

New Features:

  • Add iOS Shortcuts actions for on-demand and interactive band synchronization without opening the Edge interface.
  • Add an iOS 27 long-running sync action with cancellable execution and truthful saved-batch progress.

Bug Fixes:

  • Prevent Shortcut invocations from reporting successful synchronization when work is only started, incomplete, cancelled, or fails due to pairing, permissions, storage, or startup issues.
  • Preserve sync ownership, durable data, and cleanup behavior across overlapping requests, cancellation, deadlines, and app-owned sessions.

Enhancements:

  • Share a headless-capable Flutter engine and synchronization bridge across foreground, background, and Shortcut execution paths.
  • Support selective suppression of only Bluetooth-unavailable and unreachable-band errors through the Shortcut option.

Build:

  • Add the ShortcutIntents Xcode test scheme and associated iOS project configuration.

Documentation:

  • Document iOS Shortcut setup, results, lifecycle behavior, long-running execution, and device validation guidance.
  • Update the README to reference unattended band synchronization through iOS Shortcuts.

Tests:

  • Add Dart, native iOS, and AppIntents system-invocation regression coverage for readiness, concurrency, cancellation, deadlines, progress, error classification, and app lifecycle behavior.

Route Sync Data through a shared headless-capable Flutter engine and the existing band ownership and commit-before-ACK persistence path. Add opt-in connectivity-error suppression, an interactive foreground fallback, and Dart/native/system-invocation regression tests.
Expose Sync Data (Long Running) on iOS 27 with extended execution, system-managed progress, and cancellation through the shared sync bridge. Keep the ordinary action and deployment target unchanged, and cover the additional intent with native and system-invocation tests.
@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented Sep 13, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds iOS Shortcuts support for bounded synchronization on iOS 16+ and an iOS 27 long-running variant, backed by a shared readiness-aware Flutter bridge, serialized BLE ownership, commit-before-ACK persistence, truthful result/progress reporting, and extensive native, Dart, and system-invocation coverage.

Sequence diagram for an iOS Shortcut band sync

sequenceDiagram
    actor User
    participant Shortcuts
    participant SyncDataIntent
    participant ShortcutSyncBridge
    participant Flutter
    participant BleEngine
    participant BandHost
    participant Band

    User->>Shortcuts: Run Sync Data
    Shortcuts->>SyncDataIntent: perform()
    SyncDataIntent->>ShortcutSyncBridge: sync()
    ShortcutSyncBridge->>Flutter: run(id, budgetMs)
    Flutter-->>ShortcutSyncBridge: ready
    Flutter->>BleEngine: runSync(timeout)
    BleEngine->>Band: Synchronize history
    BleEngine->>BandHost: commitNativeBatch(...)
    BandHost-->>BleEngine: Data committed
    BleEngine-->>Flutter: complete or partial result
    Flutter-->>ShortcutSyncBridge: Correlated reply
    ShortcutSyncBridge-->>SyncDataIntent: ShortcutSyncReply
    SyncDataIntent-->>Shortcuts: Result message
Loading

State diagram for Shortcut sync outcomes

stateDiagram-v2
    [*] --> WaitingForDart
    WaitingForDart --> Running: ready
    WaitingForDart --> TimedOut: deadline reached
    Running --> Connecting: paired and Bluetooth available
    Running --> AlreadyRunning: BLE ownership unavailable
    Running --> Skipped: bluetoothUnavailable or bandUnreachable
    Running --> Failed: pairing, permission, setup, storage, or startup error
    Connecting --> Syncing: band reachable
    Connecting --> Skipped: bandUnreachable and ignore enabled
    Connecting --> Failed: connection failure
    Syncing --> Partial: deadline, cancellation, or early transfer end
    Syncing --> Persisting: batch received
    Persisting --> Syncing: commitNativeBatch succeeds
    Persisting --> Failed: persistence failure
    Syncing --> Completed: transfer finished and backlog drained
    Completed --> [*]
    Partial --> [*]
    AlreadyRunning --> [*]
    Skipped --> [*]
    Failed --> [*]
    TimedOut --> [*]
Loading

File-Level Changes

Change Details Files
Expose bounded and long-running band synchronization as native iOS App Intents.
  • Add iOS 16 Sync Data and interactive Open Edge and Sync actions with explicit result states and selective connectivity-error suppression.
  • Add the iOS 27 LongRunningIntent/CancellableIntent variant with a ten-minute application timeout and indeterminate saved-batch progress.
  • Register the new Shortcut action and preserve the existing deployment target with compiler and availability guards.
ios/OpenStrapIntents.swift
ios/Runner/LongSyncDataIntent.swift
ios/Runner.xcodeproj/project.pbxproj
Build a shared native-to-Dart synchronization bridge for headless and foreground Shortcut execution.
  • Retain one headless-capable Flutter engine and attach foreground scenes to it.
  • Wait for an explicit Dart readiness handshake, correlate request IDs, enforce deadlines, forward cancellation, and ignore late replies.
  • Preserve app-owned sessions while serializing competing Shortcut/background/UI requests.
ios/Runner/AppDelegate.swift
ios/Runner/SceneDelegate.swift
ios/Runner/ShortcutSyncBridge.swift
ios/Runner/Info.plist
lib/main.dart
lib/state/app_state.dart
Route Shortcut synchronization through durable, ownership-aware BLE and persistence paths.
  • Extract reusable headless engine construction with commit-before-ACK persistence callbacks.
  • Add foreground-session reuse and headless fallback with BLE ownership and cleanup guards.
  • Classify completion, partial, already-running, timeout, prerequisite, and connectivity outcomes without claiming asynchronous work completed.
lib/sync/background_sync.dart
lib/sync/ios_shortcut_sync.dart
lib/sync/shortcut_sync_task.dart
lib/state/app_state.dart
Add regression, system-invocation, and compatibility coverage for Shortcut lifecycle behavior.
  • Test readiness, malformed replies, overlapping requests, cancellation, deadlines, progress filtering, suppression allowlists, and data-safety behavior.
  • Add the separate ShortcutIntents AppIntentsTesting scheme for background, relaunch, foreground fallback, and long-running invocation.
  • Document simulator limitations and remaining real-band validation scenarios.
ios/RunnerTests/RunnerTests.swift
ios/RunnerTests/LongSyncDataIntentTests.swift
ios/ShortcutUITests/ShortcutUITests.swift
ios/ShortcutUITests/Info.plist
ios/Runner.xcodeproj/xcshareddata/xcschemes/ShortcutIntents.xcscheme
test/app_state_shortcut_sync_test.dart
test/ios_shortcut_sync_test.dart
test/shortcut_sync_task_test.dart
guides/IOS_SHORTCUTS.md
README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant