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:
2026-08-01 09:12:49 -04:00
parent 94e60cd444
commit ba1726fa77
35 changed files with 897 additions and 117 deletions
+5 -3
View File
@@ -238,9 +238,11 @@ public enum BoardAnnouncer {
public var lockAfter: ReadOnlyLockReason?
/// The reload-breakage condition before and after, same rule: a different file failing to
/// load is a different sentence and is worth saying.
public var breakageBefore: BoardLoadError?
public var breakageAfter: BoardLoadError?
/// load is a different sentence and is worth saying. **The whole aggregate**, not just its
/// first defect a second broken lane appearing under an already-broken one changes the
/// sentence the strip is showing ("and 2 more"), so it is news by the same test.
public var breakageBefore: BoardLoadFailure?
public var breakageAfter: BoardLoadFailure?
public init() {}
}