Edition split follow-through: 12-editions.md and 13-native-undo.md join the corpus; git-era docs (06, 07) are Pro-scoped and cross-references realigned. Resolution session rulings written in place: caret chords yield to any focused text control (04, 11); the drop settle holds its proposal as overlay state and 02 gains the overlays family; Duplicate gets the save-panel fallback and a cancellable copy walk (03); Finder open is a standard document open (02); failed first opens record before loading with the folder name provisional (02); trash pointer ranges skip by kind, full-height marquee surface, Select All by kind, rows-only trashed universe (02, 04); Empty Trash counts entries (03); create handoff reads as one arrival (02); range-anchor lifecycle, board- background click grammar, jump landing cards, lane-domain shift-arrows (04); Reduce Motion restated per voice (10). Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
18 KiB
Card Window
The standalone per-card window. Opened by fast double-click, ⌘↩, or the context menu; at most one window per card (reopening a live card focuses the existing window); board and card windows share one live store, so edits reflect everywhere instantly (02-architecture.md).
Status: designed — composition, body column, and the attributes sidebar are all settled. The storage-facing rules the pathfinder settled painfully — Preview/Edit over WYSIWYG, the untouched-body byte-identical guarantee, validate-before-write on the raw outlet, dirty-buffer-wins — carry over unchanged.
Composition
Two full-height columns: a wide body column (leading) and a narrow attributes sidebar (trailing), each scrolling independently. Visual reference: assets/card-sidebar-reference.png — a GitLab-style issue pane; its pattern (stacked small-caps sections, quiet read-first rows, actions at the bottom) is what carries over, not its enhanced-schema content.
- Body column, top to bottom: the title field — large, borderless; edits write through to frontmatter on commit (Return or focus loss); clearing it removes the
titlekey (titles are optional — the untitled placeholder shows here as on the face); Return commits and moves focus into the body. Escape abandons (settled — the board inline rename's abandon, applied here): the field reverts to the on-disk title and focus moves into the body, never a commit. The Edit-mode collision resolves by focus, 06-history-undo.md's first-responder rule: while the title field is focused, Escape is the title abandon even with the body in Edit; with the body editor focused, Escape is the Edit→Preview flip as specified. Beneath it, a quiet created/modified line ("Created ⟨date⟩ · Modified ⟨date⟩ · by ⟨modified-by⟩", secondary styling, omitting whichever keys are absent — the "by" segment renders only when the self-reported provenance stamp is present, 01-storage-format.md; this is provenance made visible where git history may not exist) — the read-only readout the pathfinder dropped with its inspector, back where the mockup puts it. Then the body (Preview/Edit, below). - Attributes sidebar: everything about the card that isn't the body — sections below. Fixed narrow width derived from font metrics (full relative scaling, 10-accessibility.md); the window's resize flex goes to the body.
(The pathfinder's compositions are both gone: the metadata bar — labels, assignees, due — left with those fields' move to the enhanced schema, and the horizontal attachments strip dissolves into the sidebar.)
Body: Preview / Edit — not WYSIWYG
Settled the hard way in the pathfinder (WYSIWYG built, then reversed): the body is read/write raw Markdown with a fully rendered preview. TextEditor can't lay out tables, so rendered-reading + raw-editing is the honest, lossless pairing for a file-backed app.
Mode grammar
- Preview is the resting state: a card opens in Preview — unless its body is empty, which opens straight into Edit with the cursor ready (a new card has nothing to preview, so ⌘↩ during creation flows title → body without a mode stop).
- ⌘E toggles (View ▸ Edit Body, checkmark state — 11-command-nexus.md). Return in Preview also enters Edit — the board's edit key applied to the body; fixed grammar like the board's Return, not a menu item. Escape in Edit returns to Preview.
- Clicking never edits (the same pivot as the board's click grammar, 04-interactions.md): clicking the rendered body selects text — Preview is selectable and copyable — and nothing else. The one interactive exception is task-list checkboxes, below.
- Leaving Edit flushes the debounce (mode flip, raw-source entry, window close) — the preview never lags the text that produced it, and neither does disk.
Preview
- Renders headings, bold/italic/code, bullet/ordered/task lists, fenced + indented code, nested quotes, GFM tables (per-column alignment, columns sized to contents with the browser sizing rule), thematic breaks, HTML shown verbatim as literal code-styled text (never interpreted — no web view, per 00-vision.md's no-web-tech stance), and images resolved against the card's own folder (
). - Remote images are never fetched — Preview does no networking (sandbox-quiet, files-first). An
renders as a quiet placeholder chip carrying the alt text (or the URL); the file-relative form above is the supported image story. - Task-list checkboxes are live: clicking a
- [ ]/- [x]checkbox flips exactly that marker in the source — a single-character textual edit; every other byte of the body is untouched. This is the deliberate exception to "Preview only reads": checklists are kanban's working currency, and a mode flip to tick a box is ceremony. A toggle is an ordinary user edit — the standard atomic write, auto-committed and undoable on git boards. The pointer-free path is the system focus model (settled): checkboxes — like Preview's links — are real controls in the keyboard-focus and accessibility tree, so Full Keyboard Access Tab-reaches them and Space toggles, and VoiceOver toggles with VO-Space (10-accessibility.md's real-accessible-checkboxes promise, honored natively). Without FKA they are not in the key loop — standard macOS content behavior, so ordinary Tab users never wade through a long checklist. In-content controls are content, not commands: no menu item, no chord — 04's every-function-has-a-menu-item contract covers commands, and 11-command-nexus.md scopes them accordingly. Under the read-only lock (02-architecture.md) the controls disable in place — an in-content mutation menu validation can't reach (and not the only such path: the attachment row's ⌫/Remove shares the posture — 02's every-entry-point predicate). - Links: external URLs open in the browser; relative links open the target file with its default app (resolved against the card folder, like images).
- Edit ▸ Find (⌘F) is find-in-text here — the standard find bar over the focused body surface (Preview's selectable text, the Edit editor, raw source); board search is a board-window concern (04-interactions.md ▸ Search).
Edit
- A monospaced editor with lightweight Markdown syntax highlighting — headings emphasized, bold/italic rendered as such, code tinted, link targets and structural markers dimmed. Highlighting is presentation only: the text is the raw Markdown, character for character — no hidden transforms, no smart substitutions.
- Saved on a ~700 ms debounce; flushed on leaving Edit, entering source mode, and window close.
- ⌘Z here is the text view's own undo — session-scoped, ending when the editor loses focus or the mode flips; it works on every board, git or not. Board-level undo routing: 06-history-undo.md ▸ Undo routing; commit granularity (one commit per Edit session — the Edit→Preview flip is the effective Save button; never per save tick): 06 ▸ Rules ▸ Auto-commit.
Write rules (settled, storage-facing)
- An untouched body is never rewritten — plain string comparison, so it stays byte-identical on disk. Three-gate write: untouched → never re-serialized; reverted → not written; echo of an external edit → not written back.
- Concurrent external edits — dirty buffer wins. A dirty Edit buffer is never reloaded under the cursor: while the user has unsaved keystrokes, watcher reloads update everything else (board, Preview, other windows) but leave the buffer alone; the debounced save then writes it — deliberate last-writer-wins, the same no-merge-UI philosophy as sync (07-sync-collab.md). A clean buffer follows disk. On git boards, flush-before-overwrite (06-history-undo.md) guarantees the overwritten external version was committed first — one revert away; on no-git and repo-nested boards it is lost — the app manages no git there, so flush-before-overwrite never runs (07's accepted caveat).
Raw source outlet
A toggle (View ▸ Raw Source, ⌥⌘E — 11-command-nexus.md) swaps the entire content area — title, body, and sidebar — for the literal on-disk index.md (frontmatter and all) in a monospaced editor with Cancel/Apply: the same frontmatter is being edited as raw text, so interactive controls over it would fight the raw edit. Entering source mode flushes any pending title/body edits first, then reads the file fresh from disk. Apply validates through the same fail-fast parse the loader uses (detailed alert on error, stays in source mode) before writing byte-for-byte (including a modified-by stamp the user typed or kept — Apply is the one app write that doesn't clear it, 01-storage-format.md); the watcher reload then refreshes every window. Cancel (and window close) discards without ceremony. This is the escape hatch that keeps everything — unknown keys, exotic formatting — reachable in-app. A pull landing mid-session neither blocks on the open buffer nor invalidates it (07-sync-collab.md — same-card signpost, Apply stays last-writer-wins); branch switch and undo restore instead settle it explicitly via save-or-discard (06-history-undo.md ▸ Branch switching).
Key grammar in source mode, completing the window's key story: Escape is Cancel, ⌘↩ is Apply, and toggling off via ⌥⌘E (menu or toolbar) is Apply too — leaving-by-toggle commits, mirroring leaving-Edit-flushes; a failed validation keeps source mode open (toggle stays checked) with the alert. Return just types — it's an editor. View ▸ Edit Body (⌘E) disables while source mode is active, matching its toolbar item.
The attributes sidebar
Stacked sections under small-caps headers, in this order; quiet rows, read-optimized, edit affordances only where a section edits. The sidebar is the card's non-body inventory — future attributes (enhanced-schema fields, if they ever ship) slot in as new sections rather than growing new bars.
Attachments
- Shows every top-level file of
attachments/— including files also embedded in the body (settled: the section is the card's complete file inventory, no reference-tracking magic; an image appearing in both places is honest, not a bug). Subfolders are tolerated but not surfaced (01-storage-format.md's attachments rules). - Compact rows: small QuickLook thumbnail (Finder-icon fallback) + middle-truncated filename, one row per file. The section header carries a quiet add affordance; empty, the section stays with a one-line hint (drop files, or File ▸ Add Attachment…, ⇧⌘A) — the drop surface remains the whole window (name collisions auto-rename, Finder-style — 01-storage-format.md). Drop precedence is split by payload (settled): file drops import as attachments anywhere in the window — Edit mode included, the text editor never intercepts a file drop; dragged text lands in the Edit editor at the caret within its bounds as ordinary insertion, and is inert elsewhere in the window.
- Row interactions: double-click or Return opens; context menu Open / Reveal in Finder / Remove (moves to the system Trash, never hard-deletes — 03-board-ui.md's naming constraint keeps this distinct from board deletion); rows drag out their file URL.
- Keyboard-native, new in the rewrite (the pathfinder's strip was pointer-only): the section is focusable; arrows move between rows, Space QuickLooks the selected row, Return opens it, ⌫ removes it (same system-Trash semantics).
Style
The card-level styling home: the embedded style editor — background palette grid (with the leading None well) and curated symbol grid, per 03-board-ui.md ▸ Styling ▸ Controls. Card styling is discoverable here without a context menu; the same component appears in the board popover and behind Style….
Details — unknown frontmatter keys
- Read-only key/value rows for every unknown frontmatter key, shown only when any exist, in file order (01-storage-format.md preserves key order verbatim — the sidebar honors it). This is the files-first payoff surfaced: an agent overlay (
project:,sphere:— 08-agent-integration.md) or any hand-added key is visible to the human without opening raw source. - Values render as plain text, leniently — exotic YAML shapes display best-effort, never error. Reserved enhanced-schema keys (
labels,assignees,due,remote, …) are ordinary unknown keys in this version and appear here like any other — no special rendering. - Editing is deliberately not offered: the raw source outlet is the write path for frontmatter the app doesn't own.
History (git boards only)
- The card's commit trail, read-only (settled): every commit that touched this card's folder, newest first — semantic subject, relative date, author. The trail is where the commit-message and attribution machinery (06-history-undo.md) pays off for humans: "Move card 'X' to Doing — 2 days ago — Claude" reads as a story, agent and hand edits included (foreign authorship and
modified-byrefinement render as the author). - The listing follows the card across lane moves (path changes; the UUID folder is the identity to track). A cross-board arrival starts fresh — not because identity changes (a move keeps its UUID; the import boundary remints only on collision — 01-storage-format.md) but because the destination board's repo has no commits for the arriving folder; the old board keeps the old trail either way.
- The section is absent on boards without app-managed git (mode none, repo-nested) — same honesty rule as the popover's git section (06-history-undo.md). Rows are focusable (arrows), but carry no actions in v1 — restoring an old version stays a git-client task for now; a per-row forward-restore and lane history are wishlist items, deliberately.
- Menu path (contract): View ▸ History in the card window focuses the section — no default chord.
Actions (bottom)
- Delete — tombstones the card (destructive styling; the window then dismisses itself per Deletion & lifecycle below; recoverable from the board's trash quasi-lane).
- Reveal in Finder — the card's folder.
Window
- The subtitle shows the card's place: "⟨board⟩ › ⟨lane⟩" under the window title, live-updating as the card moves (the window follows its card).
- New windows open at the last-used card-window size, cascaded; frames restore per card across relaunch where state restoration allows.
- Toolbar (settled — 03-board-ui.md ▸ Toolbar): default set Edit Body (single toggle, on-state in Edit) · Raw Source (toggle; while active, Edit Body disables) · Add Attachment; user-customizable like the board window's.
Deletion & lifecycle
- The window follows its card across lanes (keyed by board URL + GUID) — within its board. A cross-board move dismisses the window like a delete: the card left this board — its UUID travels with the move (reminted only on an import-boundary collision, 01-storage-format.md's identity lifecycle), but the window's key is board URL + GUID, and the board half no longer names it.
- Window dismisses itself if the card is deleted — and a tombstone counts as deleted: ⌫ on the board closes the card's open window (the card is gone from the board's perspective; Put Back and reopen if it was a slip). Liveness is effective — ancestor-walked (settled; 02-architecture.md's rule extended to its last consumer): tombstoning or deleting the card's lane dismisses the window too, the card's own flag notwithstanding — the card renders nowhere and the trash shows only the lane's single subsuming entry, so no window may stay open, much less writable, over it. Put Back of the lane reopens nothing — reopening is the user's act, like any open. Dismissal never eats typed work silently where a save can land (settled): a dirty Edit buffer flushes into the tombstoned card's folder before the window dismisses — a surgical body write that leaves
deleted:intact, so the keystrokes survive Put Back and enter history on git boards (the composer reads it as an edit to a deleted card — accurate). An open raw-source buffer discards instead: its Apply writes the whole pre-tombstoneindex.mdand would silently undelete the card — a foreign delete is never reverted by a stale buffer. A card hard-deleted externally (folder gone) discards both — nowhere left to write, the inline-rename rule. Cards in the shown trash quasi-lane don't open at all — restore first (03-board-ui.md). Reopening a live card focuses the existing window.
Changes from Kanban
- Two-column composition replaces the pathfinder's vertical title/strip/body stack: body column (title atop it, created/modified line beneath) plus a full-height attributes sidebar.
- The sidebar revives the dropped readouts: created/modified return under the title; unknown frontmatter keys get the read-only Details section (the pathfinder's inspector casualties, rehomed).
- Empty body opens in Edit; Return in Preview enters Edit; Escape returns to Preview (the pathfinder always opened in Preview, toggle-only).
- Live task-list checkboxes in Preview — the pathfinder's preview was fully inert.
- Syntax-highlighted editor — the pathfinder used a plain monospaced
TextEditor. - Keyboard-navigable attachments with Space-QuickLook — the strip was pointer-only.
- The window gains a live board › lane subtitle.
Open questions
None currently — the embedded-attachment duplication question is closed (the sidebar shows every file), and the click-grammar pivot is recorded in 04-interactions.md.