Every open passes through a real loading window — the walk moves off the main actor
Phase 2 of the decision surface: the pre-snapshot loading state ruled 2026-07-29 (02 § Launch and window lifecycle), built. The board window appears immediately at its saved frame, titled with the registry record's cached name, its content a centered spinner behind an injectable ~200ms grace — no skeletons, and the first snapshot snaps in place. The tree walk runs off-main via BoardStoreRegistry.acquireOffMain (per-board single-flight keyed by file identity — concurrent opens of one root share a walk, restoration of many boards is genuinely parallel), landing in BoardStore's new designated init(rootURL:loaded:); the self-walking init survives as a convenience for its ~470 callers. ⌘W during the walk is real: configureWindow split into a loading half (frame restore, frame tracking, close interception — installed before the walk) and a store half (toolbar, widget, hideTitle, undo — installed at the snap), and the walk lives in an explicitly held BoardOpenWalk so the user's close and SwiftUI's teardown end in one cancel(). Cancellation is discard-on-completion: nil from acquireOffMain means nothing was built, nothing retained, and no open-now flag was ever set. Failure keeps today's sequence exactly: record the launch failure, welcome's row carries it, the window retires. Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -589,8 +589,12 @@ public final class BoardStore: HealHost {
|
||||
/// banner, the lock, "a failed reload never replaces a good snapshot" — exists only *because*
|
||||
/// this one succeeded.
|
||||
///
|
||||
/// The walk is synchronous because the caller has nothing to render until it lands; the
|
||||
/// asynchronous, off-main pipeline starts with the first reload.
|
||||
/// The walk runs here, on whatever actor the caller is on — the storeless shape, and the one
|
||||
/// every test and every synchronous consumer uses. The **window's** open no longer takes it:
|
||||
/// 02-architecture.md's pre-snapshot loading state (ruled 2026-07-29) gave the caller something
|
||||
/// to render before the snapshot exists, which retired this init's old rationale ("the caller
|
||||
/// has nothing to render until it lands"), so `BoardStoreRegistry.acquireOffMain` walks off the
|
||||
/// main actor and hands the result to `init(rootURL:loaded:)` below.
|
||||
///
|
||||
/// **It writes nothing, the opened board's defects included.** `defects` is recorded here and
|
||||
/// acted on by whoever wired this store up — `BoardStoreRegistry.acquire` calls
|
||||
@@ -598,8 +602,23 @@ public final class BoardStore: HealHost {
|
||||
/// with a reload behind it rather than a write into a board nothing is watching yet. A store
|
||||
/// built directly (a test, a storeless consumer) heals when it is asked to, and on every reload
|
||||
/// thereafter.
|
||||
public init(rootURL: URL) throws(BoardLoadFailure) {
|
||||
public convenience init(rootURL: URL) throws(BoardLoadFailure) {
|
||||
let result = try BoardLoader.load(boardRoot: rootURL)
|
||||
self.init(rootURL: rootURL, loaded: result)
|
||||
}
|
||||
|
||||
/// The same board, from a walk that already happened somewhere else.
|
||||
///
|
||||
/// **The designated init, and the only one that is not a load**: `LoadResult` is `Sendable` and
|
||||
/// `BoardLoader` is stateless statics, so the walk can run anywhere and only this assignment has
|
||||
/// to be on the main actor — exactly the split `startReload` has used for every reload since the
|
||||
/// beginning, now available to the *first* load too. It cannot fail, because failing is the
|
||||
/// walk's job and the walk is over: a caller holding a `LoadResult` holds a board that loaded.
|
||||
///
|
||||
/// `rootURL` is passed rather than read off `result.model` for the reason the property's own doc
|
||||
/// comment gives — the store's root follows an absorbed rename ahead of the snapshot that will
|
||||
/// carry it.
|
||||
public init(rootURL: URL, loaded result: LoadResult) {
|
||||
self.rootURL = rootURL
|
||||
self.snapshot = result.model
|
||||
self.loadWarnings = result.warnings
|
||||
|
||||
Reference in New Issue
Block a user