Implement undo and redo as forward commits
GitHistoryProvider is the second HistoryProviding implementation: its stack IS HEAD's first-parent ancestry, reseeded on load (redo empty), re-synced to HEAD before every crossing so agents' self-commits become the top and ⌘Z steps back exactly one commit; any arriving commit clears redo (a heal-only window deliberately does not). Restores are forward commits through the ordinary signature path — GitRestoreOperation materializes only the current-vs-target diff as working-tree writes and resolves no reset/checkout symbol at all; heal commits are transparent in-session (pointer passes over, restores exclude heal-owned paths, identity carried on landed windows via PlannedCommit.kind → GitLandedCommit). Subjects "Undo:/Redo: <crossed subject>"; menu labels never nest in-session; the root commit is not a step (crossing it would restore the empty tree). Provider binding flips: makeHistoryProvider(store, tier, git) — free binds native everywhere, Pro binds the git provider on git boards and NOTHING on mode-none/repo-nested (the pair disables through existing validation); add-git mid-session live-binds via HistoryStore.didAddGit → bindHistoryProvider (the flip only ever adds). SessionSettleGate is the reusable Save All / Discard / Cancel step: restores whose diff touches an open Edit session or raw-source buffer gate on it (Save All applies with validation — a refused buffer cancels the whole restore focused on the offender; Discard reverts via CardBodyEditSession.discardBuffer and reconciles against the working tree, deliberately skipping the second flush); untouched sessions ride through undisturbed. Built for the branch-switch card to reuse. BoardStore gains the async performWholesale sibling. CardHistorySection fills the m6 EmptyView slot: read-only, newest first, follows the card across lane moves by folder-component match (the UUID is the identity — no rename detection), absent off git mode and off Pro. 2332 tests / 403 suites green; InertGitTests untouched. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -88,6 +88,18 @@ public final class HistoryStore {
|
||||
@ObservationIgnored
|
||||
private var autoCommitWiring: ((GitAutoCommitter) -> Void)?
|
||||
|
||||
/// **The mid-session mode flip, announced** — called once, after a successful `addGit()`, and
|
||||
/// never on any other path.
|
||||
///
|
||||
/// It exists because the flip has a second consumer beyond the committer: the board's **undo
|
||||
/// substrate**. A session that composed on a mode-none board bound no provider at all
|
||||
/// (`AppModel.makeHistoryProvider`), and 06 ▸ Rules ▸ Detection's one sanctioned commanded flip
|
||||
/// means the board now has a trail to be an undo stack over. What binding it means is
|
||||
/// `AppModel.bindHistoryProvider(for:)`'s to decide and to justify; what this property does is
|
||||
/// keep that decision out of a git state that has no business knowing what a provider is.
|
||||
@ObservationIgnored
|
||||
public var didAddGit: (@MainActor () -> Void)?
|
||||
|
||||
private static let logger = Logger(subsystem: "dev.rzen.indie.Kanban", category: "git")
|
||||
|
||||
init(boardRoot: URL, mode: BoardGitMode, ledger: EchoLedger) {
|
||||
@@ -189,6 +201,8 @@ public final class HistoryStore {
|
||||
self.committer = committer
|
||||
autoCommitWiring?(committer)
|
||||
committer.start()
|
||||
// Last, after the mode and the committer: the undo binding reads both.
|
||||
didAddGit?()
|
||||
Self.logger.notice("add-git initialized a repository at \(root.path, privacy: .public)")
|
||||
return true
|
||||
case .failure(let failure):
|
||||
|
||||
Reference in New Issue
Block a user