Skip to content

feat(desktop): add independent Space tabs - #311

Open
cxxxxxn (cxxxxxn) wants to merge 16 commits into
mainfrom
feat/desktop-space-tabs
Open

cxxxxxn (cxxxxxn) wants to merge 16 commits into
mainfrom
feat/desktop-space-tabs

Conversation

@cxxxxxn

Copy link
Copy Markdown
Contributor

Summary

Add desktop-only Space Tabs so users can work in multiple Spaces without replacing the current Space's canvas, conversation or preview state. Each window continues to use one Server and one active Workspace; browser deployments retain the existing single-page experience.

  • Introduce an Electron shell with persistent Home and independent, sandboxed WebContentsViews for Spaces, immutable renderer identities, deduplicated navigation and lazy session restoration.
  • Keep the Tab strip minimal: icon-only Home, neutral Space titles and close controls, and persistent Settings/Workspace actions. Reuse the existing Home setup page for opening Workspaces.
  • Isolate Space storage and Chromium connection pools to avoid cross-Space state overwrites and SSE connection starvation; synchronize application preferences across partitions.
  • Coordinate acknowledged saves before Tab close, reload, Workspace changes, window close, application quit and update installation. Save failures retain usable pages instead of discarding them.
  • Route native menus, updater state and remote Basic Auth through the multi-view architecture; update the architecture documentation.

Independent review fixes included

  • Repeated quit/window-close requests share the same save preparation and cannot bypass pending saves, regardless of which action starts first.
  • Workspace restoration uses Server-confirmed identity, not stale client state after a successful activation followed by a failed query. An unconfirmed identity restores no Space pages; registration during a Workspace transition is rejected rather than queued.
  • A synchronous renderer input freeze covers global Canvas shortcuts, native commands and portalled controls until resume or destruction, including after an individual save acknowledgement.
  • Retained Home refreshes after Space creation/import and reactivation; request-generation and Workspace-identity checks prevent stale list responses.

Validation

  • Repository-level pnpm typecheck
  • Repository-level pnpm format
  • Repository-level pnpm lint:fix (0 errors; existing warnings remain)
  • Focused web regression suite: 113 tests passed
  • Desktop unit suite: 75 tests passed, 1 existing todo
  • Real Electron integration: five concurrent Spaces, draft/document/selection/viewport isolation and retention, undo/redo, preference synchronization, failed and delayed saves, both quit-first and close-first shutdown sequences, frozen shortcuts/portals, retained Home creation/list refresh, lazy restart restoration, Workspace menu/setup routing and Workspace switching
  • Formatting and git diff --check

Boundaries / remaining validation

  • One active Workspace per window; no split views, detached Tabs or automatic Tab suspension.
  • Unsent drafts and in-memory undo/selection survive Tab switching, not page destruction or application restart.
  • Closing a Tab does not send Agent Stop; quitting a local application still shuts down its Server.
  • Windows real-device behavior, actual update installer execution and background Agent execution with a configured model remain unverified.

Architecture reference: Desktop Space Tabs.

Add retained per-Space content views, workspace-aware session restoration, isolated storage and synchronized preferences. Coordinate save acknowledgements across tab/window/quit/update lifecycles and retain the minimal desktop tab and workspace navigation UI.

Include regression coverage for repeated shutdown requests, authoritative Workspace recovery, renderer input freezing and retained Home refreshes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Save-barrier ownership and shutdown recovery remain unsafe, and preference synchronization can feed stale updates back between renderers.

5 open findings
What changed in this PR

Adds desktop-only Space tabs, keeping each Space’s canvas, conversation, and preview state independent while sharing one Server and active Workspace.

Changes:

  • Adds persistent Home, independent Space views, and lazy tab restoration.
  • Coordinates saves across closing, reloading, Workspace switching, and shutdown.
  • Integrates scoped storage, shared preferences, native menus, updates, tests, and documentation.
