Denial is not absence — detection learns the unverifiable answer 06 ruled for it

Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
2026-08-06 17:52:20 -04:00
parent 503ec4872c
commit 4ac012a55e
10 changed files with 484 additions and 58 deletions
+33 -1
View File
@@ -340,7 +340,7 @@ struct BoardInfoView: View {
.frame(width: StyleEditorLayout.popover(bodyPointSize: CardWindowMetrics.bodyPointSize).width)
}
/// The popover's closing section, whichever of the five postures this board is in see
/// The popover's closing section, whichever of the six postures this board is in see
/// `BoardGitSection`.
@ViewBuilder
private var gitSection: some View {
@@ -372,6 +372,14 @@ struct BoardInfoView: View {
}
.padding(inset)
case .unverifiable:
Divider()
VStack(alignment: .leading, spacing: 6) {
sectionHeader("Git")
BoardGitUnverifiableNote()
}
.padding(inset)
case .branch:
Divider()
VStack(alignment: .leading, spacing: 6) {
@@ -505,6 +513,8 @@ private struct BoardRenameField: View {
/// mode, one to one and the mode-`none` and repo-nested pair is where the design is most
/// insistent: a repo-nested board gets **prose, not a disabled button**. "The option is absent
/// because it *can't* apply, and the UI should teach that rather than look broken" (06 Rules).
/// `unverifiable` (the git-detection axis) joins as a fourth Pro case, structurally identical to
/// `repoNested` but worded as its own honest prose a denial is not a nesting.
///
/// **The 2026-07-31 popover/sheet split thinned two of these cases without removing either.** Setup
/// left the popover for the board settings sheet, so mode `none` no longer renders an action here at
@@ -531,6 +541,13 @@ enum BoardGitSection: Equatable, CaseIterable {
/// since nothing setup-shaped can apply (`BoardSettingsAvailability`).
case repoNested
/// Pro, unverifiable: **not** `.repoNested` a denied ancestor check, not a found repository
/// (06 Rules Detection, "Denial is not absence"). Structurally identical to `.repoNested`
/// (no action, no Board Settings row, `BoardSettingsAvailability` false), but its own case so
/// the view renders its own honest prose rather than the nested sentence "unverifiable" is not
/// "nested".
case unverifiable
/// Pro, git mode: the branch/source line with the **switch** picker, the abnormal-state
/// explanation when the surface is held, and the Board Settings row. The remote half
/// tracking, Pull/Push, the status badges is 07-sync-collab.md's own card and joins this same
@@ -549,6 +566,7 @@ enum BoardGitSection: Equatable, CaseIterable {
case .none: return .noRepository
case .git: return .branch
case .repoNested: return .repoNested
case .unverifiable: return .unverifiable
}
}
}
@@ -566,6 +584,20 @@ private struct BoardGitNestedNote: View {
}
}
/// **The unverifiable explanation** (06-history-undo.md Rules Detection, "Denial is not
/// absence", ruled 2026-07-31), worded as its own honest sentence rather than borrowing
/// `BoardGitNestedNote`'s a denied ancestor check is not a found repository, and telling a user
/// their board is nested when the truth is "couldn't check" would be a lie dressed as caution.
private struct BoardGitUnverifiableNote: View {
var body: some View {
Text("Lanework couldn't verify whether this board sits inside a repository, so it isn't offering to add one here.")
.font(.caption)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
}
/// The contextual git note **a quiet signpost, not a feature** (12-editions.md The free tier and
/// `.git`, settled 2026-07-27, carried through the one-app collapse). The free tier has no git
/// integration (that is the Pro subscription's), so this is not a grow-in-place slot the way the old
+7
View File
@@ -159,6 +159,13 @@ enum BoardSettingsSection: String, Equatable, CaseIterable, Identifiable {
// level up so the popover's prose stands and this surface simply does not exist for
// such a board.
return []
case .unverifiable:
// **Structurally the same emptiness as `.repoNested`, for the same reason** (06 Rules
// Detection, "Denial is not absence"): a denied ancestor check can never be told apart
// from a repository actually being there, so add-git stays unreachable and this surface
// does not exist for such a board either. Only the popover's *prose* tells the two apart
// this inventory does not, because the sheet has nothing to set up on either.
return []
}
}
}