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:
@@ -405,14 +405,14 @@ struct FrontmatterAccessTests {
|
||||
#expect(document.title == .valid("Build the frontmatter engine with byte-perfect round-trip"))
|
||||
#expect(document.modifiedBy == .valid("claude"))
|
||||
#expect(document.created.value != nil)
|
||||
#expect(document.unknownFields.map(\.key) == ["source", "labels"])
|
||||
#expect(document.unknownFields.map(\.key) == ["source"], "`labels` is schema-owned since 2026-08-09")
|
||||
#expect(document.body.hasPrefix("Build the Frontmatter component.\n"))
|
||||
}
|
||||
|
||||
@Test func unknownKeysExcludeSchemaOwnedOnes() throws {
|
||||
let document = try FrontmatterDocument.parse(Fixture.rich)
|
||||
#expect(document.unknownFields.map(\.key) == [
|
||||
"project", "sphere", "labels", "template", "notes", "folded", "tagged", "quoted key",
|
||||
"project", "sphere", "template", "notes", "folded", "tagged", "quoted key",
|
||||
])
|
||||
}
|
||||
|
||||
@@ -438,8 +438,14 @@ struct FrontmatterAccessTests {
|
||||
|
||||
"""
|
||||
let document = try FrontmatterDocument.parse(text)
|
||||
// **`labels` left the reserved family on 2026-08-09** when the owner claimed it for
|
||||
// first-party use (`FrontmatterKeys.labels`) — it is schema-owned now, so it is read as a
|
||||
// field rather than carried as an unknown key. The other four are untouched, and the
|
||||
// byte-identical round trip below is unaffected either way: classification decides how a key
|
||||
// is *read*, never how it is written back.
|
||||
#expect(document.unknownFields.map(\.key)
|
||||
== ["labels", "assignees", "due", "remote", "remote-state", "template"])
|
||||
== ["assignees", "due", "remote", "remote-state", "template"])
|
||||
#expect(document.labels == .valid(["bug", "ui"]))
|
||||
#expect(document.serialized() == text)
|
||||
}
|
||||
|
||||
@@ -1004,7 +1010,7 @@ struct FrontmatterEditTests {
|
||||
#expect(reparsed.modifiedBy == .missing)
|
||||
#expect(reparsed.title == .valid("Renamed"))
|
||||
#expect(reparsed.unknownFields.map(\.key)
|
||||
== ["project", "sphere", "labels", "template", "notes", "folded", "tagged", "quoted key"])
|
||||
== ["project", "sphere", "template", "notes", "folded", "tagged", "quoted key"])
|
||||
#expect(reparsed.serialized() == document.serialized())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user