Realign code with the 2026-07-29 findings-resolution rulings

Nine rulings land as code. Reorders don't stamp — one container-change
predicate (WriteOperation.rewritesOrderOnly): within-container reorders
and the renumber rescale rewrite only order, while cross-lane, cross-board,
and trash moves stamp modified and clear modified-by; no trash special
case exists, and the m8 undo inverses conform through the same seam.
Copies are transactions: the root-strict/nested-lenient split retires for
a whole-subtree stampability preflight that refuses loudly naming the
offender, and every item-level copy severs remote/remote-state at every
level (whole-board forks carry them verbatim). Paste refuses, never
degrades: the embedded-index.md materialization and its loss row retire;
a missing staged snapshot produces nothing and posts an error-tone
one-shot named from manifest metadata. Coerce-tier fallbacks log through
the Defect stream with path context attached loader-side. Displacement is
level-uniform: a file squatting attachments inside a card heals by the
same rename ladder as board-root squatters; comments stays tolerated.
Delete Immediately joins card and lane context menus as Delete's
⌥-alternate with its own VO custom action, routed through an explicit
container so the menu target outranks standing selection. Agent guide v7
teaches the stamp discipline and the card-level attachments claim, and
sheds two stale v6 lines (lanes trash now; kind is taught). Verified
conformant, unchanged: edition-aware Undo/Redo disable, trash marquee
full-height backdrop.

Both schemes 1854 tests / 318 suites green; verify-editions 30/30.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-30 06:49:11 -04:00
parent 5ae48de0ea
commit 69084fdff7
27 changed files with 2159 additions and 542 deletions
+71 -5
View File
@@ -390,7 +390,7 @@ struct PurgeTests {
let store = try BoardStore(rootURL: fixture.root)
store.select([card1], in: .board)
store.deleteImmediately([card1])
store.deleteImmediately([card1], in: .board)
#expect(!fixture.exists("\(Ident.lane1)/\(Ident.card1)"))
#expect(!fixture.exists(".trash/\(Ident.card1)"), "03 ▸ Trash: ⌥⌘⌫ skips the trash from anywhere")
@@ -404,7 +404,7 @@ struct PurgeTests {
let store = try BoardStore(rootURL: fixture.root)
store.select([trashed], in: .trash)
store.deleteImmediately([trashed])
store.deleteImmediately([trashed], in: .trash)
#expect(!fixture.exists(".trash/\(Ident.indexless)"))
#expect(fixture.exists(".trash/\(More.newer)"), "and only what it named")
@@ -417,7 +417,7 @@ struct PurgeTests {
let store = try BoardStore(rootURL: fixture.root)
store.select([lane3], in: .board)
store.deleteImmediately([lane3])
store.deleteImmediately([lane3], in: .board)
#expect(fixture.exists(Ident.lane3))
}
@@ -473,7 +473,7 @@ struct PurgeTests {
store.select([trashed], in: .trash)
store.deleteTrashCards([trashed])
store.deleteImmediately([newer])
store.deleteImmediately([newer], in: .trash)
store.emptyTrash()
// 13-native-undo.md Rules: "Permanently delete (Delete Immediately, Empty Trash)
@@ -745,7 +745,7 @@ struct TrashConfirmationsTests {
let pending = try #require(confirmations.pending)
#expect(pending.prompt.title == "Permanently delete \u{201C}Trashed\u{201D}?")
#expect(pending.action == .purge([trashed]))
#expect(pending.action == .purge([trashed], .trash))
// Nothing has happened yet the alert is what stands between the keystroke and the loss.
#expect(fixture.exists(".trash/\(Ident.indexless)"))
@@ -756,6 +756,72 @@ struct TrashConfirmationsTests {
confirmations.confirm(in: store)
}
/// **The card and lane context menus' -alternate** Delete Immediately, routed through
/// `requestBoardPurge` rather than through `requestPurge` (11-command-nexus.md Context menus'
/// Card and Lane rows: "Delete with Delete Immediately as its -alternate").
/// `purgeConfirmsThenActs`'s twin for the board side: same alert, same rule, a board card as the
/// target instead of a trash one.
@Test("The board-side ⌥-alternate raises the same alert, and purges the board card on confirm")
func boardPurgeConfirmsThenActs() throws {
let fixture = try makeBoard()
defer { fixture.tearDown() }
let store = try BoardStore(rootURL: fixture.root)
let confirmations = TrashConfirmations()
confirmations.requestBoardPurge(of: [card1], in: store)
let pending = try #require(confirmations.pending)
#expect(pending.prompt.title == "Permanently delete \u{201C}First\u{201D}?")
#expect(pending.action == .purge([card1], .board))
// Nothing has happened yet same alert, same rule.
#expect(fixture.exists("\(Ident.lane1)/\(Ident.card1)"))
confirmations.confirm(in: store)
#expect(!fixture.exists("\(Ident.lane1)/\(Ident.card1)"))
#expect(!fixture.exists(".trash/\(Ident.card1)"), "skips the trash — purged, not moved")
#expect(confirmations.pending == nil)
}
/// A context menu names its target by where it was invoked, so a card row's Delete Immediately
/// must purge the *clicked* card even while a different card is selected `TrashMenuValidation
/// Tests.contextMenuDeleteIgnoresTheSelection`'s claim, mirrored onto the board side.
@Test("The board-side ⌥-alternate acts on its own target, not the standing selection")
func boardPurgeIgnoresTheSelection() throws {
let fixture = try makeBoard()
defer { fixture.tearDown() }
let store = try BoardStore(rootURL: fixture.root)
let confirmations = TrashConfirmations()
// A right-click on `card1` without first selecting it must still purge `card1`, never the
// card the standing selection happens to hold (`CardFaceView.targetIDs`'s targeting rule).
store.select([card2], in: .board)
confirmations.requestBoardPurge(of: [card1], in: store)
let pending = try #require(confirmations.pending)
#expect(pending.action == .purge([card1], .board))
confirmations.confirm(in: store)
#expect(!fixture.exists("\(Ident.lane1)/\(Ident.card1)"), "the clicked card is gone")
#expect(fixture.exists("\(Ident.lane1)/\(Ident.card2)"), "the selected card was never the subject")
}
/// `TrashModel.canDeleteImmediately` is cards only (`TrashValidationTests
/// .canDeleteImmediatelyIsCardsOnly`: "a lane's delete is physical already there is nothing for
/// 'skip the trash' to mean on one"), and the lane row's alternate inherits that unchanged: it is
/// wired per 11-command-nexus.md's Lane row, but presently inert on a lane-only target the same
/// posture File Delete Immediately already takes on a lane-only selection.
@Test("A lane-only target raises no prompt — the alternate is still cards only")
func boardPurgeIsStillCardsOnlyForALaneTarget() throws {
let fixture = try makeBoard()
defer { fixture.tearDown() }
let store = try BoardStore(rootURL: fixture.root)
let confirmations = TrashConfirmations()
confirmations.requestBoardPurge(of: [lane1], in: store)
#expect(confirmations.pending == nil)
#expect(fixture.exists(Ident.lane1))
}
/// 03-board-ui.md § Trash: "on a trash card, Delete (/) is permanent Both confirm exactly
/// where the loss is real."
@Test("The trash's own Delete confirms; the board's goes straight through")