import Foundation // OSSignposter on Darwin; nucleicd's Linux build has no `os`, so every call no-ops there. #if canImport(os) import os #endif /// Startup signposting (docs/MAIN_THREAD_PERFORMANCE_PLAN.md item 6, feeding item 9's /// "startup hydration and maintenance" measurement pass): named `os_signpost` intervals over /// the launch sequence, so Instruments' os_signpost track (subsystem "com.nucleic", category /// "startup") can attribute launch latency to its phases instead of one opaque blob: /// /// • `LaunchToFirstFrame` — begun in `NucleicApp.init` (the first code we own; the dyld + /// Swift-runtime slice *before* it is what Instruments' App Launch template already /// covers), ended when the root view's `.task` fires — i.e. the first frame at which the /// window's content hierarchy is live and interactive. /// • `Hydration` — the ordered project/session install plus the concurrent noncritical /// hydration group (activity-feed seeding, todo loading, provider probing). /// • `LockReconcile` — the launch lock/nvrsion reconciliation gate that commands await /// (`AppStore.awaitStartupLockReconciliation`), running concurrently with hydration. /// • `DeferredMaintenance` — the post-first-paint maintenance batch /// (`AppStore.runDeferredStartupMaintenanceOnce`). /// /// `@MainActor` because the in-flight interval state is shared mutable and every caller — /// the app's init/`.task` and the store's launch tasks — is already main-actor-isolated. @MainActor public enum StartupSignposts { public enum Phase: Sendable, Hashable { case launchToFirstFrame case hydration case lockReconcile case deferredMaintenance /// Signpost interval names must be `StaticString`s and byte-identical at begin/end, /// hence a switch over literals rather than anything derived at runtime. var name: StaticString { switch self { case .launchToFirstFrame: return "LaunchToFirstFrame" case .hydration: return "Hydration" case .lockReconcile: return "LockReconcile" case .deferredMaintenance: return "DeferredMaintenance" } } } #if canImport(os) private static let signposter = OSSignposter(subsystem: "com.nucleic", category: "startup") /// In-flight interval states by phase. Each phase runs at most once per launch; a stray /// double-begin just replaces (and orphans) the earlier interval rather than trapping. private static var inFlight: [Phase: OSSignpostIntervalState] = [:] #endif public static func begin(_ phase: Phase) { #if canImport(os) inFlight[phase] = signposter.beginInterval(phase.name) #endif } /// Ends `phase` if it's open; a no-op otherwise (e.g. `end` on a phase whose `begin` was /// skipped because the process isn't the GUI app). public static func end(_ phase: Phase) { #if canImport(os) guard let state = inFlight.removeValue(forKey: phase) else { return } signposter.endInterval(phase.name, state) #endif } }