fixing/merge-conflict#1
Open
Pavitra-programmers wants to merge 3851 commits into
Open
Conversation
* fix(den): make enterprise MCP OAuth opt-in * feat(den-web): add MCP OAuth recovery controls * fix(den): tighten MCP OAuth rollout controls * fix(mcp): support Salesforce OAuth discovery * fix(den-web): make MCP OAuth migration recoverable * fix(den): simplify enterprise MCP OAuth rollout * refactor(den-web): simplify MCP discovery UI * refactor(den-web): streamline MCP connection setup
…facture an outage (#2823) On corporate Windows machines with TLS interception, the health check's direct tools/list probe (Node undici, no OS trust store) threw 'fetch failed' and was misclassified as cloud_tools_missing — flipping usable to false, blocking delivery from being marked applied, and worst, feeding the extensions-preview steering plugin a per-prompt instruction telling the model Cloud agent access is not ready. The model then refused MCP tools that the engine (Bun, OS trust) had registered, connected, and could call the whole time: a false-negative probe manufactured a real outage. - transport-thrown probes now report probe_unreachable (diagnostic only): when the engine says the MCP is connected they no longer join failures, so usable/phase/delivery reflect the engine's reality - the probe now prefers Electron net.fetch (Chromium, OS trust store) when embedded, falling back to global fetch elsewhere - steering fails open: engine connected + probe-side failure returns the neutral instruction, never 'Direct the user to Repair and test' - direct probe failures stay visible in the health JSON for support
…yments (#2830) * feat(app,den-web): hide OpenWork Models surfaces on self-hosted deployments Desktop: areOpenWorkModelsPromosDisabled() now also returns true when the effective Den control plane is not app.openworklabs.com, silencing the model picker promo group, picker modal card, status-bar hint, startup dialog, the onboarding 'Use OpenWork Models' option, and the Settings > AI rows. den-web: single-org (self-hosted) dashboards drop the 'OpenWork Models' nav child and redirect /dashboard/inference to LLM Providers. Includes fraimz flows + voiceovers for both journeys. * fix(evals): repair self-hosted fraimz flow after Daytona run - navigate back to the session when a reload lands on settings - screenshot validator cannot see input placeholders; require 'All models' - voiceover intro reflects the disposable sandbox environment * fix(evals): adapt self-hosted fraimz flow to dev's welcome-route provider step Upstream removed the session-route held-first-send provider step; the provider choice now only appears during welcome workspace setup. Frames 3/7 drive it through the real journey (reset onboarding latch -> create a workspace from the welcome page), with Base UI React-props clicks and post-reload settling.
…able org mode (#2824) Two failures found while running the eval suites against a Daytona den server sandbox: 1. pkill patterns anchored on repo paths (ee/apps/den-api/src/main.ts) never match the real cmdline ('tsx watch src/main.ts' is cwd-relative), so re-running the start script silently kept the old den-api on the port — the health check then passed against the stale process and env changes never took effect. Match the cwd-relative cmdline instead (main.ts / server.ts are unique per app here). 2. den-api's DEN_ORG_MODE now defaults to single_org, which blocks the email signups scripts/seed-demo-org.ts performs — a fresh sandbox could not seed the Acme demo org. Default the server to multi_org (overridable) to match the seeded demo this sandbox exists for.
…rection, deterministic (#2829) * docs(voiceover): runtime config ownership script + scaffolded flow * docs(voiceover): simplify runtime-config-ownership to four frames * docs(voiceover): reframe as one-way managed config with predictability guarantee * feat(server,app): one-way managed runtime config with legacy sweep and debug card The managed runtime config file becomes the only thing OpenWork writes: - choke-point helper routes disabled-provider changes to a new /workspace/:id/runtime-config/disabled-providers route (runtime DB -> managed file) for local workspaces; remote keeps engine config.update; a guard test bans any other config.update call site - managed file build is byte-deterministic (sorted-key stringify) - one-time startup sweep removes only unambiguous OpenWork-written keys (mcp.openwork-cloud, agent.openwork, default_agent=openwork, openwork plugin entries) from ~/.config/opencode/* with jsonc-preserving edits, a timestamped backup, and an idempotent state marker - Debug settings card shows the managed file path, last-rebuilt time, server-side-redacted content, and sweep results
* feat(den-web): simplify cloud landing page * refactor(den-web): simplify landing shader
* fix(app): hide model promotions on custom Den * fix(app): avoid duplicate model promo state
* feat(den): sync SCIM groups to teams * test(evals): make SCIM group proof repeatable
…tch banned (#2835) Every bare Node fetch in the server (undici) bypasses the OS certificate store, so on enterprise machines with TLS interception any external call fails with a generic 'fetch failed' while Electron and the engine succeed (field incident class). One shared helper now routes egress: externalFetch prefers Electron net.fetch (Chromium stack, OS trust) when embedded and falls back to global fetch standalone; loopbackFetch documents engine/127.0.0.1 traffic where CA trust is irrelevant and streaming performance matters. All server call sites migrated; a guard test fails the build on new bare fetch call sites. Engine-side plugin bundles (src/opencode-plugins) are deliberately out of scope — they run inside Bun, which trusts the OS store.
…es OpenWork Connect (last in sidebar) (#2836) * feat(settings): rename Extensions to Extensions (Legacy), Connect to OpenWork Connect - Extensions tab becomes "Extensions (Legacy)" across all locales; description shifts to the local-MCP story ("Local MCP servers and OpenCode plugins…"). Plugins/marketplace inside it keep working unchanged. - Connect tab becomes "OpenWork Connect" and always renders as the last settings sidebar item (memory tab now inserts before it). - General hub Extensions card uses the shared i18n keys. - fraimz flow + approved voiceover: extensions-legacy-rename. * test(fraimz): click into OpenWork Connect in frame 2 to avoid duplicate-frame guard
… state (#2832) * fix(plugins): steer Cloud tool availability from the engine's own MCP state The extensions-preview steering previously phoned home to the OpenWork server and asserted the server's health verdict to the model. Field incident: that verdict can disagree with the engine (corporate TLS broke the server's probe while the engine's MCP was connected), and the model obeyed the wrong claim — refusing tools it actually had. Invariant now enforced: tool-availability steering is computed from the same process that owns the tools. The plugin asks the engine's mcp status in-process (connected → ready, disabled → disabled, needs_auth → sign-in, failed → degraded), falls back to server connect-state only when the engine has no entry at all, and fails open to the neutral instruction on any engine error. * fix(plugins): fail open on unknown engine cloud status * fix(plugins): remove degraded steering — steering is ready/sign-in/disabled/neutral only
…on-demand (#2834) * fix(server): engine-attested Cloud MCP health; network probe becomes on-demand Background health re-verified the engine's MCP over the server's own network stack on every check — a duplicate verifier that can disagree with the engine (field incident: corporate TLS). The engine is now the authority: by default health attests tools from the engine's mcp status (connected implies initial tools/list succeeded on opencode >=1.17) and never touches the network. The direct tools/list probe runs only when explicitly requested (GET health?probe=1) and on reconcile (an explicit repair action). /experimental/connect/state — consumed per prompt by the steering plugin — is pinned to probe:false. * test(server): make Cloud MCP health cleanup Windows-safe * test(server): make Cloud MCP reconcile Windows-safe
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…f bold Co-authored-by: Cursor <cursoragent@cursor.com>
…t seed Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Allowlist the Desktop Policies tag in the agent catalog policy so search_capabilities/execute_capability can list, create, update, and delete desktop policies. Route-level auth is unchanged and enforced on replay: reads need org admin, mutations need super-admin plus the Enterprise entitlement and mcp:write scope. Adds the desktop-policies-cloud-mcp voiceover + fraimz flow proving the rail end to end: capability search, MCP read/update, dashboard + member desktop pickup, and an ordinary member's write refused.
On engines where JSON is a LONGTEXT alias (MariaDB), mysql2/Drizzle
returns the desktop_policy.policy column as a JSON-encoded string on
read. The canonical normalize functions failed the object parse and
silently collapsed every read to {} — list responses, the effective
policy calculation, and /v1/me/desktop-config all lost restrictions
even though writes stored the correct document.
Coerce JSON-string input once at the normalize entry points so every
consumer behaves identically for strings and objects, and widen
calculateEffectiveDesktopPolicy to accept raw column values it already
normalizes internally. Covered by desktop-policy-json-column-strings
bun tests.
…s none Fresh sandboxes land on #/session with the create-workspace empty state (not /welcome); cloud MCP auto-config only syncs once a workspace exists.
…on policy The dev server can bind [::1] only (Daytona sandboxes); navigation between loopback origens should behave the same as 127.0.0.1/localhost. Also harden the desktop-policies-cloud-mcp flow: reconnect CDP around cross-origen navigations and accept a healthy cloud-MCP maintenance outcome when the first-sync marker was already consumed.
…icies flow The main window's navigation poli-cy intentionally blocks external origens (they reroute to the built-in browser), so the dashboard frames now use the designed affordance: open the Den dashboard with the browser.open_url control action, drive it as a second CDP target, and close the tabs before returning to the app frames. Session-page action availability is awaited (and create_task retried) since control actions register per route.
- Fix admin Delete user: validate usr_ TypeIDs via isDenTypeId instead of a wrong user_ prefix check that 400'd every real id - Add owner-only DELETE /v1/org with fresh-session reauth, best-effort Stripe subscription cancellation, and a full org-scoped purge across all org tables - Add Danger zone at the bottom of dashboard Settings > General with type-the-org-name confirmation dialog - Repair pre-broken dev gates: route-access-policy parser (apostrophe comment) and connected-account revocation contract drift; defuse organization-capabilities mock-pollution landmine
…edentials (#3076) Production forensics showed every runtime credential invalidation was written by the terminal-401 path: any unresolved 401 (gateway redeploys, VPN flaps, provider session flushes) wiped the member's stored tokens and forced a reconnect - including from background search probes the user never saw (confirmed cases: Notion, Stripe, Salesforce, Granola). New policy: - invalidation only during user-initiated tool execution, never during tool-discovery probes - 401 is terminal only with an explicit WWW-Authenticate invalid_token bearer challenge; 403 bearer/scope policy unchanged - every invalidation emits a credential-invalidation diagnostic and Den logs external_mcp_credential_invalidated unconditionally
…ory-aware back/forward (#3071) * feat(chat): render capability calls as sentences, not JSON cards Paper chat-transcript rendering rules, step 1: - MCP/dynamic tool calls render as plain muted sentence lines with no tool icon: dot-matrix while running, small green dot + past-tense verb + duration when done - Connection/tool names map to human sentences ("Searched your connections for "gmail drafts list"", "Asked Granola ..."); body.query renders as quoted plain text - Raw input/output, tool name, and call id move under a collapsed "Technical details" panel - Durations measured client-side from live streaming; restored history shows no duration instead of a fabricated one - Failed calls and sub-agent (task) runs keep the existing card with reconnect/Retry until their dedicated treatments land - Dot-matrix loader promoted to shared components/ui (currentColor, reduced-motion static frame); sidebar re-exports it Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): aggregate consecutive command/edit/read/search tool calls Consecutive tool-only steps (across assistant messages) collapse into one line — live totals plus a self-replacing "Now:" line while running, past tense when done. Chevron expands the chronological list with status dots, monospace actions, per-call durations, failure reasons, and a "Show N more" cap. Prose, reasoning, or any other tool breaks the run, per the Paper transcript artboard. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): failure-as-instruction lines and two-line sub-agent runs Failed capability calls now use the sentence line: red dot, one line saying what to do next, inline Reconnect/Retry when the error maps to a known connection (logic extracted into useChatToolReconnect, shared with the generic Tool card). Sub-agent task runs render the Paper two-line treatment: task title + agent name, then live status or "Completed" with duration; prompt/result under the collapsed panel. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): separate merged reasoning sections with a paragraph break Consecutive reasoning parts were concatenated with no separator, so each section's bold "**Title**" got glued onto the previous paragraph's last sentence mid-line. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): linkify bare https:// URLs in user message bubbles User bubbles render plain text (not markdown), so pasted URLs never became clickable. Bare http(s) URLs now render as anchors with the same link styling as assistant markdown; search highlighting still applies to the surrounding text. Co-authored-by: Cursor <cursoragent@cursor.com> * style(chat): drop traffic-light status colors from tool call lines All tool call dots are now neutral gray; failure state reads through the words ("failed", "Failed — reason") in muted text instead of green/red dots. The only living marks in the transcript stay the dot-matrix on running rows. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): collapse thinking by default, clickable file rows in aggregates Reasoning renders as a collapsed "Thinking… / Thought" toggle instead of always-expanded prose. Aggregate file rows show "Edited/Read <name>" with just the file name (absolute path in the tooltip); clicking opens the file in the artifact preview via the same open-target flow as the artifact chips. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): humanize native and plugin execute_capability calls CamelCase native capabilities ("getCapabilitiesGoogleWorkspaceCalendar Events") become verb sentences ("Fetched Google Workspace Calendar Events"). Opaque "plugin:…" refs pull the human name from the output ("Used skill "Plan My Day""). Structured provider errors render as a sentence ("The provider rejected the call: invalid request — Invalid ISO datetime.") instead of echoing raw JSON. Co-authored-by: Cursor <cursoragent@cursor.com> * style(sidebar): drop workspace color dot from pinned and archived rows Co-authored-by: Cursor <cursoragent@cursor.com> * style(chat): remove static gray status dots from tool call lines Co-authored-by: Cursor <cursoragent@cursor.com> * feat(sidebar): move conversation history back/forward controls into sidebar Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): collapsed failed capability line expanding into Paper failure card Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): render site favicons next to links in user and assistant text Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): Paper file chips in aggregate rows and per-turn FILES artifact strip Co-authored-by: Cursor <cursoragent@cursor.com> * style(sidebar): move history arrows to top right of sidebar titlebar row Co-authored-by: Cursor <cursoragent@cursor.com> * style(sidebar): align history arrows with titlebar toggle row Co-authored-by: Cursor <cursoragent@cursor.com> * style(sidebar): add vertical spacing between session rows Co-authored-by: Cursor <cursoragent@cursor.com> * style(sidebar): apply row gap inside reorder groups and group content Co-authored-by: Cursor <cursoragent@cursor.com> * style(sidebar): selected session uses subtle color emphasis instead of bold Co-authored-by: Cursor <cursoragent@cursor.com> * test(evals): chat-transcript-sentences fraimz with dev-only transcript seed Co-authored-by: Cursor <cursoragent@cursor.com> * style(chat): remove underline from links; assert no-underline in fraimz Co-authored-by: Cursor <cursoragent@cursor.com> * test(evals): make chat-transcript flow idempotent via renderer reload Co-authored-by: Cursor <cursoragent@cursor.com> * feat(workbench): Arc-style tab context menu, joined split pill, resizable panes Co-authored-by: Cursor <cursoragent@cursor.com> * test(evals): workbench-split-view fraimz Co-authored-by: Cursor <cursoragent@cursor.com> * feat(workbench): vertical tab system in sidebar with history-aware split view The sidebar is now the vertical tab list (Arc model): the horizontal tab strip is gone, session rows carry the tab semantics, 'Open in split view' lives in the row context/dropdown menus, and the active split pair renders as a joined pill at the top of the sidebar. Conversation history entries now record the split session too, so back/forward restores the exact split layout of each step. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(split-view): per-conversation model picker with last-used memory Each session surface now resolves its own model: picker open state is local to the pane, selections are remembered per session in localStorage (openwork.sessionModels.v1), and sends resolve the session's remembered model/variant before falling back to the global default. The full model picker targets the session it was opened from; opening it without a session still edits the global default. Co-authored-by: Cursor <cursoragent@cursor.com> * ui: hide workspace name from the session header Co-authored-by: Cursor <cursoragent@cursor.com> * ui(welcome): match Paper first-load design Pixel-dither mosaic background (Dithering shader, dark:invert for dark mode) on a plain ground instead of the colored grain gradient, real OpenWork mark in the card, larger welcome typography, and 48px primary/outline buttons per the first-load spec. Co-authored-by: Cursor <cursoragent@cursor.com> * ui(signin): unify forced sign-in with the Paper welcome card The fullscreen sign-in gate now renders the same first-load card as WelcomePage (dither background, logo row, welcome typography, 48px primary button). Forced sign-in only removes the Use Without Cloud option; the fallback notice, on-premises server affordance, paste-code disclosure, and dev-mode control-plane editor stay inside the card. Drops the old two-column showcase layout. Co-authored-by: Cursor <cursoragent@cursor.com> * ui: Paper card for onboarding stages, sidebar workspaces header + groups, OpenWork Models dialog redesign - page.tsx primitives: dither background + bounded card so every org-setup stage (org selection, resources, branding restart, prepared workspace, loading/error) matches the sign-in card design - attribution/provider onboarding steps wrapped in the same bounded card - welcome page now marks the route ready so the faded boot splash no longer blocks clicks on /welcome - sidebar: WORKSPACES section header with + (create workspace), removed the footer Add-workspace button, removed the 'Create a Group' link from the show-more row, added a hover folder+ action on workspace rows to create groups - OpenWork Models startup dialog redesigned in the Paper card language: model list rows, checkmark highlights, stacked primary/secondary actions Co-authored-by: Cursor <cursoragent@cursor.com> * ui(sidebar): align section labels and titles to one shared text lane PINNED / WORKSPACES / group labels now start at the same 44px lane as session titles and workspace names; icons, dots, and chevrons hang in the left gutter. Co-authored-by: Cursor <cursoragent@cursor.com> * Redesign session empty state as chat-first hero with policy-driven prompts - New SessionEmptyHero: 'What do you need done?' composer with suggestion cards, following the Paper first-chat design. Suggestions come from desktop policies (organization onboarding prompts) when configured, with built-in defaults otherwise. - Chat-first onboarding: with no workspace yet, the same hero shows and running a task creates a default 'OpenWork Chat' workspace under the home folder instead of asking where to put it (modal fallback off desktop). - Fix prompt handoff: onCreateTaskWithPrompt saved drafts to a store the composer never reads; now also seeds the composer state store so the prompt actually appears in the new session's composer. Co-authored-by: Cursor <cursoragent@cursor.com> * Remove workspace color concept; left-align sidebar hierarchy - Delete WorkspaceIcon (hashed color dot) and all its usages: sidebar workspace headers and the settings workspace pickers. - Workspace titles now start flush left (16px), giving the sidebar a real indent hierarchy: sections/workspaces at 16px, group headers indented, session titles deeper. - PINNED and WORKSPACES section labels share the same 16px lane. - The dot-matrix loader still shows inline while a workspace is loading. Co-authored-by: Cursor <cursoragent@cursor.com> * Remove hover FolderPlus (new group) button from workspace rows New group stays available in the workspace options menu and session context menus. Hover padding shrinks back to two-button width. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…3078) Enterprise networks that inspect TLS (GlobalProtect and similar) present certificates signed by a corporate CA that lives in the OS trust store. Browsers trust it; the Bun-compiled installer only saw bundled Mozilla roots, so resolving an install link failed with a misleading 'check your internet or VPN' error even though the workspace was reachable. - add src/system-ca.ts: best-effort OS trust-store export (PowerShell cert stores on Windows, System.keychain via security on macOS) merged into every installer fetch via Bun's fetch tls.ca (extends bundled roots); cache pre-warmed at server start so the first resolve-link keeps its full abort budget - classify TLS trust failures separately from network reachability and say so honestly in /api/resolve-link, naming the certificate host - ship the OpenWork icon: --windows-icon for Windows compiles (was the Bun logo) and icon.icns + CFBundleIconFile in every macOS bundle path (was the blank generic icon) - reassert the webview window title after page load; the cocoa backend creates the NSWindow inside run() so pre-run titles were dropped - fraimz: installer-tls-trust flow + voiceover proving the paste screen, the honest TLS message, CA-trusted resolution, and the unchanged happy path
…ider-safe mime (#3079) Providers' AI SDK adapters only accept image/*, application/pdf, and text/plain file parts; anything else throws "'file part media type: X' functionality not supported" and the persisted part replays the error on every later prompt. - accept any file in the composer (remove the attach-time mime allowlist) - re-mime text-like attachments (xml, json, csv, yaml, html, code, svg) to text/plain so opencode inlines their content via the Read tool, the same proven mechanism as @file mentions - binaries upload to the workspace inbox as before but emit no model-facing file part; the synthetic path note gives the model tool access instead - images/PDF/Office parts unchanged (Office is rewritten server-side by the OpenWorkOfficeAttachments plugin) - drop the dead attachment-support.ts allowlist and update dropzone copy
…tifacts, no size caps (#3081) - binary attachments now emit a text/plain file part pointing at the workspace copy; opencode mediates these through the Read tool (graceful 'Cannot read binary file') and never forwards them to providers, so zips keep a transcript badge with zero provider risk - user attachment file parts are now derived as open targets/artifacts via their file:// URLs, so entries in the Files/Artifacts panel are clickable even when filenames contain spaces (regex path scanning could not match those and left dead entries) - media badge prefers the filename extension over the transport mime so a zip shows ZIP instead of PLAIN - remove the opinionated 8MB composer and 25MB session caps; size errors now come from the upload endpoint or provider; inbox upload default raised to 250MB with OPENWORK_INBOX_MAX_BYTES override no longer clamped - drop the unused composer.file_exceeds_limit locale key
…nfra failures as revocation (#3080) Two verified prod failure classes behind 'Server returned 401 after successful authentication' loops and unfixable Degraded states: 1. Refresh grants outlived the session that authorized them. The token endpoint kept minting 45-min tokens carrying a dead sid, which the resource rejected with mcp_session_revoked forever. Census at fix time: 24 live zombie grants across 16 users (10 deleted sessions, 14 expired). The token endpoint now checks session liveness for refresh_token grants: dead session => 400 invalid_grant + grant family cleanup, so clients fall into clean re-authorization. 2. hasActiveMcpSession ended in catch { return false }, reporting any DB/infra error as REVOKED (observed in prod: ~2h of rejections for a provably alive session, self-healing afterwards, with clients pointlessly rotating grants on every retry). Session liveness is now three-state (alive / missing / check_failed): check_failed maps to a retryable 503 mcp_session_check_unavailable (Retry-After, no WWW-Authenticate challenge) on the resource and fails open at the refresh gate, with a stable mcp_session_liveness_check_failed log marker. Rolling-touch failures alone no longer affect verdicts.
… chip (#3082) * feat(shell): Arc-style card shell with header panel toggle and background rail - Main content and side panel render as elevated rounded cards floating over the sidebar-colored background (seamless with left sidebar, no divider borders). - Session header gains a PanelRight toggle next to the notification bell to open/close the right side panel; active state highlighted. - Right icon rail (browser/voice/artifacts/extensions) now sits directly on the background instead of a bordered strip. - Resizable handle between cards is transparent so the background gutter shows through. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(shell): denser chrome, account chip in sidebar footer, no resize grips - Header: 36px tall with 13px medium title (was 40px/15px semibold). - Right rail: 36px wide with 15px icons (was 44px/17px). - Composer panel radius tightened to 18px. - Resizable handles no longer render the floating grip pill. - Sidebar footer now shows a profile chip: signed-in Den user with initials avatar, name and email (opens settings), or a 'Sign in' chip that launches OpenWork Cloud auth when signed out. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(shell): remove opaque paint from sidebar resize rail The rail painted a sidebar-colored overlay to mask the old sidebar border. With the seamless Arc shell background this rendered as a thick dark strip between the sidebar and the content card. The rail is now an invisible drag area with only its subtle hover line. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(shell): system UI font stack and 13px max body text - Body and --font-sans/--font-heading now lead with -apple-system / system-ui instead of IBM Plex Sans / Geist. - Base body size 14px -> 13px; Tailwind text-sm token remapped to 13px. - Composer editor 15px -> 13px; empty-state hero textarea 14px -> 13px. - Sidebar section labels (PINNED, WORKSPACES, groups, archived, split view) normalized to 12px uppercase. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(sidebar): tighter chevron-to-label gap with matching session indent Group headers use gap-1.5 (was gap-3.5) between the expander chevron and the group name; session rows shift from ps-3 to ps-1 (nested ps-7 to ps-5) so their titles stay aligned with the group label lane. * fix(shell): drop sidebar right border; account chip opens a menu - The shadcn sidebar container's variant-scoped border-e survived the earlier plain border-e-0 override and rendered as a 1px black line between the sidebar and the content card. Override now uses the same group-data-[side=left] variant. - The sidebar account chip now opens a dropdown: email header, Settings (opens settings), and Log out (server sign-out best effort, clears the stored Den session, refreshes auth state). Signed-out users get Sign in instead of Log out. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(sidebar): fade out overflowing labels instead of ellipsis New .ow-fade-truncate utility masks the last 18px of the label with a linear-gradient so long session, workspace, group, and split-pill names fade out Arc-style; short labels are unaffected. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(browser): round native WebContentsView corners to match panel card The browser WebContentsView is a native layer that CSS overflow cannot clip, so its square corners poked out past the rounded side-panel card. Electron 35 setBorderRadius(14) matches the card radius. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(shell): match side-panel gutter to outer gutter width The 4px gap between the center card and the side panel card made the rounded-corner junction read as a notch; use the same 8px gutter as the shell edges. Co-authored-by: Cursor <cursoragent@cursor.com> * Revert "fix(browser): round native WebContentsView corners to match panel card" This reverts commit 0c11542. * fix(shell): round the shell panel group so overflow clip matches the cards react-resizable-panels forces overflow:hidden on the group, which square-clipped the rounded panel cards at the shell corners. Give the outer group the same 14px radius so the clip follows the card shape. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…e icon (#3083) The dashboard already swapped the favicon to the managed square app icon client-side, but the tab flashed the default OpenWork mark until the org context loaded. The dashboard layout now resolves the active org's managed icon during SSR (via /v1/me/orgs with the request cookies) and ships it in the initial <link rel="icon">, and WorkspaceFavicon no longer resets the favicon while the org context is still loading.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why
Issue
Scope
Out of scope
Testing
Ran
...Result
CI status
Manual verification
Evidence
N/A (docs-only)Risk
Rollback