Skip to content

Land the opt-in GPUI desktop shell and shell-neutral crates in one change - #7655

Open
devin-ai-integration[bot] wants to merge 378 commits into
mainfrom
feat/1789571352-gpui-migration
Open

devin-ai-integration[bot] wants to merge 378 commits into
mainfrom
feat/1789571352-gpui-migration

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Problem: The Tauri → GPUI migration (ANLG-320) was spread across a twelve-PR stack (#7356, #7358, #7359, #7536#7545) that had drifted from main, carried a stale Cargo.lock, and had to be reviewed and landed strictly in order. Each PR only made sense with the others applied, and their catalogs/lockfiles conflicted with recent main work (calendar, billing, transcript deletion).

Fix: One branch rebuilt on current main that lands the whole migration as a coherent, opt-in change. Tauri stays the default shell and rollback path; nothing here changes the SQLite schema or the ProseMirror document format.

  • apps/desktop-gpui: the native GPUI shell (main window, note view + ProseMirror editor, transcript, recording, settings, onboarding, tray, deep links, single-instance forwarding). Launched via Settings → General → Try the new Anarlog (beta); the Tauri launcher execs anarlog-gpui from next to its own binary (apps/desktop/src-tauri/src/shell.rs), ANARLOG_SHELL=tauri|gpui overrides for one run.
  • Shell-neutral crates extracted from the Tauri plugins so both shells share one implementation: crash-reporting (consent, Sentry init, redaction), desktop-auth (account parsing/persistence/secret store), desktop-db-runtime (DB open + CloudSync runtime/config, moved out of plugins/db), desktop-updater (update policy + backend/event abstraction; GPUI backend checks/downloads but does not install/relaunch yet), desktop-bench (process-tree benchmark harness), plus deeplink-core / tray-core sharing routes, icons, and agenda logic.
  • GPUI CloudSync activation: account binding, E2EE recovery key, device enrollment, connected-library transport selection, gated by the same runtime tests that gate the Tauri plugin.
  • Contract tests between the two shells (deeplinks, tray, search) and ProseMirror round-trip fixtures generated from the web editor (packages/editor/src/note/roundtrip-fixtures.gen.test.ts) consumed by apps/desktop-gpui/src/editor/pm/roundtrip.rs, with UTF-16 position semantics so selections match the web editor.
  • gix author API fix (Fix tauri-plugin-git build after the gix 0.77 bump #7540) needed by the bench harness.
  • CI: gpui_linux_ci job (clippy -D warnings + tests), desktop-bench checks on Linux, macOS cargo check -p desktop-gpui as continue-on-error until Metal shaders are validated, Linux CD ships the anarlog-gpui sidecar (macOS optional). pr-description.yml reads the event file instead of env so large PR bodies don't fail the step.
  • Phase 0 inventory of the Tauri surface in apps/desktop-gpui/docs/tauri-inventory.md.

Consolidation-only changes vs. the stack: conflicts resolved additively (startup in desktop-gpui/src/main.rs keeps crash reporting + auth + CloudSync + updater; Cargo.toml keeps all extracted crates; desktop_cd.yaml keeps Sentry and Supabase env), Cargo.lock regenerated, and the desktop i18n catalogs regenerated on current main (the stack's catalogs were extracted with a Node < 22.18 where lingui extract is a silent no-op, so they had drifted; the diff vs. main is now only the three shell-switch strings).

Not in scope / known gaps (unchanged from the stack): GPUI updater install/relaunch, update state in GPUI UI, activity deferral (no GPUI recording pipeline yet), signed macOS/Windows packaging and hardware validation, Windows single-instance forwarding, rich clipboard embeds.

Supersedes #7356, #7358, #7359, #7536, #7537, #7538, #7539, #7540, #7541, #7542, #7543, #7545.

Verification

  • pnpm install --frozen-lockfile, pnpm -F @anlg/ui build, pnpm -F @anlg/desktop typecheck, pnpm -F @anlg/desktop test, pnpm -F @anlg/editor test, pnpm exec oxlint --quiet --format=github apps/desktop/src/ (0 errors)
  • lingui extract --clean --workers 1 + lingui compile --strict --workers 1 (Node 24; stable, committed)
  • cargo clippy --locked -p desktop-gpui --all-targets --no-deps -- -D warnings, cargo test --locked -p desktop-gpui (490 passed)
  • cargo test --locked -p crash-reporting -p desktop-auth -p desktop-updater -p desktop-bench (all pass)
  • cargo test --locked -p desktop-db-runtime --lib: 66 pass; 12 tests that open the CloudSync extension hang/PoolTimedOut on this VM. cargo test -p db-core 'cloudsync::' on unchanged main code hangs identically here, so this is the sandbox (no network for the extension), not the port — relying on CI for that gate.
  • dprint check + rustfmt --check on all changed files; ci.yaml license-boundary scripts and node --test (67 pass); zizmor --offline shows no findings on the changed workflow lines.
  • Not run locally: macOS/Windows lanes, signed packaging, a real GPUI session on hardware.

Link to Devin session: https://app.devin.ai/sessions/42ab0e9111f44a4c9e79fa361842f703
Open in Devin Desktop: https://app.devin.ai/desktop/session/42ab0e9111f44a4c9e79fa361842f703?variant=devin
Requested by: @ComputelessComputer


Summary by cubic

Lands the ANLG-320 Tauri → GPUI migration as one opt-in change. Tauri remains the default and rollback path; Settings → General → Try the new Anarlog (beta) launches anarlog-gpui, with ANARLOG_SHELL available per run, without changing the SQLite schema or ProseMirror document format.

GPUI shell

  • Adds apps/desktop-gpui with the main window, notes and ProseMirror editor, transcript, recording, settings, onboarding, tray, deep links, single-instance forwarding, and shared window state (persisted alongside Tauri's, close hides to the tray).
  • Adds floating and docked chat with persistent history, streaming replies, a local tool loop (search, move, correction, memo/summary edits with diff review), context mentions, voice input, automations scope, and edit proposal review.
  • Adds note attachments (images, file cards, paste and drop), clip embeds, image context for summaries, pre-meeting briefs, meeting automations and webhooks, and transcription/summary notifications.
  • Matches more of the web UI: shared layout percentages, format toolbar, tooltips, toasts, badges and Insights, folder picker, contact merge/enhance, sign-in/upgrade hand-off screens, and WebKit-style editing and clipboard HTML.
  • Extracts shell-neutral crash reporting, auth, database runtime, updater, benchmark, local API, search, voiceprint, deeplink, and tray crates for both shells.
  • Adds CloudSync runtime gating, cross-shell contract tests, and ProseMirror round-trip fixtures from the web editor.
  • Known gaps remain GPUI updater install/relaunch, signed macOS/Windows packaging, Windows single-instance forwarding, activity deferral, and some signed-in flows.

CI and release

  • Adds required Linux GPUI clippy/tests, desktop-bench checks, and a best-effort macOS GPUI check; Linux releases package the anarlog-gpui sidecar while macOS remains optional.
  • Reads large pull request descriptions from the GitHub event payload, and regenerates Cargo.lock and desktop i18n catalogs against current main.

Written for commit ccb4743. Summary will update on new commits.

Review in cubic

cursoragent and others added 30 commits September 9, 2026 07:41
The reply stream runs up to five steps: tool calls execute locally, their
parts (input-available → output-available / output-error) join the
assistant message in the AI SDK shape, and the results feed the next
generation with search_meetings outputs hydrated like
expandSearchMeetingsOutput. Tool parts render as the Disclosure cards:
the search card with its result carousel and the generic card.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
…iption reply

The chat follows the FloatingClosed / FloatingOpen / RightPanelOpen mode
machine: Open in right panel docks the chat beside the note surface with
the right-panel toolbar (history, new, float, close) and the elevated
composer; the automations tab shows its own automations-scoped chat
(no note context, chatScope: automations) with each selection keeping
its chat thread like switchTo; a send while the open note is still batch
transcribing gets the local canned reply persisted like Tauri's.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Port moveSessionContents: the busy / same-meeting / empty-source / occupied-
target checks with the frontend's messages, the audio copy and catalogue,
the transcript / summary / action-item / voiceprint re-parenting and the
note merge in one transaction, the copied-audio rollback, and the moved /
nothing_to_move / error result shapes. The tool runner now holds the store
so tools can use its helpers.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Port session-correction.ts: the exact / bounded / loose replacements over
the summaries' markdown, the transcript words (single-token bounded
replacement or the comparable phrase split across the span with
:correction:n ids) and memos, and the title; the guarded transaction of
applySessionContentCorrections; the dictionary merge into
personalization_dictionary_terms; and the applied / partial / not_found /
error results.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Ports the edit tools and their review surface from the Tauri app:
- session_proposals persistence (persist, load, apply with the staleness
  check, decline) in db/proposals.rs
- the edit tab (TabContentEdit) as an overlay page: header with
  Decline / Apply, the @pierre/diffs unified diff (file header with the
  modified icon and counts, 20px mono rows, change bars, word emphasis,
  pierre-light/dark markdown token colours, no-newline notes)
- the ToolCard for edit_memo / edit_summary in the chat (spinner, pencil,
  Streamdown-styled MarkdownPreview, error footer, Decline / Apply while
  the tool waits)
- the pending-proposals banner above the note body, opening reviews for
  proposals created by the CLI / MCP or an earlier session
- the workspace takes focus back when the focused field unmounts so the
  document-level shortcuts keep working; tool session ids follow the
  active sessions tab like useSessionTab

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
The desktop app renders Tailwind v4 colours (red-600 is #e7000b, red-500
#fb2c36, red-200 #ffc9c9, amber-500 #fd9a00); the tool card, edit review,
chat error bubble, delete menu items, and live-capture indicators used the
v3 hexes.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
@pierre/diffs builds its hunks with jsdiff (structuredPatch, four lines of
context, deletions preferred on ties) and emphasises changed words with
diffWordsWithSpace in word-alt mode, folding the blank between two changed
words into one span. Port that Myers variant instead of similar so the
review lines up with the Tauri app, keep lines unwrapped with sideways
scrolling like overflow: scroll, and drop the border under the error row.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Mirrors main's capture lifecycle change (#7437): a fresh stop that saved
live text requests the summary right away, records
refreshSummaryAfterRepair in the recovery marker, and the batch repair
regenerates the summary when it lands (also after a recovered marker
carrying the flag). The memo editor's pending body is flushed before the
snapshot like flushCanonicalSessionEditorChanges.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
finish_capture spawned the finalizing marker save and the post-audio clear
independently, so the clear could run first and leave a finalizing marker
behind. The clear now waits on the save. Summary document creation from the
enhancer and the batch start also serialise per session like
enqueueDatabaseWrite, so a live-text summary starting alongside a repair no
longer inserts a duplicate summary row.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Ports useDictation and the plugin's Recorder: the microphone button records
a temporary 16 kHz WAV (five-minute cap) through the app's audio provider,
the batch transcriber turns it into words with numSpeakers 1 and no
keywords, and the text lands in the draft with insertText's blank padding.
The VoiceStatus row (waveform bars, m:ss, stop, send / stop response),
the Starting… / Transcribing… spinners, the meeting-recording warning, the
no-speech warning and the start / transcribe error toasts with their
descriptions follow the web view; the recording is cancelled when the panel
closes or the scope swaps.

The composer editor now takes its width from the panel: a percent-wide text
child is measured before its parent's width resolves and the narrow, tall
measurement stuck, leaving a gap under multi-line drafts. Escape closing the
floating chat hands focus back to the workspace.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Ports clipPastePlugin: an embed snippet, a watch / short / embed / youtu.be
link or a clip link (resolved through the clip page) pasted into the memo or
summary editor inserts the clip block atom with the embed URL, and the paste
is consumed like the plugin's handlePaste. The model gains
replaceSelectionWith for block atoms: a selection goes first, an empty
textblock is replaced, an edge caret follows insertPoint up to the nearest
ancestor that takes a block, and the middle splits the textblock around the
node with the same type and attrs. The node renders as nothing, as it does in
the desktop app.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Renders image nodes as ResizableImageView does: the attachment id resolves
to <session>/attachments/<id> through a new fs-sync-core attachments module
the Tauri plugin now delegates to, the image takes editorWidth% of the
editor with rounded-md, the hover ring and the two resize pills whose drag
writes editorWidth back like handleResizeStart; the inline-block frame's
strut gap and the block padding follow the measured DOM. fileAttachment
nodes render FileAttachmentView's card with the mime icon or thumbnail,
name, size, and the hover open / remove actions. Clip embeds keep their
block padding.

Pasting an image from the clipboard or dropping files on the editor runs
useFileUpload: the bytes are saved under attachments, catalogued with
catalogLocalNoteAttachment's statements (session_attachments,
attachment_local_state, the transfer jobs) under the session lock, rolled
back on failure, and inserted as the image / fileAttachment node with the
web view's attr order and convertFileSrc URL; a dropped audio file runs the
audio import instead. imageTrailingParagraph keeps a paragraph after every
top-level image, and the editor fills the viewport with a flex tail like
.prosemirror-editor { min-height: 100% } instead of a fixed block.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Ports FormatToolbar: a non-empty selection in the memo or summary editor
(outside the enforced title heading) floats the bold / italic / underline /
strikethrough / code / highlight buttons over it — floating-ui's top
placement with the 8px offset, flipped below the selection and shifted
inside the note's scroll container, the ring-1 outside the box, active
buttons on bg-primary. The highlight mark parses and paints like
.note-typography mark: yellow-200 over the inline box with the 2px radius
(dark text in dark mode), which ProseText now paints as an inset background
instead of a full-line run background. Shift+Home / Shift+End extend the
selection to the line edge like the web view.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
main's #7444 added automatic, preserveExistingAudio and initialTitle to
CaptureLifecycleMarker. The shell writes them for its manual captures
(false / true / the session title at start), parses them from the web view's
markers and keeps them through recovery, so both shells read each other's
markers unchanged.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Shows the desktop's notification cards through the shared notification
crate: showBatchCompletedNotification after a re-transcribe / import batch
and after a post-stop repair that ran without live text (notifyOnCompletion),
showSummaryReadyNotification after a summary lands, both only while the
window is inactive and the notification_transcription_complete /
notification_summary_complete settings allow it, with Open Anarlog bringing
the window back on the session like openNew. The tray and the GTK
notification windows now share one GTK main-loop thread. A failed post-stop
repair on the stop that started it raises notifyFailure's toast (the
transcript-save wording without live text, the batch wording with it)
unless the note was deleted; the recovery retries stay quiet.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Ports collectEnhanceImageContext: when the selected model takes images
(modelSupportsImageInput's rules, the Cloudflare vision list), the memo's
image and image-attachment nodes and the transcript memos' markdown images
are read from the session's attachments (by id, then by file name) or their
data URLs, capped at 8 MB each, squeezed under 128 KB apiece and 768 KB in
total by re-encoding as JPEG down the 1280 → 512 edge and 82 → 52 quality
steps, sampled to ten, and sent after the user prompt as the provider's
image part (OpenAI image_url data URL, Anthropic base64 source, Gemini
inlineData) with the IMAGE_CONTEXT_NOTE ahead of the length guidance.

The shared tiptap converter now serialises a block-level image like json2md:
its own paragraph, with editorWidth in the title as char-editor-width=NN,
and the shell's body_to_markdown keeps prosemirror-markdown's newlines for
empty paragraphs (the one imageTrailingParagraph leaves after an image), so
the enhance request for a note with a pasted image is byte-identical to the
web view's.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Port `useContactSummary` / `ContactSummarySection`: the person view now
generates the relationship brief through the enhance model when the
stored `metadata_json.contactSummary` was built from a different set of
meetings, with the frontend's source hash (FNV-1a over the newest eight
sessions' ids and stamps), incremental updates over `existing_facts`,
per-meeting and total source caps, fact normalisation, one query-level
retry, and the spinner / skeleton / failure / footer states.

`llm_stream` gains a non-streaming `generate` / `generate_object` with
each provider's structured-output shape (`response_format`, Anthropic's
`output_config.format` or `json` tool, Gemini's `responseSchema`), and
orders request keys like the AI SDK. `HumanSession` carries the
`source_updated_at` stamp the brief keys on.

Verified against Tauri on one shared database: identical prompts and
system text, identical source hashes for 1, 2, and 8 sessions, identical
stored records, and pixel-matched list, skeleton, and error layouts. The
app's `* { margin: 0 }` reset disables Tailwind's `space-y-*`, so the
lists render gapless, which the port mirrors.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
…yntax

GitHub's `$/path` form resolves sibling actions at the running commit,
which is what zizmor now asks for on the `uses: ./…` lines this job
added; the pre-existing `./` references elsewhere are unchanged.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Port the composer's context flows from `chat/context/*` and
`chat/components/input/*`: `@` opens the same suggestion popup the note
editor uses and the chosen row becomes an inline chip (`TextArea` gains
atoms with the editor's caret-skip and whole-chip deletion, painted with the
shared avatar), a timeline note dragged onto the chat panel becomes a
`session:manual` ref for the next send and dropped onto a note editor an
inline mention plus a space, and the sent message carries the current note,
the dropped notes, and the mentions deduped by key. `ContextRef` now models
the session / human / organization / folder kinds and keeps unknown ones
verbatim; the prompt hydrates contact, organization, and folder refs as the
text blocks after the `<context>` block, and omits the transcript section
when nothing rendered, like `buildTranscript`.

The composer also recalls sent drafts with Up / Down at its edges under the
`History N/M` indicator, undoes with Mod-Z, and flattens the draft the way
`proseMirrorJsonToText` does (chips as `@label`, block breaks dropped).

Verified against Tauri on one database: identical stored rows and
byte-identical prompts for a mention and for a dropped note, identical
documents from an editor drop, and the same popup rows.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Port `ScheduledMeetingAutoStart` / `ScheduledSessionAutoStart`: with
`auto_start_scheduled_meetings` on, a linked, timed calendar event that
starts (or started within the five-minute grace) opens its session —
created from the event like `getOrCreateSessionForEventId` — optionally
opens the meeting link, and records automatically, with the same
due-meeting selection (newest overlapping start first, fired ids claimed,
ignored events and series skipped, a live or finalizing capture skipping or
retrying) and a 30s pending timeout. The capture marker now records
`automatic` and the real `preserveExistingAudio`, and `finalizeStopped`'s
order is kept: after the flush, an automatic capture that recorded no
speech into a session left untouched (title, attachments, `isSessionEmpty`)
loses its audio and clears its marker before anything is catalogued; the
audio is otherwise catalogued at that point rather than at `Inactive`.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Size the timeline sidebar the way `react-resizable-panels` does in the
Tauri app: a persisted share of the panel group (the window minus `pl-1`)
split like its two flex items — the sidebar's exact `flex-grow` against the
library's `toPrecision(3)` content share over the free space minus the
handle — and clamped to 200–360px, so the sidebar scales with the window
exactly as the web view's does. The share starts as 200px of the first
frame's group, follows the handle drag, and is read from and written to the
webview's `localStorage` (`react-resizable-panels:classic-main-sidebar` in
WebKit's `ItemTable` files under the data directory or the WKWebView
website data), with a copy in the shell's own `store.json` scope, so both
shells open at the width the other left.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
…ntend

Without a sidebar folder view (which the shipping app never enters) the tool returns Tauri's `No folder is selected` error instead of the shell's placeholder.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
…ared crate

`crates/local-api-core` holds the outbound webhook dispatcher, the meeting
markdown export (`exportMeetingMarkdown` and the
`automation_markdown_export_*` automation) and the cloud snapshot shape
that `plugins/local-api` exposed as Tauri commands; the plugin now delegates
to it with its bindings and tests unchanged. The core emits its JSON with
every object's keys sorted, which is the byte layout the plugin has always
produced (its build links `serde_json` without `preserve_order`), so a
build that does keep insertion order sends the same webhook bodies and run
records.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
The engine still emits transcript deltas between `Finalizing` and
`Inactive`; the shell moved the persistence queue aside at `Finalizing` and
flushed it at once, so those tail words never landed (a 20s mock capture
kept 103 of Tauri's 124 words). The queue now stays open through the
finalization and is flushed at `Inactive`, where `onStopped` awaits
`transcriptPersistence.flush()`.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
Port `automations/engine.ts` and the `local-api` plugin's `dispatch_event`
over the shared `local-api-core`: `meeting.completed` once a fresh stop's
post-stop processing settles (the awaited batch included) and
`note.enhanced` once a summary lands run the outbound webhooks, the
markdown-export starter with its `automation_markdown_export_last_run`
record, the Slack / Linear / Notion starters (which end where
`requireSupabaseSession` ends for the signed-out shell), and the enabled
custom workflows with their `lastRun` and fifty processed sessions — the
`markdown_export` step writing `<date> <title> [id].md` and replacing the
stale file, the integration steps failing with the frontend's own
messages.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
`finalizeStopped` awaits the `finalizing` marker write before it requests
the summary; when that write fails it shows `The transcript was saved, but
Anarlog could not start the summary. Try generating it again.` and asks the
recovery to retry instead of starting the summary. The shell requested the
summary at once and only logged a failed save; it now sequences the request
and the audio completion behind the save and takes the same failure path
(the toast only for a fresh stop, the recovery retries quiet).

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
The workspace reclaimed focus only when no handle was focused, but a focus
handle outlives its element: once the memo editor gave way to the summary
tab after a recording, keystrokes were dispatched to the bare root past the
workspace bindings, so Escape and the app shortcuts stopped working until
something was clicked. The check now asks whether the focused handle is
still under the workspace element.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
The onboarding's `<video autoPlay loop muted>` becomes an animated WebP of
`onboarding-video.mp4` (832×464 → 416×232, 24fps, 5s loop, pre-blurred with
`gblur=6` since GPUI has no backdrop blur, 31 KB) that GPUI's `img` plays
frame by frame — the element id keeps its frame clock — in place of the
single blurred frame that stood in for it.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
The onboarding branch of the workspace root skipped the resolved `font-sans`
family and the base text style the main root sets, so GPUI's fallback font
rendered the `font-semibold` section headings at regular weight and `Skip`
in the wrong face. The root now carries the same family, colour and size,
and the headings measure like Tauri's.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
The General page's `Where your notes and recordings are stored` label wrapped after `and` in the shell: with `min-w-0` alone Taffy sized the text column at its min-content width, where the web view's flex item keeps its max-content width. The column now takes the remaining space and the path keeps truncating, and the page's text bands match Tauri's row for row.

Co-authored-by: John Jeong <ComputelessComputer@users.noreply.github.com>
devin-ai-integration Bot and others added 9 commits September 16, 2026 15:09
…p-fixtures' into feat/1789571352-gpui-migration
…-core' into feat/1789571352-gpui-migration

Co-Authored-By: John <john@fastrepl.com>

# Conflicts:
#	.github/workflows/desktop_cd.yaml
#	apps/desktop-gpui/src/main.rs
…untime' into feat/1789571352-gpui-migration

Co-Authored-By: John <john@fastrepl.com>

# Conflicts:
#	Cargo.lock
#	Cargo.toml
…into feat/1789571352-gpui-migration

Co-Authored-By: John <john@fastrepl.com>

# Conflicts:
#	Cargo.lock
…ter-core' into feat/1789571352-gpui-migration

Co-Authored-By: John <john@fastrepl.com>

# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	apps/desktop-gpui/Cargo.toml
#	apps/desktop-gpui/src/main.rs
Co-Authored-By: John <john@fastrepl.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

devin-ai-integration Bot and others added 2 commits September 16, 2026 21:16
…us portal setup has a reactor

Co-Authored-By: John <john@fastrepl.com>
…rate; keep zbus on async-io for GPUI portal threads

Co-Authored-By: John <john@fastrepl.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Linux runtime QA at ef2a6f33e7 — shell selection verified; native GPUI rendering could not be verified on this VM.
Devin session

Results
  • Passed: Tauri Settings → General shows "Try the new Anarlog (beta)", the GPUI description, and Switch.
  • Passed: ANARLOG_SHELL=gpui makes the Tauri launcher exec the real anarlog-gpui sibling (exit 0) with --identifier/--db-path, without persisting the preference marker.
  • Passed: the zbus "no reactor running" panic on GPUI's Worker-0 is gone after dropping zbus's tokio feature from the binary.
  • Failed: GPUI's window shows stale framebuffer pixels on this headless VNC + lavapipe (llvmpipe Vulkan) setup, so native note/settings/"Switch back" flows are untested.
Tauri General — passed GPUI native presentation — blocked
Verified beta switch Native rendering blocker
Caveats found during setup
  • The vendored crates/cloudsync/vendor/cloudsync/linux/gnu/x86_64/cloudsync.so requires GLIBC_2.38, so it fails to load on Ubuntu 22.04 (glibc 2.35) with a misleading SQLite error. This is preexisting on main; QA used a temporary rebuild via crates/cloudsync/scripts/rebuild-linux.sh and restored the shipped artifact afterwards.
  • main and the crash-reporting extraction conflicted silently: is_crash_reporting_enabled referenced a static that had moved into anlg-crash-reporting; fixed in ef2a6f33e7.

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Recorded exhaustive Linux GPUI click-through at ef2a6f33e7no Rust panics in the interactive run; several UI issues noted below.
Devin session

What was exercised

Rendering: nested Sway (pixman) + lavapipe on the Linux VM; plain X11 / Xvfb presentation stayed stale (VM graphics limitation, not app code).

  • Onboarding → timeline (signed out), note create/edit/format, exact text persisted across relaunch on the same DB.
  • File/Edit/View/Help menus, search, note views, meeting-info/export/share dialogs, folder assignment, context menus.
  • WAV import + waveform/playback, recording start/stop (null sink), transcript failure state, chat provider gate.
  • All 21 settings/workspace destinations; folders, calendar, contacts, templates, dictionary, automations, stats.
  • Shell round trip Tauri → GPUI → Tauri via the UI, with the shell marker written and restored.

RUST_BACKTRACE=1 stderr (clickthrough.log) has zero panicked at / backtrace matches.

Native persisted note Classic after round trip
Native note persistence Classic General after round trip
Issues found (no data loss established)
  • Onboarding: skipping calendar / meeting-history shows "Calendar connected" / "Meeting history imported".
  • Signed out: Sync page and Developers → Cloud API spin indefinitely.
  • Folder context / template edits: navigating away before blur shows stale or missing values; blur/refresh recovers the exact saved values.
  • Settings search only matches page names ("Timezone" → no results).
  • Clipboard copy/paste inserted nothing under nested Wayland — needs a real desktop to confirm.
  • Weston 9 (xdg_wm_base v1) panics inside gpui's Wayland client at startup (UnsupportedVersion); Sway/KWin-era compositors are fine.

Untested: authenticated cloud/provider flows, OAuth imports, real audio capture/transcription, billing/Teams, CLI/MCP/webhooks. The vendored Linux cloudsync.so (needs GLIBC 2.38) was temporarily substituted with a local rebuild for the run and restored afterwards.

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