Card 737a949f: "Add an option to card context menu to copy a link to
the card folder." Implements the design ruling verbatim.
- New context-menu row "Copy Link" (CardFaceView.boardMenu, board
side only — trash cards are excluded, matching "sole selected live
card"). Writes the clicked card's folder in one pasteboard item
carrying two representations: the file:// URL under .fileURL and
the plain absolute path under .string (FolderLinkPasteboard.swift).
Enabled on a sole selected live card; disabled on a multi-selection
and wherever edit-shaped actions already disable, per the ruling.
Also exposed as a VoiceOver custom action alongside its siblings.
- Menu-bar twin: Board ▸ Copy Link (BoardCommands.swift,
CopyLinkCommand), no default chord — the every-function-a-menu-item
contract in DESIGN/11-command-nexus.md is still current, so this is
the twin that contract calls for, homed the way Open Card/Rename/
Style… already are.
- DESIGN/11-command-nexus.md: new Board-menu row and an updated Card
context-menu row.
- Tests (KanbanTests/CopyLinkTests.swift): the target predicate's
enablement (sole card / multi-selection / lane / trash / empty /
inline-editing), the pasteboard write's exact bytes via a fake
pasteboard (both representations, exact folder URL), and a
disabled-target no-op.
Caught and fixed during self-review: an early version read the
context menu's widened-selection helper (targetIDs) inside the
Copy Link row's .disabled(...), which reads store.selection. Since
.contextMenu's content closure is evaluated on every ordinary body
pass (not only when the menu opens), that resubscribed every card
face on the board to every selection change — the exact O(board)
regression RENDER-INSTRUMENTATION.md's isSelected/selectedCount
split exists to prevent, caught by BoardRenderPerformanceTests and
MarqueeRenderCostTests. Fixed by reading the already-hoisted,
non-Observable `selectedCount` parameter instead, which answers the
same "how many ride along" question at zero extra subscription cost.
xcodegen generate, the Kanban scheme build, and the full KanbanTests
suite (2816 tests) are clean.
Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy