The tier axis comes out of the git stack — compose unconditional, postures mode-driven

HistoryStore.compose(boardRoot📒) returns non-optional and runs for
every session — the nil the gate produced was the only nil it ever had.
makeHistoryProvider is a one-axis decision: git-mode boards bind the git
provider, everything else native, in every tier; Session.tier stays
recorded, dormant. BoardGitSection shrinks to the four mode postures
(.absent and .proPointer die, BoardGitNote and the .git probe with them);
every board carries all three popover tabs (BoardInfoTab.available
retired); the titlebar branch shows on any git-mode board; the settings
sheet and card History section stop reading tier. InertGitTests is
repurposed as UntouchedGitTests — the file layer still never opens .git,
now load-bearing for mode-none boards. The accessibility audit reaches the
settings sheet at last: the fixture board hosts it in every tier, so the
free-fixture disabled-row test becomes an open-and-audit test.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-08-07 20:21:28 -04:00
parent da0d7fd2d7
commit 798a8bac73
32 changed files with 830 additions and 904 deletions
+17 -12
View File
@@ -587,7 +587,7 @@ struct BoardSessionHistoryTests {
defer { tearDown() }
let bound = FakeHistoryProvider()
model.makeHistoryProvider = { _, _, _ in bound }
model.makeHistoryProvider = { _, _ in bound }
let ref = try openBoard(model, at: fixture.root)
let session = try #require(model.session(for: ref))
@@ -597,28 +597,30 @@ struct BoardSessionHistoryTests {
#expect(bound.undoCount == 1, "the window's manager reaches whatever the root bound")
}
@Test("The tier reaches the composition root, and the session records what it composed under")
func theTierIsAComposedFact() throws {
@Test("The session records the tier it composed under — and the provider root never sees it")
func theTierIsARecordedFact() throws {
let fixture = try makeBoard()
defer { fixture.tearDown() }
let (model, tearDown) = try makeModel()
defer { tearDown() }
// 12-editions.md The entitlement: the tier is read at composition, once, and handed to the
// root that binds the provider. What this pins is that the *argument arrives* the matrix it
// feeds is `GitUndoBindingTests`', since after the re-ruling of 2026-07-31 the tier decides
// only whether a git state is composed at all, and the mode decides the substrate.
var seen: [Tier] = []
// 12-editions.md The entitlement: the tier is read at composition, once, and recorded.
// **PIVOT 2026-08-07**: it is no longer *handed* anywhere. This test used to pin the argument
// arriving at `makeHistoryProvider` (`{ _, tier, _ in }`); the parameter is gone, so what is
// pinned now is the pair of facts that replaced it the seam takes a store and a git state
// and nothing else, and the session still carries the tier for the base/Pro split yet to be
// ruled. The substrate matrix itself is `GitUndoBindingTests`'.
var seen = 0
model.currentTier = { .pro }
model.makeHistoryProvider = { _, tier, _ in
seen.append(tier)
model.makeHistoryProvider = { _, _ in
seen += 1
return NativeHistoryProvider()
}
let ref = try openBoard(model, at: fixture.root)
let session = try #require(model.session(for: ref))
#expect(seen == [.pro])
#expect(seen == 1, "called once per board, with no tier to consult")
#expect(session.tier == .pro, "the session carries the fact it composed under")
}
@@ -635,7 +637,10 @@ struct BoardSessionHistoryTests {
// The subscription lapses mid-session the one thing 12 The entitlement says must not
// disturb a board that is already on screen: "an open board finishes with the provider it
// composed; the next open composes the native stack over inert `.git`".
// composed". (Its second clause "the next open composes the native stack over inert
// `.git`" went with PIVOT 2026-08-07: the next open composes the git stack too. What is
// pinned here is the recorded fact's immutability, which is what makes the first clause
// true whatever a future split gates.)
model.currentTier = { .free }
#expect(try #require(model.session(for: ref)).tier == .pro)