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:
@@ -14,11 +14,14 @@ import SwiftUI
|
||||
/// - **A read-only board disables them too** (02-architecture.md ▸ The lock's scope, which names "the
|
||||
/// popover's git controls" outright).
|
||||
/// - **A switch in flight disables them**, so a second click cannot start a second checkout.
|
||||
/// - **An unreadable repository reads as broken, never as still loading** (06 ▸ Rules, the
|
||||
/// corrupt-`.git` loud failure, ruled 2026-07-31: "Never a silent placeholder discovered only in
|
||||
/// the popover").
|
||||
struct BoardGitBranchSurface: Equatable {
|
||||
|
||||
/// What the branch line reads — the branch name, the short hash on a detached HEAD
|
||||
/// (`GitRepository.branchName` decides which), or the placeholder while the first read is in
|
||||
/// flight.
|
||||
/// (`GitRepository.branchName` decides which), the placeholder while the first read is in
|
||||
/// flight, or `unavailableLabel` when there is no readable repository for it to name.
|
||||
let branchLabel: String
|
||||
|
||||
/// Whether that label is the placeholder rather than an answer.
|
||||
@@ -27,34 +30,74 @@ struct BoardGitBranchSurface: Equatable {
|
||||
/// The pause's own sentence (`GitRepositoryPause.explanation`), or `nil` when the surface is live.
|
||||
let pauseExplanation: String?
|
||||
|
||||
/// **Whether the pause is the unopenable repository** — the one pause whose surface is not the
|
||||
/// pause note: nothing is in progress and no tool is coming to finish it, so the section says
|
||||
/// its own sentence instead (`unreadableNote`), and the branch line has no answer to wait for.
|
||||
let isRepositoryUnreadable: Bool
|
||||
|
||||
/// Whether the branch controls accept a click — the popover's switch picker, and the settings
|
||||
/// sheet's create field (`BoardSettingsSheet`), which resolves this same surface so that a
|
||||
/// paused repository, a read-only board and a switch in flight close both by one rule.
|
||||
let controlsEnabled: Bool
|
||||
|
||||
/// The line the branch display is read as by VoiceOver.
|
||||
///
|
||||
/// The broken case is spelled out rather than left to fall through "Branch \(label)": the label
|
||||
/// is a *state* there, not a name, and "Branch Unavailable" would read as a branch somebody
|
||||
/// called Unavailable.
|
||||
var accessibilityLabel: String {
|
||||
isReadingBranch ? "Reading branch" : "Branch \(branchLabel)"
|
||||
if isRepositoryUnreadable { return "Branch unavailable" }
|
||||
return isReadingBranch ? "Reading branch" : "Branch \(branchLabel)"
|
||||
}
|
||||
|
||||
static let placeholder = "…"
|
||||
|
||||
/// **What the branch line reads when the repository will not open** — an answer, not a
|
||||
/// placeholder, which is the whole of the ruling's "fails loudly" at this one control: the
|
||||
/// placeholder means "still reading" and would go on meaning it forever here.
|
||||
static let unavailableLabel = "Unavailable"
|
||||
|
||||
/// The second half of the paused sentence — 06's "says resolving it belongs to the tool that
|
||||
/// created it", said in the app's own voice and paired with the promise that makes it safe to
|
||||
/// wait: the app is not going to touch the repository behind the user's back.
|
||||
static let pauseCaption =
|
||||
"Finishing it belongs to the tool that started it; Lanework leaves the repository untouched."
|
||||
|
||||
/// **The popover's own sentence for an unreadable repository** (06 ▸ Rules, the corrupt-`.git`
|
||||
/// loud failure, ruled 2026-07-31: "with the whole git surface paused … and the popover's git
|
||||
/// section naming the state").
|
||||
///
|
||||
/// A sibling of the nested and unverifiable notes (`BoardInfoPopover`) and written in their
|
||||
/// register — one sentence, the state first and the consequence after — rather than the pause
|
||||
/// note's two lines, because both of *those* lines would be wrong here: nothing is "in
|
||||
/// progress", and there is no tool whose job it is to finish it. What it keeps from the pause
|
||||
/// note is the promise that matters most on a repository the app cannot read, in the ruling's
|
||||
/// own words.
|
||||
///
|
||||
/// It is deliberately **not** the banner's sentence (`BannerCenter.repositoryUnreadableMessage`)
|
||||
/// re-used: the strip announces a condition to somebody who has not asked, and this answers
|
||||
/// somebody looking straight at the git section — the register the neighbouring notes set.
|
||||
static let unreadableNote =
|
||||
"Lanework can't read this board's git repository, so history is paused; the repository is left untouched."
|
||||
|
||||
static func resolve(
|
||||
branch: String?,
|
||||
pause: GitRepositoryPause?,
|
||||
isSwitching: Bool,
|
||||
isWritable: Bool
|
||||
) -> BoardGitBranchSurface {
|
||||
BoardGitBranchSurface(
|
||||
branchLabel: branch ?? placeholder,
|
||||
isReadingBranch: branch == nil,
|
||||
// Derived from the pause rather than passed in beside it: the pause *is* how this state is
|
||||
// carried everywhere else (`GitRepositoryPause.unreadable`, seeded by the detection-time
|
||||
// probe and refreshed by every later read), so a second parameter would be a second answer
|
||||
// to one question — and a caller could hold them apart.
|
||||
let unreadable = pause == .unreadable
|
||||
return BoardGitBranchSurface(
|
||||
branchLabel: unreadable ? unavailableLabel : (branch ?? placeholder),
|
||||
// Never "reading" on an unreadable repository: there is nothing in flight, and the line
|
||||
// the ruling forbids is exactly the one that says otherwise forever.
|
||||
isReadingBranch: !unreadable && branch == nil,
|
||||
pauseExplanation: pause?.explanation,
|
||||
isRepositoryUnreadable: unreadable,
|
||||
controlsEnabled: pause == nil && isWritable && !isSwitching
|
||||
)
|
||||
}
|
||||
@@ -95,7 +138,13 @@ struct BoardGitControls: View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
branchRow
|
||||
|
||||
if let explanation = surface.pauseExplanation {
|
||||
// **The unreadable repository names itself in its own sentence** (06 ▸ Rules, the
|
||||
// corrupt-`.git` loud failure) — checked before the pause note because it *is* a pause,
|
||||
// and the pause note's second line ("finishing it belongs to the tool that started it")
|
||||
// would be advice about an operation nobody started.
|
||||
if surface.isRepositoryUnreadable {
|
||||
caption(BoardGitBranchSurface.unreadableNote, tone: .primary)
|
||||
} else if let explanation = surface.pauseExplanation {
|
||||
pauseNote(explanation)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user