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:
@@ -33,10 +33,9 @@ private func makeMixedBoard() throws -> WriterFixture {
|
||||
return fixture
|
||||
}
|
||||
|
||||
/// An `AppModel` whose app-side state lives in temp rather than in the shared App Group container —
|
||||
/// both halves of it: the registry file, and the clipboard's staging store, whose launch sweep would
|
||||
/// otherwise collect the developer's own staged copy (and the sibling edition's, since there is one
|
||||
/// store now).
|
||||
/// An `AppModel` whose app-side state lives in temp rather than in the app's real Application
|
||||
/// Support home — both halves of it: the registry file, and the clipboard's staging store, whose
|
||||
/// launch sweep would otherwise collect the developer's own staged copy.
|
||||
@MainActor
|
||||
private func makeModel() throws -> (model: AppModel, tearDown: () -> Void) {
|
||||
let folder = FileManager.default.temporaryDirectory
|
||||
@@ -219,13 +218,13 @@ struct AppModelTests {
|
||||
let record = try #require(model.boardRegistry.record(id: recordID))
|
||||
#expect(record.laneCount == 2, "the counts the welcome row will show are the working ones")
|
||||
#expect(record.cardCount == 2)
|
||||
#expect(!record.isOpen(inEdition: model.boardRegistry.editionID))
|
||||
#expect(!record.isOpenNow)
|
||||
#expect(model.boardRegistry.restorables().isEmpty)
|
||||
|
||||
// Twice is a no-op, which is what lets the window's close interception and its disappear both
|
||||
// call this without the sequence running twice.
|
||||
await model.closeBoard(ref: ref, cause: .userClose)
|
||||
#expect(model.boardRegistry.record(id: recordID)?.isOpen(inEdition: model.boardRegistry.editionID) == false)
|
||||
#expect(model.boardRegistry.record(id: recordID)?.isOpenNow == false)
|
||||
}
|
||||
|
||||
@Test("Quit closes every board and leaves them all flagged for the next launch")
|
||||
|
||||
Reference in New Issue
Block a user