Disown AppKit window restoration — launches present welcome again instead of a windowless shell

macOS keeps Saved Application State per app, and on macOS 26 its mere
existence — even describing zero windows, which repeated dev kills
guarantee — counts as "a restored session": SwiftUI then treats every
scene's defaultLaunchBehavior as moot and presents nothing. The app
launched as a windowless shell with no way back, since windowOpener is
captured by the first scene that appears — so Open Recent, the
re-grant Grant click, and Dock reopen all silently buffered or
no-opped. Proven by -ApplePersistenceIgnoreState YES presenting
correctly on the same state; with the fix, welcome presented 3/3
consecutive plain launches.

Three changes:
- App.init registers ApplePersistenceIgnoreState — restoration is the
  registry's job (02 § Launch and window lifecycle), every scene
  already declares restorationBehavior(.disabled), and AppKit's layer
  was pure liability. Registered before NSApplicationMain runs, which
  is what makes a registration-domain default early enough.
- The restore bootstrap presents at every launch as the app's one
  reliable presenter; welcome is never system-presented (.suppressed)
  — the pass opens it when nothing else lands on screen.
  LaunchPlan.presentsBootstrap retired.
- captureWindowActions returns the replayed Finder-open count so the
  pass counts those as opens — a cold document launch doesn't get
  welcome stacked beside its board.

Both suites green, verify-editions 30/30.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-29 22:48:04 -04:00
parent 546ed94412
commit 90954a47d6
5 changed files with 48 additions and 28 deletions
+8 -2
View File
@@ -310,16 +310,22 @@ public final class AppModel {
/// What `CaptureOpenWindow` calls. A method rather than two assignments so the launch flow, which
/// needs the actions before any `onAppear` has run, has one thing to call.
func captureWindowActions(open: OpenWindowAction, dismiss: DismissWindowAction) {
///
/// Returns how many buffered Finder-open URLs it replayed the restore bootstrap's input: a
/// launch that already opened a document's board must not put welcome up beside it, and only this
/// method knows the buffer wasn't empty.
@discardableResult
func captureWindowActions(open: OpenWindowAction, dismiss: DismissWindowAction) -> Int {
windowOpener = open
windowDismisser = dismiss
guard !pendingOpenURLs.isEmpty else { return }
guard !pendingOpenURLs.isEmpty else { return 0 }
let urls = pendingOpenURLs
pendingOpenURLs.removeAll()
for url in urls {
openBoard(at: url)
}
return urls.count
}
// MARK: Recents