Comments, phase 1 — storage, writer primitives, and the undo inventory

The kind: comment field table lands in IntegrityRules (the per-kind
hook's first exercise), CommentThread reads one card's thread
window-scoped (the board walk stays O(cards)), and CommentWriter gains
the five gestures: draft save, post (rename .draft to a fresh UUID,
created/modified restamped in the bracket), edit, delete into
comments/.trash/, and the purge with its crash-residue memo. Post and
delete register move-based undo steps; draft saves, edits, and the
purge deliberately register nothing (13's no-capture rule). Copy
boundaries strip comments/.trash, carry .draft verbatim, and remint
threads; comments graduates to a displacing claimed name, with .draft,
.trash, and a comment's attachments claimed one level down.
CommentPath classifies changed paths into the 06 verb family for
later announcer/composer wiring.

One stated narrowing pending a ruling (filed on the findings board):
the copy transaction's refuse-whole preflight stays cards-and-lanes —
an unstampable copied comment copies verbatim with a log line, because
comment defects never refuse.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-30 19:36:21 -04:00
parent e6dd4c0aa6
commit f68ac3668e
16 changed files with 2881 additions and 63 deletions
+8
View File
@@ -95,6 +95,7 @@ extension FrontmatterDocument {
record(FrontmatterKeys.created, created)
record(FrontmatterKeys.modified, modified)
record(FrontmatterKeys.modifiedBy, modifiedBy)
record(FrontmatterKeys.author, author)
record(FrontmatterKeys.background, background)
record(FrontmatterKeys.icon, icon)
record(FrontmatterKeys.iconColor, iconColor)
@@ -158,6 +159,13 @@ extension FrontmatterDocument {
/// Schema-owned, not an unknown key: the app clears it on every app-mediated write.
public var modifiedBy: FieldValue<String> { read(FrontmatterKeys.modifiedBy, Self.string) }
/// A comment's self-reported `author` lenient like every other string field, and **content**
/// rather than overlay: no app write ever clears it (01-storage-format.md § Enhanced schema; see
/// `FrontmatterKeys.author`). On any other kind the key is an ordinary unknown one; reading it
/// here costs the same one pass and keeps the coerce tier's trace complete for the one kind whose
/// field table names it.
public var author: FieldValue<String> { read(FrontmatterKeys.author, Self.string) }
/// The object's kind as written `board`, `lane`, `card` (01-storage-format.md § Frontmatter,
/// re-ruled 2026-07-29). Lenient like every other string field: any scalar coerces to the text
/// the author typed, and **the value is never policed** a reading outside the schema's three