import Foundation import Testing @testable import Kanban /// Template **instantiation** — "create a board from this template", on disk (09-templates.md /// ▸ Instantiation). /// /// The round trip is the heart of it: instantiate, then load the result through the ordinary /// `BoardLoader` and ask whether what came back is a board born today. Everything 09 promises is an /// assertion about those bytes — /// /// - copied, **minus `.trash/` and `.git`**, and minus nothing else; /// - **fresh GUIDs** at every level — no identity survives from the template; /// - **fresh `created`/`modified`**, `modified-by` cleared — born today, not forked; /// - `title` = the name the user typed into the save panel; /// - `template:` carried and inert; strays, bodies and attachment bytes verbatim. /// /// — plus the promise that makes it safe to run at all: **nothing half-made is ever left at the /// destination**, whether the user cancelled or the disk said no. // MARK: - Helpers /// `writeFailure`'s twin for the engine's two-outcome vocabulary. private func instantiationFailure(_ operation: () throws -> Void) -> TemplateEngine.Failure? { do { try operation() Issue.record("expected the instantiation to fail, but it succeeded") return nil } catch let failure as TemplateEngine.Failure { return failure } catch { Issue.record("expected a TemplateEngine.Failure, got \(error)") return nil } } /// Every path under `root`, root-relative, hidden entries included. private func tree(of root: URL) -> Set { var paths: Set = [] let walker = FileManager.default.enumerator(at: root, includingPropertiesForKeys: nil, options: []) while let url = walker?.nextObject() as? URL { paths.insert(url.path.replacingOccurrences(of: root.path + "/", with: "")) } return paths } /// Every UUID-shaped folder name under `root` — the identities a copy either kept or reminted. private func identities(under root: URL) -> Set { Set(tree(of: root) .flatMap { $0.split(separator: "/").map(String.init) } .filter(BoardLoader.isUUIDShaped) .map { $0.lowercased() }) } /// The two GUIDs the bundled Basic template ships with — hard-coded on purpose: "no id survives /// from the template" is only an assertion if the test knows the ids it is looking for. private enum BundledBasic { static let toDo = "3f2a9c41-6b0e-4d7a-9f31-2c8b5e0a7d14" static let done = "8d3b1f22-4a7c-4e59-8b06-1d9f3c2e6a85" } private func bundledBasic() throws -> BoardTemplate { try #require(TemplateEngine.bundledTemplates().first { $0.slug == "basic" }) } // MARK: - The hand-built template /// A template carrying everything 09 and 01 have a rule about: the two exclusions, a legacy /// `deleted:` key, strays at board and lane level, a symlink, an attachment, and a loose file /// beside a card's `index.md`. private struct FixtureTemplate { let fixture: WriterFixture let root: URL static let name = "Fixture.kanban" static let blurb = "A fixture blurb, which becomes the new board's description.\n" init() throws { fixture = try WriterFixture() root = fixture.url(Self.name) let path = Self.name // The board: a template key, an agent overlay, old stamps, and someone else's attribution. try fixture.item(path, """ --- schema: 1 title: Fixture Template icon: rectangle.split.3x1 iconColor: fern template: {order: 42} project: lanework created: 2026-01-01T09:00:00Z modified: 2026-02-02T09:00:00Z modified-by: claude --- \(Self.blurb) """) // Board-level strays — "the copy is literal apart from the stated exclusions". try fixture.file("\(path)/CLAUDE.user.md", Data("board instructions\n".utf8)) try fixture.file("\(path)/.gitignore", Data(".DS_Store\n".utf8)) // The two exclusions. try fixture.file("\(path)/.git/HEAD", Data("ref: refs/heads/main\n".utf8)) try FileManager.default.createDirectory( at: root.appendingPathComponent(".git/objects", isDirectory: true), withIntermediateDirectories: true ) try fixture.item("\(path)/.trash/\(Ident.card4)", Item.rich(order: "1024", title: "Thrown Away")) // A symlink, never traversed, copied as a link. try FileManager.default.createSymbolicLink( atPath: root.appendingPathComponent("link.md").path, withDestinationPath: "../outside.txt" ) // A lane with a starter card: an attachment, a loose file, and a body. try fixture.item("\(path)/\(Ident.lane1)", Item.rich(order: "1024", title: "To Do")) try fixture.item("\(path)/\(Ident.lane1)/\(Ident.card1)", Item.rich(order: "1024", title: "Starter")) try fixture.file("\(path)/\(Ident.lane1)/\(Ident.card1)/attachments/shot.png", Data([0x01, 0x02, 0x03])) try fixture.file("\(path)/\(Ident.lane1)/\(Ident.card1)/notes.txt", Data("loose\n".utf8)) // A card an older app version tombstoned in place — the legacy `deleted:` key. try fixture.item("\(path)/\(Ident.lane1)/\(Ident.card2)", """ --- schema: 1 title: Legacy Tombstone order: 2048 deleted: 2026-01-01T00:00:00Z --- still here """) // A second lane with a stray folder of its own — lane-level strays stay verbatim. try fixture.item("\(path)/\(Ident.lane2)", Item.rich(order: "2048", title: "Done")) try fixture.file("\(path)/\(Ident.lane2)/notes/scratch.md", Data("scratch\n".utf8)) } func tearDown() { fixture.tearDown() } func template() throws -> BoardTemplate { switch TemplateEngine.load(templateAt: root, origin: .user) { case let .success(template): return template case let .failure(error): throw error } } /// Where an instantiation lands — a sibling of the template inside the same temp root, which is /// also what makes "nothing was left behind" a one-line assertion. func destination(named name: String = "New Board.kanban") -> URL { fixture.url(name) } } // MARK: - Round trip @Suite("TemplateEngine — the bundled round trip") struct TemplateEngineRoundTripTests { @Test("Instantiating Basic produces a board that loads clean") func basicLoadsClean() throws { let fixture = try WriterFixture() defer { fixture.tearDown() } let destination = fixture.url("Q3 Planning.kanban") try TemplateEngine.instantiate(template: try bundledBasic(), to: destination, title: "Q3 Planning") let result = try BoardLoader.load(boardRoot: destination) #expect(result.warnings.isEmpty, "a board the app just instantiated must load without a murmur") #expect(result.looseCardFiles.isEmpty) #expect(result.legacyTombstones.isEmpty) #expect(result.model.lanes.map { $0.title.value } == ["To Do", "Done"]) #expect(result.model.lanes.map(\.order) == [1024, 2048]) } @Test("The title is the document name the user chose, not the template's") func titleIsTheChosenName() throws { let fixture = try WriterFixture() defer { fixture.tearDown() } let destination = fixture.url("Q3 Planning.kanban") try TemplateEngine.instantiate( template: try bundledBasic(), to: destination, title: TemplateEngine.documentName(of: destination) ) // 01-storage-format.md § Board naming: display name and folder name start out matching. #expect(try BoardLoader.load(boardRoot: destination).model.title.value == "Q3 Planning") } @Test("An extension-less location is as legal a board, and keeps its whole name as the title") func extensionlessLocationWorks() throws { let fixture = try WriterFixture() defer { fixture.tearDown() } let destination = fixture.url("Plain") try TemplateEngine.instantiate( template: try bundledBasic(), to: destination, title: TemplateEngine.documentName(of: destination) ) #expect(try BoardLoader.load(boardRoot: destination).model.title.value == "Plain") } @Test("No id survives from the template — every lane folder is a fresh mint") func everyIdentityIsReminted() throws { let fixture = try WriterFixture() defer { fixture.tearDown() } let destination = fixture.url("Minted.kanban") try TemplateEngine.instantiate(template: try bundledBasic(), to: destination, title: "Minted") let minted = identities(under: destination) #expect(minted.count == 2) #expect(minted.isDisjoint(with: [BundledBasic.toDo, BundledBasic.done]), "template GUIDs are inert — instantiation remints at its own boundary") #expect(minted.allSatisfy { $0 == $0.lowercased() && UUID(uuidString: $0) != nil }) } @Test("Born today: created and modified are fresh, and modified-by is absent") func stampsAreFresh() throws { let fixture = try WriterFixture() defer { fixture.tearDown() } let destination = fixture.url("Born.kanban") let start = Date() try TemplateEngine.instantiate(template: try bundledBasic(), to: destination, title: "Born") let model = try BoardLoader.load(boardRoot: destination).model let template = try bundledBasic().model let boardCreated = try #require(model.created.value) #expect(boardCreated.timeIntervalSince(start) > -2, "born today, not forked from the template") #expect(boardCreated != template.created.value) #expect(try #require(model.modified.value).timeIntervalSince(start) > -2) #expect(model.modifiedBy.isMissing) for lane in model.lanes { #expect(try #require(lane.created.value).timeIntervalSince(start) > -2) #expect(try #require(lane.modified.value).timeIntervalSince(start) > -2) #expect(lane.modifiedBy.isMissing) } } @Test("The template: key is carried onto the instantiated board, inert") func templateKeyIsCarriedInert() throws { let fixture = try WriterFixture() defer { fixture.tearDown() } let destination = fixture.url("Inert.kanban") try TemplateEngine.instantiate(template: try bundledBasic(), to: destination, title: "Inert") let model = try BoardLoader.load(boardRoot: destination).model let template = try bundledBasic().model #expect(model.template == template.template, "kept, ignored, and preserved like any unknown key") #expect(model.document.body == template.document.body, "the blurb becomes the new board's description, byte for byte") } @Test("The icon and its tint are inherited from the template") func iconIsInherited() throws { let fixture = try WriterFixture() defer { fixture.tearDown() } let destination = fixture.url("Styled.kanban") let basic = try bundledBasic() try TemplateEngine.instantiate(template: basic, to: destination, title: "Styled") let model = try BoardLoader.load(boardRoot: destination).model #expect(model.icon.value == basic.model.icon.value) #expect(model.iconColor.value == basic.model.iconColor.value) } @Test("The bundled template itself is never touched by instantiating it") func theTemplateIsReadOnly() throws { let fixture = try WriterFixture() defer { fixture.tearDown() } let basic = try bundledBasic() let before = tree(of: basic.url) let bytes = try Data(contentsOf: basic.url.appendingPathComponent("index.md")) try TemplateEngine.instantiate(template: basic, to: fixture.url("Copy.kanban"), title: "Copy") #expect(tree(of: basic.url) == before) #expect(try Data(contentsOf: basic.url.appendingPathComponent("index.md")) == bytes) } } // MARK: - The hand-built template @Suite("TemplateEngine — a hand-dropped template's edges") struct TemplateEngineFixtureTests { @Test("`.git` and `.trash/` are the two exclusions, and they are the only ones") func theTwoExclusionsAreExcluded() throws { let source = try FixtureTemplate() defer { source.tearDown() } let destination = source.destination() try TemplateEngine.instantiate(template: try source.template(), to: destination, title: "New Board") let paths = tree(of: destination) #expect(!paths.contains { $0 == ".git" || $0.hasPrefix(".git/") }, "a template is content, not history — no board is silently born in git mode") #expect(!paths.contains { $0 == ".trash" || $0.hasPrefix(".trash/") }, "a new board isn't born with trash") // And everything else did come along — `.gitignore` included, which is a stray the // exclusion must not swallow: the two exclusions are exact names, not prefixes. #expect(paths.contains("CLAUDE.user.md")) #expect(paths.contains(".gitignore")) #expect(paths.contains("link.md")) #expect(paths.contains { $0.hasSuffix("notes/scratch.md") }, "a lane-level stray folder is a resident") } @Test("Strays and attachments arrive byte for byte") func straysAndAttachmentsAreVerbatim() throws { let source = try FixtureTemplate() defer { source.tearDown() } let destination = source.destination() try TemplateEngine.instantiate(template: try source.template(), to: destination, title: "New Board") #expect(try Data(contentsOf: destination.appendingPathComponent("CLAUDE.user.md")) == Data("board instructions\n".utf8)) #expect(try Data(contentsOf: destination.appendingPathComponent(".gitignore")) == Data(".DS_Store\n".utf8)) let card = try #require(cardFolders(under: destination).first { folder in FileManager.default.fileExists(atPath: folder.appendingPathComponent("attachments/shot.png").path) }) #expect(try Data(contentsOf: card.appendingPathComponent("attachments/shot.png")) == Data([0x01, 0x02, 0x03])) } @Test("A card's body survives the fresh stamps — frontmatter is edited, bytes are not rewritten") func bodiesSurviveTheRestamp() throws { let source = try FixtureTemplate() defer { source.tearDown() } let destination = source.destination() try TemplateEngine.instantiate(template: try source.template(), to: destination, title: "New Board") let model = try BoardLoader.load(boardRoot: destination).model let starter = try #require(model.lanes.flatMap(\.cards).first { $0.title.value == "Starter" }) #expect(starter.document.body == "Starter body — with *markdown*.\n") #expect(starter.document.value(for: "project") == .string("lanework"), "unknown keys ride along, comment and all") #expect(starter.modifiedBy.isMissing, "an app-mediated write clears a foreign attribution") #expect(try #require(starter.created.value).timeIntervalSinceNow > -60, "born today") // The board's own blurb is its description now, untouched. #expect(model.document.body == FixtureTemplate.blurb) } @Test("A symlink is copied as a link, never traversed") func symlinksArriveAsLinks() throws { let source = try FixtureTemplate() defer { source.tearDown() } let destination = source.destination() try TemplateEngine.instantiate(template: try source.template(), to: destination, title: "New Board") let link = destination.appendingPathComponent("link.md") let values = try link.resourceValues(forKeys: [.isSymbolicLinkKey]) #expect(values.isSymbolicLink == true) #expect(try FileManager.default.destinationOfSymbolicLink(atPath: link.path) == "../outside.txt", "the link itself travels, never its target") } @Test("A loose file beside a card's index.md lands in attachments/ — instantiation is an import boundary") func looseCardFilesAreNormalizedOnArrival() throws { let source = try FixtureTemplate() defer { source.tearDown() } let destination = source.destination() try TemplateEngine.instantiate(template: try source.template(), to: destination, title: "New Board") let result = try BoardLoader.load(boardRoot: destination) #expect(result.looseCardFiles.isEmpty, "the new board lands already normalized rather than opening with a notice about its own birth") let starter = try #require(result.model.lanes.flatMap(\.cards).first { $0.title.value == "Starter" }) #expect(starter.attachments == ["notes.txt", "shot.png"]) let card = try #require(cardFolders(under: destination).first { folder in FileManager.default.fileExists(atPath: folder.appendingPathComponent("attachments/notes.txt").path) }) #expect(!FileManager.default.fileExists(atPath: card.appendingPathComponent("notes.txt").path)) #expect(try Data(contentsOf: card.appendingPathComponent("attachments/notes.txt")) == Data("loose\n".utf8)) } @Test("A legacy deleted: key copies through and is the store's to migrate, not the engine's") func legacyTombstonesCopyThroughForTheOneMigrator() throws { let source = try FixtureTemplate() defer { source.tearDown() } let destination = source.destination() try TemplateEngine.instantiate(template: try source.template(), to: destination, title: "New Board") let result = try BoardLoader.load(boardRoot: destination) let tombstoned = try #require(result.model.lanes.flatMap(\.cards).first { $0.title.value == "Legacy Tombstone" }) #expect(tombstoned.isDeleted, "neither stripped (a silent resurrection) nor dropped (destroyed content)") #expect(result.legacyTombstones.count == 1, "the new board's first load hands it to 01's one migrator, exactly as any other board's would") } @Test("Every identity in the tree is fresh — cards and strays under a card included") func everyIdentityIsReminted() throws { let source = try FixtureTemplate() defer { source.tearDown() } let destination = source.destination() try TemplateEngine.instantiate(template: try source.template(), to: destination, title: "New Board") let minted = identities(under: destination) #expect(minted.count == 4, "two lanes and two cards — the trashed card was not copied") #expect(minted.isDisjoint(with: identities(under: source.root))) } @Test("The template survives its own instantiation untouched") func theTemplateIsNeverWritten() throws { let source = try FixtureTemplate() defer { source.tearDown() } let before = tree(of: source.root) let boardBytes = try Data(contentsOf: source.root.appendingPathComponent("index.md")) try TemplateEngine.instantiate(template: try source.template(), to: source.destination(), title: "New Board") #expect(tree(of: source.root) == before, "the loose file was normalized in the copy, not in the template") #expect(try Data(contentsOf: source.root.appendingPathComponent("index.md")) == boardBytes) } } // MARK: - Nothing half-made @Suite("TemplateEngine — the destination is all or nothing") struct TemplateEngineAtomicityTests { @Test("Cancelling mid-walk leaves nothing at the destination") func cancellingRemovesThePartialBoard() throws { let source = try FixtureTemplate() defer { source.tearDown() } let destination = source.destination() // Trips on the fourth read: the destination exists by then and the walk is inside it, so // there is a genuine partial tree to remove rather than nothing to clean up. var reads = 0 let failure = instantiationFailure { try TemplateEngine.instantiate( template: try source.template(), to: destination, title: "New Board", isCancelled: { reads += 1 return reads > 3 } ) } #expect(failure == TemplateEngine.Failure.cancelled) #expect(!FileManager.default.fileExists(atPath: destination.path), "a cancelled create never happened") #expect(try Set(source.fixture.entryNames("")) == [FixtureTemplate.name]) } @Test("Cancelling before the first item never creates the destination at all") func cancellingBeforeTheWalkCreatesNothing() throws { let source = try FixtureTemplate() defer { source.tearDown() } let failure = instantiationFailure { try TemplateEngine.instantiate( template: try source.template(), to: source.destination(), title: "New Board", isCancelled: { true } ) } #expect(failure == TemplateEngine.Failure.cancelled) #expect(try Set(source.fixture.entryNames("")) == [FixtureTemplate.name]) } @Test("A destination that is already taken is refused cleanly, and never clobbered") func collisionIsRefusedWithoutTouchingWhatIsThere() throws { let source = try FixtureTemplate() defer { source.tearDown() } let destination = source.destination(named: "Taken.kanban") try FileManager.default.createDirectory(at: destination, withIntermediateDirectories: true) try Data("mine\n".utf8).write(to: destination.appendingPathComponent("index.md")) let failure = instantiationFailure { try TemplateEngine.instantiate(template: try source.template(), to: destination, title: "Taken") } guard case let .failed(error) = failure else { Issue.record("expected an ordinary failure, got \(String(describing: failure))") return } #expect(error.operation == .createBoard) #expect(error.path == destination.path) #expect(try Data(contentsOf: destination.appendingPathComponent("index.md")) == Data("mine\n".utf8), "an existing name is the user's — a create never replaces one") #expect(try Set(FileManager.default.contentsOfDirectory(atPath: destination.path)) == ["index.md"]) } @Test("A template that is not there fails as a create, naming the path") func aMissingTemplateFailsCleanly() throws { let source = try FixtureTemplate() defer { source.tearDown() } let template = try source.template() try FileManager.default.removeItem(at: source.root) let destination = source.destination() let failure = instantiationFailure { try TemplateEngine.instantiate(template: template, to: destination, title: "New Board") } guard case .failed = failure else { Issue.record("expected an ordinary failure, got \(String(describing: failure))") return } #expect(!FileManager.default.fileExists(atPath: destination.path), "the destination this call made goes with the failure") } } // MARK: - The copy contract /// **Instantiation is a copy transaction, and it severs tracker identity** — the two 2026-07-29 /// rulings applied to the flow 01 names alongside paste and the ⌥-drag duplicate (01-storage-format.md /// § Frontmatter's compound-operations clause; § Fractal layout ▸ Rules' item-level sever). @Suite("TemplateEngine — the copy contract") struct TemplateEngineCopyContractTests { /// A template carrying a readable-but-uneditable card refuses the **whole** create, naming that /// card, and leaves nothing where the user pointed — the former root-strict/descendants-lenient /// split would have made a board from it with one silently unstamped card inside. @Test("An uneditable card in the template refuses the create, naming it") func anUneditableCardRefusesTheCreate() throws { let template = try FixtureTemplate() defer { template.tearDown() } try template.fixture.item( "\(FixtureTemplate.name)/\(Ident.lane1)/\(Ident.card3)", Item.uneditable ) let destination = template.destination() let failure = instantiationFailure { try TemplateEngine.instantiate(template: try template.template(), to: destination, title: "Doomed") } guard case let .failed(write) = failure else { Issue.record("expected an ordinary failure, got \(String(describing: failure))") return } if case .uneditableFrontmatter = write.reason {} else { Issue.record("expected the uneditable-shape refusal, got \(write.reason)") } #expect(write.operation == .createBoard, "the create is what refused") #expect( !FileManager.default.fileExists(atPath: destination.path), "construct-then-clean: the partial destination goes with the refusal" ) } /// A template whose `.trash/` holds a broken card still instantiates: the preflight runs on the /// **destination**, after the copy applied its exclusions, so a card that was never going to be /// copied cannot refuse the create it has nothing to do with. @Test("An uneditable card in the template's trash refuses nothing — it is never copied") func anUneditableTrashCardIsIrrelevant() throws { let template = try FixtureTemplate() defer { template.tearDown() } try template.fixture.item("\(FixtureTemplate.name)/.trash/\(Ident.card3)", Item.uneditable) let destination = template.destination() try TemplateEngine.instantiate(template: try template.template(), to: destination, title: "Fine") #expect(FileManager.default.fileExists(atPath: destination.appendingPathComponent("index.md").path)) #expect( !FileManager.default.fileExists(atPath: destination.appendingPathComponent(".trash").path), "and the trash was excluded, as always" ) } /// **The tracker sever, at every level an instantiation materializes** — board root, lane, and card. /// A template can carry the keys in from the board it was saved from (Save as Template is a fork and /// keeps them verbatim), and the board born from it must not claim those remote objects. @Test("Instantiation drops the reserved tracker keys at every level") func instantiationSeversTrackerIdentity() throws { let fixture = try WriterFixture() defer { fixture.tearDown() } let name = "Tracked.kanban" try fixture.item(name, """ --- schema: 1 title: Tracked Template template: {order: 1} project: lanework remote: gitea#7 --- Blurb. """) try fixture.item("\(name)/\(Ident.lane1)", Item.tracked(order: "1024", title: "To Do", key: "remote-state")) try fixture.item( "\(name)/\(Ident.lane1)/\(Ident.card1)", Item.tracked(order: "1024", title: "Starter", key: "remote") ) let template: BoardTemplate = switch TemplateEngine.load(templateAt: fixture.url(name), origin: .user) { case let .success(loaded): loaded case let .failure(error): throw error } let destination = fixture.url("Born.kanban") try TemplateEngine.instantiate(template: template, to: destination, title: "Born") let board = try FrontmatterDocument.parse(String( decoding: Data(contentsOf: destination.appendingPathComponent("index.md")), as: UTF8.self )) #expect(board.value(for: "remote") == nil, "the board born today claims no remote object") #expect(board.value(for: "project") != nil, "and every other unknown key rode along") let lanes = ((try? BoardLoader.directoryCandidates(in: destination)) ?? []) .filter { BoardLoader.isUUIDShaped($0.lastPathComponent) } let lane = try FrontmatterDocument.parse(String( decoding: Data(contentsOf: try #require(lanes.first).appendingPathComponent("index.md")), as: UTF8.self )) #expect(lane.value(for: "remote-state") == nil) let card = try FrontmatterDocument.parse(String( decoding: Data(contentsOf: try #require(cardFolders(under: destination).first) .appendingPathComponent("index.md")), as: UTF8.self )) #expect(card.value(for: "remote") == nil) #expect(card.value(for: "project") != nil) } /// **Save as Template is a whole-board fork and is exempt** (01 ▸ Identity lifecycle's carve-out): /// it "carries them verbatim", GUIDs, timestamps and tracker keys alike, because a fork is a new /// namespace rather than a second claimant inside one board. The sever belongs to *item-level* /// copies, and this is the line between them. @Test("Save as Template carries the tracker keys verbatim") func saveAsTemplateIsExempt() throws { let fixture = try WriterFixture() defer { fixture.tearDown() } try fixture.item("Board.kanban", """ --- schema: 1 title: Live Board remote: gitea#7 --- Body. """) try fixture.item("Board.kanban/\(Ident.lane1)", Item.tracked(order: "1024", title: "To Do", key: "remote-state")) try fixture.item( "Board.kanban/\(Ident.lane1)/\(Ident.card1)", Item.tracked(order: "1024", title: "Card", key: "remote") ) let store = fixture.url("Store") let saved = try TemplateEngine.saveAsTemplate( boardAt: fixture.url("Board.kanban"), titled: "Live Board", into: store ) let board = try FrontmatterDocument.parse(String( decoding: Data(contentsOf: saved.appendingPathComponent("index.md")), as: UTF8.self )) #expect(board.value(for: "remote") != nil, "a fork carries them verbatim") let lane = try FrontmatterDocument.parse(String( decoding: Data(contentsOf: saved.appendingPathComponent(Ident.lane1).appendingPathComponent("index.md")), as: UTF8.self )) #expect(lane.value(for: "remote-state") != nil) } } // MARK: - Shared /// Every card folder under an instantiated board — `//`, by the loader's own level /// detection, so the tests never hard-code a minted identity they cannot know. private func cardFolders(under root: URL) -> [URL] { let lanes = ((try? BoardLoader.directoryCandidates(in: root)) ?? []) .filter { BoardLoader.isUUIDShaped($0.lastPathComponent) } return lanes.flatMap { lane in ((try? BoardLoader.directoryCandidates(in: lane)) ?? []) .filter { BoardLoader.isUUIDShaped($0.lastPathComponent) } } }