Step 2 of strategy/01-git-excision.md: CommitMessageEngine and the composer seam relocate to a neutral module renamed away from commit vocabulary (ChangeNarrator, ChangeNarrationRequest, ChangeNarrating, SemanticChangeNarration, ChangeAuthorship), GitChangedPath extracts from GitCommitOperation as ChangedPath, and the one git tie severs — authorship's foreign case carries a display name, not a GitIdentity. The spec tests transplant as ChangeNarratorTests, alive until the journal work begins. 3,009 tests green. Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
54 lines
2.7 KiB
Swift
54 lines
2.7 KiB
Swift
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
|
|
}
|
|
}
|