Build HistoryStore — opt-in git and mode detection
The pro-m1 foundation card. SwiftGitX 0.4.0 (bundled libgit2, the pathfinder's pin) joins the one target; new Kanban/Git/ holds BoardGitMode (pure nearest-.git-wins detection, .git-as-file counts, NSString ancestor walk), HistoryStore (@MainActor @Observable; compose() is the tier gate — free tier gets no object, no detection, no stat), GitRepository (scope-confined SwiftGitX handles: create = init + HEAD forced to main + whole-tree "Initial board state" commit; branch reads incl. unborn/detached; path-history ranks), GitIdentity (derived default as a pure function + repo-local config reader — not libgit2's merged ladder), and GitPathHistory (Mutex-guarded lazy ranker). beginSession composes the git state beside the tier and feeds BoardStore.makeIdentityHistoryRanker; git-mode loads pass the git-backed IdentityHistoryRanker to BoardLoader. The popover's git slot resolves a pure five-way matrix: free tier unchanged (absent / BoardGitNote), Pro mode-aware — Add Git on mode none, honest prose on repo-nested, read-only branch line on git. Provider binding unchanged: both tiers still bind native until the undo/redo card. 42 new tests across 8 suites, all repositories built through bundled libgit2; InertGitTests untouched and green. 2194 tests / 375 suites. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -283,10 +283,20 @@ struct BoardWindowHost: View {
|
||||
// card windows share that machinery and have no board to describe. It goes in after the
|
||||
// load rather than at attach because it carries the store; the controller installs it once,
|
||||
// whichever of the two arrives second.
|
||||
//
|
||||
// The tier and the git state come from the **session**, which `start()` began a moment ago,
|
||||
// rather than from the entitlement or the disk: a board's popover must describe the board as
|
||||
// it opened (12-editions.md ▸ The entitlement, "an open board finishes with the provider it
|
||||
// composed"; 06-history-undo.md ▸ Rules, mode is an open-time fact). A `nil` session cannot
|
||||
// happen on this path — `beginSession` precedes `configureWindow` — and reads as the free
|
||||
// tier's posture, which is the harmless direction.
|
||||
let session = appModel.session(for: ref)
|
||||
windowController.installTitlebarAccessory(
|
||||
boardInfoTitlebarAccessory(
|
||||
store: store,
|
||||
recents: appModel.styleRecents,
|
||||
tier: session?.tier ?? .free,
|
||||
git: session?.git,
|
||||
presentation: boardInfo
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user