Repository navigation
Fade overflowing sidebar labels - #415
Conversation
wingleeio
left a comment
There was a problem hiding this comment.
Security audit and review of f7f73bd77cce890fdb837cb364d01c427a8607bb: requesting changes for the nested-fade rendering regression described inline. No actionable security vulnerability found in the reviewed change, but this revision should not merge yet.
Security scope: inspected the UI diff, all changes in the pinned renderer versus the previous renderer, dependency provenance, and shader/host data flow. The full source tree of fork commit 53869c204efb866d19af292cab8b1773898eeedd exactly matches merged upstream commit 1561532176f54262e360acbb8bc00c6fcf183975 (tree e5f21c24b5c7a161cb80b6a2c58c1a8c8382b065). No added application network access, command execution, authentication changes, or new unsafe Rust was found. The immutable renderer pin is unchanged in the tested candidate.
Validation and conflict handling:
- Prepared a local merge with main at
b4dd24d7346a50fe73658d06e4d75ddb9a61c50e. Resolved the disclosure-header conflict by keeping both this PR's faded label and main's sharedsidebar_separatorhelper. Nothing was pushed. - On that locally resolved candidate,
cargo test --locked -p zeron-ui --lib -- --test-threads=1passed 1,058 tests, 0 failures. Changed Rust files pass rustfmt and the diff passes whitespace checks. - Built and ran an isolated Linux/X11 production Shell fixture with synthetic sessions. Two otherwise identical 1100×440 windows differ only in whether titles fit or overflow horizontally. The overflowing
Session 04remains fully bright at the bottom scroll edge; the fittingSession 04correctly fades. The adjacent icon still fades in both cases, making the inconsistency visible. - Existing PR CI and the pinned renderer's Windows CI succeeded. Those tests do not cover nested horizontal/vertical fades. The renderer's WGPU unit test cannot be invoked directly through the application's workspace because it is a dependency with its own dev-dependencies; no new local shader-test pass is claimed.
Fresh GitHub user attachments from the controlled fixture (look at the bottom Session 04 row):
Overflowing labels: vertical fade is lost
Fitting labels: vertical fade remains active
wingleeio
left a comment
There was a problem hiding this comment.
Fixed and re-audited cd247d721113a71065c2e4ca1ba92877beb78a9e. The original nested-fade finding is resolved; no remaining actionable security or correctness findings.
The conflict resolution preserves both the faded disclosure label and main's shared sidebar separator. The only additional implementation change retains the active wrapper fade during painting, keyed by window, and carries its vertical bounds and independent top/bottom bands into overflowing label fades. Fitting labels inherit the original parent scope; paint state is restored after each child. Interior mutability avoids scheduling global-observer notifications for each painted label. No dependency revision, network, command execution, authentication, or unsafe-memory changes were added by the fix. The pinned renderer source tree remains identical to the previously audited upstream merge.
Validation:
- Full local UI suite: 1,059 passed, 0 failed.
- New paint-level regression exercises fitting → overflowing → fitting behavior through repeated width changes, top-only/bottom-only/combined/no vertical fades, asymmetric bands, and restoration for siblings and elements outside the scroll container.
- Rebuilt and reran the Linux/X11 production Shell fixture that exposed the bug. The bottom-row
Session 04prefix now matches pixel-for-pixel between overflowing and fitting titles (x=86..152, y=469..484), while long text retains its right-edge fade. - Changed-file rustfmt and diff whitespace checks passed. No intervening PR or main changes were found before applying this fix.
Fresh GitHub user attachments from the fixed build, using isolated synthetic sessions. Cross-platform CI is running on the pushed head at review submission; these screenshots are Linux fixture evidence.
Fixed overflowing title: horizontal and vertical fades both apply
Fitting title: matching vertical fade at the bottom edge
Upstream: zeronsh/zeron 01b705f "Fade overflowing sidebar labels (zeronsh#415)" Ticket 15 of the 2026-09 upstream-ports program. Desktop (cherry-picked, conflicts resolved by intent across the rebrand): - edge_fade.rs: fade_label_overflow — a right-edge fade that eases in as a label's overflow grows from zero to one band (label_fade_outset's smoothstep), unlike scroll chrome which snaps at 1px; the paint-time PaintFades stack keeps a label's wrapper scope alive so an overflowing label inherits its scroll container's vertical fade (window-scoped, so a nested draw of another window never leaks it); both new tests land (painted_label_retains_scroll_fade_across_overflow_transitions, label_fade_enters_continuously_and_settles_at_one_band). - shell.rs: sidebar_faded_label wraps the chat row's device line, title, and branch — nowrap content behind a tracked overflow-hidden wrapper. - shell/spaces.rs: the disclosure header label, the spaces-filter label + device tag, and the archived shelf titles adopt the same wrapper. Exclusions (per AGENTS.md GPUI-pin rule): - The Cargo.toml hunk adding [patch."https://github.com/zeronsh/zui"] gpui* = gaelcado/zui@53869c20… ("temporary renderer override for the companion per-pixel text fade PR") is DROPPED, along with its Cargo.lock churn: roboco stays on hoangvu12/zui (patch rev == top-level pin). The label fade needs no gaelcado-only gpui API — EdgeFade/with_edge_fade/ Global/WindowId all exist at our pin; only the renderer's text opacity granularity differs (per-glyph, not per-pixel), so edge_fade.rs's module doc keeps roboco's "per-glyph granularity" wording. If the per-pixel text fade lands in hoangvu12/zui later, both pins move together per AGENTS.md. - The shell.rs/spaces.rs hunks' popover::search_highlight(…) label content is CONTEXT roboco does not carry (it rides 74558a2, ticket 16): the faded wrappers wrap roboco's plain label children instead. Web parity (web/packages/app, same commit): - components/sidebar-faded-label.tsx: the mask-image right-edge fade — ramp width --rb-label-fade-inset, 0 while the label fits, eased to one 20px band by label_fade_outset (the same curve, unit-tested); one shared module-level ResizeObserver measures every mounted label. Ancestor masks compose for free, so the sidebar's vertical scroll fade keeps fading rows inside an overflowing label (the free web peer of PaintFades). - chat-list.tsx / archived-section.tsx / sidebar-disclosure.tsx / space-filter.tsx: the device line, chat title, branch, archived title, disclosure label, spaces-filter name and device tag become faded labels — the ellipsis truncation is gone (CSS guards in the test). - app.css: .sidebar-label-fade/.sidebar-label-fill/.sidebar-label-fade-inner; the label classes drop text-overflow: ellipsis. Tests: roboco-ui edge_fade 2 tests pass. Web: sidebar-fade 7 (2 new label tests + the CSS guards), sidebar-view/archived/sidebar-store/sidebar-tween/ sidebar-tooltip 54, picker-search 17 all pass; tsc --noEmit clean.
* Refine Files panel toggle with a custom tree icon * Move Files search into the panel titlebar * Refine Files tree icon geometry * Fix command palette session row arguments * Add theme-aware indentation guides to file trees * Add file browser button to diff file headers * Make file tree titlebar search adapt to narrow panels * test(ui): reproduce activity replay after batched transcript catch-up * Color file tree entries with shared remote-safe Git status * feat: add Antigravity ACP, improve context UI, and persist window geometry (#349) * feat: add antigravity agy harness with grouped reasoning models drive google's agy cli over its own stream-json print mode: one process per session with prompts written to stdin, step updates normalized into text, tool and context-usage events, and the terminal result frame as the turn end. steers queue for the next turn, interrupts signal the process, and resumes reopen the conversation with --conversation. agy lists every effort as its own model id, so variants are grouped into one model with a low/medium/high ladder and the picked level is folded back into the variant id at run time. headless agy cannot prompt for permission, so sessions run in accept-edits mode unless auto-approve is on, and denied actions surface as an error explaining how to allow them. wires the harness through the proto id, engine registry, account slugs, desktop pickers and settings, and the ios catalog and brand mark. * fix: always skip agy permissions and report context windows zeron has no approval ui and headless agy auto-denies anything it would prompt for, so runs always pass --dangerously-skip-permissions, matching the claude and codex harnesses. denied actions can now only come from agy's own deny rules, and the error says so instead of pointing at a missing auto-approve toggle. agy reports token counts but no context window, so context usage now carries the published window for the gemini, claude and gpt-oss model families, leaving it unreported when agy picks its own default model. * fix: count cached agy tokens and fit the context window tooltip once prompt caching kicks in agy moves the cached prefix out of input_tokens into cache_read_tokens, so the context indicator dropped and climbed between steps. context usage now reports their sum, which grows steadily across a run. the context window tooltip was fixed at 260px regardless of its text, so it now sizes to its content up to that width and groups token counts by thousands. * feat: list antigravity skills as slash commands zeron showed no slash commands for antigravity. commands now come from agy's own `-p=/skills` json listing, which answers without a model turn, covering built-in and global skills. names are deduped in listing order and descriptions trimmed to their first sentence for the picker, and a non-empty listing is cached like the model catalog. agy's cli commands such as /usage and /model are refused under --input-format stream-json, so they are not offered. the listing runs from home because the command list is not scoped to a session, so workspace skills are not listed but still expand when typed. * feat: drive antigravity over its acp server with sign-in on enable replace the agy stream-json driver with google's antigravity acp server (agy_acp_server 1.1.1) on the shared acp harness. the pinned release archive for the platform downloads and unpacks once into the managed adapters dir, reusing the npm installer's atomic marker and lock. antigravity is now off by default. turning it on in settings runs the server's google sign-in from home, outside any project, so preview discovery never consumes the one-shot oauth redirect; the app opens the single sign-in tab from the polled url and the toggle flips only once sign-in succeeds. turning it off signs out through acp logout, and a run without a login points to settings instead of opening a browser. effort variants group by their display name, since a signed-in catalog pairs gemini-3.1-pro-low with gemini-pro-agent for high, and each level sends the id the server advertises. skills from the global gemini skill folders are listed as slash commands next to the server's own, with logout hidden. the context indicator is hidden until a window is reported, and its tooltip no longer clips wrapped text. * fix: address antigravity review feedback * feat: add phased sign-in feedback for antigravity setup * fix: read antigravity auth settings the way the server does resolves the three auth-settings findings from the pr review: expand a home-relative GEMINI_HOME like the server's os.path.expanduser, parse settings.json as hjson since the server reads it with hjson.load, and canonicalize the vertex-ai alias to the advertised agent-platform id. * test: pin antigravity's live and fallback model catalogues covers the review's catalogue recommendation: a newer flash the signed-in account advertises reaches the picker as its own grouped row, while the offline fallback stays on the models the pinned 1.1.1 archive bundles. * feat: persist window geometry and restore its display * fix: persist screen-sized macOS window geometry * fix: align Antigravity auth settings paths with its server * fix(transcript): skip replay animations for historical activity * Add configurable shortcut to open model picker (#433) Co-authored-by: wing-anara <wing@anara.com> * Fix token refresh storms and preserve sessions during transient DNS failures (#352) * fix(auth): share refresh attempts and bound retry cooldown * fix(auth): keep transient token failures distinct from sign-out * fix(engine): preserve DNS and HTTP transport error causes * fix(transcript): track replay incrementally and preserve live animations * Polish command palette and add quick theme action (#407) * Polish command palette layout and add theme action * Polish palette content spacing and action accessibility * Reuse sidebar separator and refine palette search icon * Dim the workspace behind the command palette * Use Solar sun and moon icons across appearance controls * Make command palette section separator full width * Suppress unflagged Enter repeats in command palette * feat(ui): add configurable conversation width in appearance settings * fix(transcript): retain opening history across replay updates * Fade overflowing sidebar labels (#415) * Fade overflowing sidebar session titles * Extend sidebar fades to branch and device labels * Slightly strengthen sidebar label fades * Widen sidebar label fades to 20 pixels * Smooth sidebar fade onset and use per-pixel text rendering * Add reproducible sidebar CPU comparison and supplied preview * Document measured sidebar fade CPU comparison * Keep sidebar fade PR focused on behavior * Preserve vertical scroll fades inside overflowing labels --------- Co-authored-by: wing-anara <wing@anara.com> * Release v0.2.73 * Fix truncated Cursor catalogs and refresh harness models (#436) Co-authored-by: wing-anara <wing@anara.com> * Add collapsible pinned sidebar section with animated divider * chore: release v0.2.74 * Fix keyboard focus when opening the model selector (#438) Co-authored-by: wing-anara <wing@anara.com> * chore: release v0.2.75 * Add animated drag transfers between pinned and regular sessions * Remove sidebar section drag highlights * Simplify pinned and archived section headers * Right-align pinned and archived disclosure chevrons * Reduce spacing above archived sessions * fix(cursor): recover abandoned runs and stabilize model discovery * fix(ui): align elapsed timer with working indicator text * fix(ui): format elapsed time in hours and days * test(cursor): stress steering bursts and prioritize cancellation * chore: release v0.2.76 * Fix blank session revisits and transcript attachment race * Show a bounded local transcript tail before rebuilding whale history * Verify opening previews and cached revisits never replay tool animations * Prevent whale replay from starving desktop networking * Prepare whale transcript presentation off the UI thread * chore: release v0.2.77 * Prevent replaying sidebar movement after successful drops * Reconcile sidebar pins against authoritative registry snapshots * Validate sidebar pin changes consistently before accepting drops * Serialize optimistic pin writes and reconcile acknowledged state * Exercise pin write transport and migration persistence failures * Clear pin write notices after successful recovery * Sync sidebar pins with per-item ordering keys * fix(cursor): preserve SDK failure diagnostics and update to 1.0.31 * test(cursor): verify token refresh against aged live SDK sessions * ci(cursor): automate SDK updates and gate releases on auth compatibility * Preserve Cursor user context through steering and startup interruption * chore: release v0.2.78 * feat(ui): add configurable compact sidebar and project icons * Refine sidebar accordions and compact row layout * Reorder sidebar icons and use terminal remote icon * Render archived sessions with shared sidebar data and layout * Let sidebar titles use empty action space * Use frosted project monograms and refine sidebar action icons * Refine project badge colors and open sidebar options to the right * Add compact transcript mode: one collapsed work accordion per turn Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Select project monograms from a fixed curated palette * Use Earth icon for remote sessions * fix(actions): bound project file reads and reject special files * Discover monorepo project icons and default to compact sidebar * Rename sidebar location option and update globe artwork * fix(actions): preserve project identity for queued worktree setup * Improve monogram hover contrast and show project tooltips * Show compact-mode "Worked for Xm Ys" after the turn settles Stamp durationMs on the assistant entry at segment finish and, in compact mode, fade that into a subtitle under the work accordion when the live working trailer goes away. * Simplify project icons, add device tooltip, and split compact mode - Drop monorepo icon discovery; lookup checks root-level artwork only. - Project icon tooltip uses the pull-request badge card and shows the owning device name under the project name. - Selected rows keep the monogram's hover tint without hovering. - Remote session icon uses the Solar "global" glyph. - View options menu shows Compact mode in its own Layout section. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Match archived "Show more" height to compact rows Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Persist compact-mode turn duration and replace the work summary Stamp and recover "Worked for" duration across relaunch, then crossfade the compact accordion title from the tool summary into that line once the turn settles. * Drop guessed compact durations and the turn-duration sidecar Trust durationMs plus the in-session live timer. Do not infer Idle updated_at, do not rewrite compact-turn-durations.json, and do not resync the transcript every second while Working. * chore: release v0.2.79 * Remove Cursor SDK diagnostics from device settings * Expand compact "Worked for" into the normal transcript layout Collapsed compact mode still hides the turn behind the work header. Opening it now reveals thinking, tools, and narration as ordinary transcript rows instead of "Wrote" chips. The final reply stays outside the toggle. * Make the explorer a docked portion of one right pane The explorer column and the surface host now form a single right pane under one shared header. The explorer toggle docks or undocks its portion, opening the pane with only the explorer when the pane was closed. The pane toggle (outermost, like the left sidebar's) closes both portions and reopens whichever were visible before, defaulting to the surface host. Programmatic opens (files, browser links, subagent chips) go through set_surfaces_open so they never close a pane the user has open. The header carries the explorer seam hairline and the rightmost column carries the window corners. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Let the pane toggle drive only the surface host The right-pane toggle now opens or closes just the surface host. With only the explorer docked it opens the surface host beside it, and it never hides the explorer: undocking is the explorer toggle's job alone. Closing the last surface tab collapses the surface host, leaving a docked explorer to keep the pane open on its own, or closing the pane entirely when nothing else is docked. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * chore: ignore agents.md * chore: ignore .agents directory * ios: fix transcript follow, normalize model catalogs, desktop networking parity (#468) * ios: normalize model catalogs, verified cursors, 300s checkpoint deadline Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: keep transcript follow alive across stale gestures and appends; opaque session header Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: 50-scenario transcript scroll matrix test Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: keep history anchor exactly in place during streaming restore() clamped the anchor row to keep 44pt visible on every relayout, so a row straddling the top edge by more than height-44 shifted the reader's viewport whenever content below streamed in. Only apply the clamp when the anchor row itself shrank (a fold collapsing). Matrix: tail-gap threshold accounts for block trailing padding, pinned offsets may retreat by measured content shrink, jump uses arm()+jump like the button. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ci: rerun ios-tests Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Wing Lee <wing@anara.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Give the explorer a secondary header for search and visibility Move the file search field and the show-hidden eye out of the titlebar and into a toolbar row inside the file pane, using the same toolbar band the editor's breadcrumb header uses so both columns share one header height. The titlebar explorer slot now carries only the explorer and pane toggles; the compact/expanding titlebar search is gone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Compact sidebar account control and nest view options (#465) * Use a compact avatar button for the sidebar account menu * Match account button hover shape to circular avatar * Size sidebar avatar to match remote session icon * Nest sidebar view options in category submenus * Separate sidebar Show options and use a Compact switch * Share model selector hover intent with sidebar submenus --------- Co-authored-by: wing-anara <wing@anara.com> * Add custom sidebar sections with session drag and drop (#486) Co-authored-by: wing-anara <wing@anara.com> * chore: release v0.2.80 * Sync sidebar sections across devices (#487) Co-authored-by: wing-anara <wing@anara.com> * chore: release v0.2.81 * Add zeron mcp server with parent-linked chats `zeron mcp` serves MCP on stdio and proxies every tool into the running engine's localhost IPC, so an agent in one chat can create, read, message, wait on, interrupt, and archive other chats. The protocol layer is hand-rolled (initialize/ping/tools/list/tools/call over newline JSON-RPC) to avoid a new SDK dependency. Chats created through the server record the creating chat as parent (`Chat.parent_chat_id` / `parentChatId` on the registry row, serde defaulted so older rows read as parentless). `list_chats { parent }` returns a chat's children. The left sidebar, project tabs, jump slots and Archived section hide chats that have a parent; they stay reachable by id, deep link, and MCP. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Add Mod+E files-panel shortcut and space the pane toggles The explorer's own toggle (the titlebar tree button) gets a customizable shortcut, Cmd+E on macOS and Ctrl+E elsewhere, listed under Panels in Settings > Shortcuts. It docks or undocks the explorer portion of the right pane and never touches the surface host, matching the button. A settings file written before this shortcut existed keeps a custom binding that already used the chord; the new row then arrives unbound instead of double-bound. The explorer toggle and the pane toggle rendered edge to edge as one fused block. The slot now carries the same 4px gap the surface strip keeps between its controls, and the reserved slot width grows to match. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Drop the doubled hairline over the explorer seam The explorer column is padded down by the titlebar height and its left border already runs through the header band. The header's explorer slot drew the same hairline on the same pixels, and the stacked alpha read as a lighter line than the seam below it. The slot no longer draws one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * ios: durable outbox + send watchdog, fix transcript scroll jumps, session UX polish (#479) * ios: durable chat2 outbox, send watchdog, split backfill deadlines Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: keep realized heights across transcript updates, diff rows instead of reloadData UITableView drops every measured height on reloadData/endUpdates and falls back to the 140pt estimate, so a long transcript's content size collapsed and re-expanded under the finger on each structural update — the visible jump while reading history. Cache measured heights by row id and serve them as estimates, apply structural changes as insert/delete batches (falling back to reloadData above 400 changes), and only apply the 44pt fold clamp in anchor restore when the row's content version actually changed, not when a hosted cell settled its own measurement. Restore outbox pushes in order on startup. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: center jump-to-latest, fade composer chips, show connectivity in session strip Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: grow composer shell with multi-line draft under software keyboard Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: bound session stores and harden chat2 durability Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: make animated jump-to-latest realize the tail first and self-correct Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: dial pending-outbox stores past the warm cap, make stop() terminal, real-store durability tests Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: export snapshots off the main thread on background flush (0x8BADF00D watchdog) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: retire armed debounce/retry timers when a background flush starts Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: retire saver timers up front, keep background flush sequential Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Wing Lee <wing@anara.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Separate Antigravity detection and authentication from server availability * Make Antigravity enablement follow detection and expose explicit sign-in * Record Antigravity validation status and disk-limited follow-ups * fix(acp): own process groups and preserve Pi crash context * fix(pi): preserve descendant cleanup grace and verify durable resume * Remove repository-local validation status report * fix(acp): reject requests after EOF and retain the latest stderr tail * ios: bound snapshot write cadence and store residency by bytes (#490) * ios: bound snapshot cadence and residency by bytes Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: guard deferred snapshots against stale store ownership Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ios: keep eviction flush alive after store dealloc Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Wing Lee <wing@anara.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Consume complete HTTP request headers in catalog test fixtures * Let the engine surface Antigravity launch errors uniformly * Allow Antigravity cold discovery up to ninety seconds * fix(harness): detect current OpenCode server versions and auth failures * fix(harness): version OpenCode commands and surface HTTP rejection * feat(harness): select OpenCode agents through cached model options * fix(harness): normalize OpenCode status retry and tool progress events * docs(harness): record OpenCode compatibility and extend isolated probes * Drop reference-integration name from ACP comments * fix(harness): select newest CLI and honor configured model metadata * fix(harness): finish portable version probes and diagnostics * fix(harness): retain catalogs by credential and binary context * fix(engine): persist contextual model catalogs and refresh in background * fix(ui): retain model rows after refresh errors and send force * feat(claude): share initialize discovery for live models and commands * fix(models): classify discovery failures and reject unauthorized stale catalogs * fix(codex): reject empty catalogs and retire discovery children * fix(ui): preserve saved models absent from refreshed catalogs * test(harness): align refresh regression with last-good catalogs * test(opencode): retain same-context catalogs on empty refresh * docs(models): record full validation and live discovery results * fix(harness): own archive adapter temporary roots through shutdown Port the scratch guard from upstream #475, retaining process-group shutdown and limiting roots to resolved archive launches. Add a managed live-probe mode. Co-authored-by: LoikStyle <131105263+LoikStyle@users.noreply.github.com> * fix(engine): allow remote adapter catalog discovery to finish Co-authored-by: laurentcodes <stlaurentcodes@gmail.com> * fix(harness): strip echoed wakeup blocks from Antigravity streams Port upstream #452 streaming filter and chunk-boundary regression coverage. Co-authored-by: laurentcodes <stlaurentcodes@gmail.com> * test(harness): prove cancel notifications omit request ids * test(harness): preserve large frames amid stdout noise and CRLF * test(harness): drain a full update queue before turn completion * test(harness): empty assistant chunks produce no segment events * fix(harness): retain bounded startup command and mode metadata * fix(harness): reject foreign session permissions and ignore their traffic * fix(harness): redact credentials in crash diagnostics * fix(harness): discard prompt settlement after cancel escalation * test(harness): dropping an idle stream reaps its warm adapter * fix(harness): configure Antigravity siblings and capture stdout sign-in URLs * test(harness): exercise Pi steering without the extension * fix(harness): redact quoted and whitespace-padded credentials * fix(harness): bound OpenCode submission and confirm ambiguous idle turns * fix(harness): make scratch roots private and retain guards during cancellation * style(harness): format adapter regression tests * fix(harness): ignore JSON objects that are not RPC responses * test(harness): expose event status in the OpenCode HTTP fixture * refactor(harness): name the stdout observer callback type * fix(harness): require explicit Antigravity installation * feat(settings): install Antigravity explicitly on the selected device * test(harness): expose Antigravity detection in the live probe * fix(opencode): version permission reply bodies at 2.0.4 * fix(opencode): bind both task and subagent spawn tools * test(opencode): allow explicit permission answers in the live probe * test(engine): handle partial archive request headers * test(engine): require the Antigravity server for enablement * Bump version to v0.2.82 * Add rich composer references and completion * Fix rich-reference recovery for Cursor * Validate portable rich invocation delivery * Preserve OpenCode command intent through delivery * Stabilize adaptive composer menus * Verify Cursor rich-reference recovery envelopes * Document rich composer visual evidence * Preserve commands and skip unreadable skills * Gate composer references and harden discovery * Improve command discovery and mention chips Share workspace command probes across catalogs while refreshing between opens, and refine composer chip styling and layout. * Refine Composer Mention Chips * Refresh rich composer screenshots and review notes * Move composer completion preferences to Shortcuts for active agents * Animate the compact work fold's body under TOOL_FOLD Toggling the "Worked for" shell used to sync() immediately, so the folded rows popped in/out at full height instead of folding like every other transcript expander. Body rows now stay mounted through the 140ms ease-out tween: each sibling clips to a shared height budget (lerp from the measured total toward the new target), a prepaint probe keeps row heights current, and a settle sweep drops the rows once the retention window elapses. Reversals seed `from` with the budget in flight so mid-tween toggles continue smoothly, and reduced motion transitions instantly without retaining the body. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Fix rich composer review regressions * Correct composer completion settings documentation * Clarify Harness Completion Settings Documentation * Add explicit platform-aware agent CLI installers * Route and cancel explicit installs on the selected device * Offer Install and Cancel for every eligible agent * Document audited agent installation commands * Preserve device switching and manual installation hints * Install OpenCode 2.x from @opencode/cli when npm is the fallback * Restore simple reference chips and trim composer review artifacts * Consolidate composer and reference test fixtures * Bound skill discovery and reject special files * Refresh completion catalogs and harden pasted references * Fix Add action button hover corners * Bump version to v0.2.83 * fix(files): keep explorer available for archived chats (#500) * Apply the conversation width setting to the composer (#453) * fix(ui): align composer with configurable transcript width * fix(ui): smooth composer reflow during dock transitions * fix(ui): preserve composer width in narrow panes * Replace Opus 5 with Opus 5.5 in the Claude catalog Claude Code 2.1.280 ships claude-opus-5-5 (and claude-opus-5-5[1m]) as the current Opus, demoting Opus 5 to a previous version. Swap the curated row so the bare `opus` alias resolves to Opus 5.5, mirror the CLI's picker copy, and update the label-pinned discovery/normalize tests. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Fix reduced-motion dock test after the snap_reflow merge PR #453 added DockFrame::snap_reflow (set whenever motion is reduced) and 3c7185b added reduced_motion_cancels_panel_geometry_and_chrome_together in parallel; each was green alone, but merged the test compares against a settled frame without the flag and fails deterministically on main. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Bump version to v0.2.84 * Point the claude_models live-union fixture at Opus 5.5 The fake initialize response still resolved default/opus[1m] to Opus 5, which no longer has a curated row after #505, so the union no longer put claude-opus-5 second. Mirror what Claude Code 2.1.280 actually reports. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs: acknowledge The Context Company and invite sponsorships * docs: remove redundant top-level sponsor links * landing: swap troll tweets for real testimonials Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * landing: show GitHub star count on Star buttons Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * landing: star count next to the nav GitHub icon Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * landing: agent icons above the headline, add Used by developers from logos Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * landing: Supported by section with sponsor button under the main shot Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * landing: restyle Supported by as a quiet sponsor row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * landing: remove Supported by section Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * landing: Used by logos rest in the harness-icon faint color Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(opencode): auto-approve tool permissions as a temporary workaround (#533) * Bump version to v0.2.85 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Polish settings, providers and sign-in (#449) * Redesign settings as a floating keyboard-accessible modal * Align settings surfaces and controls with Zeron glass patterns * Refine settings overlay material and page density * Fix settings overlay stacking and reconstruct measured I/O switch * Tighten settings navigation and reuse overflow edge fades * Refine settings glass controls and remove render-time overhead * Add dialog-contained dropdown positioning Measure dropdowns after layout, constrain them to dialog bounds, and flip above the trigger when needed. Cover containment and long-menu scrolling with unit and GPUI tests. * Polish settings controls and contain their dropdowns Share modal bounds with dropdown placement, restore full-size appearance previews and icons, and group related settings with consistent spacing. Improve responsive rows and device cards, and use contained menus for theme, font, device, and title selectors. * Refine settings navigation, material, and keyboard behavior Match main-sidebar spacing, group settings under category headings, and move conversation behavior into its own page. Follow the command palette material and make Cmd+, toggle the modal without focusing its first entry. Add regression coverage for navigation, focus, and moved conversation controls. * Tighten settings layout and refine glass controls Remove redundant descriptions and the sidebar heading, separate notification groups, and constrain row metadata. Align appearance actions, group material choices, match dropdown chevrons, and replace beveled switches with tinted tracks and translucent thumbs. * Update appearance copy tests for concise settings labels * Protect frosted floating surfaces from backdrop contrast loss * Keep settings descriptions and metadata readable on glass * Render workspace command regression through the window lifecycle * Restore thin light glass and original dark material * Tune light frosted surface coverage * Group agent access preferences in Settings * Inline agent preferences and refine glass switches * Preserve accent hue in light switch tracks * Restore switch marks and contain settings chrome * Align and strengthen switch state marks * Use classic I/O proportions in settings switches * Refine glass switches against I/O reference * Match settings switches to selected material * Tighten settings descriptions and row spacing * Contain settings dropdown scrolling and refine controls * Simplify agent details and polish device cards * Unify settings actions and refine pill switches * Refine settings switch and reorganize conversation controls * Center switch marks in a wider track * Unify settings tabs and retire hidden accounts route * Refine settings close control and dark toggle accent * Balance settings switch proportions and glass lighting * Reduce settings switch thumb inset * Unify settings choices and tighten conversation and device layouts * Align device identity and actions in settings cards * Use title case for settings sidebar headings * Settings, providers and sign-in polish on top of the settings redesign Settings - Full-window settings page (Back at top, Esc/⌘, keep working), Cursor-style filled blocks, shared glass select for every dropdown, smaller switches. - General tab (send key, compact mode, Escape, thread naming via the composer's model picker); Agents renamed to Providers. - Devices page rebuilt on the block/row pattern. - Sidebar footer: account name, settings toggle with active state. Providers and accounts - Compact account list with mini usage meters; the live account marked by an avatar ring, switching/removal in a ⋯ menu, optimistic switch/forget. - Usage probes: concurrent, persisted stale-while-revalidate cache, only 401/403 refreshes a token, Retry-After backoff, reasons instead of a bare "Usage unavailable"; Claude credentials read Keychain-first. - One add-account flow for Claude Code, Codex, Cursor and Antigravity; Claude uses the CLI's loopback callback (paste-code is a fallback). - Remote-device logins forward the callback port over the P2P mux, scoped to the login, the requesting device and its lifetime. - `$` skills and separate `/` commands on by default. Fixes - Frosted/opaque switches no longer need a restart (the window's native backdrop update was dropped while that window dispatched the click). - Single-flight usage/refresh markers released on cancel; login URLs open only for https or loopback; tunnel ports must be ≥1024 and match the authorize redirect; paste-code `state` no longer reuses the PKCE verifier; `/usr/bin/security` by absolute path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Build zui from zeronsh/zui instead of a contributor fork The per-pixel text-fade renderer change is upstream as zeronsh/zui 1561532 (#12, tree-identical to the fork revision it replaces), so drop the [patch] that redirected gpui/gpui_macros/gpui_platform/gpui_tokio to gaelcado/zui and pin zui 1561532 directly. gpui-component moves to 5086ff4f, which pins the same zui revision, so the graph keeps a single gpui. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Wing <wing@anara.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * Bump version to v0.2.86 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Honor system proxy settings in packaged desktop apps (#504) * fix(network): honor system proxy settings * Keep loopback HTTP off the system proxy reqwest's system-proxy support has no loopback exemption, and macOS's proxy bypass list is not consulted, so enabling it would route calls to the local `opencode serve` (which carry its Basic-auth password) through any machine-wide proxy. Build the opencode client with no_proxy(), and fetch favicons for loopback pages directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Wing <wing@anara.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * Reopen Settings on the section last viewed (#541) Generic ways into Settings (Cmd-, / Ctrl-,, the footer gear, the command palette's "Open settings", /settings) now reopen the section that was showing when Settings was last left, instead of always landing on General. The section is persisted as `settingsSection` in ui-settings.json through the shell's own settings copy, debounced like other settings. Links that name a section (open_settings(section), ZERON_OPEN_ROUTE= settings/<section>) still open that section and become the remembered one, as does switching sections inside Settings. A remembered section that is unknown, hidden on this platform (Appshots off-desktop) or a legacy alias (Agents -> Providers) reopens as General or its canonical page. Deserialization is lenient: a missing, unknown or malformed value reads as General without discarding the rest of the file. Escape inside Settings still closes it, but only after closing what is open inside it without holding focus: the footer account menu, the device rename dialog, the add-account login flow on Providers, and the theme import / mapping review dialogs. Previously an Escape with one of those open (e.g. the login dialog, whose card never takes focus) closed Settings underneath the dialog. Supersedes #380, which did this against the previous settings design. Co-authored-by: Wing <wing@anara.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * Retry the Windows identity lock through sharing violations (#527) DeviceIdentityLock::acquire opens device-id.lock with share_mode(0) and retries 200 times, but only on ErrorKind::PermissionDenied. When two engine processes race for the lock, the losing open fails with ERROR_SHARING_VIOLATION (raw os error 32), which Rust reports as ErrorKind::Uncategorized, not PermissionDenied. The retry guard never matched it, so the race failed engine startup outright instead of waiting the intended 5ms. The guard now also matches the raw ERROR_SHARING_VIOLATION code. acquire_retries_through_sharing_violations holds the lock file with share_mode(0) for 50ms and locks in the retry; it fails without the fix. * Stabilize iOS CI animation and persistence tests (#511) Synchronize iOS tests with display updates and persistence completion, add deterministic DocSaver scheduling coverage, and conditionally run iOS CI for relevant pull request changes. * Show the text cursor over selectable chat text (#529) * Show the text cursor over selectable chat text Every selectable region (markdown paragraphs and their table/list/quote kin, code lines, user bubbles) builds on one wrapper that was already shared: relative + the selection underlay + the text. selectable_ text_wrap() centralizes that wrapper and adds .cursor(CursorStyle::IBeam), so hovering selectable text reads as text; the composer was previously the only I-beam in the app. Links and code action buttons already paint their own cursor_pointer() hitboxes above this wrapper, and GPUI resolves the topmost hitbox under the mouse, so hover targets keep the hand cursor. selectable_text_wrap_is_ibeam_cursor locks the cursor style. * Keep arrow cursor over code scrollbars --------- Co-authored-by: Wing <44917547+wingleeio@users.noreply.github.com> * Fix Windows terminals starting in C:\Windows instead of the project checkout (#528) * Strip verbatim path prefixes from ConPTY current directories RunProjectAction canonicalizes the checkout host-side, and std::fs::canonicalize returns \?\-prefixed verbatim paths on Windows. CreateProcessW current directories do not accept them: cmd.exe treats the prefix as UNC and silently falls back to the Windows directory, so project-action terminals start in C:\Windows instead of the checkout. plain_current_dir strips \?\ (and rewrites \?\UNC\server\share to \server\share) before the cwd reaches the spawn. plain_current_dir_strips_verbatim_prefixes covers the transform. * Harden Windows terminal cwd normalization --------- Co-authored-by: Wing <44917547+wingleeio@users.noreply.github.com> * Restore tab drag-reorder on Windows (#536) * Restore surface-tab drag reordering on Windows and fix chip drops Tab drag-reorder on the right-panel surface strip was dead on Windows and drop-broken on every platform. The chip's on_drag was gated behind click_activation_drag_enabled() (false on Windows since the Windows support line) because GPUI's 2px drag-promotion threshold turns ordinary Windows click jitter into accidental drags. The gate is deleted: drags attach on all platforms. This depends on zeronsh/zui#13, which raises the Windows threshold to the system drag rectangle (SM_CXDRAG, 4px) and must land first, with a zui pin bump. Merging this before that would bring the accidental drags back. The updated jitter test (3px sub-threshold jitter stays a click) fails against the current 2px pin on purpose; it is the guard for that merge order. Removing the gate also un-gates file-tree row, search result, and terminal tab drags on Windows. The strip's on_drop could never fire over a chip: the chip's block_mouse_except_scroll() carve-out (titlebar/scroll) cuts the strip out of gpui's hover stack, so MouseUp hit-testing never reached the strip's drop listener while the pointer was over a tab. Reordering only worked in the 4px gaps between chips, on every platform. The chip now receives the drop itself; bubble dispatch reaches the chip before the strip, and the handler consumes the drag, so the two never double-apply. Tests: surface_tab_drag_reorders_the_strip locks the end-to-end reorder (written red-first on Windows: "surface tab drag never started"); the Windows jitter test now pins sub-threshold (3px) jitter to still click without dragging; the platform-policy assertion expects the drag to start everywhere. * Pin org-owned ZUI drag threshold dependencies --------- Co-authored-by: Wing <44917547+wingleeio@users.noreply.github.com> * Pass window to add_diff_surface from the Diff workspace command main added WorkspaceCommand::Diff after this branch was cut; the new add_diff_surface signature needs the window for its subscription. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Laurent <stlaurentcodes@gmail.com> Co-authored-by: Wing <44917547+wingleeio@users.noreply.github.com> Co-authored-by: wing-anara <wing@anara.com> Co-authored-by: Gaël Cado <130941423+gaelcado@users.noreply.github.com> Co-authored-by: grahamwinter <wwinterr@pm.me> Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Wing <contact@winglee.io> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: wing-anara <wingleeanara@gmail.com> Co-authored-by: LoikStyle <131105263+LoikStyle@users.noreply.github.com> Co-authored-by: gaelcado <cado.gael@gmail.com> Co-authored-by: dcdyouget <57359111+dcdyouget@users.noreply.github.com> Co-authored-by: Vu Nguyen <hggaming91@gmail.com>




Replace ellipses on overflowing sidebar labels with a 20 px right-edge fade: active and archived session titles, branch names, project/device metadata, project-filter labels, and device group headings. Fitting labels remain opaque except for the existing vertical scroll fade.
Ease the right-edge fade into view as overflow grows. Preserve search highlighting, adjacent controls, branch/PR spacing, and the sidebar and command palette's vertical fades. Label fades inherit the active scroll container's vertical bounds and asymmetric fade bands; paint scopes are restored before siblings render. This fixes the reviewed regression where long labels stayed bright at vertical scroll edges.
Merge main while retaining both faded disclosure labels and the shared sidebar separator introduced by #407.
The existing renderer override remains pinned to
gaelcado/zui@53869c204efb866d19af292cab8b1773898eeedd. Its entire source tree is identical to upstreamzeronsh/zui@1561532176f54262e360acbb8bc00c6fcf183975from merged zeronsh/zui#12. Migrating away from the override also requires aligning gpui-base's GPUI dependency pin.Validation at
cd247d721113a71065c2e4ca1ba92877beb78a9e: