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

Delete Immediately is removed entirely (ruling ae1dd96, Redesign card
d40bfac1): the delete vocabulary is purely staged — board → trash,
trash → permanent (confirmed on no-git boards), Empty Trash for bulk.
Gone: File ▸ Delete Immediately (⌥⌘⌫) and its validation, both
⌥-alternate context rows (card + the permanently-disabled lane row),
the VO custom action, BoardStore.deleteImmediately,
TrashModel.canDeleteImmediately, TrashConfirmations' .purge action
(zero surviving callers — trash-side Delete always used
.deleteTrashCards), and the pinning tests. purgePrompt drops its
now-single-purpose container parameter (.trash is the only surviving
caller). BoardWriter.purgeItem survives — create-undo rollback still
needs it — with its comment rewritten. README's trash paragraph drops
the ⌥⌘⌫ sentence.

The other 2026-07-30 rulings (2ec2c95 registry freshness stamp,
c741b02 unified-log-as-coerce-consumer) required no code changes —
already conformant.

Both schemes 1844 tests / 318 suites green.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-30 15:13:31 -04:00
parent 9ca8ed84de
commit 785ef5fe14
15 changed files with 83 additions and 483 deletions
+5 -47
View File
@@ -224,42 +224,18 @@ struct TrashPhrasingTests {
let snapshot = try load(fixture)
let sole = try #require(TrashModel.purgePrompt(
for: [cardF], in: .trash, snapshot: snapshot, unrecoverable: true
for: [cardF], snapshot: snapshot, unrecoverable: true
))
#expect(sole.title == "Permanently delete \u{201C}Newest\u{201D}?")
#expect(sole.message == "This can\u{2019}t be undone.")
#expect(sole.confirmTitle == "Delete")
let several = try #require(TrashModel.purgePrompt(
for: [cardE, cardF], in: .trash, snapshot: snapshot, unrecoverable: true
for: [cardE, cardF], snapshot: snapshot, unrecoverable: true
))
#expect(several.title == "Permanently delete 2 cards?")
}
@MainActor
@Test("Delete Immediately reads the same either side of the boundary")
func purgePromptSpansContainers() throws {
let fixture = try makeBoard()
defer { fixture.tearDown() }
let snapshot = try load(fixture)
let fromBoard = try #require(TrashModel.purgePrompt(
for: [card1], in: .board, snapshot: snapshot, unrecoverable: true
))
#expect(fromBoard.title == "Permanently delete \u{201C}First\u{201D}?",
"11 ▸ Delete Immediately skips the trash from anywhere")
}
@MainActor
@Test("A lane in the set contributes nothing — no purge path reaches one")
func lanesAreNeverPurged() throws {
let fixture = try makeBoard()
defer { fixture.tearDown() }
let snapshot = try load(fixture)
#expect(TrashModel.purgePrompt(for: [laneA], in: .board, snapshot: snapshot, unrecoverable: true) == nil)
}
@MainActor
@Test("An untitled card reads as the untitled rendering, never as an empty pair of quotes")
func untitledReadsAsARendering() throws {
@@ -271,7 +247,7 @@ struct TrashPhrasingTests {
let snapshot = try load(fixture)
let prompt = try #require(TrashModel.purgePrompt(
for: [cardD], in: .trash, snapshot: snapshot, unrecoverable: true
for: [cardD], snapshot: snapshot, unrecoverable: true
))
#expect(prompt.title == "Permanently delete \u{201C}Untitled\u{201D}?")
}
@@ -284,9 +260,9 @@ struct TrashPhrasingTests {
let snapshot = try load(fixture)
#expect(TrashModel.purgePrompt(
for: [ItemID(rawValue: Ident.indexless)], in: .trash, snapshot: snapshot, unrecoverable: true
for: [ItemID(rawValue: Ident.indexless)], snapshot: snapshot, unrecoverable: true
) == nil)
#expect(TrashModel.purgePrompt(for: [], in: .board, snapshot: snapshot, unrecoverable: true) == nil)
#expect(TrashModel.purgePrompt(for: [], snapshot: snapshot, unrecoverable: true) == nil)
}
@MainActor
@@ -344,22 +320,4 @@ struct TrashValidationTests {
selection: ItemReferenceSet(ids: [cardD], container: .board), in: snapshot
))
}
@Test("Delete Immediately is cards only, in either container")
func canDeleteImmediatelyIsCardsOnly() throws {
let fixture = try makeBoard()
defer { fixture.tearDown() }
let snapshot = try load(fixture)
#expect(TrashModel.canDeleteImmediately(
selection: ItemReferenceSet(ids: [card1], container: .board), in: snapshot
))
#expect(TrashModel.canDeleteImmediately(
selection: ItemReferenceSet(ids: [cardD], container: .trash), in: snapshot
))
#expect(!TrashModel.canDeleteImmediately(
selection: ItemReferenceSet(ids: [laneA], container: .board), in: snapshot
), "a lane's delete is physical already — there is nothing for 'skip the trash' to mean")
#expect(!TrashModel.canDeleteImmediately(selection: .empty, in: snapshot))
}
}