The decision surface — a refused open becomes a live repair, in place
Phase 3 of the decision surface, completing the card (01 ▸ Malformed input, settled 2026-07-31). An attended open's fail-fast walk transforms the loading window's content into one aggregated surface — never a sheet, never a chain: defects grouped by class, each class stated once with its files listed (Reveal in Finder + Open in Editor per row), a class-level default preselected, per-item override behind a disclosure. Only honest choices: YAML and malformed-schema get Editor + Re-check (Skip below the root); newer-than-app gets Skip alone and blocks the board at the root; the two root repairs — minted index, schema: 1 stamp — are defaults. Repair and Open applies fixes in one store-less write bracket and re-walks: clean proceeds, remainder re-aggregates into the same surface. Cancel and ⌘W retire to welcome's row; restored opens never see the surface at all (OpenOrigin rides the PendingOpen carrier). Skips are per-open consent that rides the session — the store retains the skip set and every reload passes it — and the opened board posts a warning-tone notice naming what was left out, each item's Reveal riding the banner strip's new reveal control. On Pro boards the repair bracket binds its own EchoLedger, heal-marks everything, and the store adopts it before the committer starts, so repairs land as one separate commit authored Lanework Integrity — pinned end to end. Also fixed en route: a retired loading window left its close interception installed and returned false from windowShouldClose forever, blocking quit. Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -246,6 +246,54 @@ public final class EchoLedger: Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
/// **Marks everything this ledger holds as a heal** — the whole-ledger form of `markHeal(at:)`,
|
||||
/// for a ledger whose *every* receipt is a heal by construction.
|
||||
///
|
||||
/// Its one caller is the decision surface's repair bracket (01-storage-format.md § Malformed
|
||||
/// input: "On Pro boards the repairs drop heal-marked receipts and commit separately as one
|
||||
/// repair commit"). Repairs run **before** the board has a store — there is no `BoardStore` yet,
|
||||
/// so no `performWrite` to bind — so the repair binds a ledger of its own for the duration of the
|
||||
/// bracket. Everything that lands in it is a repair, which is exactly the condition that makes a
|
||||
/// blanket mark honest here and would make it a lie on a session ledger.
|
||||
///
|
||||
/// Path-by-path marking would need the repair runner to enumerate the files each `BoardWriter`
|
||||
/// call happened to touch — `createBoard` writes `index.md` *and* seeds `.gitignore` — which is
|
||||
/// bookkeeping the Writer exists to keep call sites out of.
|
||||
public func markAllAsHeal() {
|
||||
receipts.withLock { store in
|
||||
for path in store.keys {
|
||||
store[path]?.isHeal = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// **Takes over another ledger's receipts, attributes and all** — the repair bracket's ledger
|
||||
/// handed to the board's own once the board finally has one.
|
||||
///
|
||||
/// The decision surface repairs a board that has no store, then re-walks it; the walk succeeds,
|
||||
/// the store is built, and only *then* does a session ledger exist. Without this the repair's
|
||||
/// receipts would die with the temporary ledger and Pro's committer would author the app's own
|
||||
/// repair as `Lanework External` — the one misattribution the whole mechanism exists to prevent.
|
||||
///
|
||||
/// **Safe because a receipt vouches against disk, not against a clock** (`Receipt.isSatisfied`):
|
||||
/// the repaired files are on disk exactly as the repair left them, and the re-walk that just
|
||||
/// succeeded read those very bytes. An adopted receipt is therefore satisfiable the moment it
|
||||
/// arrives, which is the same standing a receipt dropped inside a write bracket has.
|
||||
///
|
||||
/// Plain overwrite, the supersession rule: the adopting ledger is brand new in the only case that
|
||||
/// calls this, and a receipt it already held for the same path would be the newer of the two —
|
||||
/// which is the one case the ledger's own `recordWrite` also resolves by keeping what it has been
|
||||
/// told last. Nothing is removed from `other`; it is discarded whole by its caller.
|
||||
public func adopt(_ other: EchoLedger) {
|
||||
let entries = other.receipts.withLock { $0 }
|
||||
guard !entries.isEmpty else { return }
|
||||
receipts.withLock { store in
|
||||
for (path, entry) in entries {
|
||||
store[path] = entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static func forget(_ store: inout [String: Entry], under path: String) {
|
||||
let prefix = path + "/"
|
||||
for key in Array(store.keys) where key.hasPrefix(prefix) {
|
||||
|
||||
Reference in New Issue
Block a user