File Description
pnpm-lock.yaml Records desktop’s shared-package dependency.
packages/​shared/​src/​types/​desktop-tabs.ts Defines shared tab IPC contracts.
packages/​shared/​package.json Exports tab types.
docs/​README.md Indexes tab architecture documentation.
docs/​architecture/​web-architecture.md Documents independent desktop renderers.
docs/​architecture/​preview-workspace.md Explains desktop preview isolation.
docs/​architecture/​desktop-tabs.md Documents tab architecture and lifecycle.
docs/​architecture/​desktop-startup.md Updates startup and authentication flows.
docs/​architecture/​desktop-auto-update.md Documents save-aware installation.
apps/​web/​src/​utils/​desktopStorage.ts Adds scoped storage and preference synchronization.
apps/​web/​src/​utils/​desktopStorage.test.ts Tests storage isolation and migration.
apps/​web/​src/​utils/​desktopNavigation.ts Classifies cross-Space navigation.
apps/​web/​src/​utils/​desktopNavigation.test.ts Tests navigation intent preservation.
apps/​web/​src/​utils/​desktopInput.ts Freezes renderer input during saves.
apps/​web/​src/​store/​workspaceStore.ts Coordinates Workspace transitions and recovery.
apps/​web/​src/​store/​workspaceStore.test.ts Tests authoritative Workspace recovery.
apps/​web/​src/​store/​toolStore.ts Uses shared preference persistence.
apps/​web/​src/​store/​previewWorkspace/​persistence.ts Scopes preview layout storage.
apps/​web/​src/​store/​panelStore.ts Scopes panel persistence.
apps/​web/​src/​store/​conversationTitleStore.ts Scopes conversation title drafts.
apps/​web/​src/​store/​conversationPreparation.ts Scopes conversation preparation metadata.
apps/​web/​src/​store/​chatStore.ts Scopes persisted chat metadata.
apps/​web/​src/​store/​chatPreferencesStore.ts Uses synchronized preference storage.
apps/​web/​src/​store/​canvasStore.ts Scopes view state and adds flushing.
apps/​web/​src/​pages/​CanvasListPage.tsx Adapts retained Home and fences list refreshes.
apps/​web/​src/​pages/​CanvasListPage.test.tsx Tests Home refreshes and Workspace controls.
apps/​web/​src/​main.tsx Selects Shell rendering and installs input guards.
apps/​web/​src/​i18n/​resources/​zh-CN/​common.json Adds Chinese tab and Workspace labels.
apps/​web/​src/​i18n/​resources/​en/​common.json Adds English tab and Workspace labels.
apps/​web/​src/​i18n/​index.ts Synchronizes language preferences.
apps/​web/​src/​hooks/​useElectron.ts Exposes typed tab bridge access.
apps/​web/​src/​hooks/​useDesktopContent.ts Handles saves, navigation, status, and preferences.
apps/​web/​src/​hooks/​useDesktopContent.test.tsx Tests save acknowledgements and input freezing.
apps/​web/​src/​hooks/​useCanvasActions.ts Invalidates Home after creation and import.
apps/​web/​src/​hooks/​useCanvasActions.test.tsx Tests list invalidation.
apps/​web/​src/​hooks/​useAppUpdate.ts Supports inline updater feedback.
apps/​web/​src/​hooks/​useAppUpdate.test.ts Tests updater feedback and failures.
apps/​web/​src/​hooks/​shortcuts/​useCanvasShortcuts.lockKeys.test.ts Tests shortcut blocking during saves.
apps/​web/​src/​components/​Shell/​WindowChrome.tsx Suppresses duplicate content chrome.
apps/​web/​src/​components/​Shell/​UpdateButton.tsx Supports Shell-specific update presentation.
apps/​web/​src/​components/​Shell/​NativeMenuBridge.tsx Adapts menu labels and frozen-input handling.
apps/​web/​src/​components/​Shell/​NativeMenuBridge.test.tsx Tests frozen native commands.
apps/​web/​src/​components/​Shell/​DesktopTabShell.tsx Adds tab strip and persistent actions.
apps/​web/​src/​components/​Shell/​DesktopTabShell.test.tsx Tests tab presentation and controls.
apps/​web/​src/​components/​Shell/​DesktopHomeMenu.tsx Adds Home-rendered Workspace menu.
apps/​web/​src/​components/​Panels/​Header/​Header.tsx Adapts controls for tabbed desktop.
apps/​web/​src/​App.tsx Integrates navigation interception and save overlays.
apps/​desktop/​src/​updater.ts Coordinates installation saves and status broadcasts.
apps/​desktop/​src/​updater.test.ts Tests save refusal and broadcasting.
apps/​desktop/​src/​tab-session.ts Validates navigation and session records.
apps/​desktop/​src/​tab-session.test.ts Tests session and navigation validation.
apps/​desktop/​src/​remote-basic-auth.ts Reuses credentials across content renderers.
apps/​desktop/​src/​remote-basic-auth.test.ts Tests cross-renderer credential reuse.
apps/​desktop/​src/​preload.ts Exposes renderer identity and tab IPC.
apps/​desktop/​src/​main.ts Integrates tab hosting and coordinated shutdown.
apps/​desktop/​src/​mac-menu.ts Targets active content and tab closing.
apps/​desktop/​src/​desktop-tabs.ts Implements tab authority, persistence, and lifecycle.
apps/​desktop/​src/​desktop-tabs.test.ts Tests lifecycle, isolation, and IPC ownership.
apps/​desktop/​package.json Adds shared dependency and integration-test command.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

