FI
ForgeOrchestrator

Getting Started

Pick an orchestrator, define your actions, and evaluate.

Requirements

  • iOS 18+ / macOS 15+
  • Swift 6.3+ (Xcode 26 or later)

Installation

Pick an Orchestrator

Three orchestrators, three flow shapes. Pick the one that matches your use case.

Orchestrator Runs State sharing Use case
SequenceOrchestrator Once None App launch gates (onboarding, force update, terms)
PipelineOrchestrator Once PipelineContext Data-loading flows where actions share results
MonitorOrchestrator Interval or on demand None Background checks — expired terms, periodic sync

Define an Action

Each orchestrator has its own action protocol — SequenceAction, PipelineAction, MonitorAction — all built on the shared OrchestratedAction base. Every action provides an id, a priority, a shouldRun() gate, and an execute() body.

OnboardingAction.swift
import ForgeOrchestrator

struct OnboardingAction: SequenceAction {
    let id = ActionID("onboarding")
    let priority: ActionPriority = .high

    func shouldRun() async -> Bool {
        !UserDefaults.standard.bool(forKey: "hasCompletedOnboarding")
    }

    func execute() async {
        let signal = CompletionSignal()
        OnboardingPresenter.show { signal.complete() }
        await signal.wait()
        UserDefaults.standard.set(true, forKey: "hasCompletedOnboarding")
    }
}

Use CompletionSignal to bridge UI: if your action shows a screen and needs to wait for the user, create a CompletionSignal, pass it to the presenter, and await signal.wait(). The presenter calls signal.complete() when done.

Evaluate at Launch

TaskFlowApp.swift
import SwiftUI
import ForgeOrchestrator

@main
struct TaskFlowApp: App {
    @State private var orchestrator = SequenceOrchestrator()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .task {
                    orchestrator.register([
                        ForceUpdateAction(),
                        OnboardingAction(),
                        WhatsNewAction(),
                    ])
                    await orchestrator.evaluate()
                }
        }
    }
}

Orchestrators are @MainActor @Observable: bind isProcessing, currentActionId, eligibleCount, and completedCount directly to SwiftUI views for progress UI.