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
    }
}
