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
+16
View File
@@ -589,6 +589,22 @@ public enum FrontmatterKeys {
public static let remote = "remote"
public static let remoteState = "remote-state"
/// **A comment's self-reported author** (01-storage-format.md § Enhanced schema, the
/// `kind: comment` field table): "lenient self-reported *content*, not overlay: **unlike
/// `modified-by` it survives app writes**; the app writes the macOS account's full name, agents
/// write their own, tracker sync writes the remote author verbatim, and missing renders
/// unattributed".
///
/// **Named here without joining `schemaOwned`**, `remote`'s precedent and its reason turned
/// around: the key belongs to the comment field table and to no other kind, so on a board, a lane
/// or a card it is an ordinary unknown key and `schemaOwned` is exactly the set the card
/// window's Details section subtracts. Listing it would *hide* a hand-added `author:` from the one
/// surface that exists to show hand-added keys; a comment has no such surface to be affected
/// either way.
///
/// Nothing clears it, anywhere: `updateIndex` clears `modified-by` and only that.
public static let author = "author"
public static let schemaOwned: Set<String> = [
schema, title, order, width, created, modified, modifiedBy, deleted, background, icon,
iconColor, kind,