Michael, thanks much for your help which led to resolving our issues. We ran Hello World on-device, studied both samples, and rebuilt our app's window lifecycle around them. Everything you suggested is now implemented:
Adopted:
A window-first startup screen (your last question answered by implementation): the app now launches into a front-door window — Create / Open / content library — and the immersive space opens only on user intent. Structurally it's Hello World's single-window pattern: the front door, the authoring menu, and the player's transport bar are three content states of ONE persistent Window scene, not separate windows. (We tried a dedicated startup window with hand-offs first; the single-window design proved far cleaner.) On your side-by-side question: verified on-device — at the front door (no space open), other apps' windows coexist normally; entering a scene hides them (both our modes are immersive spaces — even Passthrough is .mixed); exiting back to the front door brings them back. During editing itself, full immersion IS the product — a spatial 3D editor — so that stays immersive-first by design.
The Objects-in-Orbit attachment pattern for the "main window closed while immersed" state: a persistent ViewAttachmentComponent with BillboardComponent and conditional content, offering Reopen plus an Exit that returns to the startup window. One practical note: we place it at 0.85 m — at 1.0–1.3 m it can sit behind the user's own tool windows, and depth compositing is honest.
exit(0) is gone. Message received on programmatic quit being unsupported. "Quitting" is now: exit to the startup window → user closes it → zero scenes → the system recedes the app. (Your Solar System module's Exit button was a helpful precedent.)
On your remaining question — the file-launch difference: scenes can be authored with a play-on-open flag, so another Vision Pro user tapping a shared scene file gets a playback experience — watching the created animation via a compact transport bar, the Solar System pattern — rather than the authoring UI. Deliberate authorial intent, not an inconsistency.
Findings from the implementation your team may find useful:
defaultLaunchBehavior(.presented) doesn't cover RE-ACTIVATION of a running app: with the main window closed and tool windows alive, an icon tap re-presents only the tool windows, .presented notwithstanding. We recover via a UIApplication.didBecomeActiveNotification observer that reopens the main window — works, but feels like it should be the launch-behavior API's job.
The last-closed-window zombie shaped most of our bugs: a window closed as the last regular scene is backgrounded, never eliminated — no onDisappear, and it still counts as "open." Practical corollary we learned the hard way: programmatic dismissWindow teardowns must be ordered so every dismissal has an open sibling, or scenes zombify and the app can't recede. Your lifecycle sample's three-state enum (.inTransition / .open(phase) / .closed) turned out to be essential — we think it might deserve louder billing in the docs.
An immersion-style transition asymmetry worth a look: the .immersionStyle(selection:) value is read at presentation, and a .mixed → .full restyle applied to a just-opened space fails reliably on-device (space renders pure black; .full → .mixed tolerates the same timing). We fixed it by ensuring the selection binding is correct before openImmersiveSpace (computed binding reading our model live). Happy to file a Feedback with a repro if useful.
An open question on the earlier scenePhase discussion: the ~61 s out-of-view backgrounding seems CONDITIONAL, and we've been unable to pin the conditions experimentally. Our parked main window reliably backgrounds after ~a minute in BOTH immersion styles, with or without other windows open; your Orbit module's lone parked window stayed .active for 3+ minutes. Ruled out experimentally: immersion style (both behave the same), presence of other windows (none open, still backgrounds), and the window's own update activity (we made our menu fully static — still backgrounds on schedule). Whatever the discriminating condition is, it isn't observable from the app side. If the rules were documented, apps relying on the show-benign-UI-on-background pattern could set expectations correctly.
Thanks again for the direction — the samples were exactly the map we needed. FB24076974 remains our enhancement request for a close signal on the last nonimmersive scene; everything else above is running today.