An unopenable repository fails loudly — the standing row, the paused surface, the honest heal

Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
2026-08-06 18:44:12 -04:00
parent 52df210284
commit 0d8ecdb78b
20 changed files with 938 additions and 42 deletions
+70
View File
@@ -583,6 +583,37 @@ struct BranchSwitchSequenceTests {
#expect(GitRepository.branchName(at: fixture.root) == "main")
}
/// The same refusal through the **real** pause rather than an injected one: an unreadable
/// repository is a `GitRepositoryPause` like any other, so the switch's existing gate closes on
/// it with nothing added here (06-history-undo.md Rules, the corrupt-`.git` loud failure, ruled
/// 2026-07-31: "the whole git surface paused").
@Test("A switch refuses against a repository the app cannot open, and changes nothing")
@MainActor
func anUnreadableRepositoryRefusesTheSwitch() async throws {
let (fixture, git) = try await makeGitBoard()
defer { fixture.tearDown() }
let switcher = try makeSwitcher(git)
#expect(GitBranchOperation.createAndSwitch("redesign", at: fixture.root) == .switched("redesign"))
#expect(GitBranchOperation.checkout("main", at: fixture.root) == .switched("main"))
var asked = 0
switcher.settleSessions = { asked += 1; return .proceed }
let head = fixture.root.appendingPathComponent(".git/HEAD")
let savedHead = try Data(contentsOf: head)
try FileManager.default.removeItem(at: head)
await git.committer?.refreshPause()
#expect(git.isRepositoryUnreadable)
#expect(await switcher.switchTo("redesign") == false)
#expect(asked == 0, "no modal, no stamp, no checkout — nothing is attempted at all")
#expect(switcher.lastFailure == nil, "a pause is not a failure; the standing banner is the message")
// The repository is exactly as it was found, which is the promise the row makes.
try savedHead.write(to: head)
#expect(GitRepository.branchName(at: fixture.root) == "main")
}
/// "Contention outlasting the brief retry surfaces as a *waiting* state in the operation's
/// in-progress banner row a wait that persists implausibly long names the lock path never an
/// error dialog, never a hammer."
@@ -946,6 +977,45 @@ struct BoardGitBranchSurfaceTests {
).controlsEnabled)
}
/// **The corrupt-`.git` loud failure at this one control** (06-history-undo.md Rules, ruled
/// 2026-07-31: "Never a silent placeholder discovered only in the popover"). The bug this pins
/// against is the shipped one: `GitRepository.branchName` answers `nil` on a repository it cannot
/// open, and the placeholder meant "still reading" forever.
@Test("An unreadable repository reads as broken, never as still loading")
func anUnreadableSurface() {
let surface = BoardGitBranchSurface.resolve(
branch: nil,
pause: .unreadable,
isSwitching: false,
isWritable: true
)
#expect(surface.branchLabel == BoardGitBranchSurface.unavailableLabel)
#expect(surface.branchLabel != BoardGitBranchSurface.placeholder)
#expect(!surface.isReadingBranch, "there is nothing in flight to be waiting for")
#expect(surface.isRepositoryUnreadable)
#expect(!surface.controlsEnabled, "the whole git surface is paused")
#expect(surface.accessibilityLabel == "Branch unavailable")
// The section's own sentence a sibling of the popover's nested and unverifiable notes, and
// not the pause note, whose second line would be advice about an operation nobody started.
#expect(BoardGitBranchSurface.unreadableNote
== "Lanework can't read this board's git repository, so history is paused; the repository is left untouched.")
}
@Test("A branch name read before the repository broke does not survive the pause")
func anUnreadableSurfaceDropsAStaleBranch() {
let surface = BoardGitBranchSurface.resolve(
branch: "main",
pause: .unreadable,
isSwitching: false,
isWritable: true
)
#expect(surface.branchLabel == BoardGitBranchSurface.unavailableLabel,
"the line must not go on naming a branch nothing can read")
}
@Test("Before the first read the line is a placeholder, not a guess at a branch name")
func theReadingSurface() {
let surface = BoardGitBranchSurface.resolve(