The git surfaces leave the glass — tab, trail, branch line, and the remote pair, peeled

Step 3 of strategy/01-git-excision.md: the popover strip is Info/Theme/Sync, the titlebar widget says the name alone, the card window's History section and its slot go, Board ▸ Pull/Push comes out with the RemoteCommands scaffold, and View ▸ History re-tags from the commit trail to the deferred foreign-change journal. The Sync placeholder re-annotates to the future ops-based sync service. Four git test suites leave with the surfaces they pinned (BoardGitSetup, BoardInfoPopover, BranchSwitch, GitUndo). The git engine still compiles underneath, unreferenced by UI. 2,890 tests green.

Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
2026-08-08 10:52:57 -04:00
parent ae7be98eaa
commit 1d97a2931c
16 changed files with 119 additions and 4525 deletions
+1 -38
View File
@@ -257,7 +257,7 @@ final class CardWindowSession: CardSessionFlushing {
///
/// This file owns identity, lifecycle, the title and subtitle, and where the window opens. The
/// two-column composition inside it is `CardWindowView`'s, and what fills those columns the title
/// field, Preview/Edit, the sidebar's five sections arrives card by card underneath a composition
/// field, Preview/Edit, the sidebar's four sections arrives card by card underneath a composition
/// that does not move. The *window-scoped* state those surfaces need lives here, because a window is
/// what it is scoped to: the body column's mode (`CardBodyPresentation`) and the raw-source outlet
/// (`CardRawSourceSession`), both published through the focus system so the View menu's rows can
@@ -288,9 +288,6 @@ struct CardWindowHost: View {
/// snapshot the store applies a cache that died with the view would regenerate every thumbnail
/// on every reload (`AttachmentThumbnailCache`).
@State private var thumbnails = AttachmentThumbnailCache()
/// This card's commit trail (05-card-window.md History). Held here for `thumbnails`' reason
/// it must survive every snapshot and surfaced to the view only in git mode (`cardHistory`).
@State private var history = CardHistory()
/// Whether a close is waiting on the dirty-buffer modal. Set when `windowShouldClose` could not
/// flush; cleared by the resolution that lets the close resume.
@State private var isClosePending = false
@@ -417,31 +414,6 @@ struct CardWindowHost: View {
.onDisappear { finish() }
}
/// **This card's commit trail, or nothing at all** (05-card-window.md History).
///
/// `nil` is the section's absence rule, read from the board's own git state rather than from a
/// flag: a mode other than `git` means a board the app manages no history for, on any tier. The
/// question stopped having a tier half at 12-editions.md PIVOT 2026-08-07 every session
/// composes a git state now, so what decides the section is whether *this board's* history is
/// git-backed. The object is held by this host so it survives every snapshot, `thumbnails`'
/// reason exactly.
private var cardHistory: CardHistory? {
guard appModel.session(for: ref.board)?.gitMode == .git else { return nil }
return history
}
/// What a trail re-read depends on: this card, and the number of commits the board has landed.
///
/// The count is the committer's own (`GitAutoCommitter.commitCount`), which advances for every
/// commit the app makes the debounced ones, the launch catch-up, and a restore's. A foreign
/// commit an agent made *itself* moves HEAD without touching it; the trail then refreshes at the
/// next commit or the next open, which is the same freshness bound the popover's branch line has
/// and a great deal cheaper than polling HEAD from a sidebar.
private func historyReloadKey(store: BoardStore) -> String {
let commits = appModel.session(for: ref.board)?.git?.committer?.commitCount ?? 0
return "\(ref.cardID)#\(commits)"
}
/// **The minimum grows only while the comments pane is beside the body** (05-card-window.md
/// Composition) which is the whole reason the stacked mount exists, so a narrow display keeps
/// the minimum it always had.
@@ -475,20 +447,11 @@ struct CardWindowHost: View {
comments: session.comments,
thumbnails: thumbnails,
undo: session.undo,
history: cardHistory,
fileDrop: CardWindowDropDelegate(store: store, cardID: placement.card.id),
onToggleTask: { offset, checked in
store.toggleTaskMarker(inCard: placement.card.id, bodyOffset: offset, checked: checked)
}
)
// **The trail, re-read when a commit lands** (05 History). The id is the pair of facts
// the answer depends on: which card this is, and how many commits this board has made
// so the section refreshes after the app's own commits, after an agent's that the watcher
// committed, and after a Z's restore, with nothing here knowing what a committer is.
.task(id: historyReloadKey(store: store)) {
guard let cardHistory else { return }
await cardHistory.load(boardRoot: store.rootURL, cardFolderName: ref.cardID)
}
// **The listing is the snapshot's, republished** `Card.attachments`, which the loader
// fills from `attachments/`'s top-level files in Finder order. Every write in the
// section is bracketed, so the reload that refreshes this arrives by itself and the