Files
lanework/DESIGN/11-command-nexus.md
T
rzen b0ffff1aa1 The app learns Appearance — Auto, Light, Dark from the View menu and a toolbar pull-down
View ▸ Appearance (11-command-nexus.md): three radio-exclusive rows,
app-wide, persisted, needing no window in front — the View menu's new
last group. AppearanceStore owns the override's rules (absent key =
Auto, lenient reads degrade to Auto, remove-at-default) with an
injectable apply seam so test hosts never touch NSApp; the one real
apply hands NSApp.appearance its answer in applicationDidFinishLaunching,
the global side effect KanbanApp.init must not carry. The board toolbar
gains its first .picker item — an NSMenuToolbarItem whose rows re-fetch
their spec fresh, checkmark read at menu-open like every other menu row —
and Appearance joins the search field as the second default item,
centered beside it (03-board-ui.md ▸ Toolbar, ratified 2026-08-07).

Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
2026-08-07 12:55:45 -04:00

129 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Command Nexus
The single source of truth for **every command and action the app can perform** — what exists, the context it applies in, its default binding, and whether it can be customized. Behavior is specified in the home docs (cross-referenced per row); this inventory is normative for *existence, context, and bindings*: a command absent here doesn't exist, and adding one means adding a row here first. 04-interactions.md's contract underwrites the tables — every board function has a menu item, keyboard-reachable and remappable, with a default chord only where one earns its keyspace — the "— (no default)" rows below are deliberate — and configuration as the one carve-out (04 ▸ The map) — and 04 remains normative for the behavior behind the rows.
## Customizability classes
| Class | Meaning | Customization |
|---|---|---|
| **M** | Menu command | Remappable system-natively (System Settings ▸ Keyboard ▸ App Shortcuts — 04 ▸ Configurable bindings). Titles are API. |
| **M** | Menu command, effectively fixed | Undo/Redo only: NSUndoManager rewrites their titles dynamically, which defeats title-matched remapping (04). |
| **G** | Fixed grammar key | Platform grammar, deliberately not remappable — Finder's own Return/arrows aren't either (04 ▸ Grammar). |
| **P** | Pointer grammar | Clicks, drags, modifiers — not customizable. |
| **C** | Configuration control | Form-like controls (board popover, board settings sheet, chooser, welcome); the keyboard path is reachability (Board Info ⌘I / Board ▸ Board Settings… + Tab-reachable controls), not bindings — 04's configuration carve-out, containers per the 2026-07-31 popover/sheet split. |
**Toolbar presence is a separate axis**, orthogonal to the classes: toolbar items mirror menu commands, their presence per window is user-customizable (Customize Toolbar — 03-board-ui.md ▸ Toolbar; defaults and catalogs live there), and a toolbar is never a function's only home. Labels match menu titles except Undo/Redo, whose toolbar labels stay static (03).
## Menu commands (M unless noted)
| Menu | Command | Default | Context |
|---|---|---|---|
| App | Settings… | ⌘, | Everywhere; the app-wide preferences pane. v1 holds one control: "Restore open boards at launch" (02 ▸ Launch and window lifecycle) |
| File | New Card | ⌘N | Board window; disabled on a zero-lane board. Target rule: 04 |
| File | New Lane | ⇧⌘N | Board window |
| File | New Board… (opens the template chooser) | ⌥⌘N | Everywhere |
| File | Open… | ⌘O | Everywhere; standard open panel (boards = `.kanban` packages and extension-less board folders — 01) |
| File | Open Recent ▸ (with Clear Menu) | — | Everywhere; reads the board registry (02) |
| File | Board Info (toggles the board popover — opens it closed, closes it open) | ⌘I | Board window |
| File | Duplicate (the board — a Finder-style "copy" sibling, 03 ▸ Welcome; never the selection) | ⇧⌘S | Board window |
| File | Save as Template | — (no default) | Board window; 09-templates.md |
| File | Reveal in Finder | — (no default) | Board window: the selection's folder(s), or the board root with nothing selected; card window: the card's folder — the selected attachment's file instead when the attachments section is focused; welcome: the selected recent's folder (disabled on unavailable rows) — the context-menu entry's required twin |
| File | Add Attachment… | ⇧⌘A | Card window |
| File | Add Comment | — (no default) | Card window (all tiers — 12); if Show Comments is off, turns it on (persisted, the same user choice) and focuses the composer — 05 ▸ The comments column |
| File | Delete | ⌘⌫ | Board window, any card or lane selection — staged by place (resettled 2026-07-28; lanes rejoined 2026-07-29): board cards and lanes move to `.trash/`, trash selections delete permanently (03's recoverability confirm — freight-counting for lanes). Deliberately **not** extended to the card window: an enabled ⌘⌫ key equivalent would steal delete-to-line-start from the window's text surfaces, so there the card's delete is the sidebar Actions button (05). **Delete Immediately (⌥⌘⌫) is deliberately absent** (removed 2026-07-30): permanence is only reachable inside the trash — 03 ▸ Trash |
| File | Empty Trash… (confirmed) | ⇧⌘⌫ | Board window, trash shown and non-empty (whole-trash scope, search-independent — 03 ▸ Trash) |
| File | Close | ⌘W | Any window; flushes per 02 ▸ Windows |
| Edit | Undo / Redo (M) | ⌘Z / ⇧⌘Z | Focus-routed (06 ▸ Undo routing): text undo in a focused editor, git undo otherwise; git undo disabled on no-git and repo-nested boards, during 06's abnormal-state pause (detached HEAD, in-progress merge/rebase), and under the read-only lock (02) |
| Edit | Cut / Copy / Paste | ⌘X / ⌘C / ⌘V | Board window: cards and lanes (cards-XOR-lanes selections; lane paste lands after the anchor lane — 04 ▸ Clipboard; on a zero-lane board only a lane payload pastes — 04 ▸ ⌘N target rule); in the trash, ⌘C copies out and ⌘X/⌘V is the keyboard restore path (resettled 2026-07-28 — 04 ▸ The trash); paste never targets the trash; text editors: standard text clipboard |
| Edit | Select All | ⌘A | Board: all visible cards on the active board side (filter-respecting); on the active trash side it selects all visible trash rows, both kinds — the container boundary decides which "all" is meant, and trash selection is kind-blind (04 ▸ The trash); text editors: the text |
| Edit | Find | ⌘F | Board window: board search (04 ▸ Search); card window: find-in-text (05) |
| Edit | Find Next / Find Previous | ⌘G / ⇧⌘G | Card window: the find bar's stepping — the rows enable only while the comments-thread find bar is up and step *that* bar; otherwise they disable and the chord falls through the responder chain to the focused text surface's own NSTextFinder stepping (pinned 2026-07-31 — routing by focus applied to find); disabled in the board window — board search is a live filter, not a cursor. **Use Selection for Find (⌘E) is deliberately absent**: the chord belongs to View ▸ Edit Body, which outranks the text view's binding; a user who wants it back remaps Edit Body system-natively |
| Board | Open Card | ⌘↩ | Board window, sole selected live card; during an inline title edit (placeholder or rename), commits it and opens — the one board command enabled mid-edit (04 ▸ Grammar) |
| Board | Rename | — (cards: Return in place) | Board window, sole selected card/lane; a lane's only rename path (Return on a lane creates); exists for completeness and remapping |
| Board | Style… (the style editor; selection-aware) | ⌥⌘S | Board window: selected cards or lane; nothing selected = the board |
| Board | Move Up / Move Down | ⌥⌘↑ / ⌥⌘↓ | Card selection within one lane (within-lane sort, logical order; non-contiguous selections gather behind their first card on the first press); disabled when the selection spans lanes; inert on lanes and on trash cards |
| Board | Move Left / Move Right | ⌘← / ⌘→ | Lane selection only (one slot; never into the trash) — cards cross lanes by drag or Cut/Paste, not ⌘-arrows; disabled while any text control is focused (04 ▸ Grammar, caret-chords rule) |
| Board | Increase Lane Width / Decrease Lane Width (the stepper's re-divide semantics, never the window's size — 03 ▸ Lane) | ⌥⌘→ / ⌥⌘← | Selected lane(s) — batches over a multi-lane selection like style (03 ▸ Lane); disabled while any text control is focused (04 ▸ Grammar, caret-chords rule) |
| Board | Pull / Push | — (no default) | Remote-backed boards only (07); disabled during 06's abnormal-state pause (the whole git surface holds) and on an unresolvable remote (07's one-time remote picker case); popover twins exist |
| Board | Board Settings… | — (no default) | Opens the board settings sheet (03 — the 2026-07-31 popover/sheet split); popover row twins it |
| View | Show Trash (checkmark toggle) | — (no default) | Board window — ⇧⌘T is deliberately left to the system's Show Tab Bar: window tabbing stays enabled (settled; see Standard macOS furniture), so the chord is the system's; assign one via the remapping mechanism if wanted (04 ▸ Configurable bindings) |
| View | Zoom In | ⌘+ | Board window; steps the board's zoom one rung up the ladder (03 ▸ Layout — zoom). Disabled at the top rung, and while a drag session is in flight (a drag freezes geometry the level feeds — the dragged run's heights and the resting-layout cache) |
| View | Zoom Out | ⌘− | Board window; the twin, one rung down. Disabled at the bottom rung and under the same guard |
| View | Actual Size | ⌘0 | Board window; returns to 100%, where the strip renders exactly what it rendered before zoom existed. Disabled when already there, and under the same guard. The level is app-wide and persisted across restarts (the Show Comments precedent) — a zoom is a viewing comfort, not a property of any one board |
| View | Edit Body (checkmark toggle) | ⌘E | Card window; disabled while Raw Source is active |
| View | Show Comments (checkmark toggle) | — (no default) | Card window; app-wide, persisted across restarts (re-ruled 2026-07-29 — no content-derived auto-show; 05 ▸ The comments column) |
| View | Comments Beside Body (checkmark toggle) | — (no default) | Card window; checked = side-by-side (default), unchecked = body over comments; app-wide, persisted (05 ▸ Composition) |
| View | Raw Source (checkmark toggle; toggling off = Apply) | ⌥⌘E | Card window |
| View | History | — (no default) | Card window; focuses the sidebar History section (05); git boards only — section absent, item disabled on mode none / repo-nested |
| View | Appearance ▸ Auto | — (no default) | Everywhere (no board or card window needed); app-wide, persisted across restarts — follows the system appearance; radio-exclusive with Light/Dark, checkmark on the active one (03-board-ui.md ▸ Toolbar) |
| View | Appearance ▸ Light | — (no default) | Everywhere; app-wide, persisted across restarts; radio-exclusive with Auto/Dark |
| View | Appearance ▸ Dark | — (no default) | Everywhere; app-wide, persisted across restarts; radio-exclusive with Auto/Light |
| Window | Welcome to Lanework | — (no default) | Everywhere; shows (or focuses) the welcome window (02 ▸ Launch and window lifecycle) |
## Fixed grammar keys (G)
All board grammar keys are inert while a title editor is focused, and menu dispatch narrows to the text domain — board-scoped commands disable, text chords route to the field, Open Card ⌘↩ excepted (04 ▸ Grammar, focused-editor rule).
| Key | Context | Action |
|---|---|---|
| Arrows / ⇧-arrows | Board window | Spatial card navigation / extend selection; lane selected: ←/→ move lane selection; shown trash is the last container |
| ⌥↑ / ⌥↓ / ⌥← / ⌥→ | Board window | Jump: lane's first/last card; first/last lane; ⌥→ reaches the shown trash |
| Return | Board, lane selected | Create card at its bottom (placeholder; Return commits and re-selects the lane) |
| Return | Board, sole selected card | Inline rename; committing empty removes `title`; inert on multi-card selections |
| Escape | Board window | One layer per press: abandon editor, else clear search (focus to board), else deselect |
| ⌫ | Board, any selection | Delete, staged by place — plain-key synonym of File ▸ Delete (board side moves to `.trash/`, trash side deletes permanently with 03's confirm), kept grammar so no second "Delete" title exists (04) |
| Return | Card window, Preview | Enter Edit |
| Escape | Card window, Edit | Return to Preview |
| Return | Card window, title field | Commit title, focus into body |
| ⌘↩ | Card window, comment composer or inline comment editor focused | Post the draft (rename + restamp, one commit) / end the edit session at its commit point — 05 ▸ The comments column; twinned by the Comment / Save buttons |
| Escape | Card window, comment composer focused | Focus moves out, draft file untouched — Escape never discards a draft (ruled 2026-07-29; 05 ▸ The comments column) |
| Escape | Card window, inline comment editor focused | Cancel — revert to session-start bytes and end the session, the Cancel button's keyboard twin (05) |
| Escape | Card window, title field | Abandon: revert to the on-disk title, focus into body — routes by focus, winning over Edit-mode's Escape while the field is focused (05) |
| Escape / ⌘↩ | Card window, source mode | Cancel / Apply (leaving-by-toggle is Apply too — 05) |
| Arrows / Space / Return / ⌫ | Card window, attachments section focused | Row navigation / QuickLook / open / Remove to *system* Trash (05) |
## Pointer grammar (P)
- **Selection clicks** (board): click selects, ⌘-click toggles, ⇧-click range-extends, click-drag rubber-bands; lane empty-space click selects the lane, double-click creates a card. **Clicking never edits**; fast double-click opens the card window (04 ▸ Selection).
- **Drag & drop — the locality model** (04): within-board move / cross-board copy; **⌥ always forces copy, ⌘ always forces move**; multi-drag; lane header is the lane drag surface; drag-to-restore from the trash.
- **Lane edge drag** (03 ▸ Lane): window-growing resize between integer widths — the one width control that moves the window.
- **Finder file drops** (04): onto a card = attach; onto lane empty space = one card per file; anywhere on the card window = attach (05's payload-split precedence).
- **Preview** (05): task-list checkbox toggle (the one interactive exception), link opens, text selection. **In-content controls aren't P-only** (settled): checkboxes and links are real controls in the focus/accessibility tree, so Full Keyboard Access + Space and VO-Space reach them (05 ▸ Task-list checkboxes) — content rides the system focus model rather than earning command rows; "a command absent here doesn't exist" scopes to commands, not content.
- **Lane header new-card button** (03, labeled "New card in ⟨lane⟩" — 10): creates in **the button's lane**, appended at the bottom — the click names its target, overriding 04's selection-derived ⌘N target rule (settled); placeholder and abandon semantics exactly as ⌘N. The card window's attachments-section **quiet add affordance** (05) is the same class: a pointer twin of File ▸ Add Attachment…, no separate behavior.
- **Attachment rows** drag out their file URL (05). **Welcome rows**: single click selects, double click opens (03).
## Context menus
Context menus are the per-item action inventory VoiceOver reads (10 ▸ The board through VoiceOver). Every entry is a twin of a menu command, a fixed grammar key, or a configuration control — no function's only home:
| Surface | Entries |
|---|---|
| Card | Open, Rename, Style…, quick-style recents row (03), Delete (the ⌥-alternate Delete Immediately row retired with the command, 2026-07-30) |
| Lane | One menu, invoked on the header or lane empty space (settled — a full lane still has its header): Rename, Style…, quick-style recents row (03), Width control (stepper — menu twins Increase/Decrease Lane Width), Delete |
| Trash selection | Delete (permanent — 03's recoverability confirm), Reveal in Finder (inspection before a purge; twin of File ▸ Reveal in Finder, not edit-shaped, enabled on trash selections — 04 ▸ The trash) |
| Attachment row | Open, Remove (system Trash) — twins of the focused section's grammar keys (Return / ⌫ — 05); Reveal in Finder — twin of File ▸ Reveal in Finder in its attachments-focused context |
| Comment | Edit (inline session — 05 ▸ The comments column), Delete (immediate, undoable — 01), Reveal in Finder |
| Welcome recent | Open, Reveal in Finder, Forget (C — registry management, welcome-scoped) |
## Configuration controls (C)
- **Board popover** (Board Info ⌘I — 03 ▸ Board popover; light surface per the 2026-07-31 popover/sheet split): board rename; embedded style editor; posture lines (repo-nested explanation, unreadable/paused states — 06); branch display and switch picker; ahead/behind with Pull/Push buttons and the status badges; the Board Settings… row.
- **Board settings sheet** (Board ▸ Board Settings…, or the popover row — 03 ▸ Board settings sheet): add-git (mode none, 06); branch create; commit-identity name/email (06); add/change remote with inline verify, credential fields, the SSH key surface — machine key Copy + Verify, key import by paste or drag, the per-host key picker, removal of an unreferenced import, confirm-gated machine-key regeneration — the Authentication-needed capture and TOFU confirms (07); the push-on-commit toggle.
- **Style editor** (three anchors — 03 ▸ Styling ▸ Controls): grids arrow-navigable, every well Tab-reachable.
- **Template chooser** (09): template selection; Reveal in Finder for the user store.
- **Welcome** (03): recents list; Forget.
- **Comments header** (05 ▸ The comments column): the sort-direction control (ascending/descending, app-wide persisted) — Tab-reachable beside the count.
## Standard macOS furniture
System-provided: App menu (About, Hide, Quit), Window menu, Help (carries the one line teaching the System Settings remap path — 04). The app's own additions to this furniture are inventoried in Menu commands above — App ▸ Settings… and Window ▸ Welcome to Lanework; the remaining app-wide preferences, quick-style recents and `NSUserKeyEquivalents`, need no UI. **No Print story in v1** (⌘P unused). Customize Toolbar… per system convention (03). **Window tabbing stays enabled** (settled): the system's Show Tab Bar / tab items appear with their standard chords — ⇧⌘T is the system's, which is why Show Trash ships without a default (Menu commands above); tabbed board windows are ordinary system behavior, each tab still a full board window (a tab's saved per-board frame applies when it stands alone — 02-architecture.md).
## Changes from Kanban
- New doc — no pathfinder counterpart; 04's map table moved here (04 keeps the behavioral rules).
- The first compilation audit added two commands that existed only as context/pointer surfaces, violating 04's contract: **File ▸ Open… (⌘O)** and **File ▸ Reveal in Finder** (no default; selection-aware).
## Open questions
None currently.