🧠 Review effort: Balanced


💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/desktop/src/desktop-tabs.ts Outdated
Comment thread apps/desktop/src/main.ts
Comment thread apps/web/src/hooks/useDesktopContent.ts Outdated
Comment thread apps/web/src/i18n/index.ts Outdated
Comment thread apps/web/src/components/Shell/DesktopTabShell.tsx Outdated
Preserve save ownership during competing quits, recover shutdown from unavailable pages, avoid preference echo loops, and retain keyboard Tab focus. Add unit and real Electron regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@cxxxxxn

Copy link
Copy Markdown
Contributor Author

Addressed all five Copilot findings in 06fe439.

  • Shutdown can explicitly discard unavailable pages after saving healthy pages; cancellation keeps the application open. Workspace changes remain strict.
  • A rejected competing quit no longer releases another operation's save barrier.
  • Incoming World and language preference updates hydrate local state without invoking the outbound writer; explicit Settings language selections still persist.
  • Keyboard Tab activation requests Shell-native focus and restores the selected button after IPC acknowledgement. Ordinary clicks still focus content.

Validation: 80 desktop tests passed (1 existing TODO), 118 focused web tests passed, repository typecheck/format/lint passed, and expanded isolated real-Electron smoke passed (competing quit ownership, rapid preference writes with exact outbound counts, continuous keyboard navigation, crashed Home shutdown cancellation/confirmation). Native OS-focus assertions were explicitly skipped because this automation environment did not activate any fixture window; native focus invocation is covered by unit tests. Architecture documentation updated. Please re-review the new commit.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Preference ordering and Workspace save-failure feedback remain unresolved.

1 open finding
4 resolved since last review
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Previously missed (2)

In code that hasn't changed since last review

Medium severity Expose workspace save-barrier failures in the Store error

apps/​web/​src/​store/​workspaceStore.ts:172

[P2] Publish save-barrier failures in the Workspace Store. This await is outside the error-handling block, so a rejected save leaves the Store's error unchanged. WorkspaceSetupPage catches activation rejections and relies on that error for feedback (lines 112–136 and 201–207). When a background Space cannot save, selecting a Workspace from /setup therefore fails without showing the reason there. Record the barrier error before rethrowing, while retaining the current Workspace identity.

Medium severity Ignore stale preference notifications after newer local writes

apps/​web/​src/​utils/​desktopStorage.ts:58

