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:
@@ -91,6 +91,10 @@ struct CardWindowView: View {
|
||||
let comments: CardComments
|
||||
/// This window's thumbnail memory, held by the host so it outlives a snapshot.
|
||||
let thumbnails: AttachmentThumbnailCache
|
||||
/// **This card's commit trail** (05 ▸ History), or `nil` on every board with no app-managed git —
|
||||
/// the free tier, mode none, and repo-nested boards. The `nil` *is* the section's absence rule;
|
||||
/// see `historySlot`.
|
||||
let history: CardHistory?
|
||||
/// The whole-window file drop (05 ▸ Attachments: "the drop surface remains the **whole
|
||||
/// window**"). `nil` only where a caller has no store to import through.
|
||||
let fileDrop: CardWindowDropDelegate?
|
||||
@@ -325,22 +329,21 @@ struct CardWindowView: View {
|
||||
}
|
||||
}
|
||||
|
||||
/// **The History section's reserved place in the stack** — between Details and Actions, 05's
|
||||
/// order (05 ▸ History: "the card's commit trail, read-only … newest first — semantic subject,
|
||||
/// relative date, author").
|
||||
/// **The History section** — between Details and Actions, 05's order (05 ▸ History: "the card's
|
||||
/// commit trail, read-only … newest first — semantic subject, relative date, author").
|
||||
///
|
||||
/// Nothing is drawn yet, deliberately: the section is conditional on a git mode that does not
|
||||
/// exist here, so a header over empty space would claim a commit trail on every board — and on
|
||||
/// the boards where it is *absent* by design (mode none, repo-nested) it would be claiming one
|
||||
/// that can never arrive. What the slot reserves is the **position**, so filling it in moves
|
||||
/// nothing above or below it.
|
||||
/// **Absence is the `nil`, and it is the whole rule.** "The section is absent on boards without
|
||||
/// app-managed git (mode none, repo-nested) — same honesty rule as the popover's git section",
|
||||
/// and the free tier has no git state at all (12-editions.md ▸ The free tier and `.git`). The host
|
||||
/// builds a `CardHistory` only in mode `git`, so there is no placeholder here to decide about:
|
||||
/// what the slot reserves is the **position**, and on every other board that position is empty.
|
||||
///
|
||||
// m7-git: the trail itself, plus the two rules that come with it — absence on boards without
|
||||
// app-managed git (the same honesty rule as the board popover's git section, 06-history-undo.md)
|
||||
// and View ▸ History, which focuses this section (11-command-nexus.md).
|
||||
// A later card: View ▸ History, which focuses this section (11-command-nexus.md).
|
||||
@ViewBuilder
|
||||
private var historySlot: some View {
|
||||
EmptyView()
|
||||
if let history {
|
||||
CardHistorySection(history: history)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user