A reserved key comes to life — the card window's sidebar grows a Labels section, and labels stops being somebody else's

`labels` has been a reserved tracker key since the rewrite: preserved verbatim, never
interpreted, drawn only as an anonymous row in the Details section beside `assignees` and
`due`. The owner's cards claim it for first-party use, so it joins the schema — read
leniently (a list of names, a bare scalar coercing to one, a mapping malformed and
preserved), written canonically (a quoted flow list in the order the user arranged, no
auto-sort), and removed outright when the last label goes, the way an expanded lane drops
`collapsed`.

Identity is case-insensitive and display is case-preserving, so a card carries `bug` once
however many ways the board spells it, and entries the reading cannot name ride through the
write untouched at the tail.

The section sits second, above Details — which is the point rather than a layout preference:
Details is where keys the app does *not* own are shown, and this key just stopped being one.
Rows rather than chips, because the sidebar is twenty-six characters wide. The add field
autocompletes against the board's own used-labels universe, derived from every live and
trashed card with no store beside the files, and says out loud when Return would mint a word
the board has never used.

Writes ride a `.relabel` operation of their own, because the commit composer has said
"Relabel card 'X'" since long before there was a control to press — and now the undo row says
it too.

Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
2026-08-09 12:06:01 -04:00
parent fd31ed24f4
commit da37ed61bf
24 changed files with 1928 additions and 29 deletions
+15
View File
@@ -169,6 +169,14 @@ public enum AppPreferences {
/// the key is declared here with its neighbours for `WindowID`'s reason.
public static let quickStyleBackgroundsKey = "quickStyleBackgrounds"
/// **The recently applied labels** the tie-break half of the card menu's "most frequently and
/// recently used" twelve (`LabelRecents`, which owns the list rule; `LabelRanking`;
/// `FrontmatterKeys.labels`, activated 2026-08-09). `quickStyleBackgroundsKey`'s neighbour in every
/// respect: an array of strings, most-recent-first, app-wide, a user preference and never board
/// data the labels a board *has* are derived from its own cards (`LabelIndex`), and this is only
/// a memory of what this user reached for.
public static let labelRecentsKey = "labelRecents"
/// **The board's zoom level** "app-wide and persisted across restarts" (11-command-nexus.md
/// View Actual Size; 03-board-ui.md Layout zoom). A rung on `BoardZoom.levels`, stored as
/// the multiplier itself. Read and written by `BoardZoomStore`, which owns the ladder's rules; the
@@ -347,6 +355,12 @@ public final class AppModel {
/// board-scoped and this list deliberately is not.
public let styleRecents: StyleRecents
/// The recently applied labels, app-wide (`LabelRecents`; `FrontmatterKeys.labels`). Owned here
/// for `styleRecents`' reason exactly app-scoped, persisted beside it, and reached by the card
/// context menu and the card window's sidebar through the environment, since a `BoardStore` is
/// board-scoped and this list deliberately is not.
public let labelRecents: LabelRecents
/// The board's app-wide zoom level (03-board-ui.md Layout zoom). Owned here for
/// `styleRecents`' reason exactly: app-scoped, persisted beside it, and reached by every board
/// window through the environment while the menu rows and the toolbar buttons, which live
@@ -688,6 +702,7 @@ public final class AppModel {
) {
boardRegistry = BoardRegistry(storageURL: registryStorageURL)
styleRecents = StyleRecents(defaults: preferences)
labelRecents = LabelRecents(defaults: preferences)
zoom = BoardZoomStore(defaults: preferences)
appearance = AppearanceStore(defaults: preferences)
printProfiles = PrintProfileStore(defaults: preferences)
+3
View File
@@ -492,6 +492,9 @@ struct CardWindowHost: View {
// editor feeds are app-wide state (02-architecture.md § Per-board app state), so
// they come from the model every window shares rather than from this board's store.
recents: appModel.styleRecents,
// The same argument one field over: the labels this user reached for lately are
// app-wide state (`LabelRecents`), so they come from the model every window shares.
labelRecents: appModel.labelRecents,
cardFolder: Self.cardFolder(root: store.rootURL, placement: placement),
bodyPresentation: bodyPresentation,
bodySession: session.body,