Skip to content

Commit 05275e8

Browse files
lefarcenSiri-RayPerishCodeLooperjoeylee12629-star
authored
fix(workspace): preserve scoped projects after main sync (#6320)
* fix(daemon): surface AMR OpenCode stall context (#6040) * fix(daemon): surface AMR OpenCode stall context * fix(daemon): accept runtime-omitted OpenCode diagnostics Generated-By: looper 0.11.0 (runner=fixer, agent=codex) * fix(ci): make static gate runner-independent (#6039) --------- Co-authored-by: PerishFire <39043006+PerishCode@users.noreply.github.com> * test(e2e): parallelize restoration group (#6169) * test(e2e): parallelize restoration group * test(e2e): identify conversations from persisted prompts Generated-By: looper 0.11.0 (runner=fixer, agent=codex) * test(e2e): wait for conversation persistence --------- Co-authored-by: Looper <looper@noreply.github.com> * feat(landing-page): sharpen the Codex agent page for "codex ui" intent (#6200) The /agents/codex-design/ page ranks #1 for "codex design" but only ~6th with a 1.3% CTR for "codex ui", a query that grew from 30 to ~90 daily impressions this month. A live SERP check shows the intent is mostly "build UI with Codex" (our intent), with a minority looking for the Codex app's own interface. - Retitle to "Codex Design: Build UI with OpenAI Codex" (title + H1). - Lead the frontend section with the query phrase and an answer-shaped opening paragraph, so the section is extractable for AI answers. - Add a disambiguation paragraph separating the Codex app's own UI from the UI you build with Codex, and route the former back to the main line. - Add two FAQ entries covering both readings; they also feed the FAQPage schema, which already earns a text snippet on this query. Applied across all 11 shipped locales (en, zh authored; the other nine translated with the page's terminology preserved). Co-authored-by: Joey <236967869+joeylee12629-star@users.noreply.github.com> * Add Clone Audit plugin (#5687) * Add Clone Audit plugin * Update open-design.json * fix: make clone audit skill reusable * fix: sanitize clone audit provenance path * fix(e2e): bound tools-dev runtime lifecycle (#6204) * test(e2e): refresh full-pool UI fixtures (#6211) * fix(web): allow skipping required chat questions (#6177) * fix(web): allow skipping required chat questions * fix(web): auto-skip unanswered chat questions --------- Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> * docs(tools-pack): add build cache contract (#6207) * docs(tools-pack): add build cache contract Document the tools-pack build-graph cache as a contract: the exact-match acceptance model, determinant rules, materialization-time parameters, the signing boundary, and fail-closed confidence grading. The rules come from an audit of all 11 cache nodes. Two are written down because nothing currently enforces them: a node key must carry the key of every upstream node it consumes, and a node key must not restate a list that already exists as a constant. Known low-confidence points are declared explicitly so fail-closed grading stays checkable rather than becoming a verbal convention. * docs(tools-pack): clarify cache materialization exceptions Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * docs(tools-pack): document NSIS base version scope Generated-By: looper 0.11.2 (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> * docs(landing-page): add 0.16.0 release post, localize and re-cover 0.15.1 (#6236) * docs(landing-page): localize 0.15.1 post, fix its cover, add 0.16.0 release post The 0.15.1 blog post shipped English-only and with an off-brand cover: a Fauvist oil painting overlaid with large display type, which reads nothing like the warm editorial illustrations every other release post uses. It also pointed `socialImage` at a 309KB JPEG while a WebP sat unused beside it. Regenerate the cover in the established house style (cream paper ground, sage/terracotta watercolour washes, pencil sketch resolving into a calm product surface), drop the stray JPEG, and add the full ten-locale i18n block so /zh/, /ja/, /ko/, /de/, /fr/, /ru/, /es/, /pt-br/, /it/ and /tr/ read in their own language instead of falling back to English. Also add the missing 0.16.0 "Reliable Delivery" post with a cover plus two inline figures in the same style, localized across the same ten locales. The 0.16.1 patch is a single preview fix, too thin to carry its own page, so it lands as a closing section of the 0.16.0 post and the download CTA points there. * docs(landing-page): fix doubled apostrophes and locale copy in release posts Three defects surfaced reviewing the localized bodies. The French, Italian and Turkish bodies rendered every apostrophe twice — "aujourd''hui", "all''interno", "0.16.1''i". The `''` escape belongs to single-quoted YAML scalars, but `bodyHtml` is a block scalar, where content is literal. 173 occurrences across the two posts. Korean used Japanese corner brackets and Brazilian Portuguese and Turkish used French guillemets. All three take curly double quotes. The Chinese copy read as translation rather than prose. "标签" opens the release line as a UI label, not a version tag; "抢画框", "编辑策展位" and "安静修复" are literal renderings that say nothing in Chinese; "画廊" is not the term the product itself uses for a gallery, which keeps the English word. The tag fix also lands on 0.10.0 through 0.15.0, which share the phrasing — leaving the series half-corrected would read worse than either state alone. * docs(landing-page): drop the leading tag word from release post openings Every release post opened with the word for a git tag before the version identifier — "Tag open-design-v0.16.0", "Etiqueta …", "タグ …", and in Chinese "标签", which reads as a UI label rather than a version. The word carries no information the identifier does not already carry, and in several languages it lands as a category noun the sentence never uses again. Drop it across all nine release posts and every locale, in both the summary and the opening line, leaving the version identifier to open the dateline. Spanish and Brazilian Portuguese lose the feminine agreement that referred back to the removed noun; Turkish loses the trailing "etiketi" apposition for the same reason. * docs(landing-page): correct the 0.16.1 interval in the 0.16.0 post 0.16.0 was published 2026-07-22 14:42 UTC and 0.16.1 on 2026-07-23 16:11 UTC — 25.5 hours apart. "Two days later" overstated it, and the same wording had been carried into all ten localized bodies, so every published route repeated it. --------- Co-authored-by: Joey <236967869+joeylee12629-star@users.noreply.github.com> * feat(integrations): add the local Open Design Cloud flow for Codex (#6055) * feat(daemon): expose Vela login through CLI and MCP * feat(mcp): add interactive local brief card * feat(packaged): bootstrap local MCP headlessly * feat(daemon): secure local BYOK credential profiles * feat(cli): manage secure BYOK profiles * feat(web): store BYOK keys in secure profiles * fix(runs): deduplicate cloud generation requests * feat(daemon): add end-to-end plugin observability * fix(pack): include native PTY runtime in desktop packages Lazy-load node-pty in the daemon so missing native binaries only disable Terminal and interactive Keychain operations instead of crashing startup. Ship and validate target prebuilds in macOS and Windows packages. Repair the macOS spawn helper before signing, and invalidate stale Windows packaging caches. Cover the packaged PTY path in macOS and Windows smoke tests. Require Vela CLI for every beta desktop build target. * fix(mcp): localize and stabilize plugin briefs Keep collect and confirm on one MCP Apps card, report intrinsic size changes, and remove the fragile widget-state fallback. Localize brief forms, summaries, status, and public errors from the current request or Host locale while preserving stable protocol ids and selections. Keep internal runtime identifiers out of user-facing MCP guidance. * fix(packaged): register live Studio URLs with daemon Register the packaged web sidecar loopback origin over namespace-scoped daemon IPC after dynamic binding. Invalidate install-info by the live web port and remove the second MCP URL cache so run and project responses use the current Studio address. Validate loopback origins and cover registration, rebind, and cache refresh. * fix(mcp): stabilize brief confirmation lifecycle Keep confirmed briefs locked after Host publication failures and retry only the cached follow-up message instead of confirming twice. Replace blank initialization with a compact loading state, accept immediate and delayed tool results, and bump the MCP Apps resource to v3 so Codex does not reuse the stale card. Add an executable JSDOM Host bridge harness covering double-submit, publication retry, delayed results, and repeated draft notifications. Validated with the full daemon suite, workspace typecheck, and guard. * fix(mcp): prevent brief app resize feedback loops Replace the self-observed intrinsic-height loop with deduplicated body measurements so Codex MCP app iframes do not repeatedly resize themselves and fail sandbox startup. Bump the brief resource URI to v4 to avoid cached v3 cards and cover the regression with the focused brief-app spec. Validated with daemon tests/build, workspace guard/typecheck, a verified beta DMG, and a direct packaged MCP resource smoke. * fix(mcp): use the final Open Design plugin identity Make open-design the only accepted external plugin ID across MCP tools, run attribution, artifact version origins, and telemetry. Rename the Brief MCP App resource to v5 and reject the unpublished old ID instead of aliasing it. Validated with 171 daemon tests, 5 web tests, daemon/web typechecks, and guard. * chore(pack): bump Vela CLI to 0.0.27 * chore(nix): refresh pnpm dependency hashes * fix(mcp): honor host and plugin request contracts Respect independently advertised MCP Apps capabilities and prefer the Codex-native follow-up bridge so confirmed briefs render as readable user turns instead of context-only messages. Bump the brief resource to v6 to invalidate stale cards.\n\nMark Vela login and account probes as open-world interactions, and require stable request IDs for attributed generation so lost responses cannot create a second logical run. * fix(cli): support keyless BYOK profiles Add an explicit --no-api-key save mode for local and self-hosted providers while keeping credential-bearing profiles stdin-only. Reject missing or conflicting credential modes and cover both paths in the CLI tests. * fix(pack): replace headless owner when desktop opens Advertise headless packaged runtimes as having no visible window, then shut them down before a normal desktop launch continues instead of treating SHOW as a successful focus. Validated with the focused packaged headless and launcher lifecycle tests (20 passed). * fix(pack): clean up failed headless startup Acquire the headless identity, sidecars, and IPC server through one failure-atomic lifecycle so later bootstrap errors close every previously acquired owner in reverse order. Cover MCP-install and web-identity publication failures; validated with 22 focused tests and the packaged typecheck. * fix(byok): remove raw provider request contract Expose only daemon-owned BYOK profile references from shared run types and the web transport, while retaining the daemon's fail-closed rejection for legacy or untyped raw credential payloads. Validated with 76 web provider tests plus web and contracts typechecks. * fix(daemon): preserve interrupted run idempotency Hydrate queued or running durable requests as DAEMON_RESTARTED failures before idempotency reuse, preserving the original request and workflow mappings instead of creating a second cloud operation. Share the restart transition with boot reconciliation and expose synthetic terminal events to reattaching clients. Validated with 48 focused tests and the daemon typecheck. * fix(byok): roll back failed credential metadata writes Snapshot secure-store values before mutation and compensate create, update, and delete operations when profile metadata cannot be persisted, preventing orphaned or lost credentials. Validated with nine focused credential-service tests and the daemon typecheck. * fix(web): reconcile selected BYOK profile metadata Treat the daemon's selected secure profile as authoritative for protocol, endpoint, model, and API version so CLI profile edits cannot leave the browser showing stale execution settings. Validated with 66 config tests and the web typecheck. * fix(byok): migrate legacy credentials before cleanup Import each supported legacy browser credential into a stable daemon-owned secure profile before removing plaintext copies. Keep the original browser record on secure-store or unsupported-provider failures and surface a Settings recovery path. Cover successful migration, duplicate projections, and injected secure-backend failure while preserving existing Bedrock downgrade behavior in memory. * fix(byok): secure Windows profiles with DPAPI Dispatch native Windows BYOK profiles to a CurrentUser DPAPI backend rooted under the resolved daemon data directory. Secrets enter PowerShell only through stdin, encrypted blobs stay separate from non-secret profile metadata, and API responses remain secret-free. Add platform dispatch coverage, a Windows-only real DPAPI round-trip test, and the packaged Windows smoke path for create, resolve, response-redaction, and delete behavior. * fix(web): preserve config writes during hydration * fix(byok): persist secure credentials across entry flows * test(byok): cover secure onboarding persistence --------- Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com> Co-authored-by: lefarcen <935902669@qq.com> * test: strengthen E2E coverage and fixtures (#6150) * test: strengthen e2e coverage and fixtures * test: allow artifact route when starting conversation * test: keep e2e count assertions stable Use the shared stable-count helper for no-request and duplicate-event windows so delayed async events cannot escape the assertions. Generated-By: looper 0.11.0 (runner=fixer, agent=codex) * fix: add e2e assertion import extension Use the explicit runtime extension required by the e2e NodeNext typecheck.\n\nGenerated-By: looper 0.11.0 (runner=fixer, agent=codex) * fix: preserve design system provenance and settle e2e assertions Keep disabled design systems available to project recovery and provenance while filtering only runtime injection. Make hover and cancellation checks observe their full settled windows. Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * test(e2e): preserve unique restoration run IDs Pass the restoration fixture's run ID prefix through routeSuccessfulRuns so each mocked request receives a distinct run identity. Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * test(e2e): stabilize agent and async count fixtures Route restoration agent requests through the shared JSON and SSE fixture, capture autosave baselines after a quiet period, and observe onboarding cancellation for a bounded stable window.\n\nGenerated-By: looper 0.11.2 (runner=fixer, agent=codex) * fix: honor disabled design systems in daemon runs Filter disabled persisted project selections at prompt and analytics boundaries, and keep restoration run fixtures unique.\n\nGenerated-By: looper 0.11.2 (runner=fixer, agent=codex) * test(e2e): shorten cancellation duplicate check Generated-By: looper 0.11.2 (runner=fixer, agent=codex) * fix(daemon): continue stalled post-tool sessions (#6237) * fix(daemon): continue stalled post-tool sessions * fix(daemon): separate post-tool continuation budget Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(daemon): preserve retry telemetry budget Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(daemon): align retry failure telemetry Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(tools-pack): carry workspace build key into tarballs (#6235) * fix(amr): recover late login failures and trace auth stages (#5986) * fix(amr): recover late login failures and trace auth stages * fix(amr): preserve scoped cancel attempt IDs Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(amr): defer unsupported Vela auth stages Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(amr): narrow fallback telemetry to shipped Vela Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(amr): preserve live login after stale cancel Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(amr): preserve cancel during login startup Retain cancellation intent when a provisional cancel races the delayed canonical login response, then cancel the canonical attempt before polling can begin. Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(amr): rejoin newer login after startup cancel Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(amr): preserve cancel across web login starts Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(amr): retain cancel when status refresh fails Generated-By: looper 0.11.1 (runner=fixer, agent=codex) * fix(amr): cancel onboarding status preflight Treat cancellation before an auth attempt exists as a local preflight cancel so a delayed status response cannot start login.\n\nGenerated-By: looper 0.11.1 (runner=fixer, agent=codex) * ci: constrain Actions cache writes (#6270) * fix(tools-pack): carry workspace build key into tarballs * ci: constrain Actions cache writes * fix(daemon): auto-mint assistantMessageId when clients omit pin (#6107) * fix(daemon): auto-mint assistantMessageId when API clients omit it Web always supplies assistantMessageId. Headless/MCP/eval clients that already send conversationId but omit the pin left lastMessageId null and skipped multi-turn native session resume (missing_cursor). Mint the id server-side whenever a conversation is bound and the client did not, and seed the user message the same way the old MCP-only path did. * fix(daemon): validate conversation ownership before omit-pin seed Reorder project-ownership checks before minting assistantMessageId and seeding the user prompt so cross-project omit-pin requests cannot corrupt foreign chats. Make ChatRunCreateRequest.assistantMessageId optional and expose conversationId/assistantMessageId on McpRunCreateRequest with contract tests for the omit-pin shape. Generated-By: looper 0.11.1 (runner=fixer, agent=grok-build) * fix(daemon): reject missing conversation before omit-pin mint Return CONVERSATION_NOT_FOUND when a client supplies a stale or mistyped conversationId so omit-pin does not mint an unpersisted assistantMessageId and plugin snapshot resolve does not FK-crash with a 500. Generated-By: looper 0.11.1 (runner=fixer, agent=grok-build) * fix(daemon): seed latest turn and fallback-bound user prompts Prefer currentPrompt over full message transcripts when seeding omit-pin user turns, and still seed after conversationId fallback when the client already supplied assistantMessageId. Generated-By: looper 0.11.1 (runner=fixer, agent=grok-build) * fix(daemon): preserve attachments on omit-pin seeded user turns Copy request attachments and commentAttachments into the server-seeded user message so omit-pin/headless clients keep chips and annotation context after conversation reload. Generated-By: looper 0.11.1 (runner=fixer, agent=grok-build) * fix(daemon): treat empty currentPrompt as authoritative omit-pin seed Attachments-only ChatRequest turns send currentPrompt as '' while message is the flattened transcript. Prefer any string currentPrompt, including empty, so seeded user rows keep empty content and do not duplicate history. Generated-By: looper 0.11.1 (runner=fixer, agent=grok-build) * fix(daemon): seed turn metadata and bump project activity on omit-pin Persist sessionMode, runContext, and appliedPluginSnapshot on omit-pin seeded user turns so reload/retry keep applied context. Call updateProject after seed so listProjects reorders headless/API activity like PUT /messages. Generated-By: looper 0.11.1 (runner=fixer, agent=grok-build) * fix(daemon): require projectId for bound conversation ownership Reject POST /api/runs when conversationId is present but projectId is missing or non-string, so omit-pin cannot seed messages without owning project context. Cover both early and post-fallback ownership checks. Generated-By: looper 0.11.1 (runner=fixer, agent=grok-build) * fix(daemon): preserve slideIndex and BMP kind on omit-pin seeds Keep deck annotation slideIndex and classify .bmp as image when seeding user messages for clients that omit assistantMessageId. Generated-By: looper 0.11.1 (runner=fixer, agent=grok-build) * fix(daemon): seed empty message when omit-pin has attachments When currentPrompt is unset and message is empty, still seed the user turn if attachment metadata is present so chips/annotations survive reload. Generated-By: looper 0.11.1 (runner=fixer, agent=grok-build) * fix(daemon): seed omit-pin chat content from original request Plugin resolution may rewrite meta.message with a rendered scenario brief for the run; persist requestBody currentPrompt/message for the user turn so the internal brief is not shown as chat content. Generated-By: looper 0.11.1 (runner=fixer, agent=grok-build) * fix(web): persist browser preview viewport (#4899) * fix(daemon): honor Kiro ACP turn completion (#6268) * fix(daemon): isolate plugin-started Local Codex runs (#6273) Disable Codex plugins only for externally attributed Open Design Plugin runs so Local Codex cannot recursively enter collect_brief or Cloud login. Preserve normal Local Codex plugin loading and the existing operator-wide override. Validated with the focused runtime args suite, workspace typecheck, guard, and an isolated source smoke that produced a valid artifact without Cloud login. Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com> * fix(landing): accept signed Vela team plan leads (#6283) * fix: durably deliver enterprise leads * fix(landing): make contact sales KV canonical * feat(prompts): introduce on-demand discovery in SP v2.0 (#6223) * feat(prompts): introduce on-demand discovery in SP v2.0 * fix(prompts): prevent nested deck label overlap * fix(plugins): stabilize od-default task routing * fix: address prompt and deck audit regressions * fix(prompts): restore plan mode precedence * fix(daemon): accept all form answer headers --------- Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com> * fix(web): surface BYOK migration validation errors (#6280) * fix(web): surface BYOK migration validation errors Preserve structured daemon errors during legacy credential migration and reserve offline guidance for fetch failures. Keep legacy browser credentials until migration succeeds, and cover HTTP validation, malformed responses, and network failures. Validated with focused web tests, web typecheck, workspace guard, and workspace typecheck. * fix(web): stabilize BYOK persistence error telemetry Map secure-profile HTTP and network failures to semantic error codes before emitting settings_byok_test_result, while preserving existing fallback behavior for unrelated connection-test errors. Validated with the complete web test suite, web typecheck, workspace typecheck, guard, and git diff --check. --------- Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com> * fix(ui): improve dark-mode contrast for off-state toggles (#5825) * fix(ui): improve dark-mode contrast for off-state toggles The default off-state track uses --border-strong (#c9d0da light / #46433c dark). In dark mode #46433c is only ~5% lighter than the --bg-subtle (#252321) panel behind it, making the toggle nearly invisible when off and users unsure of the control state. Bump the off-state track to #6b6862 with a subtle inset border, and add a thin outline to the white thumb so it stays visible against the (now lighter) track. On-state already uses --text (#e8e4dc) and is left unchanged. Applies to both .toggle-row (used by speaker-notes toggle in the deck tab) and .compact-toggle (used by SurfaceOptions toggles). Hover lift gives an additional interactive affordance. Fixes #5298 * fix(ui): fix two dark-mode toggle blocking issues from review Two correctness issues called out by mrcfps: 1. System dark theme never gets the contrast fix — the default "system" theme mode removes [data-theme] and falls back to @media prefers-color-scheme. Added a parallel block scoped to html:not([data-theme]) inside @media (prefers-color-scheme: dark). 2. Hover override wins over on-state — .compact-toggle:hover and .toggle-row:hover have higher specificity than .on variants, so hovering an ON toggle dropped its track from bright var(--text) to #75726c. Changed to :not(.on):hover so the hover lift only applies when off, leaving the on-state always bright. Both applied to both selector paths (explicit data-theme and system dark). * fix(web): keep Azure deployment names editable (#6034) * chore(plugin-previews): refresh baked preview manifest (#6293) Co-authored-by: open-design-bot <bot@open-design.ai> * fix(byok): withdraw Windows DPAPI backend (#6308) * fix(byok): withdraw Windows DPAPI backend * fix(byok): clean up retired Windows secret blobs Generated-By: looper 0.11.2 (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> * fix(web): dismiss stale todo after continuation starts (#6307) * fix(web): preserve shared project update timestamps * fix(web): reconcile shared timestamps on home * fix(web): preserve workspace scope in preview assets * fix(collab): avoid unscoped shared cover requests * fix(web): avoid double-wrapping preview assets * fix(web): preserve first prompt across project refresh * test(web): target the active shared project card * test(web): keep empty BYOK profile type-safe * test(e2e): require explicit workspace scope * fix(web): finish scoped preview hydration * test(e2e): align manual edit with current inspector * fix(web): reconcile files after event stream readiness * fix(web): keep local project creation workspace-independent * fix(web): preserve scoped auth recovery state * test(e2e): assert explicit Personal workspace scope * test(e2e): preserve visual AMR account fixture * test(web): await scoped cover source * UI polish batch: cloud sign-in, onboarding, composer menu (#6281) * UI polish batch: cloud sign-in, onboarding, composer menu Sign-in surfaces (rail callout, balance-gate dialog, onboarding) had drifted from the visual system and lost some redundant chrome; this batch tightens them up alongside a couple of composer/design-files reorganizations that were sitting in the same working tree: - Rail's signed-out callout: reorder copy above the login pill, give the pill an icon + accent-green label, restore the Escape hatch the pill had before it lost its close affordance. - AmrBalanceDialog (insufficient-balance / signed-out gate): add a full-bleed art banner above the copy, drop the now-redundant icon badge, tighten spacing/shadows to match. - Onboarding cloud landing: switch from a single centered column to a two-column layout (form pane + full-bleed art panel), move the language switcher into the footer, swap the local-CLI/BYOK links for icon Buttons, and add a dismiss control to the activation-retry hint. - Composer "+" menu: fold 插件/设计百宝箱 back in as hover-expand submenu rows instead of standalone quick pills above the input. - Design files panel: move new-document/upload actions out of the always-visible toolbar into the empty-state actions only. - Message center: drop the redundant header close button (backdrop click and Escape still dismiss it) and restyle the list from bordered cards to a divider-separated list. - New `key` / `robot` / `translate` / `arrow-right` icons; language menu switches from the `languages` glyph to `translate`. - Tab launcher popover reverts to the glass material; language dropdown gets a max-height + scroll so long lists don't blow out the popover. Rebased the composer-quick-pill removal onto this branch's own accessibility work on those pills (opener-based focus return via `ComposerStandalonePanel`) rather than reverting it — the "next step" card still drives the same standalone-panel API, just without a pill to hand focus back to. Also updated/removed the tests that pinned the now-removed surfaces (quick-pill popup contract, message-center close button, onboarding top bar, design-files toolbar upload trigger) so none of this lands with a newly-red suite. * perf(web): optimize onboarding cloud artwork * fix(web): invalidate project file reads after mutations * fix(web): disable readonly project starter mutations * fix(web): preserve focus for standalone composer panels * test(e2e): require explicit workspace scope * fix(web): invalidate file reads on project events * test(e2e): seed explicit settings workspace * test(e2e): align manual edit with current inspector * fix(web): refresh deployments when share opens * test(e2e): follow composer design system entry * fix(web): keep local project creation workspace-independent * fix(web): preserve scoped auth recovery state * test(e2e): follow current entry settings flows * fix(web): preserve AMR retry across settings * test(e2e): model explicit personal workspace recovery * test(e2e): stabilize AMR logout settings recovery * fix(projects): return workspace scope on create --------- Co-authored-by: lefarcen <935902669@qq.com> * test(e2e): lock design system team partition * fix(workspace): stabilize scoped project lifecycle * test(e2e): stabilize retained workspace transitions * fix(workspace): retain exact scope through transient outages * test(workspace): lock outage identity boundaries --------- Co-authored-by: Ray Xi <2667192167@qq.com> Co-authored-by: PerishFire <39043006+PerishCode@users.noreply.github.com> Co-authored-by: Looper <looper@noreply.github.com> Co-authored-by: Joey-nexu <joeylee12629@gmail.com> Co-authored-by: Joey <236967869+joeylee12629-star@users.noreply.github.com> Co-authored-by: bestthanapon <thanapon.suwannasuk@gmail.com> Co-authored-by: open-design-crew[bot] <299007234+open-design-crew[bot]@users.noreply.github.com> Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com> Co-authored-by: Amy <58060647+AmyShang-alt@users.noreply.github.com> Co-authored-by: Marc Chan <mrc@powerformer.com> Co-authored-by: _HDCoder <2728073932@qq.com> Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com> Co-authored-by: Nicholas-Xiong <2482929840@qq.com> Co-authored-by: mehmet turac <mehmetturac@gmail.com> Co-authored-by: open-design-release-bot[bot] <295937643+open-design-release-bot[bot]@users.noreply.github.com> Co-authored-by: open-design-bot <bot@open-design.ai> Co-authored-by: CHENGLONG WANG <honam884844@gmail.com>
1 parent aa38aaa commit 05275e8

359 files changed

Lines changed: 34341 additions & 5652 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/setup-workspace/action.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ inputs:
1414
description: JSON array of labels selected for this job's runs-on value
1515
required: false
1616
default: '[]'
17+
save-pnpm-cache:
18+
description: Save a missing pnpm cache after install; trusted main seed jobs only
19+
required: false
20+
default: 'false'
1721

1822
runs:
1923
using: composite
@@ -62,13 +66,21 @@ runs:
6266
shell: bash
6367
run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
6468

65-
- name: Cache pnpm store
69+
- name: Restore pnpm store
70+
id: pnpm-cache-restore
6671
if: ${{ steps.persistent-pnpm-store.outputs.enabled != 'true' }}
67-
uses: actions/cache@v5.0.5
72+
uses: actions/cache/restore@v5
6873
with:
6974
path: ${{ steps.pnpm-store.outputs.path }}
7075
key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
7176

7277
- name: Install dependencies
7378
shell: bash
7479
run: pnpm install --frozen-lockfile
80+
81+
- name: Save pnpm store
82+
if: ${{ inputs.save-pnpm-cache == 'true' && steps.persistent-pnpm-store.outputs.enabled != 'true' && steps.pnpm-cache-restore.outputs.cache-hit != 'true' && github.ref == 'refs/heads/main' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') }}
83+
uses: actions/cache/save@v5
84+
with:
85+
path: ${{ steps.pnpm-store.outputs.path }}
86+
key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: cache-maintenance
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- pnpm-lock.yaml
8+
- .github/actions/setup-workspace/action.yml
9+
- .github/workflows/cache-maintenance.yml
10+
pull_request_target:
11+
types: [closed]
12+
workflow_dispatch:
13+
14+
permissions:
15+
actions: write
16+
contents: read
17+
18+
jobs:
19+
seed-pnpm-windows:
20+
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main')
21+
runs-on: windows-latest
22+
timeout-minutes: 15
23+
steps:
24+
- name: Checkout main
25+
uses: actions/checkout@v6.0.2
26+
27+
- name: Seed Windows pnpm cache
28+
uses: ./.github/actions/setup-workspace
29+
with:
30+
save-pnpm-cache: 'true'
31+
32+
clean-closed-pr-buildkit:
33+
if: github.event_name == 'pull_request_target' && github.repository == 'nexu-io/open-design'
34+
runs-on: ubuntu-24.04
35+
timeout-minutes: 5
36+
steps:
37+
- name: Delete closed PR BuildKit caches
38+
env:
39+
CACHE_REF: refs/pull/${{ github.event.pull_request.number }}/merge
40+
GH_TOKEN: ${{ github.token }}
41+
run: |
42+
set -euo pipefail
43+
44+
cache_rows="$(
45+
gh cache list \
46+
--repo "$GITHUB_REPOSITORY" \
47+
--ref "$CACHE_REF" \
48+
--limit 10000 \
49+
--json id,key,sizeInBytes \
50+
--jq '.[] | select((.key | startswith("buildkit-blob-")) or (.key | startswith("index-buildkit-"))) | [.id, .key, .sizeInBytes] | @tsv'
51+
)"
52+
53+
if [ -z "$cache_rows" ]; then
54+
echo "No closed-PR BuildKit caches found for $CACHE_REF"
55+
exit 0
56+
fi
57+
58+
count=0
59+
bytes=0
60+
while IFS=$'\t' read -r cache_id cache_key cache_size; do
61+
[ -n "$cache_id" ] || continue
62+
echo "Deleting cache id=$cache_id key=$cache_key bytes=$cache_size ref=$CACHE_REF"
63+
gh cache delete "$cache_id" --repo "$GITHUB_REPOSITORY"
64+
count=$((count + 1))
65+
bytes=$((bytes + cache_size))
66+
done <<< "$cache_rows"
67+
68+
echo "Deleted $count closed-PR BuildKit caches ($bytes bytes) for $CACHE_REF"

.github/workflows/landing-page-ci.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ jobs:
8181
- name: Setup workspace
8282
uses: ./.github/actions/setup-workspace
8383

84-
- name: Cache generated previews
84+
- name: Restore generated previews
8585
id: previews-cache
86-
uses: actions/cache@v5.0.5
86+
uses: actions/cache/restore@v5
8787
with:
8888
path: apps/landing-page/public/previews
8989
key: landing-page-previews-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml', 'package.json', 'apps/landing-page/package.json', 'apps/landing-page/scripts/generate-previews.ts', 'apps/landing-page/scripts/fallback-preview-card.ts', 'skills/**', 'design-templates/**', 'templates/live-artifacts/**', 'plugins/_official/**') }}
@@ -125,6 +125,13 @@ jobs:
125125
OD_LANDING_NOINDEX: '1'
126126
run: pnpm --filter @open-design/landing-page build:static
127127

128+
- name: Save generated previews
129+
if: ${{ steps.previews-cache.outputs.cache-hit != 'true' && github.ref == 'refs/heads/main' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
130+
uses: actions/cache/save@v5
131+
with:
132+
path: apps/landing-page/public/previews
133+
key: landing-page-previews-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml', 'package.json', 'apps/landing-page/package.json', 'apps/landing-page/scripts/generate-previews.ts', 'apps/landing-page/scripts/fallback-preview-card.ts', 'skills/**', 'design-templates/**', 'templates/live-artifacts/**', 'plugins/_official/**') }}
134+
128135
- name: Lint changed blog SEO
129136
# The build above sets OD_LANDING_NOINDEX=1, so every rendered page in
130137
# `out/` carries `noindex`. Pass the same flag through so the SEO linter

.github/workflows/release-beta-s.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,8 @@ jobs:
754754
-BuildJsonPath "C:\.tmp\runner\od-beta\win_x64\build\build.json" `
755755
-IndexPath "C:\.tmp\runner\od-beta\win_x64\build\index.json" `
756756
-ReportRoot "C:\.tmp\runner\od-beta\win_x64\release-report\win_x64" `
757-
-OutputsPath "C:\.tmp\runner\od-beta\win_x64\build\outputs.json"
757+
-OutputsPath "C:\.tmp\runner\od-beta\win_x64\build\outputs.json" `
758+
-RequireVelaCli
758759
759760
- name: Write win_x64 release report
760761
if: ${{ always() }}

.github/workflows/release-beta.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,7 @@ jobs:
651651
--app-version "$update_version" \
652652
--mac-compression normal \
653653
--to dmg \
654+
--require-vela-cli \
654655
--json)"
655656
printf '%s\n' "$update_output" > "$update_build_json_path"
656657
{
@@ -718,7 +719,7 @@ jobs:
718719
run: |
719720
set -euo pipefail
720721
prefix="${{ steps.mac_arm64_tools_pack_cache_key.outputs.prefix }}"
721-
keep=3
722+
keep=1
722723
cache_ids="$(gh cache list --key "$prefix" --sort created_at --order desc --limit 100 --json id,key,createdAt --jq ".[$keep:] | .[].id")"
723724
count=0
724725
while IFS= read -r cache_id; do
@@ -866,6 +867,7 @@ jobs:
866867
--mac-compression normal
867868
--to "${{ inputs.mac_x64_target }}"
868869
--json
870+
--require-vela-cli
869871
)
870872
case "${{ inputs.mac_x64_sign_mode }}" in
871873
no) ;;
@@ -899,6 +901,7 @@ jobs:
899901
--mac-compression normal
900902
--to "${{ inputs.mac_x64_target }}"
901903
--json
904+
--require-vela-cli
902905
)
903906
case "${{ inputs.mac_x64_sign_mode }}" in
904907
no) ;;
@@ -988,7 +991,7 @@ jobs:
988991
run: |
989992
set -euo pipefail
990993
prefix="${{ steps.mac_x64_tools_pack_cache_key.outputs.prefix }}"
991-
keep=3
994+
keep=1
992995
cache_ids="$(gh cache list --key "$prefix" --sort created_at --order desc --limit 100 --json id,key,createdAt --jq ".[$keep:] | .[].id")"
993996
count=0
994997
while IFS= read -r cache_id; do
@@ -1134,7 +1137,7 @@ jobs:
11341137
$ErrorActionPreference = "Stop"
11351138
New-Item -ItemType Directory -Force -Path "${{ runner.temp }}\release-build\win_x64" | Out-Null
11361139
pnpm.cmd exec tools-pack win cleanup --dir "${{ runner.temp }}\tools-pack" --namespace release-beta-win --json
1137-
$buildArgs = @("exec", "tools-pack", "win", "build", "--dir", "${{ runner.temp }}\tools-pack", "--cache-dir", "${{ runner.temp }}\tools-pack-cache", "--namespace", "release-beta-win", "--portable", "--app-version", "${{ needs.metadata.outputs.beta_version }}", "--to", "${{ inputs.win_x64_target }}", "--json")
1140+
$buildArgs = @("exec", "tools-pack", "win", "build", "--dir", "${{ runner.temp }}\tools-pack", "--cache-dir", "${{ runner.temp }}\tools-pack-cache", "--namespace", "release-beta-win", "--portable", "--app-version", "${{ needs.metadata.outputs.beta_version }}", "--to", "${{ inputs.win_x64_target }}", "--require-vela-cli", "--json")
11381141
if ("${{ inputs.win_x64_sign_mode }}" -eq "on") { $buildArgs += "--signed" }
11391142
$buildOutput = pnpm.cmd @buildArgs
11401143
if ($LASTEXITCODE -ne 0) { throw "tools-pack win build failed with exit code $LASTEXITCODE" }
@@ -1153,7 +1156,7 @@ jobs:
11531156
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "${{ runner.temp }}\tools-pack-cache"
11541157
New-Item -ItemType Directory -Force -Path "${{ runner.temp }}\release-build\win_x64" | Out-Null
11551158
pnpm.cmd exec tools-pack win cleanup --dir "${{ runner.temp }}\tools-pack" --namespace release-beta-win --json
1156-
$buildArgs = @("exec", "tools-pack", "win", "build", "--dir", "${{ runner.temp }}\tools-pack", "--cache-dir", "${{ runner.temp }}\tools-pack-cache", "--namespace", "release-beta-win", "--portable", "--app-version", "${{ needs.metadata.outputs.beta_version }}", "--to", "${{ inputs.win_x64_target }}", "--json")
1159+
$buildArgs = @("exec", "tools-pack", "win", "build", "--dir", "${{ runner.temp }}\tools-pack", "--cache-dir", "${{ runner.temp }}\tools-pack-cache", "--namespace", "release-beta-win", "--portable", "--app-version", "${{ needs.metadata.outputs.beta_version }}", "--to", "${{ inputs.win_x64_target }}", "--require-vela-cli", "--json")
11571160
if ("${{ inputs.win_x64_sign_mode }}" -eq "on") { $buildArgs += "--signed" }
11581161
$buildOutput = pnpm.cmd @buildArgs
11591162
if ($LASTEXITCODE -ne 0) { throw "tools-pack win fallback build failed with exit code $LASTEXITCODE" }
@@ -1220,7 +1223,7 @@ jobs:
12201223
$match = [regex]::Match("${{ needs.metadata.outputs.beta_version }}", "^(?<base>\d+\.\d+\.\d+)-beta\.(?<number>\d+)$")
12211224
if (-not $match.Success) { throw "full Windows smoke requires a counted beta version; got ${{ needs.metadata.outputs.beta_version }}" }
12221225
$updateVersion = "{0}-beta.{1}" -f $match.Groups["base"].Value, ([int]$match.Groups["number"].Value + 1)
1223-
$buildArgs = @("exec", "tools-pack", "win", "build", "--dir", "${{ runner.temp }}\release-work\win_x64\tools-pack-update-fixture", "--cache-dir", "${{ runner.temp }}\tools-pack-cache", "--namespace", "release-beta-win", "--app-version", $updateVersion, "--to", "nsis", "--json")
1226+
$buildArgs = @("exec", "tools-pack", "win", "build", "--dir", "${{ runner.temp }}\release-work\win_x64\tools-pack-update-fixture", "--cache-dir", "${{ runner.temp }}\tools-pack-cache", "--namespace", "release-beta-win", "--app-version", $updateVersion, "--to", "nsis", "--require-vela-cli", "--json")
12241227
if ("${{ inputs.win_x64_sign_mode }}" -eq "on") { $buildArgs += "--signed" }
12251228
$updateOutput = pnpm.cmd @buildArgs
12261229
if ($LASTEXITCODE -ne 0) { throw "tools-pack win update fixture failed with exit code $LASTEXITCODE" }
@@ -1287,7 +1290,7 @@ jobs:
12871290
GH_TOKEN: ${{ github.token }}
12881291
run: |
12891292
$prefix = "${{ steps.win_tools_pack_cache_key.outputs.prefix }}"
1290-
$keep = 3
1293+
$keep = 1
12911294
$caches = @(gh cache list --key $prefix --sort created_at --order desc --limit 100 --json id,key,createdAt | ConvertFrom-Json)
12921295
$stale = @($caches | Select-Object -Skip $keep)
12931296
foreach ($cache in $stale) { gh cache delete $cache.id }

.github/workflows/release-prerelease.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ jobs:
538538
run: |
539539
set -euo pipefail
540540
prefix="${{ steps.mac_arm64_tools_pack_cache_key.outputs.prefix }}"
541-
keep=3
541+
keep=1
542542
cache_ids="$(gh cache list --key "$prefix" --sort created_at --order desc --limit 100 --json id,key,createdAt --jq ".[$keep:] | .[].id")"
543543
count=0
544544
while IFS= read -r cache_id; do
@@ -805,7 +805,7 @@ jobs:
805805
run: |
806806
set -euo pipefail
807807
prefix="${{ steps.mac_x64_tools_pack_cache_key.outputs.prefix }}"
808-
keep=3
808+
keep=1
809809
cache_ids="$(gh cache list --key "$prefix" --sort created_at --order desc --limit 100 --json id,key,createdAt --jq ".[$keep:] | .[].id")"
810810
count=0
811811
while IFS= read -r cache_id; do
@@ -1051,7 +1051,7 @@ jobs:
10511051
GH_TOKEN: ${{ github.token }}
10521052
run: |
10531053
$prefix = "${{ steps.win_tools_pack_cache_key.outputs.prefix }}"
1054-
$keep = 3
1054+
$keep = 1
10551055
$caches = @(gh cache list --key $prefix --sort created_at --order desc --limit 100 --json id,key,createdAt | ConvertFrom-Json)
10561056
$stale = @($caches | Select-Object -Skip $keep)
10571057
foreach ($cache in $stale) {

.github/workflows/release-preview.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ jobs:
530530
run: |
531531
set -euo pipefail
532532
prefix="${{ steps.mac_arm64_tools_pack_cache_key.outputs.prefix }}"
533-
keep=3
533+
keep=1
534534
cache_ids="$(gh cache list --key "$prefix" --sort created_at --order desc --limit 100 --json id,key,createdAt --jq ".[$keep:] | .[].id")"
535535
count=0
536536
while IFS= read -r cache_id; do
@@ -771,7 +771,7 @@ jobs:
771771
run: |
772772
set -euo pipefail
773773
prefix="${{ steps.mac_x64_tools_pack_cache_key.outputs.prefix }}"
774-
keep=3
774+
keep=1
775775
cache_ids="$(gh cache list --key "$prefix" --sort created_at --order desc --limit 100 --json id,key,createdAt --jq ".[$keep:] | .[].id")"
776776
count=0
777777
while IFS= read -r cache_id; do
@@ -1033,7 +1033,7 @@ jobs:
10331033
GH_TOKEN: ${{ github.token }}
10341034
run: |
10351035
$prefix = "${{ steps.win_tools_pack_cache_key.outputs.prefix }}"
1036-
$keep = 3
1036+
$keep = 1
10371037
$caches = @(gh cache list --key $prefix --sort created_at --order desc --limit 100 --json id,key,createdAt | ConvertFrom-Json)
10381038
$stale = @($caches | Select-Object -Skip $keep)
10391039
foreach ($cache in $stale) {

.github/workflows/release-stable.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ jobs:
862862
GH_TOKEN: ${{ github.token }}
863863
run: |
864864
$prefix = "${{ steps.win_tools_pack_cache_key.outputs.prefix }}"
865-
$keep = 3
865+
$keep = 1
866866
$caches = @(gh cache list --key $prefix --sort created_at --order desc --limit 100 --json id,key,createdAt | ConvertFrom-Json)
867867
$stale = @($caches | Select-Object -Skip $keep)
868868
foreach ($cache in $stale) {

.github/workflows/visual-baseline.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ jobs:
2727

2828
- name: Setup workspace
2929
uses: ./.github/actions/setup-workspace
30+
with:
31+
save-pnpm-cache: 'true'
3032

3133
- name: Setup Playwright
3234
uses: ./.github/actions/setup-playwright

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This file is the single source of truth for agents entering this repository. Rea
1111
- References and current plans: `docs/references.md`, `docs/code-review-guidelines.md`, `specs/current/maintainability-roadmap.md`, `specs/current/ci.md` (CI scope confidence methodology — required before changing confidence or guard fields in `scripts/scopes.ts`).
1212
- Directory-level agent guidance: `.github/AGENTS.md`, `apps/AGENTS.md`, `packages/AGENTS.md`, `tools/AGENTS.md`, `e2e/AGENTS.md`.
1313
- Packaged auto-update architecture and high-confidence local harness: read `tools/pack/AGENTS.md` section "Packaged auto-update architecture and harness" before touching packaged updater code, release-channel identity, installer behavior, or updater UI.
14+
- Packaged build cache contract: `tools/pack/CACHE.md` (determinant rules, materialization-time parameters, confidence grading — required before changing any build-cache node key).
1415

1516
## Workspace directories
1617

0 commit comments

Comments
 (0)