fixing/merge-conflict - #1
Open
Pavitra-programmers wants to merge 4096 commits into
Open
Conversation
…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.
…ks (#3087) The installer returned Bun's runtime CA list as soon as it was non-empty, which skipped the thorough platform store enumeration. On a network that re-signs HTTPS, a runtime reporting a partial set of public roots therefore never picked up the corporate CA, and resolving an install link failed with "the secure connection isn't trusted on this computer yet". Union the runtime list, the platform stores, and NODE_EXTRA_CA_CERTS instead of preferring one, so a partial source can no longer mask a complete one. NODE_EXTRA_CA_CERTS gives IT a deterministic override matching what the desktop shell already honors. macOS also reads SystemRootCertificates; the user-writable login keychain stays out, because `security find-certificate` ignores trust settings and any local process can write there. Startup logs and the TLS rejection now carry per-source counts, so an untrusted certificate is distinguishable from a trust store that could not be read. Co-authored-by: Cursor <cursoragent@cursor.com>
A capability that outran the bounded deadline was reported as an unrecognized provider error, telling the member to look up a JSON-RPC code with a provider that never sent one. The abort reason was a plain Error, and the SDK only rethrows an McpError untouched -- everything else becomes String(reason) on a RequestTimeout, so the deadline reached diagnostics indistinguishable from a provider-declared -32001. Abort with a marked McpError instead and check that marker before any JSON-RPC code is read as the provider's. Co-authored-by: Cursor <cursoragent@cursor.com>
…on launch (#3085) * feat(composer): render connect skills as /slug pills; land on empty state on default load - New [connect-skill ...] draft token keeps the OpenWork Cloud skill invocation self-contained; composer shows a compact violet /slug pill and the full connect prompt is expanded only at send time. - Skill pills (local + connect) now display /name to match the slash menu. - Remove startup last-session restore: a fresh app load with no session in the URL lands on the empty new-task state; workspace switching still restores the last opened session. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(hero): reuse the full session composer in the empty-state hero The 'What do you need done?' empty state now renders ReactSessionComposer (skills/commands/MCP menu, agent picker, model picker, mentions) instead of a plain textarea. A new NewTaskComposer wrapper wires workspace-scoped data from route-level state, so agent/model choices made before the session exists carry into the created session. The draft (including skill pill tokens) is seeded into the session composer on Run task, as before. Attachments stay disabled pre-session with an explanatory tooltip. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(hero): one-step run — auto-send the seeded draft in the created session Run task from the empty-state hero previously seeded the draft into the new session's composer and required a second Enter to send. The route now marks the created session for auto-send (both the workspace path and the chat-first path), and the session surface consumes the mark and fires its normal send path once the composer is usable (model idle, not streaming, model available). If those conditions never hold, the mark is simply never consumed and the seeded draft stays for manual sending — same one code path as the send button, so token expansion, analytics, and remote endpoints all behave identically. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(session): stop loading pane takeovers and add quiet cloud-worker shimmer - Route refreshes no longer replace an already-rendered session surface with the full loading pane; the pane only gates the first paint. - Each blocking step of a route refresh now has a 15s watchdog so a hung desktop bridge or unresponsive server surfaces an error instead of an indefinite loading state. - Remote (cloud worker) sessions show a quiet text shimmer instead of the dot-ticker loading pane. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): even vertical rhythm between transcript step rows Step messages rendered inside a plain block scroll container, so two rows in different messages sat flush (0px) while rows within one message were 8px apart. The result was tool/Thought pairs visually glued together with larger gaps between them, tracking message boundaries rather than meaning. The scroll area is now a flex column with the same 8px gap. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): collapse a finished turn's steps into one "Worked for" line A completed turn now shows a single muted "Worked for 1m 19s" row that expands back into the full step run; only the live turn streams its steps in place. Duration comes from server message timestamps so it survives a reload, falling back to a step count when they are missing. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): fold the answer message's thinking into the collapsed run The final message carries both its reasoning and the answer text, so its "Thought" row used to sit above the answer even once the run collapsed. A collapsed run now renders that reasoning and the message below shows text only, leaving just the summary line and the answer. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): only fold long finished runs; short ones stay listed A finished turn with a handful of step rows reads fine as a list, so the "Worked for" summary now appears only above four rows. Live turns always stream their steps in place. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): name org MCP capability calls and recover their ask "mcp:<connection-id>:<tool>" capability names matched neither the dotted nor the plugin: shape, so every org MCP call read "Ran a capability"; the trailing tool name carries the meaning. extractQuery also required an object body, dropping the ask whenever it arrived as a JSON string, which left the failed-call card without its quote. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
The union fix is only observable where the runtime returns a partial non-empty CA list, which is Windows: Bun reports 0 system certificates on macOS, so the short-circuit it replaced never triggered there. Adds a cross-platform corporate-CA repro (root -> re-signing intermediate -> leaf, none of it in Bun's bundled roots) that drives the compiled binary's real /api/resolve-link route, plus a windows-2022 job that runs it twice: once with the root untrusted, then again with nothing changed except an Import-Certificate into LocalMachine\Root. Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(den): expose desktop activation status Co-authored-by: Cursor <cursoragent@cursor.com> * feat(installer): recover failed browser activation Co-authored-by: Cursor <cursoragent@cursor.com> * feat(den-web): guide organization desktop activation Co-authored-by: Cursor <cursoragent@cursor.com> * test(installer): support deterministic activation demos Co-authored-by: Cursor <cursoragent@cursor.com> * test(evals): prove organization activation journey Co-authored-by: Cursor <cursoragent@cursor.com> * feat(den-web): apply the Paper install-guide design Rework the organization install guide to match the approved Paper flow: step cards carry complete/active/pending styling with chevrons, step 2 splits into an already-installed panel plus a preview of the installer as it appears on this computer, and step 3 pairs the return button with an explicit waiting or connected state. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
The nuke manifest left three kinds of state behind, so workspaces and sessions reappeared after a fresh start: - $XDG_STATE_HOME/opencode (prompt history, frecency, kv, locks) was never targeted; only the opencode data/config/cache dirs were. - ~/.openwork/openwork-server holds per-workspace audit logs and is a sibling of the orchestrator dir, which was the only ~/.openwork entry. - Each workspace's .opencode/openwork state survived by design. Workspace registry files in userData are now named individually so a single locked file can no longer leave the registry intact, and the known workspace paths are threaded from the workspace store through the preview IPC, the execute IPC, and the cleanup-worker payload. Workspace folders and user files inside them stay untouched. Also drops the redundant building icon from the org onboarding headers. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…#3096) * feat(shell): fold the bottom status bar into the sidebar account menu Co-authored-by: Cursor <cursoragent@cursor.com> * fix(shell): drop the heavy status pill background in the sidebar footer Co-authored-by: Cursor <cursoragent@cursor.com> * docs(evals): point Settings selectors at the sidebar account menu Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
The installer artifact shipped in v0.18.1 reported 1.0.0 because the mac Info.plist hardcoded it and nothing else carried a version at all, so a user or support engineer could not tell which build they had. - resolve one version from the release tag (local builds fall back to apps/installer/package.json) and stamp it into the compiled binary, the mac Info.plist, the DMG volume name, and the Windows version resource - add `--version` to the installer CLI and a quiet footer in the window - keep apps/installer/package.json on the release train via bump-version Published asset filenames are unchanged.
…o three primitives (#3097) * refactor(paths): resolve OpenWork and OpenCode paths from one primitive Path resolution was duplicated ~35 times across the server, desktop shell, installer and bootstrap CLI. Three copies even carried a comment saying they "must agree byte-for-byte" with each other, which is what a shared module is for. Four of the copies had already drifted into real defects: - The Settings global-opencode-config route hardcoded ~/.config/opencode and honored neither OPENCODE_CONFIG_DIR nor XDG_CONFIG_HOME, while the MCP subsystem honored both. Since the desktop runtime sets OPENCODE_CONFIG_DIR under OPENWORK_DEV_MODE=1, editing global config in the app read and wrote the developer's real config instead of the dev sandbox, escaping isolation. - server.json resolution on the server ignored APPDATA and XDG_CONFIG_HOME, so the server and the desktop shell disagreed on the path on Windows. - runtimeDbPath repeated the same wrong ~/.config/openwork default. - The desktop checked only root-level opencode.json(c) while the server also checked .opencode/, so the runtime created a shadowing root config for workspaces that already had a hidden one. packages/paths ships raw ESM plus hand-written declarations so the Electron main process can import it directly, and every resolver takes injectable env/homeDir/platform so it is testable without touching the real filesystem. The hardened OPENCODE_CONFIG_DIR validation from the MCP resolver is preserved as the canonical behaviour. Also makes the runtime-config store test hermetic: it merged the global MCP layer, so it observed whatever MCP servers the developer had configured. It fails on dev on any machine with a global MCP entry. * refactor(url): normalize base URLs from one primitive and honor OPENCODE_MODELS_URL The embedded server inlined its own dev/prod models-URL branch, so an operator setting OPENCODE_MODELS_URL was silently ignored on that path and a dev session without the local inference stack running got a dead catalog URL and an empty model list. It now uses the resolver that honors the override and probes the local stack before falling back to production. apps/server/src/cli.ts spawned the engine without setting the models URL or sweeping legacy config at all; both boot paths now agree. Adds @openwork/types/url and collapses the byte-identical copies onto it: DEN_API_BASE had four independent readers in den-web (one of which was a bare inline expression in a layout), and the app had two identical server-URL normalizers. Note for a follow-up: apps/orchestrator and packages/openwork-bootstrap strip a single trailing slash (/\/$/) where the rest of the monorepo strips all of them (/\/+$/), so "http://host//" normalizes differently across process boundaries and breaks origin equality and cache keys. Both are left untouched here — the orchestrator is out of scope for this change and the bootstrap CLI ships as raw .mjs that cannot import this package's source. * refactor(server): build workspace-keyed SQLite stores from one factory Four stores (runtime_opencode_configs, openwork_workspace_configs, cloud_plugin_install_configs, session_group_states) each carried their own copy of the same ~50 lines: the table definition, a bun branch using drizzle upsert, a node branch using raw ON CONFLICT SQL, the CREATE TABLE DDL written out twice per file so it could be used from both branches, a local isRecord, and a private dbByPath cache. That last part was the actual hazard: four independent connection caches pointing at the same SQLite file. They now share one cache and one connection, and the DDL is generated once per table instead of eight times in total. session_group_states keeps its extra schema_version column through the factory's extraColumns option rather than being forced into a lossy shape. All four stores keep their existing exported names and signatures, so callers are untouched and no migration is involved. * fix(evals): make the core flow require a real assistant reply The canonical proof could pass without the agent ever responding. The prompt is "Reply with exactly: core-flow ok", so asserting that the page contains "core-flow ok" is satisfied by the echoed user bubble alone — waitForText and the screenshot's requireText were both tautologies. Observed on a real Daytona run: the step passed in 1.4s with a frame showing only the user message and no reply. Scoping the assertion to an assistant message makes the same step wait 5.9s for the response to stream in. Verified against a user-only transcript: the previous predicate passes, the new one fails, and it still passes on a transcript that has a real reply. * fix(build): make the new paths package resolvable in every build context Adding a workspace package is not free: three build contexts resolve the workspace by hand and each needed teaching about it. - apps/installer declares its own bun `workspaces` array, so `bun install` reported "@openwork/paths@workspace:* failed to resolve" and the Windows compile step failed outright. Added the package to that array. - The Windows trust job already carries a copy fallback for install-config because bun 1.3.9 on Windows can fail to create the parent-relative workspace symlink. @openwork/paths hits the same case, so it now uses the same fallback. - Dockerfile.den copies apps/desktop/package.json for version metadata, which drags apps/desktop's dependencies into pnpm workspace resolution. That failed with ERR_PNPM_WORKSPACE_PKG_NOT_FOUND while building packages/email, so the image now copies packages/paths too. Also verified the packaged desktop app, since the Electron main process had no non-builtin runtime imports before this change and a missing module there would only show up as a boot failure in a real build: electron-builder resolves the pnpm workspace symlink and ships /node_modules/@openwork/paths/index.mjs inside app.asar, and the packaged app boots with no module-resolution errors.
…apsed chip (#3100) Co-authored-by: Cursor <cursoragent@cursor.com>
Rebuilds step 2 of the organization install guide around the fresh-install case, matching the approved Paper design: - Eyebrow, "Open the file you just downloaded" heading, a file chip naming the real installer artifact, two numbered actions, a calm amber OS trust note, a handoff note, an OR divider, the demoted already-installed row with the single dark primary button, and a quiet manual-paste disclosure. - Copy is per-OS (macOS / Windows / Linux) and follows the platform the user actually downloaded, falling back to browser platform detection. - The file chip shows the real published artifact name from genericInstallerArtifactName() (no version, because the published assets carry none) and is omitted when the platform or arch is unknown, so the page never invents a filename. - The handoff note describes what the installer really does instead of promising that this page auto-advances to step 3, which it cannot observe: the installer resolves its own activation grant from the install token, so the web page's code is a different code. - Installer preview: fake CTA flattened to a hairline outline, badge relabelled "PREVIEW · WHAT YOU'LL SEE ON YOUR COMPUTER" with a neutral dot, and the column stretches to match the left column height. Eval flows are updated for the new copy and for the manual-paste disclosure. Co-authored-by: Cursor <cursoragent@cursor.com>
…#3107) The expired-install-link assertion pinned copy that no longer shipped, so the suite failed on a clean checkout. Assert the actual contract (no raw API error code leaks, the message names the link, expiry, and who to ask) so wording can improve without breaking the test.
The installer artifact shipped in v0.18.1 reported 1.0.0 because the mac Info.plist hardcoded it and nothing else carried a version at all, so a user or support engineer could not tell which build they had. - resolve one version from the release tag (local builds fall back to apps/installer/package.json) and stamp it into the compiled binary, the mac Info.plist, the DMG volume name, and the Windows version resource - add `--version` to the installer CLI and a quiet footer in the window - keep apps/installer/package.json on the release train via bump-version Published asset filenames are unchanged.
…otstrap, self-diagnosing failures (#3344) * fix(evals): bootstrap den app specs reliably * fix(evals): define app readiness as an interactive UI, share the predicate, resolve workspace id from product state * fix(evals): rename shadowed route binding
* feat: Add a useful right-panel action chooser Open-Work-Snacks-Run: e9cf7d72-908a-42f2-884b-ba24ae0422db:b7b433ddc491c04a22aedcef4b450d3dcee8f989d260f43d0179e4b61f769033 * test(evals): detect current right-panel chooser --------- Co-authored-by: open-work-snacks <open-work-snacks@users.noreply.github.com>
* fix(release): respect protected dev workflow * docs(release): require AUR PR merge confirmation
Open-Work-Snacks-Run: b4c2b9fa-471a-4e08-ac32-d2a4d3bf42b1:7c64e983a335d6f0304e3eacd7dc2350309a6a7bd427ca2b1d95a91725de1696 Co-authored-by: open-work-snacks <open-work-snacks@users.noreply.github.com>
* feat: Add platform-number shortcuts for visible chat sessions Open-Work-Snacks-Run: acb7f568-3f18-4119-a164-75f92b5be370:4aa2d15810291d5c4e67fdd411d5266237d1bd97f03c33691c20898c46da7f69 * fix: keep session number shortcuts global * fix: allow session jumps through select popovers --------- Co-authored-by: open-work-snacks <open-work-snacks@users.noreply.github.com>
… of failing opaquely (#3345)
Open-Work-Snacks-Run: 024e0020-9163-4b43-9471-6703dca8c034:b3d42022a8e50740946186f9815c8272402d78b39d1df89d63764ee13aaf1abf Co-authored-by: open-work-snacks <open-work-snacks@users.noreply.github.com>
* fix(den): harden email sign-in resolution * test(lab): avoid reserved port reuse
* feat: Animate overflowing chat titles on hover and focus Open-Work-Snacks-Run: 5608fb1b-df16-45af-8993-bfd5b562a3df:1d9b982f8426b8991c95edb816b8f9ab286e7da4941aefe4d30095ef7f8b65eb * test(evals): target current session title marquee * fix(app): suppress tooltip during title reveal --------- Co-authored-by: open-work-snacks <open-work-snacks@users.noreply.github.com>
* build(deps-dev): bump vite from 6.4.1 to 6.4.3 Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.4.1 to 6.4.3. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v6.4.3/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v6.4.3/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-version: 6.4.3 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com> * fix: allow dependabot vite transitive deps --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: OmarMcAdam <gh@mcadam.io>
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.38 to 8.5.18. - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](postcss/postcss@8.4.38...8.5.18) --- updated-dependencies: - dependency-name: postcss dependency-version: 8.5.18 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@better-auth/scim](https://github.com/better-auth/better-auth/tree/HEAD/packages/scim) from 1.6.11 to 1.6.25. - [Release notes](https://github.com/better-auth/better-auth/releases) - [Changelog](https://github.com/better-auth/better-auth/blob/main/packages/scim/CHANGELOG.md) - [Commits](https://github.com/better-auth/better-auth/commits/v1.6.25/packages/scim) --- updated-dependencies: - dependency-name: "@better-auth/scim" dependency-version: 1.6.25 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [tailwind-merge](https://github.com/dcastil/tailwind-merge) from 3.5.0 to 3.6.0. - [Release notes](https://github.com/dcastil/tailwind-merge/releases) - [Commits](dcastil/tailwind-merge@v3.5.0...v3.6.0) --- updated-dependencies: - dependency-name: tailwind-merge dependency-version: 3.6.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [minimatch](https://github.com/isaacs/minimatch) from 10.1.1 to 10.2.5. - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](isaacs/minimatch@v10.1.1...v10.2.5) --- updated-dependencies: - dependency-name: minimatch dependency-version: 10.2.5 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [tsx](https://github.com/privatenumber/tsx) from 4.21.0 to 4.23.1. - [Release notes](https://github.com/privatenumber/tsx/releases) - [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs) - [Commits](privatenumber/tsx@v4.21.0...v4.23.1) --- updated-dependencies: - dependency-name: tsx dependency-version: 4.23.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@codemirror/lang-markdown](https://github.com/codemirror/lang-markdown) from 6.5.0 to 6.5.1. - [Changelog](https://github.com/codemirror/lang-markdown/blob/main/CHANGELOG.md) - [Commits](https://github.com/codemirror/lang-markdown/commits) --- updated-dependencies: - dependency-name: "@codemirror/lang-markdown" dependency-version: 6.5.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* build(deps): bump next from 16.2.1 to 16.2.11 Bumps [next](https://github.com/vercel/next.js) from 16.2.1 to 16.2.11. - [Release notes](https://github.com/vercel/next.js/releases) - [Commits](vercel/next.js@v16.2.1...v16.2.11) --- updated-dependencies: - dependency-name: next dependency-version: 16.2.11 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> * fix: pin next browser mapping transitive --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: OmarMcAdam <gh@mcadam.io>
* build(deps): bump react-dom and @types/react-dom Bumps [react-dom](https://github.com/react/react/tree/HEAD/packages/react-dom) and [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom). These dependencies needed to be updated together. Updates `react-dom` from 18.2.0 to 19.2.8 - [Release notes](https://github.com/react/react/releases) - [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/react/react/commits/v19.2.8/packages/react-dom) Updates `@types/react-dom` from 18.2.25 to 19.2.3 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom) --- updated-dependencies: - dependency-name: "@types/react-dom" dependency-version: 19.2.3 dependency-type: direct:development update-type: version-update:semver-major - dependency-name: react-dom dependency-version: 19.2.8 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * fix: align react catalog with react dom --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: OmarMcAdam <gh@mcadam.io>
…3376) The boot takeover showed a progress bar hardcoded to two thirds that only pulsed, so a slow sandbox read as frozen at 66%. It also ran two spinners at once, and Retry appeared only after a hard failure, leaving a slow but healthy boot with nothing to do. Progress is now derived from the status we already poll, so it can never claim more than we can prove: a provisioning sandbox is still being reserved, while a waking or updating one demonstrably exists. Only the active checkpoint animates. At 45s the copy escalates and Retry / Sign out appear. Also fixes the dot ticker, which computed to fully transparent: the --dls-*-rgb tokens are space-separated but the rules used legacy comma rgba(), so the indicator was invisible everywhere it was used, including the composer wait state. Co-authored-by: Cursor <cursoragent@cursor.com>
…3375) Providers were identifiable only by a two-letter monogram unless they were one of the three brands with a bundled inline SVG, which made the connect dialog read as a wall of grey initials. Adds a logo resolution ladder (inline SVG, Simple Icons, favicon, monogram last) so a provider only falls back to initials once every source is exhausted. Long-tail catalog ids are slugified domains, so unslugging "302ai" to "302.ai" recovers a real mark instead of "30". Builds on that to group the dialog into Connected and All providers, lead the API-key step with the provider's own logo, and make the model picker's API-keys row reflect whether any keys exist yet. Co-authored-by: Cursor <cursoragent@cursor.com>
better-sqlite3 11.10.0 ships no `node-v137` (Node 24) prebuild, so every CI
install fell through `prebuild-install` to `node-gyp rebuild`, which downloads
the Node headers from nodejs.org mid-install. When that request stalls the whole
install dies:
prebuild-install warn install No prebuilt binaries found (target=24.13.0 ...)
gyp ERR! stack AggregateError [ETIMEDOUT]
[ELIFECYCLE] Command failed with exit code 1
Bump better-sqlite3 to ^12.11.1, which publishes node-v137 (and v127/v141/v147)
prebuilds, so installs fetch a binary instead of compiling. 12.0.0 was a
build-matrix-only major (dropped EOL Node 18 / Electron 26-28); the JS API is
unchanged and Electron 35 (ABI 133) prebuilds are still published.
Also cache the pnpm store in the tests workflow, matching the release/alpha
workflows: OpenWork Tests was re-downloading all 1453 packages every run
("reused 0"), which is both slow and extra network surface to flake on.
…ehind its components, timeline observability (#3359) * feat(evals): timeline primitive, workspace seeding, and honest visual expectations * fix(evals): seed completes onboarding and engine boot; wait on product state not route shapes * fix(evals): keep app-smoke on the product's own workspace creation path * test(evals): app pointed at a TLS-broken den must name the fault (welcome surface, no onboarding needed) * chore(evals): single-spec sandbox runner * test(evals): adapt the TLS-fault spec to the real pre-workspace surface * test(evals): choose the sign-in control from real buttons * test(evals): TLS-intercepted den — no false 'connected', and diagnostics name the interception * test(evals): one frame — sign-in against a broken den changes nothing visually * test(evals): name the TLS spec after what it actually proves * fix(evals): short per-probe timeouts so busy renderers are retried, not waited on * fix(evals): read the created workspace via the proven in-page server call, not an unverified bridge channel * test(evals): poll patiently through the cold-profile renderer block * fix(evals): poll for the created workspace record through renderer blocks * fix(evals): resolve the workspace id from product state after onboarding instead of a hanging server fetch * fix(evals): idempotent reads retry through renderer blocks * fix(evals): retry reads to a deadline, not a fixed attempt count * fix(evals): re-attach to the app's current page target when evaluations stop answering * fix(evals): background prep does not make the welcome surface un-interactive * chore(evals): verify the X display actually answers before spawning Electron * chore(evals): clear stale Electron processes before each sandbox spec run * fix(evals): resolve the workspace id after onboarding completes, not before * fix(evals): report the workspace id even while the welcome surface is showing * test(evals): assert the first-run workspace id after onboarding adopts it * test(evals): use the resolved workspace id; report loaded skills on failure * fix(evals): parse the skill name from the row, and drop a regex that never compiled * test(evals): wait for the assistant to settle; use the session control when the button is not text * test(evals): wait for output to stabilise; stop assuming session ids appear in the route * fix(evals): settings and extensions surfaces are interactive too * test(evals): read the created session id from the product's session list * test(evals): drop an exact timing threshold that can flake by a millisecond * test(evals): first run signs in through a real browser, then shares a skill via a marketplace * chore(evals): verify the display in the full runner; give single-spec runs den env * refactor(evals): move environment healing behind the components that own it Target re-attach now lives in @openwork/cdp (evaluateOnSurface), display liveness and stale-surface cleanup in @openwork/hosts (spawnElectron), and resolveHost no longer picks the Daytona host when the caller is already inside a sandbox. The sandbox runner scripts drop the logic they were carrying. * test(evals): match the real desktop-auth handoff URL and read Den's deep link from the browser * test(evals): switch the browser from sign-up to sign-in for a seeded account * chore(evals): let a single-spec run ensure the Den stack when the spec needs it * test(evals): collapse workspace arrangement to the proven onboarding path seedWorkspace arranged a workspace over the local server API and left the engine unconfigured and the model catalog empty — a state the product's own onboarding never produces, so specs failed on arrangement instead of their subject. Every spec now goes through createAndSelectWorkspace, the path the passing journeys already proved. Also read the created session id from the field session.list_sessions really returns: items carry sessionId, not id (probed live; the old extraction never matched, so the wait timed out even with sessions present). * test(evals): drive den web's real two-step sign-in and read the sign-in code input Probed live on a running den: auth is an email-only step (Next) that routes to a password step (Sign in) — there is no single form and no sign-up/sign-in toggle. After sign-in the deep link is not an anchor or page text; it is a readonly input holding the openwork://den-auth?grant=… sign-in code next to Open OpenWork, so read it from there. * fix(evals): keep pnpm version redirection warm inside isolated Electron profiles Each surface's fresh HOME hides the host's pnpm tool cache, so the pinned pnpm (packageManager) is re-downloaded from the network on every spawn (21MB). On the eval sandbox one failed download degenerated into a self-sustaining recursive 'pnpm add pnpm' cascade that outlived the run and starved later spawns. Point PNPM_HOME at the host's real pnpm home; the redirect is then local and instant (verified: fresh HOME resolves in 0.75s with no downloads). * chore(evals): export den eval env only when a den actually answers Exporting OPENWORK_EVAL_DEN_API_URL unconditionally made den-gated specs run against nothing and die in 3ms with 'fetch failed' instead of skipping with their own reason. Probe /health first; with OPENWORK_SPEC_NEEDS_DEN=1 the stack is still ensured before the probe. * test(evals): scroll the claimed skill row into view before its screenshot The skills menu is a scrollable list: /browser-automation was loaded (the DOM assertions passed) while the screenshot showed only the rows above it, so the visual validator honestly reported it absent. * fix(evals): survive renderer freeze bursts while reading the skills menu The workspace engine boot blocks the renderer JS thread in bursts. Bare 20s evaluations (plug-menu clicks) died with raw CDP timeouts, and the measure evaluations gave their outer CDP call the same 20s deadline as the in-page poll, so the two raced under load. Fold the menu clicks into a guarded, retried wait and give the measures headroom over their inner deadlines. * test(evals): reveal the menu row a visual claim names before its screenshot The capability menu is a scrollable popover: all four sections were in the DOM (the code assertion passed) while Agents sat above the fold, so the validator honestly reported it invisible. Scroll the named row into view and let the code assertion carry section completeness. * test(evals): assert the capability menu visuals a person can actually see The vision loop caught a real product defect: with a long command list the capability popover extends under the window header, so its first section row (Agents) is covered and unclickable (repo workspace, popover top at y=17 under the title bar). Keep four-section completeness as the DOM assertion, scope the visual claim to the visible sections, and record the defect where the claim is made. * test(evals): arm the slow-cloud scenario separately and drive the menu with retried waits The scenario opened the plug menu inside its own evaluate with fixed 100/300ms delays right after a reload; under load those clicks land before React handlers attach and the whole block times out. Arm the fetch delay and the connect witness in one small mutation, open the menu with the guarded retried helper, then measure. * test(evals): arrange the real cloud-connected desktop state for slow-cloud skills The scenario set window.__OPENWORK_GATEWAY__, which flips the app into the hosted gateway runtime and rewires the local openwork-server client to the page origin — so client.listSkills hit the Vite dev server and local skills never rendered, a state no desktop user can reach. The den auth token and active org id it also set are the real cloud-connected desktop arrangement, so keep only those. Drop the unused resetSkillsCloudState. * test(evals): drop the slow-cloud skills block whose arrangement cannot be faithful On desktop, den traffic goes through the main process, so the renderer fetch hook never delayed anything (denRequestCount stayed 0), and the gateway marker it used instead rewired the local server to the page origin. The block therefore only ever measured an impossible state. Cloud latency belongs in a den-boundary fault spec like app-den-tls-fault, where the fault is injected for real.
#3387) * feat(evals): timeline primitive, workspace seeding, and honest visual expectations * fix(evals): seed completes onboarding and engine boot; wait on product state not route shapes * fix(evals): keep app-smoke on the product's own workspace creation path * test(evals): app pointed at a TLS-broken den must name the fault (welcome surface, no onboarding needed) * chore(evals): single-spec sandbox runner * test(evals): adapt the TLS-fault spec to the real pre-workspace surface * test(evals): choose the sign-in control from real buttons * test(evals): TLS-intercepted den — no false 'connected', and diagnostics name the interception * test(evals): one frame — sign-in against a broken den changes nothing visually * test(evals): name the TLS spec after what it actually proves * fix(evals): short per-probe timeouts so busy renderers are retried, not waited on * fix(evals): read the created workspace via the proven in-page server call, not an unverified bridge channel * test(evals): poll patiently through the cold-profile renderer block * fix(evals): poll for the created workspace record through renderer blocks * fix(evals): resolve the workspace id from product state after onboarding instead of a hanging server fetch * fix(evals): idempotent reads retry through renderer blocks * fix(evals): retry reads to a deadline, not a fixed attempt count * fix(evals): re-attach to the app's current page target when evaluations stop answering * fix(evals): background prep does not make the welcome surface un-interactive * chore(evals): verify the X display actually answers before spawning Electron * chore(evals): clear stale Electron processes before each sandbox spec run * fix(evals): resolve the workspace id after onboarding completes, not before * fix(evals): report the workspace id even while the welcome surface is showing * test(evals): assert the first-run workspace id after onboarding adopts it * test(evals): use the resolved workspace id; report loaded skills on failure * fix(evals): parse the skill name from the row, and drop a regex that never compiled * test(evals): wait for the assistant to settle; use the session control when the button is not text * test(evals): wait for output to stabilise; stop assuming session ids appear in the route * fix(evals): settings and extensions surfaces are interactive too * test(evals): read the created session id from the product's session list * test(evals): drop an exact timing threshold that can flake by a millisecond * test(evals): first run signs in through a real browser, then shares a skill via a marketplace * chore(evals): verify the display in the full runner; give single-spec runs den env * refactor(evals): move environment healing behind the components that own it Target re-attach now lives in @openwork/cdp (evaluateOnSurface), display liveness and stale-surface cleanup in @openwork/hosts (spawnElectron), and resolveHost no longer picks the Daytona host when the caller is already inside a sandbox. The sandbox runner scripts drop the logic they were carrying. * test(evals): match the real desktop-auth handoff URL and read Den's deep link from the browser * test(evals): switch the browser from sign-up to sign-in for a seeded account * chore(evals): let a single-spec run ensure the Den stack when the spec needs it * test(evals): collapse workspace arrangement to the proven onboarding path seedWorkspace arranged a workspace over the local server API and left the engine unconfigured and the model catalog empty — a state the product's own onboarding never produces, so specs failed on arrangement instead of their subject. Every spec now goes through createAndSelectWorkspace, the path the passing journeys already proved. Also read the created session id from the field session.list_sessions really returns: items carry sessionId, not id (probed live; the old extraction never matched, so the wait timed out even with sessions present). * test(evals): drive den web's real two-step sign-in and read the sign-in code input Probed live on a running den: auth is an email-only step (Next) that routes to a password step (Sign in) — there is no single form and no sign-up/sign-in toggle. After sign-in the deep link is not an anchor or page text; it is a readonly input holding the openwork://den-auth?grant=… sign-in code next to Open OpenWork, so read it from there. * fix(evals): keep pnpm version redirection warm inside isolated Electron profiles Each surface's fresh HOME hides the host's pnpm tool cache, so the pinned pnpm (packageManager) is re-downloaded from the network on every spawn (21MB). On the eval sandbox one failed download degenerated into a self-sustaining recursive 'pnpm add pnpm' cascade that outlived the run and starved later spawns. Point PNPM_HOME at the host's real pnpm home; the redirect is then local and instant (verified: fresh HOME resolves in 0.75s with no downloads). * chore(evals): export den eval env only when a den actually answers Exporting OPENWORK_EVAL_DEN_API_URL unconditionally made den-gated specs run against nothing and die in 3ms with 'fetch failed' instead of skipping with their own reason. Probe /health first; with OPENWORK_SPEC_NEEDS_DEN=1 the stack is still ensured before the probe. * test(evals): scroll the claimed skill row into view before its screenshot The skills menu is a scrollable list: /browser-automation was loaded (the DOM assertions passed) while the screenshot showed only the rows above it, so the visual validator honestly reported it absent. * fix(evals): survive renderer freeze bursts while reading the skills menu The workspace engine boot blocks the renderer JS thread in bursts. Bare 20s evaluations (plug-menu clicks) died with raw CDP timeouts, and the measure evaluations gave their outer CDP call the same 20s deadline as the in-page poll, so the two raced under load. Fold the menu clicks into a guarded, retried wait and give the measures headroom over their inner deadlines. * test(evals): reveal the menu row a visual claim names before its screenshot The capability menu is a scrollable popover: all four sections were in the DOM (the code assertion passed) while Agents sat above the fold, so the validator honestly reported it invisible. Scroll the named row into view and let the code assertion carry section completeness. * test(evals): assert the capability menu visuals a person can actually see The vision loop caught a real product defect: with a long command list the capability popover extends under the window header, so its first section row (Agents) is covered and unclickable (repo workspace, popover top at y=17 under the title bar). Keep four-section completeness as the DOM assertion, scope the visual claim to the visible sections, and record the defect where the claim is made. * test(evals): arm the slow-cloud scenario separately and drive the menu with retried waits The scenario opened the plug menu inside its own evaluate with fixed 100/300ms delays right after a reload; under load those clicks land before React handlers attach and the whole block times out. Arm the fetch delay and the connect witness in one small mutation, open the menu with the guarded retried helper, then measure. * test(evals): arrange the real cloud-connected desktop state for slow-cloud skills The scenario set window.__OPENWORK_GATEWAY__, which flips the app into the hosted gateway runtime and rewires the local openwork-server client to the page origin — so client.listSkills hit the Vite dev server and local skills never rendered, a state no desktop user can reach. The den auth token and active org id it also set are the real cloud-connected desktop arrangement, so keep only those. Drop the unused resetSkillsCloudState. * test(evals): drop the slow-cloud skills block whose arrangement cannot be faithful On desktop, den traffic goes through the main process, so the renderer fetch hook never delayed anything (denRequestCount stayed 0), and the gateway marker it used instead rewired the local server to the page origin. The block therefore only ever measured an impossible state. Cloud latency belongs in a den-boundary fault spec like app-den-tls-fault, where the fault is injected for real. * test(evals): wait for the sign-in outcome, and give org specs a workspace before sign-in signInInBrowser returned right after clicking Sign in, so the next frame honestly showed 'Working...'. Wait for the signed-in outcome (or the sign-in code) before returning. The signed-in org shell offers no Add workspace entry, and the workspace.create control there reports ok while creating nothing (its error lands in closed-modal state) — probed live twice. Arrange org specs the way a member actually gets there: create the workspace on the proven welcome path first, then sign in; organization onboarding is completed when it appears and the existing workspace is reselected either way. * test(evals): send the role the marketplace access grant API requires POST /v1/marketplaces/:id/access rejects a grant without role (viewer|editor|manager). Viewer is what sharing with a colleague means. * test(evals): read shared skill names from the plugin's resolved components The resolved marketplace payload carries plugins with component counts only; skill names live on GET /v1/plugins/:id/resolved as items[].configObject (objectType skill, title). Read them as the member so visibility stays the colleague's, not the admin's. * test(evals): poll the model catalog past its first paint, and pin the managed-recovery defect The picker can paint 'No models' before the engine's catalog lands (observed live: 0 models on first read, 7 shortly after on the same boot), so the primary test polls up to 90s before asserting. The managed test now pins today's truth: after an admin publishes a provider, Retry does not deliver it to the composer even though the API already entitles the member (probed live, 201 + readable as the member, empty notice survives 90s+). The spec asserts the notice stays honest and the composer stays usable; when live recovery ships, the pinned wait fails loudly and the recovery assertions come back from history. * test(evals): pin the managed defect without typing (no editor without a model) With no selectable model the composer renders no contenteditable editor, so the pinned block asserts what is really there: the persistent notice with Retry and no crash. * test(evals): pin only the persistent notice after Retry (the button reads Refreshing mid-flight) * feat(evals): make surface placement explicit, and own browser disposal resolveHost() reads one ambient env var, so a whole process got one host: everything local, or everything in one sandbox. A spec could not say 'app here, browser there' or 'two desktops in two sandboxes' — the topology was inherited from the environment instead of declared. - desktop({ host }) and the new chrome({ host }) take a placement. - localHost() / daytonaSandbox(id) name one, with REPO_ROOT wiring kept inside the package. daytonaSandbox() fails loudly from inside a sandbox, where the CLI indirection has nothing to target. - resolveHost() default behaviour is unchanged, so existing specs are untouched. chrome() also fixes a real leak: attachSurface only closes the CDP socket, so the hand-rolled spawnChrome + attachSurface in first-run-cloud-share left a browser process running after every run. Disposing now stops the client and then disposes the surface, which is what kills it.
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