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:53:23 -04:00
parent 503ec4872c
commit 26239200ea
10 changed files with 464 additions and 58 deletions
+13 -5
View File
@@ -93,17 +93,20 @@ enum GitRepository {
/// git's since 2026-07-31, so it is almost always already there; when it is not, seeding it here
/// puts it *in* the initial commit rather than after it (`seedGitignoreIfAbsent`).
///
/// **Create re-runs full detection and refuses anything but mode none** (06 Rules Detection,
/// ruled 2026-07-31): "as hardening, add-git's create re-runs full detection and refuses unless it
/// reads clean none, so the forbidden nested init is impossible even on a raced or stale read."
/// **Create re-runs full detection and refuses anything but clean mode none** (06 Rules
/// Detection, ruled 2026-07-31): "as hardening, add-git's create re-runs full detection and
/// refuses unless it reads clean none, so the forbidden nested init is impossible even on a
/// raced or stale read."
///
/// The caller (`HistoryStore.addGit`) has already established mode `none` from the mode it
/// detected at board open, which can be minutes old a `git init` in a terminal at the board root
/// *or anywhere above it* between the two would otherwise slip past a root-only check and
/// initialize a repository inside the user's, which is the one init 06 forbids outright. The whole
/// walk runs again here, at the moment of the write, so the refusal is structural rather than
/// probable. (Detection has no *unverifiable* answer yet 06's denial-is-not-absence distinction
/// is not built so "clean none" is spelled `.none` for now.)
/// probable. **`.unverifiable` refuses too** a denied ancestor check can never be told apart
/// from a repository actually being there, so only a genuinely clean `.none` reading proceeds; a
/// stale `.none` that has since become unverifiable is refused exactly like one that has since
/// become repo-nested.
///
/// Returns the branch the root commit landed on, which is the popover's display line.
nonisolated static func create(at boardRoot: URL) -> Result<String, GitOperationFailure> {
@@ -122,6 +125,11 @@ enum GitRepository {
operation: operation,
message: "this board lives inside a repository; Lanework leaves it to that repository"
))
case .unverifiable:
return .failure(GitOperationFailure(
operation: operation,
message: "this board's surroundings could not be fully checked, so Lanework will not add a repository here"
))
}
let gitDirectory: URL