Realign code with the 2026-07-31 rulings

The trash sorts by modified descending — the arrival rank mint retires
(Ranks.isOrderedForTrash one comparator, loader + merged order agree;
the legacy deleted: migration stamps modified from the tombstone
timestamp where parseable; delete undo steps validate existence-only;
agent guide v8). Trash selection goes kind-blind — ranges, marquee,
Select All, and the successor walk sweep both kinds; the guard moves to
the exits (mixed-payload drop refusal, copy/cut validation). The copy
stamping preflight widens back to comment depth (load-scoped posture —
the board always loads, the gesture refuses whole). Fixes a latent
no-op: trashed-lane drag restore never fired (DragSession.beginLanes
hard-coded the board container).

2403 tests in 413 suites green.

Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
2026-07-31 18:35:07 -04:00
parent 542ab169a3
commit bec75e4282
37 changed files with 1200 additions and 551 deletions
+10 -9
View File
@@ -12,7 +12,7 @@ import SwiftUI
///
/// **Its cards are ordinary cards in a special place**, so there is nothing to derive and nothing
/// to draw differently: the column renders `store.snapshot.trash` which the loader parsed with the
/// same card parse the lanes use and sorted by `order` like any lane's children through the very
/// same card parse the lanes use and sorted by `modified` descending, the trash's own order through the very
/// same `CardFaceView` a lane renders. "A trashed card is an ordinary card in a special place
/// search, selection, rendering, styling, and clipboard all treat it exactly like any other card"
/// (03 § Trash), and one view is the only way to make *rendering* literally true rather than
@@ -24,11 +24,11 @@ import SwiftUI
/// **A trashed lane is an opaque unit** "one distinct dimmed row showing its title and held-card
/// count no styling accents, never expandable" (03 § Trash) so it gets its own small view
/// (`TrashLaneRowView`) rather than a third card-face role: what a card face draws is exactly what
/// the design says this row must not. The two kinds **interleave purely by trash rank**, which is
/// the design says this row must not. The two kinds **interleave by `modified` descending**, which is
/// `BoardModel.trashEntries`' merge and not a second one written here.
///
/// Newest-first falls out of the ranks (every arrival of either kind mints one above the current
/// top), so there is no timestamp sort and no entry type here at all.
/// Newest-first falls out of the stamp (every arrival of either kind restamps `modified` on the way
/// in 03 § Trash, re-ruled 2026-07-31), so no rank is minted anywhere in this container.
///
/// ### What makes it a column and not a lane
///
@@ -52,9 +52,9 @@ import SwiftUI
/// trash, lanes extended 2026-07-29) the drag becomes the pointer's delete gesture, and release
/// moves the dragged item(s) into `.trash/`. So the column declares an `onDrop`
/// (`TrashDropDelegate`), and it is the narrowest one on the board: a board drag from **this** board,
/// unmodified. It diverges from every other drop in one way, and the ranks are what make the
/// divergence honest: **the shadow always takes the topmost row**, because every arrival mints a rank
/// above the current top.
/// unmodified. It diverges from every other drop in one way, and the stamp is what makes the
/// divergence honest: **the shadow always takes the topmost row**, because every arrival restamps
/// `modified` and the column is sorted by it, newest first.
///
/// The drag *out* is the restore, and it is deliberately not special at either level: a trash card's
/// drag is an ordinary `.cards` session in the `.trash` container
@@ -155,8 +155,9 @@ struct TrashLaneView: View {
))
}
/// The rows the column shows **both kinds, interleaved by rank** (03-board-ui.md § Trash:
/// "Lane rows and cards interleave in the one trash column purely by trash rank").
/// The rows the column shows **both kinds, interleaved by `modified` descending**
/// (03-board-ui.md § Trash: "Lane rows and cards interleave in the one trash column by `modified`
/// descending").
///
/// **Shown, the trash's contents "participate in the filter exactly like any other card"**
/// (03 § Trash "the point of the pivot"), so the search predicate narrows this collection