Keep launcher callbacks scoped to their account and finish menu localization
3 files changed,
+34
−9
docs/superpowers/specs/2026-09-20-mac-document-windows.md+23 −0native/apple/Sources/DocsApp/DocsAccountWindow.swift+8 −6native/apple/Sources/DocsKit/DocsWorkspace.swift+3 −3
CI passed — run details
diff --git a/docs/superpowers/specs/2026-09-20-mac-document-windows.md b/docs/superpowers/specs/2026-09-20-mac-document-windows.md| index 13d65e5..4de6ef9 100644 |
| --- a/docs/superpowers/specs/2026-09-20-mac-document-windows.md |
| +++ b/docs/superpowers/specs/2026-09-20-mac-document-windows.md |
| @@ -44,3 +44,26 @@ registry lifecycle ends only after the actual guarded close. Edit commands obey |
| the first responder, not merely the focused scene. Render reconciliation compares |
| actual optimistic text storage, updates CRDT metadata and acknowledges visually |
| equal generations. Zoom keeps logical layout independent of magnified viewport. |
| + |
| +## Verification and remaining coverage |
| + |
| +Implementation reviewed by GPT-6 Astra (high), including a final account-isolation |
| +and localization review. Both native Mac test suites and iOS simulator builds pass. |
| +A synthetic AppKit interaction fixture exercises Sheets typing successive characters, |
| +failed-save draft retention, Escape, and whole-row/column selection. A live SwiftUI |
| +scene probe verified File actions and Window > Home after closing Home. |
| + |
| +Docs regression tests cover minimal text-storage reconciliation, metadata-only |
| +updates and fixed logical page width. Deliberately restoring full storage replacement |
| +and viewport-dependent width made the corresponding tests fail. A synthetic WebKit |
| +fixture matches native heading, bold and body line breaks and body line spacing. |
| + |
| +This verifies the measured typography cases, not universal browser/TextKit parity. |
| +Complex lists, inline code, mixed styles, margin collapsing and multi-page pagination |
| +need a larger shared layout fixture suite before exact parity can be claimed. The |
| +existing native line-based page breaking and web block-based pagination differ. |
| +That remaining work is triggered by the requested exact cross-platform typesetting |
| +acceptance check; it is not considered complete by this branch. |
| + |
| +Builds are local ad-hoc Mac applications, not signed distribution or TestFlight |
| +releases. No server deployment, merge or publication was performed. |
diff --git a/native/apple/Sources/DocsApp/DocsAccountWindow.swift b/native/apple/Sources/DocsApp/DocsAccountWindow.swift| index 4438cef..3f7cbe1 100644 |
| --- a/native/apple/Sources/DocsApp/DocsAccountWindow.swift |
| +++ b/native/apple/Sources/DocsApp/DocsAccountWindow.swift |
| @@ -14,19 +14,21 @@ struct DocsAccountWindow: View { |
| Group { |
| if let client = connection.client { |
| #if os(macOS) |
| + if let account = connection.activeAccountID { |
| DocsWorkspace(client: client, accounts: connection.showAccounts, signOut: { |
| - guard windows.canSignOut(connection.activeAccountID) else { return } |
| - windows.entries.removeAll { $0.account == connection.activeAccountID } |
| + guard connection.activeAccountID == account, windows.canSignOut(account) else { return } |
| + windows.entries.removeAll { $0.account == account } |
| connection.signOut() |
| - }, canSignOut: windows.canSignOut(connection.activeAccountID), createRequested: $windows.createRequested, openDocument: { document, title in |
| - guard let account = connection.activeAccountID else { return } |
| + }, canSignOut: windows.canSignOut(account), createRequested: $windows.createRequested, openDocument: { document, title in |
| + guard connection.activeAccountID == account else { return } |
| let id = windows.reserve(account: account, document: document, title: title, client: client) |
| openWindow(id: "document", value: id) |
| }, updateRecents: { documents in |
| - guard let account = connection.activeAccountID else { return } |
| + guard connection.activeAccountID == account else { return } |
| windows.updateRecents(documents, account: account, client: client) |
| }) |
| - .id(connection.activeAccountID) |
| + .id(account) |
| + } |
| #else |
| DocsWorkspace(client: client, accounts: connection.showAccounts, signOut: connection.signOut) |
| .id(connection.activeAccountID) |
diff --git a/native/apple/Sources/DocsKit/DocsWorkspace.swift b/native/apple/Sources/DocsKit/DocsWorkspace.swift| index 810d1a7..5bf4c69 100644 |
| --- a/native/apple/Sources/DocsKit/DocsWorkspace.swift |
| +++ b/native/apple/Sources/DocsKit/DocsWorkspace.swift |
| @@ -205,13 +205,13 @@ import SwiftUI |
| } |
| }.padding(28) |
| } |
| - .navigationTitle("Home") |
| + .navigationTitle(docsMacString("Home")) |
| .searchable(text: $query, prompt: Text("docs.list.search.label", bundle: DocsResources.bundle)) |
| .onSubmit(of: .search) { Task { await model.load(query: query) } } |
| .toolbar { |
| - if let accounts { Button(docsMacString("Accounts"), action: accounts) } |
| + if let accounts { Button(docsMacString("Accounts"), action: accounts).disabled(model.creatingDocument) } |
| Button(docsMacString("New document"), systemImage: "plus") { creating = true }.disabled(!model.canCreate) |
| - Button(docsMacString("Sign out"), action: signOut).disabled(!canSignOut).help(docsMacString("Close this account’s document windows before signing out.")) |
| + Button(docsMacString("Sign out"), action: signOut).disabled(!canSignOut || model.creatingDocument).help(docsMacString("Close this account’s document windows before signing out.")) |
| } |
| } |
| } |