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<String> {
    var paths: Set<String> = []
    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<String> {
    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])
    }

    /// **An instantiated board is a board created today**, so it is born with the noise definition
    /// every board carries (06-history-undo.md ▸ Repository hygiene, re-ruled 2026-07-31; the bundled
    /// templates carry no `.gitignore` of their own, so this is the seeding half rather than the
    /// copying one — which `TemplateEngineFixtureTests` pins from the other side, where a template
    /// that *does* carry one has it copied through byte for byte and left alone).
    @Test("An instantiated board carries the seeded .gitignore")
    func instantiationSeedsTheIgnoreFile() 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")

        #expect(try Data(contentsOf: destination.appendingPathComponent(IntegrityRules.gitignoreFileName))
                    == Data(BoardWriter.gitignoreSeed.utf8))
    }

    @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 — `<root>/<lane>/<card>`, 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) }
    }
}
