Build the template engine — board-as-template instantiation

A template is a board folder the ordinary loader reads — no second
schema, no Swift catalog. BoardTemplate became exactly that: a loaded
BoardModel with chooser-facing derivations, the lane-title stub gone.
TemplateEngine instantiates by the copy-remint-restamp walk: .git and
.trash excluded at top level only — both names mean something at a
board root and nowhere else, and .gitignore must survive — every
materialized folder reminted, created/modified stamped fresh (born
today, not forked), modified-by cleared, the template: key carried
inert, the blurb and style inherited, and loose card files normalized
at this import boundary per the paste precedent so a new board never
opens with a notice about a mess its own birth made. Legacy deleted:
keys copy through verbatim to the one migrator — stripping would
resurrect, skipping would destroy. Atomicity is construct-then-clean:
a sibling temp can be sandbox-refused and a cross-volume rename is
just a second copy, so the call removes what it created on every
non-board exit and never touches an occupied destination. The
cancellable per-item walk extracted into BoardTreeCopy serves
Duplicate and instantiation with two parameters — top-level exclusions
and folder-attribute carriage, the only axes they differ on.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-28 18:46:23 -04:00
parent 797d020d01
commit b6f559375b
13 changed files with 1446 additions and 316 deletions
+11 -2
View File
@@ -748,7 +748,13 @@ public enum BoardWriter: Sendable {
/// ones a caller can stamp them without re-deriving any path. The mint only has to avoid
/// what is on disk in that folder: the siblings not yet renamed are still there under their
/// original names, and `freshUUIDName` checks for exactly that.
private static func remintDescendants(
///
/// **Internal rather than `private`**: template instantiation (`TemplateEngine`) is the same
/// remint one level up "mint fresh GUIDs for every lane/card folder" (09-templates.md
/// Instantiation) is `copyItem`'s rule applied to a whole board rather than to one item, and
/// pointing this at a copied *board root* is literally that. A second implementation of "which
/// folders are identities" is exactly what must not exist.
static func remintDescendants(
of folder: URL,
collecting copied: inout [URL],
operation: WriteOperation
@@ -767,7 +773,10 @@ public enum BoardWriter: Sendable {
/// missing, unreadable, or uneditable `index.md` is left exactly as the copy found it rather
/// than failing the gesture. `order` is not touched: a nested item keeps its rank among its
/// own siblings, which travelled with it.
private static func stampCopiedDescendant(
///
/// **Internal rather than `private`**, with `remintDescendants` and for its reason: an
/// instantiated board's lanes and cards are stamped by this exact rule, leniency included.
static func stampCopiedDescendant(
at folder: URL,
stamps: CopyStamps,
now: Date,