[P2] Ignore preference notifications older than an acknowledged local write. If A's zh-CN notification is queued while B synchronously commits en, this listener later replaces B's newer local value with zh-CN. Main remains on en; DesktopTabs.setPreference excludes the writer from broadcasts, so B receives no corrective update. This can leave language or input-mode settings inconsistent across Spaces. Include per-key revisions in snapshots, write acknowledgements and notifications, and ignore older revisions. Add a regression test that delivers A's notification after B's write succeeds.

🧠 Review effort: Balanced

Treat preference notifications as invalidations to avoid applying queued stale values. Surface Workspace save-barrier failures with Store errors and setup toasts. Add focused and real Electron regression coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 20, 2026 06:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Preference event handling can restore stale state, and native Close can target an unrelated Space from an auxiliary window.

No open issues 🎉

2 previously missed issues

In code that hasn't changed since last review

Medium severity Cmd+W closes the wrong target in auxiliary windows

apps/​desktop/​src/​mac-menu.ts:293

Replacing Electron's focused-window Close role with an unconditional Tab close also changes Cmd+W in auxiliary windows. For example, in the remote Basic Auth window it targets the main window's active Space (or does nothing on Home) instead of dismissing sign-in. Use the callback's focusedWindow argument: delegate to closeActiveTab only for the main window, and close other focused windows normally.

Medium severity Native event rehydrates stale preference over newer value

apps/​web/​src/​hooks/​useDesktopContent.ts:204

Home and Shell share localStorage. Shell's preference hydration can queue a native storage event for Home; if Home commits a newer toggle before that event runs, these assignments restore the old Store value even though storage and main hold the newer value. The IPC snapshot check does not cover native events. Read the current localStorage value here, as the rehydrate calls above do. Add a regression test where event.newValue differs from the current stored value.

1 resolved since last review
1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

cxxxxxn (cxxxxxn) and others added 2 commits October 20, 2026 15:26
Route native Close to the focused auxiliary window instead of the active Space. Hydrate native storage events from current values for World, MiniMap and language, with regression coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Preserve both desktop Tab and resource-reference translations. Validate merged dependencies, desktop lifecycle and preference synchronization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 20, 2026 07:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Cross-renderer lifecycle changes need human sign-off, with unresolved recovery issues and unverified Windows and installer behavior.

2 open issues
1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

