Build out a Playwright-based regression-detection harness covering the compat-matrix surfaces (KDE-W, KDE-X, GNOME, Sway, i3, Niri, packaging formats). Adds: - Planning + decision docs under docs/testing/ — README, matrix, runbook, automation, cases/ (11 case files), quick-entry-closeout - Playwright scaffolding (config, tsconfig) - 78 spec runners under tools/test-harness/src/runners/ — T## case- doc runners and S## distribution/smoke runners - Substrate primitives in tools/test-harness/src/lib/: AX-tree loader (snapshotAx + waitForAxNode + axTreeToSnapshot), focus- shifter, eipc-registry, niri-native bridge, drag-drop bridge, electron-mocks, claudeai page-objects, inspector client S03 (DEB Depends declared) and S04 (RPM Requires declared) ship marked test.fail() — they're regression detectors for the case-doc gap (deb.sh emits no Depends:, rpm.sh sets AutoReqProv: no), and the expected-failure shape lets them report green on every host until upstream packaging starts declaring runtime deps. 127 files, no runtime changes; harness is opt-in via 'cd tools/test-harness && npx playwright test'. Co-authored-by: Claude <claude@anthropic.com>
9.0 KiB
Code Tab — Handoffs to Other Apps
Tests covering desktop notifications, "Open in" external editor, "Show in Files" file manager, connector OAuth round-trips, IDE handoff, and graceful failure of the macOS/Windows-only /desktop CLI command. See ../matrix.md for status.
T23 — Desktop notifications fire
Severity: Critical Surface: Notifications (libnotify / XDG Notifications) Applies to: All rows Issues: —
Steps:
- Trigger each notification source: scheduled-task fire (T27), CI completion (T22), Dispatch handoff (S24).
- Observe each notification appears.
- Click each — confirm it focuses the relevant session.
Expected: Notifications appear in the active DE's notification area (Plasma's notification daemon, Mako on wlroots, gnome-shell, etc.) and are clickable to focus the relevant session.
Diagnostics on failure: gdbus call --session --dest=org.freedesktop.Notifications --object-path=/org/freedesktop/Notifications --method=org.freedesktop.DBus.Introspectable.Introspect, notify-send "test" (sanity check daemon), launcher log, DE-specific notification logs.
References: Scheduled tasks, Monitor pull request status
Code anchors: build-reference/app-extracted/.vite/build/index.js:494456 (new hA.Notification(r) — backed by Electron's libnotify on Linux); :495110 (showNotification(title, body, tag, navigateTo) dispatches Swift on macOS, Electron elsewhere); :511174, :512738 (cu-lock / tool-permission notifications wire a click callback that navigates to /local_sessions/{sessionId} to focus the session).
T24 — Open in external editor
Severity: Should Surface: Code tab → Right-click → Open in Applies to: All rows Issues: —
Steps:
- Install at least one of: VS Code, Cursor, Zed, Windsurf (any install method — flatpak, AppImage, distro package). Xcode is darwin-only and absent on Linux.
- In the Code tab, right-click a file path → Open in → choose the editor.
- Confirm the editor opens at that file.
Expected: Right-click → Open in launches the chosen editor with the file
path. Editor is invoked by URL scheme (vscode://file/<path>,
cursor://file/<path>, zed://file/<path>, windsurf://file/<path>) via
shell.openExternal, which delegates to xdg-open's
x-scheme-handler/<editor> resolution rather than hard-coded paths.
Diagnostics on failure: xdg-mime query default x-scheme-handler/vscode (or
cursor/zed/windsurf), desktop-file-validate on the editor's .desktop
file, xdg-open vscode://file/<path> from terminal (sanity check), launcher
log.
References: Open files in other apps
Code anchors: build-reference/app-extracted/.vite/build/index.js:59076
(editor enum: VSCode, Cursor, Zed, Windsurf, Xcode); :463902 (Mtt
registry — vscode://, cursor://, zed://, windsurf://, xcode:// with
darwin-only flag on Xcode); :463956 (getInstalledEditors probes via
app.getApplicationInfoForProtocol); :464011
(shell.openExternal('<scheme>://file/<encoded-path>:<line>') — path is
URL-encoded but / separators are preserved); :68816 IPC handler
LocalSessions.openInEditor(path, editor, sshConfig, line).
T25 — Show in Files / file manager
Severity: Should Surface: Code tab → Right-click → Show in Files Applies to: All rows Issues: —
Steps:
- In the Code tab, right-click a file path → "Show in Files" (Linux equivalent of macOS "Show in Finder" / Windows "Show in Explorer").
- Confirm the system file manager opens with the containing folder selected.
Expected: System file manager (Nautilus on GNOME, Dolphin on KDE, Thunar on Xfce, etc.) opens with the file pre-selected. Resolution respects xdg-mime defaults.
Diagnostics on failure: xdg-mime query default inode/directory, xdg-open <dir> from terminal, the menu label rendered (was it Linux-specific or stuck on "Show in Finder"?), launcher log.
References: Open files in other apps
Code anchors: build-reference/app-extracted/.vite/build/index.js:66652 IPC
handler FileSystem.showInFolder(path); :509431 impl thin-wraps
hA.shell.showItemInFolder(Tc(path)). Electron's showItemInFolder on Linux
falls back to xdg-open on the parent directory when no DBus FileManager1
service is present, so the file is rarely pre-selected on minimal DEs — only
the parent folder opens.
T34 — Connector OAuth round-trip
Severity: Critical Surface: Connectors → OAuth handoff Applies to: All rows Issues: —
Steps:
- In a Code-tab session, click + → Connectors → choose a service (Slack, GitHub, Linear, Notion, Google Calendar).
- Step through the OAuth flow in the system browser.
- Return to Claude Desktop and verify the connector appears in Settings → Connectors.
- Use the connector in a prompt (e.g. "list my Slack channels").
Expected: Adding a connector launches the browser via xdg-open, OAuth callback hands control back to Claude Desktop, connector appears in Settings, and is usable in subsequent prompts.
Diagnostics on failure: xdg-mime query default x-scheme-handler/https, the callback URL scheme, network captures of OAuth redirect, launcher log, DevTools console.
References: Connect external tools, Connectors for everyday life
Code anchors:
build-reference/app-extracted/.vite/build/index.js:524819
(hA.app.setAsDefaultProtocolClient("claude") — registers the claude://
deep-link scheme used by the OAuth callback); :525026 mainWindow
setWindowOpenHandler routes external URLs through MAA(url) →
:525102–:525135 (only http:/https:/mailto:/tel:/sms:/
ms-(excel|powerpoint|word): are forwarded to system handlers; everything
else is dropped); :136233 $a(url) thin-wraps hA.shell.openExternal(url)
(this is the single egress point for browser handoff); :159634
mcpSubmitOAuthCallbackUrl(serverName, callbackUrl) and :159651
claudeOAuthCallback(authorizationCode, state) — IPC bridges that consume
the deep-link callback. See docs/learnings/plugin-install.md
for orgId/sessionKey cookie chain that gates connector listing.
T38 — Continue in IDE
Severity: Should Surface: Code tab → Continue in menu Applies to: All rows Issues: —
Steps:
- In a Code-tab session, click the IDE icon (bottom right of session toolbar) → Continue in → choose an IDE.
- Confirm the IDE opens at the working directory.
Expected: Selected IDE opens the project at the current working directory. Resolution via xdg-open / .desktop files.
Diagnostics on failure: xdg-open <project-dir> sanity check, xdg-mime query default x-scheme-handler/vscode (or matching scheme for the chosen IDE), launcher log, the IDE's .desktop file.
References: Continue in another surface
Code anchors: Same IPC surface as T24 —
build-reference/app-extracted/.vite/build/index.js:68816
(LocalSessions.openInEditor(path, editor, sshConfig, line) accepts a
directory path the same way as a file path); :463902 editor registry;
:464011 shell.openExternal('<scheme>://file/<cwd>'). The "Continue in"
chooser UI is rendered server-side by claude.ai and not present in the local
asar — only the IPC bridge can be code-anchored.
T39 — /desktop CLI handoff (graceful N/A)
Note
— This test exercises the upstream
claudeCLI binary, not the Electron app. The CLI ships separately from this packaging (out ofbuild-reference/), so no anchor inapp-extracted/.vite/build/exists for the slash-command handler. Re-verify behaviour against the CLI binary that ships with the upstream version under test (currently 1.5354.0).
Severity: Could
Surface: CLI /desktop command
Applies to: All rows (Linux equally)
Issues: —
Steps:
- In a CLI session, run
/desktop. - Inspect exit code and output.
Expected: /desktop is documented as macOS/Windows-only. On Linux it must fail gracefully — print a clear "not supported on Linux" message and exit cleanly. No partial state transition, no panic, no corrupted session file.
Diagnostics on failure: Full CLI output, exit code, the session file before/after (~/.claude/sessions/...), strace if the CLI hangs.
References: Coming from the CLI