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
+8
View File
@@ -227,8 +227,16 @@ public final class ClipboardStore {
/// the text (04 Grammar). The field consumes the selector natively, so this guard is belt over
/// braces but a board command that stayed armed under an editor would be exactly the kind of
/// fall-through 04 is careful about.
///
/// **A mixed trash selection closes it this is one of the two exits the kind guard moved to**
/// (04-interactions.md The trash, ruled 2026-07-31 with kind-blind trash selection): "the
/// pasteboard's payload types are per-kind, so Cut and Copy grey out via ordinary menu validation
/// while a trash selection mixes kinds no failed gesture, no beep". It is also what keeps
/// `capture`'s single `kind` honest: the manifest names one payload type, and a set spanning both
/// never reaches it.
public func canCopy(from store: BoardStore) -> Bool {
guard !store.isEditingInline else { return false }
guard !SelectionGrammar.mixesKinds(store.selection, in: store.snapshot) else { return false }
return SelectionGrammar.kind(of: store.selection, in: store.snapshot) != nil
}