Lanes delete into the trash — rendering, grammar, drag, clipboard, a11y
Phase 2 completes the lanes-in-trash card. TrashEntry merges the trash's two kinds by rank in exactly ONE place (ItemPath.resolve's own merge deleted in favor of it — the three-merge-points finding shrinks instead of growing). TrashLaneRowView renders the opaque row — tertiary plate, level-default lane glyph never the lane's own icon, title + card count, no accents, no expansion; the column badge counts rendered rows. Selection grammar: kind-homogeneous trash selections — ranges skip the other kind, ⇧-extension stops at the kind boundary, plain arrows walk the merged order, marquee stays card-only (now load-bearing: rows register frames for arrows), Select All card-scoped; successor-on-purge crosses kinds like navigation as the interim for open Gap 7b5cbc90. Drag: TrashDrop accepts lane sessions (drop on shown trash deletes), restoreLanes routes a trash-sourced strip drop as an arrival-ranked within-board move with an undo step. Clipboard: ⌘X/⌘V lane restore via opaque lane subjects; fixed boardRoot(ofLaneFolder:) returning .trash as the root — a same-board restore looked like an import and would have reminted the lane it was restoring (pinned by test). A11y: row = one flattened "title, deleted lane, N cards" element with Delete/Reveal actions; BoardDiff crossings read lanes as deleted/restored, shown-trash churn digested at row level. Agent guide stays v7 — the literal already teaches lanes-trash-by-move and kind stamping; drift-guard pins those lines. README trash paragraph notes lanes. Both schemes 1893 tests / 322 suites green. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -666,6 +666,27 @@ struct AgentGuideContentTests {
|
||||
#expect(content.contains("*file* called `attachments` in a card"))
|
||||
}
|
||||
|
||||
/// **Lanes delete into the trash too** (08 ▸ The agent guide's present-tense list; 03-board-ui.md
|
||||
/// § Trash, re-ruled 2026-07-29): the guide has to teach the *move*, the `kind` value that tells a
|
||||
/// trashed lane from a card in the flat container, and the stamp on the way in. The shipped v7
|
||||
/// literal already says all three — this is the guard that keeps a wording pass from dropping one
|
||||
/// silently, which is the failure class the per-version changelog bullets were retired over.
|
||||
@Test("The guide teaches lanes-in-trash: the move, the kind value, and the stamp")
|
||||
func lanesInTrashVocabularyIsPresent() {
|
||||
let content = AgentGuide.content
|
||||
// The delete itself is one sentence covering both levels.
|
||||
#expect(content.contains("Delete a card or a lane = move its folder into `<board>/.trash/`"))
|
||||
#expect(content.contains("for a whole lane (create `.trash/` if missing)"))
|
||||
#expect(content.contains("travels with its cards inside it"))
|
||||
// `kind` at creation, always — depth says what an item is on the board, but `.trash/` is flat.
|
||||
#expect(content.contains("**Always write `kind`** at creation"))
|
||||
#expect(content.contains("tells a trashed lane from a card"))
|
||||
// And stamped on the way in when it is missing.
|
||||
#expect(content.contains("**Stamp `kind: lane` when you trash a lane that lacks it.**"))
|
||||
// The one place permanence is named, and it names both kinds.
|
||||
#expect(content.contains("the trash is the recoverable path for both"))
|
||||
}
|
||||
|
||||
/// The pathfinder's guide taught `media/` and tombstone deletes; both are retired
|
||||
/// (01-storage-format.md ▸ Changes from the pathfinder schema; ▸ Deletion). The one legitimate
|
||||
/// mention of `deleted:` is the warning never to write it.
|
||||
|
||||
Reference in New Issue
Block a user