The loader collects every fail-fast defect and honors per-open skips
Phase 1 of the decision surface (01 ▸ Malformed input, settled
2026-07-31): BoardLoadFailure aggregates the walk's defects in walk
order — stop-at-first retires. Environmental failures (unreadable root,
not-a-directory) stay immediate single-defect throws: there is no walk
to collect from. A defective root index is recorded and the walk
continues into the children (nothing in the walk consults the parsed
root document — verified); a defective lane, card, or trash-entry index
records and skips its subtree, Re-check's whole-walk re-aggregation
being the designed loop for what hides beneath. load(skipping:) is the
per-open skip channel: a skipped path's item is omitted from the model
and surfaces as LoadWarning.userSkipped; root paths are unskippable by
construction. The reload-breakage banner carries the aggregate ("…and
N more"), single-defect sentences byte-identical to before. Two new
multi-defect fixture boards; suite 2591 green.
Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -184,7 +184,7 @@ struct BoardWindowHost: View {
|
||||
let recordID = appModel.boardRegistry.recordOpen(of: url)
|
||||
|
||||
let store: BoardStore
|
||||
do throws(BoardLoadError) {
|
||||
do throws(BoardLoadFailure) {
|
||||
store = try appModel.storeRegistry.acquire(url)
|
||||
} catch {
|
||||
Self.logger.error("board failed to open: \(error.description, privacy: .public)")
|
||||
|
||||
@@ -575,7 +575,7 @@ struct CardWindowHost: View {
|
||||
}
|
||||
|
||||
let store: BoardStore
|
||||
do throws(BoardLoadError) {
|
||||
do throws(BoardLoadFailure) {
|
||||
store = try appModel.storeRegistry.acquire(ref.boardURL)
|
||||
} catch {
|
||||
Self.logger.error("card window could not acquire its board: \(error.description, privacy: .public)")
|
||||
|
||||
@@ -142,12 +142,17 @@ enum TemplateEngine {
|
||||
/// The loader's error is handed back whole rather than reworded: the chooser's unloadable row
|
||||
/// shows "the loader's fail-fast specifics" (09 ▸ Why this format), and a second taxonomy of
|
||||
/// board problems is precisely what a files-first app must not grow.
|
||||
///
|
||||
/// **One defect of the walk's aggregate — the first** (`BoardLoadFailure.primary`). The chooser's
|
||||
/// unloadable row is one line about a folder the user is not being invited to repair: a template
|
||||
/// store is picked from, not opened, and the decision surface exists for the board being opened.
|
||||
/// Saying which thing is wrong first is the whole of what that row can act on.
|
||||
static func load(templateAt url: URL, origin: BoardTemplate.Origin) -> Result<BoardTemplate, BoardLoadError> {
|
||||
do {
|
||||
let result = try BoardLoader.load(boardRoot: url)
|
||||
return .success(BoardTemplate(url: url, origin: origin, model: result.model))
|
||||
} catch {
|
||||
return .failure(error)
|
||||
return .failure(error.primary)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user