import Foundation // MARK: - Changed paths /// Harvested 2026-08-08 from `Kanban/Git/` per `strategy/01-git-excision.md`. This value type, and /// the narrator it feeds, are the designated core of the future activity feed / foreign-change /// journal — the "previous snapshot" input the narrator diffs against is supplied by the caller by /// contract; the journal will supply it from memory/snapshots, where the git stack supplied it from /// HEAD. /// One path found to differ between the last-recorded snapshot and the working tree (what `git /// status` reports, for the git-backed supplier). /// /// Board-root-relative and file-granular, which is the unit both consumers want: staging adds or /// removes exactly these, and attribution asks a question per *file* (06 ▸ Interaction with external /// writers: "classify every observed change, per file"). public struct ChangedPath: Sendable, Equatable, Hashable { /// The path, relative to the board root, in git's own spelling (`/` separators, no leading dot). public let path: String /// Whether the file is **gone** from the working tree. /// /// The `modified-by` rule turns on this bit — "any true deletion in the window falls back to /// `Lanework External` — a deletion leaves no file to stamp" — which is why the rename half /// below is a separate fact rather than folded in here. public let isDeletion: Bool /// Whether this path is one end of a **rename** the provider paired up (libgit2's pairing, for /// the git-backed supplier). /// /// "**A folder move is not a deletion**: items match by id across the whole board … so a moved /// card attributes by its stamp like any changed file" (06). A paired departure is therefore a /// deletion on disk that the window must not be demoted by. public let isRename: Bool /// Whether the path is **new in this commit** — surfaced rather than inferred (git's own /// `GIT_DELTA_ADDED`, for the git-backed supplier, and a rename's arriving end). /// /// It exists for the comment verb family (01-storage-format.md § Enhanced schema): comments are /// window-scoped and the board snapshot never carries them, so "Comment on 'X'" and "Edit comment /// on 'X'" cannot be told apart by a diff of two snapshots — the only thing that distinguishes a /// comment folder arriving from one being rewritten is whether HEAD already had it, which is /// exactly the question this diff already answered. public let isArrival: Bool public init(path: String, isDeletion: Bool, isRename: Bool, isArrival: Bool = false) { self.path = path self.isDeletion = isDeletion self.isRename = isRename self.isArrival = isArrival } }