Realign code with the 2026-07-29 findings-resolution rulings

Nine rulings land as code. Reorders don't stamp — one container-change
predicate (WriteOperation.rewritesOrderOnly): within-container reorders
and the renumber rescale rewrite only order, while cross-lane, cross-board,
and trash moves stamp modified and clear modified-by; no trash special
case exists, and the m8 undo inverses conform through the same seam.
Copies are transactions: the root-strict/nested-lenient split retires for
a whole-subtree stampability preflight that refuses loudly naming the
offender, and every item-level copy severs remote/remote-state at every
level (whole-board forks carry them verbatim). Paste refuses, never
degrades: the embedded-index.md materialization and its loss row retire;
a missing staged snapshot produces nothing and posts an error-tone
one-shot named from manifest metadata. Coerce-tier fallbacks log through
the Defect stream with path context attached loader-side. Displacement is
level-uniform: a file squatting attachments inside a card heals by the
same rename ladder as board-root squatters; comments stays tolerated.
Delete Immediately joins card and lane context menus as Delete's
⌥-alternate with its own VO custom action, routed through an explicit
container so the menu target outranks standing selection. Agent guide v7
teaches the stamp discipline and the card-level attachments claim, and
sheds two stale v6 lines (lanes trash now; kind is taught). Verified
conformant, unchanged: edition-aware Undo/Redo disable, trash marquee
full-height backdrop.

Both schemes 1854 tests / 318 suites green; verify-editions 30/30.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-30 06:49:11 -04:00
parent 5ae48de0ea
commit 69084fdff7
27 changed files with 2159 additions and 542 deletions
+62
View File
@@ -39,7 +39,69 @@ public enum FieldValue<Value: Sendable & Equatable>: Sendable, Equatable {
}
}
/// One **lenient** field that had no sensible reading and fell back to its default the coerce
/// tier's observability record (01-storage-format.md § Frontmatter, ruled 2026-07-29: "A
/// no-sensible-reading fallback logs: field, path, and raw text, carried as coerce-tier entries in the
/// integrity service's Defect stream").
///
/// **Two of the three facts, because this layer only has two.** `FrontmatterFields` is a pure reading
/// of one document's bytes and has no idea which file it came from, so the *path* is attached by the
/// loader, which does (`CoercedFrontmatter`). Threading a path down here to satisfy the record's shape
/// would put filesystem context into the one layer that is deliberately free of it.
public struct CoercedField: Sendable, Equatable {
/// The frontmatter key, as the schema spells it.
public let key: String
/// The value exactly as written the raw source span, which is the only form worth recording:
/// this exists so that a shape observed in the wild can later be promoted to a heuristic heal, and
/// a normalized rendering of a value nobody could read would defeat that.
public let raw: String
public init(key: String, raw: String) {
self.key = key
self.raw = raw
}
}
extension FrontmatterDocument {
// MARK: - The coerce tier's own report
/// Every **lenient** field in this document that had no sensible reading, in schema order the
/// coerce tier's whole observability contribution (01-storage-format.md § Frontmatter, ruled
/// 2026-07-29: "the family posture: every silent recovery leaves a trace").
///
/// **Read-side only, and nothing branches on it.** The values still render as their defaults
/// untitled placeholder, width 1, no color, no icon, no timestamp the bytes on disk are still
/// preserved verbatim, and no banner is raised. The list exists so the fallback is *visible*: it is
/// "the one place where an observed-in-the-wild shape can later be promoted to a heuristic heal or
/// a notice".
///
/// **The strict fields are absent, and so is `deleted`.** `schema` and `order` are the *refuse*
/// tier a malformed one fails the load loudly (`IntegrityRules.validatedSchema`/`validatedOrder`),
/// so there is no silent recovery to leave a trace of. `deleted` is the odd one out on purpose: its
/// rule is *presence, not validity* (a malformed `deleted` still deletes `Lane`/`Card.isDeleted`),
/// so nothing falls back to a default and the migration reports it under its own defect anyway.
///
/// A document whose fields all read cleanly answers `[]`, which is the overwhelmingly common case
/// and costs one pass over the lenient fields.
public var coercedFields: [CoercedField] {
var found: [CoercedField] = []
func record(_ key: String, _ field: FieldValue<some Sendable & Equatable>) {
guard let raw = field.rawText else { return }
found.append(CoercedField(key: key, raw: raw))
}
record(FrontmatterKeys.title, title)
record(FrontmatterKeys.width, width)
record(FrontmatterKeys.created, created)
record(FrontmatterKeys.modified, modified)
record(FrontmatterKeys.modifiedBy, modifiedBy)
record(FrontmatterKeys.background, background)
record(FrontmatterKeys.icon, icon)
record(FrontmatterKeys.iconColor, iconColor)
record(FrontmatterKeys.kind, kind)
return found
}
// MARK: - Strict (structure the loader fails fast on `.malformed`)
public var schema: FieldValue<Int> {