Comment thread apps/web/src/pages/CanvasListPage.tsx
throw err;
} finally {
try {
if (tabs) requireDesktopTabSuccess(await tabs.endWorkspaceChange());
Release only failed Home-owned Workspace transitions and recheck Home readiness before destroying Space views. Invalidate list refreshes after deletion to prevent stale cards and counts. Add unit and real Electron recovery regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 20, 2026 07:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Preference restoration and background result acknowledgements still have correctness issues.

1 open issue
3 previously missed issues

In code that hasn't changed since last review

Medium severity Prevent inactive Spaces from marking chat results as viewed

apps/​desktop/​src/​main.ts:1053

Retaining each Space's App also retains ChatPanel's result-acknowledgement effect (apps/web/src/components/Panels/ChatPanel/index.tsx:186–207). Its active-view predicate checks only the inner Preview tab and panel expansion, not desktop Tab activation. Open a Question conversation in Space A, switch to B, and let A finish: the hidden page can mark the result as viewed before the user returns. Track desktop activation in renderer state and include it in both active-view predicates in useActivelyViewingQuestion.ts, without unmounting the retained preview. Test that background completion stays unread until the Space becomes active.

Medium severity Surface underlying Canvas save errors in submission feedback

apps/​web/​src/​hooks/​useDesktopContent.ts:67

saveCanvasForSubmission wraps failures in CanvasSubmissionSaveError, whose message is only “Cannot submit before Canvas is saved”; the underlying save failure is in cause (canvasStore.ts:1053–1087). Close and quit feedback therefore reports a submission error instead of the disk, network, or conflict error that explains the failed save. Use the cause's message when it is an Error, falling back to the existing message otherwise.

Medium severity Remove deleted preferences from closed Space partitions

apps/​web/​src/​utils/​desktopStorage.ts:53

If a preference is deleted while a Space is closed, its persistent partition misses the notification and retains the old value. On reopening, the snapshot omits that key, so this loop leaves it in localStorage and the Store hydrates stale settings. Remove recognized preference keys absent from the snapshot before hydrating Space Stores, while preserving Home's legacy migration. Add a regression test that reopens a partition containing a deleted preference.

1 resolved since last review
1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

Track desktop activation using existing Tab snapshots, expose underlying save errors, and clear deleted preferences when reopening persistent partitions. Add focused and real Electron regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 20, 2026 08:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Cross-process save and shutdown coordination needs human sign-off, particularly while Windows behavior and actual update installation remain unverified.

2 open issues
1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

Comment thread apps/web/src/utils/desktopStorage.ts Outdated
Keep desktop preferences in main-process persistence and renderer memory, preserve browser storage, and persist legacy migration before cleanup. Cover startup ordering, synchronization, deletion, and restart recovery.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 20, 2026 09:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Preference-write failure handling and native Settings focus transfer remain unresolved, alongside redundant cross-view status broadcasts.

4 open issues
1 resolved since last review
1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

style={{ WebkitAppRegion: 'no-drag' } as CSSProperties}
aria-label={t('settings.open')}
disabled={snapshot?.busy}
onClick={() => run(tabs.command('open-settings'))}
Comment thread apps/web/src/hooks/useDesktopContent.ts
Comment thread apps/web/src/store/canvasStore.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Open-Space deletion remains unresolved, and cross-platform shutdown and installer lifecycles require final human validation.

3 open issues
2 resolved since last review
1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

Comment thread apps/web/src/pages/CanvasListPage.tsx
Tell users to close an open Space Tab before deleting it from Home. Recheck current Tabs at confirmation and guard the deletion against concurrent Tab or Workspace operations. Cover deletion failures, lock recovery, and the close-then-delete flow in real Electron.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 03:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Cross-renderer save and shutdown coordination needs human validation, particularly for unverified Windows and installer behavior.

2 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Move preference adapter error presentation out of shared utilities

apps/​web/​src/​utils/​applicationPreferenceStore.ts:6

docs/architecture/web-architecture.md:42–46 prohibits utilities from importing components. This import makes the shared preference persistence adapter depend on UI presentation for both write and hydration failures. Move error presentation to a UI-facing layer, or inject an error reporter wired there, while preserving the existing failure feedback and write-before-notify behavior.

1 resolved since last review
1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

Register content preference error feedback before Store initialization while keeping persistence utilities independent of UI components. Preserve both architecture updates when resolving the main merge.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 04:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Cross-renderer lifecycle changes require human review, particularly with Windows behavior and actual update installation still unverified.

4 open issues
1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

Comment on lines +8 to +12
'huabu.language',
'huabu-sketch-tools',
'huabu-chat-preferences',
'huabu:world-enabled',
'huabu.minimapEnabled',
Comment thread apps/web/src/utils/desktopStorage.ts Outdated
Synchronize the recent conversational Agent through the existing application preference adapter, preserving Built-In selection across partitions and restarts. Use validated single-key IPC for routine reads, retain legacy snapshots only for bootstrap, and skip preference access for already observed pen input. Add migration, error, synchronization, bounded-payload and real Electron regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 05:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Cross-renderer shutdown and actual installer behavior require final human validation, particularly on Windows.

3 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Subscribe before hydrating preference Stores

apps/​web/​src/​hooks/​useDesktopContent.ts:271

[P2] Reconcile preferences after subscribing. These Stores hydrate during module initialization, but this listener is installed only after React mounts. If another Space changes World, MiniMap, tool, or chat preferences between those steps, the invalidation can arrive before the listener exists. The new or reloaded page then keeps stale settings until another refresh. Subscribe first, then reread or rehydrate all four preferences. Add a regression case where main's value changes after Store initialization but before this effect mounts.

1 resolved since last review
1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

Reuse preference invalidation hydration to reconcile World, MiniMap, tool and chat values after the content subscription is installed. Preserve transient tool state, report read failures without losing the listener, and cover pre-mount changes, deletions, recovery, cleanup and browser compatibility with real Stores.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 05:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Cross-process lifecycle coordination needs human validation, particularly on Windows and during actual update installation.

3 open issues
2 previously missed issues

In code that hasn't changed since last review

Medium severity Focus Settings WebContents before forwarding the open-settings command

apps/​desktop/​src/​mac-menu.ts:157

After keyboard Tab activation or dismissing the Workspace menu, native keyboard focus remains in Shell. Cmd+, forwards the Settings command to the active content renderer without focusing its WebContents, so the modal opens but typing, Tab and Escape still reach Shell until the user clicks the content view. Focus the target before sending the command, matching DesktopTabs.command('open-settings').

Medium severity Drain pending conversation title renames before acknowledging close

apps/​web/​src/​hooks/​useDesktopContent.ts:113

This barrier does not wait for existing Chat title renames. renameConversationTitle sends a separate request (conversationTitleStore.ts:233) outside the canvas save queues, and normal durable renames are not stored in the persisted pending record. Closing or reloading while that request is delayed can acknowledge success and destroy the renderer before the rename completes or its failure is reported. Track and drain these title writes before acknowledging close, including renames triggered by editor blur, and retain the page if saving fails.

1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

Wait for conversation-title writes in the shared close preparation barrier, preserve failed latest intent for explicit retry, and transfer native Settings focus to content. Cover both paths with Store, lifecycle, menu and Electron regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 07:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Unresolved recovery issues and cross-renderer shutdown behavior require human review, with Windows and installer paths still unverified.

4 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Preserve browser language changes when localStorage fails

apps/​web/​src/​components/​Settings/​sections/​GeneralSettings.tsx:64

[P2] Limit mandatory language persistence to desktop Tabs. In browsers, writeApplicationPreference calls localStorage.setItem directly; a quota error now skips i18n.changeLanguage, so users cannot change even the in-memory language. Keep the existing i18next caching path for browsers and require persistence before changing language only when the Tab bridge exists. Update the tests to distinguish browser fallback from desktop write failure.

1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

Comment on lines +125 to +128
const failed = Object.entries(entries).find(
([key, value]) => value.error && (value.failedTitle || pending[key]),
);
if (failed) throw new Error(failed[1].error);
Expose title retry through persistent save-error feedback after inner Chat tabs close, retry current failed intent without overwriting newer edits, and preserve browser language fallback when localStorage is unavailable. Add Store, hook, settings and Electron regression coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 09:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Title save-barrier handling can lose unpersisted titles or block shutdown after a read-only query failure.

5 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Query failures incorrectly block closing despite persisted titles

apps/​web/​src/​store/​conversationTitleStore.ts:125

A failed title query also sets entries[key].error in refreshConversationTitles(). If a pre-send title is already persisted in pending, this predicate treats that read failure as a failed write even though no title PUT was attempted. The save barrier then blocks Tab close, Workspace switching, and quit unnecessarily. Track query errors separately from write failures, and add a regression test showing that a failed query does not block closing a safely persisted draft title.

1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

Comment thread apps/web/src/store/conversationTitleStore.ts Outdated
Track local pending-title persistence failures at the storage boundary and retry the latest snapshot before allowing close. Separate server-write errors from read feedback so failed queries do not block safely persisted drafts or hide failed writes. Cover quota recovery, creation races, and close preparation in unit and Electron regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 09:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Multi-renderer shutdown and packaged update installation still require human validation, particularly on Windows.

4 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Reject dot segments as invalid Space identities

apps/​desktop/​src/​tab-session.ts:39

Reject . and .. as Space identities. Both pass this predicate, but tabUrl() normalizes their URLs to /canvas/ and /, respectively. Opening or restoring either value therefore creates a Space renderer that loads a non-Space route. Exclude these dot segments in this shared predicate so both navigation and session restoration reject them, and add regression cases for both values.

1 resolved since last review
1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants