Remove the App Group wholesale — one sandbox, one bookmark, one flag

Phase 2 of the one-app pivot (DESIGN 12 ▸ App-side state, re-ruled
2026-07-30; reworks 566deab). AppGroup retires; what remains is
AppStateHome — ordinary sandbox Application Support as the one home for
the registry, clipboard staging and template stores, keeping the
unit-test-host redirect (the test host is the app and would sweep real
state). Scalar defaults return to UserDefaults.standard.

BoardRecord's per-edition grant slots and openNow flags collapse to one
bookmark + one isOpenNow; the legacy-key decode and adopt-in-memory
paths go (nothing shipped with group-era records), while the founding
four-keys-required / defaults-for-everything-since decode policy stays —
a bookmarkless record decodes as the born-orphan row rather than
quarantining the list. needsReopen and the pre-anchored re-grant panel
are removed whole: the only state that flow served — a record granted by
a sibling sandbox — is unrepresentable now, and a dead bookmark of our
own was already the orphan case by explicit comment. The
indexOfRecord path fallback dies with it; path is never a key again.

The cross-process freshness stamp (mtime+size re-read) and
BoardEditionPresence with its popover "Also open in…" line retire; the
clipboard prune keeps its atomic .sweeping/ claim-then-delete, reframed
for crash residue and open -n copies rather than sibling editions. The
application-groups entitlement key is gone.

1880 tests in 317 suites green (13 cross-edition tests retired with
their subject).

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-30 17:46:32 -04:00
parent 092300c7d2
commit 2c6b8fe63a
27 changed files with 385 additions and 1461 deletions
+2 -4
View File
@@ -46,10 +46,8 @@ public final class StyleRecents {
private static let logger = Logger(subsystem: "dev.rzen.indie.Kanban", category: "style-recents")
/// - Parameter defaults: the domain to persist in. Injected for the reason `BoardRegistry` takes
/// its storage URL: a test must be able to hold its own without touching the user's. The app's
/// own is the **group's shared suite** (02-architecture.md § Per-board app state, ruled
/// 2026-07-29), so the row an upgrader built up in base is the row Pro offers.
public init(defaults: UserDefaults = AppGroup.defaults) {
/// its storage URL: a test must be able to hold its own without touching the user's.
public init(defaults: UserDefaults = .standard) {
self.defaults = defaults
// Anything but an array of strings is treated as an empty list rather than as an error: this
// is a convenience, and a hand-edited or truncated preference must never be the reason a