The message engine outlives its substrate — harvested to Kanban/Changes/ as the change narrator

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
This commit is contained in:
2026-08-08 10:38:43 -04:00
parent 6d1872ad8b
commit ae7be98eaa
8 changed files with 207 additions and 182 deletions
+6 -6
View File
@@ -53,20 +53,20 @@ public struct HarvestedReceipt: Sendable, Equatable {
public struct CommitSplit: Sendable, Equatable {
/// Changes nobody vouched for an agent, a text editor, a terminal, or a blind window at launch.
public var foreign: [GitChangedPath] = []
public var foreign: [ChangedPath] = []
/// The scheduled healers' paths, heal-marked in the ledger by the Writer operations that made
/// them (`EchoLedger.markHeal`).
public var heal: [GitChangedPath] = []
public var heal: [ChangedPath] = []
/// The user acting through the app.
public var user: [GitChangedPath] = []
public var user: [ChangedPath] = []
public init() {}
/// One class of one window's changes, ready to become a commit.
public struct Group: Sendable, Equatable {
public let paths: [GitChangedPath]
public let paths: [ChangedPath]
/// Which class it is carried rather than re-derived, so the planner never has to ask a
/// list whether it contains its own members.
public let kind: Kind
@@ -171,7 +171,7 @@ public enum CommitAttribution {
/// The **nearest** receipt wins, so a rewritten `index.md` inside a moved folder answers with
/// its own content receipt rather than with the move above it.
public static func split(
_ paths: [GitChangedPath],
_ paths: [ChangedPath],
under boardRoot: URL,
receipts: [String: HarvestedReceipt]
) -> CommitSplit {
@@ -236,7 +236,7 @@ public enum CommitAttribution {
/// does which is why the agent guide teaches re-stamping on move.
///
/// A window of nothing but rename departures leaves no stamp to agree on and falls back too.
public static func foreignIdentity(for paths: [GitChangedPath], under boardRoot: URL) -> GitIdentity {
public static func foreignIdentity(for paths: [ChangedPath], under boardRoot: URL) -> GitIdentity {
var stamps: Set<String> = []
for path in paths {
if path.isDeletion {