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:
@@ -117,6 +117,7 @@ extension FrontmatterDocument {
|
||||
record(FrontmatterKeys.icon, icon)
|
||||
record(FrontmatterKeys.iconColor, iconColor)
|
||||
record(FrontmatterKeys.hero, hero)
|
||||
record(FrontmatterKeys.labels, labels)
|
||||
record(FrontmatterKeys.kind, kind)
|
||||
return found
|
||||
}
|
||||
@@ -270,6 +271,24 @@ extension FrontmatterDocument {
|
||||
}
|
||||
}
|
||||
|
||||
/// **A card's labels** (`FrontmatterKeys.labels`, whose doc comment carries the key's own story —
|
||||
/// including the 2026-08-09 reversal that took it off the reserved-tracker-keys list; the rules
|
||||
/// themselves are `CardLabels`).
|
||||
///
|
||||
/// The lenient family's shape, one collection up. A **sequence** reads as its string entries in
|
||||
/// file order, case-insensitively deduplicated with the first spelling winning. A **bare scalar**
|
||||
/// coerces to a one-element list (`labels: bug`) — the same "any scalar has a sensible reading"
|
||||
/// instinct `title` has, narrowed to strings for `CardLabels.name(of:)`'s stated reason. A
|
||||
/// **mapping**, and a non-string scalar, have no list reading at all: `.malformed`, rendering as no
|
||||
/// labels, bytes untouched, and a coerce-tier trace left behind.
|
||||
///
|
||||
/// A list holding nothing the reader can name — `labels: [{a: 1}]` — is `.valid([])` rather than
|
||||
/// malformed: the author wrote a list, which is the right shape, and it happens to contain no
|
||||
/// names. Those entries survive the next write (`FrontmatterDocument.setLabels`).
|
||||
public var labels: FieldValue<[String]> {
|
||||
read(FrontmatterKeys.labels) { value, _ in CardLabels.reading(of: value) }
|
||||
}
|
||||
|
||||
public var created: FieldValue<Date> { read(FrontmatterKeys.created) { value, _ in Self.date(value) } }
|
||||
public var modified: FieldValue<Date> { read(FrontmatterKeys.modified) { value, _ in Self.date(value) } }
|
||||
public var deleted: FieldValue<Date> { read(FrontmatterKeys.deleted) { value, _ in Self.date(value) } }
|
||||
|
||||
Reference in New Issue
Block a user