mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
eabed76a4cbc6ca6330ba11b9c15e98395e72116
2025
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
eabed76a4c |
docs: plan design system 2.0 backfill (#3776)
Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local> |
||
|
|
47119a6733 |
fix(web): make all 18 locales fully localized (UI + built-in content) (#3755)
* fix(web): make all 18 locales fully localized for UI + built-in content
The client supported many languages but coverage was incoherent: some
modules rendered English even when a non-English locale was selected, and
the locale setting didn't fully take effect. Two root causes:
- Most locale dicts relied on a `...en` spread, so any missing key silently
fell back to English. Several modules (Automations/TasksView, Design
Systems tab, parts of Settings/Integrations) were also hardcoded English
and never went through `t()`.
- Built-in content (skill / design-system / prompt-template copy) only had
de/ru/fr translations; every other locale showed English.
Changes:
- Translate every UI key in all 18 locales and drop the `...en` spread so
each locale is fully explicit (matches the existing zh-CN parity lock);
add a ja parity-lock test.
- Wire the remaining hardcoded modules through `t()` (TasksView,
DesignSystemsTab, McpClientSection, SettingsDialog) and route plugin
title/description through the existing `title_i18n`/`description_i18n`
localization layer in every render path.
- Add per-locale built-in content tables (content.<locale>.ts) for the
remaining 11 languages and register them in content.ts; zh-TW reuses
zh-CN content via a `zh` fallback in getLocalizedContent.
- Keep brand/proper nouns (Open Design, AMR, MCP, React, Figma, GitHub,
Bash/Glob/Grep, etc.) and placeholders verbatim across all languages.
- Standardize the Chinese term for "live artifact" to 实时看板 / 即時看板.
Validation: pnpm --filter @open-design/web typecheck, the i18n suite
(key/placeholder alignment across all 18 locales + zh-CN/ja parity locks),
pnpm guard, and the full web test suite (2997 passing) all green.
* fix(web): keep "Integrity" plugin-details label verbatim English in all locales
The plugin-details "Integrity" field is a technical proper noun and should
not be translated; it had been localized (完整性 / Integrität / 整合性 / …).
Restore it to "Integrity" in every locale and add a brand/proper-noun lock
test so a future translation pass can't re-localize it.
* fix(web): collapse double-escaped unicode escapes in locale dicts after merge
* fix(web): register Italian built-in-content bundle + lock locale coverage
PR review caught that Italian had UI-dictionary localization but no built-in
content bundle: LOCALIZED_CONTENT registered de…th but not `it`, so
getLocalizedContent('it') returned undefined and skill / design-system /
prompt-template copy still rendered English for Italian users.
- Add content.it.ts (skills, design systems, prompt templates) and register
it in LOCALIZED_CONTENT.
- Export hasLocalizedContent(locale) and add a test asserting every supported
non-English LOCALES entry resolves a content bundle (own bundle or an
intentional fallback such as zh-TW -> zh-CN), so a future locale can't
silently ship English built-in content again.
* fix(web): localize automation template labels in NewAutomationModal
User-visible template labels in the trigger button and template popover
now prefer the localized title over the English defaultName, so the
Automations create flow no longer leaks English (e.g. "Memory refresh")
for non-English locales. defaultName remains the intentional English
persisted routine name.
Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code)
* fix(web): localize home prompt examples for all 18 locales
The home composer's clickable example prompts only had zh/ja/en branches;
every other locale (ko, de, fr, ...) rendered English. Move the examples
into a per-locale data table keyed by Locale so all supported locales
resolve native example text, and add a coverage test that fails when a
non-English locale falls back to the English example strings.
Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code)
---------
Co-authored-by: qiongyu1999 <2694684348@qq.com>
|
||
|
|
1b9c4dcb0f |
feat(landing-page): strengthen /html-video keywords (product name + programmatic video) (#3770)
- SEO titles (19 locales): lead with the product name "html-video", then the two core keywords "HTML to video" + "programmatic video for coding agents", keep "Hyperframes". Fixes Google truncating the product name off the front of the old "HTML to Video · Hyperframes · Open Source" title. - Meta description (en/zh): inject "programmatic video for coding agents" as the category anchor in the first sentence. - H1 heading (en/zh): "HTML becomes video" → "HTML to video" so the H1 carries the exact core search phrase. - Hyperframes keyword retained throughout (43 mentions, incl. every title). Co-authored-by: 522700967-wq <joey@joeydeMacBook-Air-4.local> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
6a2a02fdf6 | feat: send newsletter welcome emails (#3761) | ||
|
|
d1ab64a7af |
fix(daemon): reject live-artifact read_json refresh sources with no file to read (#3754)
* fix(daemon): reject live-artifact read_json refresh sources with no file to read A live artifact whose document.sourceJson registers project_files.read_json without a path/file/name passes schema validation today, persists, and then fails every manual Refresh forever with "project_files.read_json requires input.path" (LAST REFRESHED stays Never). validateSource only required a toolName for daemon_tool sources and never checked tool-specific required input, so the malformed source was accepted instead of rejecting registration and letting the agent's documented fallback build a static artifact. Validate the resolved daemon refresh tool's required input at registration: project_files.read_json (explicit daemon_tool, or the local_file default that maps to it) must name a file via path/file/name. The resolution mirrors executeLocalDaemonRefreshSource so schema and runtime agree. * fix(daemon): validate read_json name selector for traversal at creation * fix(daemon): mirror selectJsonPath alias precedence and type rules at creation * fix(daemon): match validateProjectPath dot/reserved/.json rules for read_json selector * fix(daemon): case-sensitive .json extension check to match refresh runtime --------- Co-authored-by: audit <a@b.c> |
||
|
|
8dcf4ff9f4 |
fix(plugins): route picked plugins through their own pipeline and trust local installs (#3743)
* fix(plugins): route picked plugins through their own pipeline and trust local installs
Two related defects prevented an installed plugin from actually driving a
generation when the user picked it:
- HomeView "Use" attached the plugin as background context only (via
requestPluginContextUse), so submit fell back to the hidden od-default
scenario and the plugin's pipeline + SKILL.md/asset context never
applied. Route the picked plugin as the active driver instead
(usePlugin), preserving the use-with-query textarea seed behavior.
- resolvePluginFolder hard-coded trust='restricted' for every install,
ignoring sourceKind. A local scenario plugin could then never obtain the
pipeline:* capability it needs to run its own pipeline. Honor the
documented source-kind policy (local => trusted) via defaultTrustForRecord
and resolveCapabilitiesGranted.
* fix(plugins): preserve draft on use-with-query and update trust/route test coverage
Addresses review feedback on the plugin-use routing + local-trust change:
- use-with-query no longer discards the user's existing draft. routePluginUse
now APPENDS the rendered plugin query to the current prompt (matching the
legacy context-use semantics) before routing the plugin as the active
driver, instead of letting usePlugin replace the whole prompt.
- Update daemon trust coverage for the local-default flip: the installer
test asserts a local install is trusted by default, and the headless
pipeline fixture drops its ephemeral grantCaps to exercise the
stored/default grant path (local trusted => pipeline:* already granted).
- Update web + e2e tests for the new active-driver behavior: picking a
plugin now routes it as the run driver (its own pipeline) rather than
attaching it as background context. Drops two context-only `Use` regression
tests whose scenario no longer exists under active-driver routing.
* test(plugins): stabilize direct-Use e2e timing and cover plugin-use submit
The P0 "direct Use routes the plugin as the active driver" browser test could
race the in-flight apply: it submitted before `/api/plugins/:id/apply`
resolved, so the active snapshot was not yet bound and the create-project
request never fired (waitForRequest timed out). Wait for the apply response
and an enabled submit button before clicking.
Also extend the HomeView prefill unit test to drive the full plain-`use` →
type a draft → submit flow and assert the routed plugin (not od-default)
drives the run, so this path is covered at the unit layer too.
* test(e2e): assert plugin-use submit via the project request, not a run POST
The two P0 plugin-use flows ("direct Use" and "Use with query carries the
prompt") still waited on POST /api/runs after submit. Under active-driver
routing the picked plugin is a scenario pipeline whose run is fired from the
bound snapshot when the project page mounts — Home no longer posts a separate
/api/runs — so waitForRequest(isCreateRunRequest) timed out even though the
create-project request (which pins pluginId) succeeded. Assert on the project
request + navigation instead, and drop the now-unused message-listing helper.
* fix(plugins): preserve query template on use-with-query so edits flow into inputs
Routing use-with-query passed the rendered prompt as nextPrompt, which made
usePlugin null out active.queryTemplate (nextPrompt-set branch). handlePromptChange
then stopped extracting edited {{...}} values back into active.inputs, so a user
who edited the hydrated query before submit would send the stale default inputs
and the applied snapshot would disagree with the visible prompt.
routePluginUse now passes an explicit queryTemplate aligned with the combined
prompt (untouched draft prefix + raw placeholder-bearing plugin query), so
extraction keeps working. Adds a prefill test that edits a hydrated
use-with-query prompt and asserts the edited value reaches the submitted
pluginInputs.
Also stabilizes the two P0 plugin-use e2e flows: they asserted live navigation
after submit, but the real e2e daemon has no mocked plugin installed so the
live create-project call cannot complete. Assert on the create-project request
payload (which pins the routed pluginId) instead, and drop the now-unused
project-context/message helpers.
* fix(plugins): extract use-with-query inputs independent of the mutable draft prefix
The previous fix baked the user's draft prefix into the query template, so
extractPluginInputsFromPrompt anchored the whole prompt and editing that prefix
made extraction return null — a later placeholder edit then never reached
pluginInputs and the snapshot refreshed from stale defaults.
The template now carries the plugin query segment only. usePlugin/active gain a
queryTemplateAllowsPrefix flag (set by the use-with-query route when a draft
prefix exists) that tells extractPluginInputsFromPrompt to match the query as a
suffix after any leading text. Editing the draft prefix no longer breaks
placeholder extraction.
Adds a regression: existing draft -> use-with-query -> edit both the draft
prefix and a hydrated placeholder -> submit asserts pluginInputs reflects the
edited placeholder.
---------
Co-authored-by: qiongyu1999 <2694684348@qq.com>
|
||
|
|
885ac06043 |
[codex] fix newsletter subscription UI (#3760)
* fix: polish newsletter subscription UI * fix(web): lock onboarding navigation during newsletter submit Generated-By: looper 0.9.4 (runner=fixer, agent=codex) |
||
|
|
817e7de387 |
Fix Windows app font fallback (#3655)
Generated-By: looper 0.9.4 (runner=worker, agent=codex) |
||
|
|
27471da011 |
fix(web): let new projects choose target folder (#3676)
Generated-By: looper 0.9.4 (runner=worker, agent=codex) |
||
|
|
b12c055a89 |
feat(web): remove "Open existing project" card from Home view (#3749)
* feat(web): remove "Open existing project" card from Home view Drop the home-page "Open existing project" / choose-a-folder CTA (HomeExistingProjectAction) that sat between the hero and the recent projects strip. The same folder-import capability is still reachable from the New Project panel, so this only removes the redundant home surface, not the feature itself. Removes the component, its useOpenFolderImport wiring on Home, the unused onImportFolder/onImportFolderResponse props threaded into HomeView, the home.openExistingProject / openExistingProjectOpening / chooseFolderSubtitle i18n keys across all locales, the .home-existing-project CSS, and the dedicated folder-import test. * refactor(web): drop now-unused Icon/Toast imports in HomeView --------- Co-authored-by: audit <a@b.c> |
||
|
|
d4c6bbd9e1 |
Add Spark self-hosted CI runner workflows (#3750)
* Probe Spark runner CI path * Add Spark runner setup validation * Harden Spark setup install probe * Add Spark runner policy checks * Add Spark runner unit checks * Add Spark runner typecheck path * Add Spark runner daemon checks * Isolate Codex runtime tests from host PATH * Isolate headless plugin prompt capture * Fix headless prompt capture script syntax * Add Spark runner web checks * Add Spark runner build checks * Add Spark runner browser checks * Compose Spark runner CI gate * Harden Spark runner gate diagnostics * Shard Spark runner daemon checks * Add daemon parallel CI experiment * Install dependencies for daemon parallel CI * Use Vitest parallelism for daemon runner checks * Implement manual hosted backup CI gate * Prepare pnpm for hosted CI backup * Use dynamic matrix for hosted CI modes * Emit searchable CI timing lines * Fix hosted CI Node version * Optimize CI runner scheduling * Stabilize runner CI all topology * Rebalance runner CI all lanes * Harden ci-gate run identity checks Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * Fix CI runner cold-start pnpm bootstrap Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * Require both ci-gate runs for both-success Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * Fix CI summary pnpm metadata timing Generated-By: looper 0.9.5 (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
bb19ef0df5 |
feat(workspace): remove the New Side Chat launcher entry (#3758)
The '+' tab launcher in the file workspace offered a 'New Side Chat' action that spun up a conversation and opened it as a chat:<id> tab in the file area. That placement put a conversation surface inside the file workspace, inconsistent with the sidebar conversation chrome, so the entry is removed. Drops the new-side-chat LauncherAction and its createSideChat wiring (LauncherContext, FileWorkspace prop, ProjectView handleCreateSideChat) plus the now-unused workspace.newSideChat / newSideChatDescription i18n keys across all locales. Restoration rendering for already-persisted chat: tabs and the side-chat context kind are intentionally kept so existing open tabs do not break. Co-authored-by: audit <a@b.c> |
||
|
|
2db4c1b23b | Reset home scroll on plugin use (#3757) | ||
|
|
addf34bbf6 | fix web preview image export (#3752) | ||
|
|
e1e8c6cac8 | Raise viewer share menu layer (#3751) | ||
|
|
4c85cacdf6 |
fix(web): restore in-app browser / Reference Board styles dropped by #3358 (#3748)
* fix(web): restore in-app browser / Reference Board styles dropped by #3358
PR #3358 ("redesign Design Files panel", commit
|
||
|
|
0582749df5 |
Refactor beta release workflows (#3741)
* Refactor beta release workflows * Fix beta workflow runner bootstrap * Fix self-hosted beta release bootstrap * Use pnpm cmd in self-hosted beta Windows bootstrap * Pass mac notarization profile to beta builds * Allow direct Apple notarization credentials * Fix beta Windows asset handoff * Skip Windows report zip in beta publish * Fix beta metadata workflow cleanup * Stabilize self-hosted beta metadata checkout * Retry self-hosted beta manifest downloads * Use release storage for self-hosted manifests * Isolate self-hosted beta metadata scripts * Add Windows pack phase diagnostics * Disable beta self-hosted Windows security checks * Remove beta Windows security preflight * Add release-beta-s version reservation * Fix beta daily workflow caller inputs Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * Guard beta latest publish and build-only runs Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * Tighten beta latest publish guards * Fix beta publish artifact suffix handling Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * Fix beta metadata suffix and Windows publish target handling * Fix self-hosted beta release ref and publish guards Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * Fix beta release commit identity wiring Generated-By: looper 0.9.5 (runner=fixer, agent=codex) * Fix hosted beta checkout pinning Generated-By: looper 0.9.5 (runner=fixer, agent=codex) --------- Co-authored-by: Looper <looper@noreply.github.com> |
||
|
|
9def22bc95 |
fix(web): keep live-artifact tab badges and close button from overflowing onto neighbouring tabs (#3745)
Co-authored-by: audit <a@b.c> |
||
|
|
4f4314bbc3 | Fix chat run timer and question drafts (#3744) | ||
|
|
9498e6b9e6 |
[codex] stabilize main P0 CI alerts (#3740)
* test: stabilize main P0 CI alerts * fix: address main CI alert review feedback Generated-By: looper 0.9.2 (runner=fixer, agent=codex) * test: cover manual edit bridge selection Generated-By: looper 0.9.2 (runner=fixer, agent=codex) * fix: restore project instructions UI coverage Generated-By: looper 0.9.2 (runner=fixer, agent=codex) * fix: address project instructions and restoration feedback Generated-By: looper 0.9.2 (runner=fixer, agent=codex) * test: preserve file route active-tab assertions Generated-By: looper 0.9.2 (runner=fixer, agent=codex) |
||
|
|
67a8d7cc8e |
Add derived design-system token outputs (#3734)
* Add derived design system token outputs * Harden derived design token output guards --------- Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local> |
||
|
|
c0db6f998a |
fix(web): stabilize design files panel layout (#3732)
* fix(web): stabilize design files panel layout * fix(web): keep design files toolbar usable on a narrow preview split The widened preview split could still overflow a narrow panel: both grid columns pinned hard minimums (list 460 + preview 320 = 780px), so on a narrow chat/preview split the columns summed past the panel width and pushed the toolbar buttons and the preview off-screen, and the toolbar also wrapped its actions onto a second row. - Let the preview column YIELD (minmax(0, …)) while the file list keeps a usable 280px minimum, so the two columns never overflow the panel. - Keep the toolbar on a single row: nowrap + breadcrumb truncation, with the action cluster held on the right (flex-shrink: 0). - Collapse the action buttons to icons-only (titles retained for tooltip + a11y) via a container query on the list column when it is too narrow to fit labelled actions beside the breadcrumb. - Update the style regression test to the new single-row / yielding-split contract. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
02a1a5a537 |
[codex] fix connector refresh propagation (#3723)
* fix connector refresh propagation * address connector refresh review feedback * bump vela cli to 0.0.12 * chore(nix): refresh pnpm deps hash --------- Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com> |
||
|
|
57117c23c6 |
style(landing-page): full-width three-zone header on desktop (#3736)
* style(landing-page): full-width three-zone header on desktop Rework the desktop header (≥1081px) into a three-zone layout so the chrome no longer reads as squeezed in the middle of the bar: - The header now spans the full viewport width instead of aligning to the shared 1360px content container, so the brand sits near the left edge and the side actions near the right edge. - The primary nav grows to fill the middle and centers its links; brand and side keep their natural width. - Left/right padding is 60px so neither the brand nor the side actions collide with the fixed 46px decorative side-rails. - Header chrome is scaled up a step to suit the wider bar (logo 44px, nav links 16px) while keeping the side CTAs at their compact size so the three zones stay visually balanced. Desktop-only; the ≤1080px hamburger layout is untouched. * fix(landing-page): truly center header nav + mirror to canonical template Address review feedback on the three-zone header: - The nav now sits on the true bar midline at every desktop width. Equal flexible side columns (`flex: 1 1 0` + `min-width: 0` on both .brand and .nav-side) center the fixed-width nav regardless of how wide the action cluster is, with the brand left-aligned and the actions right-aligned in their columns. Measured offset from viewport center is 0 at 1100/1280/ 1440/1920px, and the nav never overlaps either side column (≥18px gap). An absolutely-centered nav was rejected because it overlapped the action cluster at mid widths. - Mirror the new desktop header @media block into the canonical design-templates/open-design-landing/example.html, which globals.css is documented (and required by apps/landing-page/AGENTS.md) to track 1:1. --------- Co-authored-by: Joey-nexu <joeylee12629@gmail.com> |
||
|
|
817885bc34 |
feat(amr): forward installationId to the vela CLI for analytics correlation (#3634)
* feat(amr): forward installationId to the vela CLI for analytics correlation When the daemon spawns the vela (amr) CLI, pass this installation's id as OD_INSTALLATION_ID once the user has consented to telemetry. vela attaches it to its analytics events so CLI activity can be correlated back to the open-design installation that launched it. Resolution mirrors the /api/analytics/config handler: consent = telemetry.metrics === true; channel-root installation.json wins over the legacy app-config.json field. Reads are synchronous and best-effort — any missing file / parse error / withheld consent simply omits the id. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(amr): bump bundled @powerformer/vela-cli to 0.0.11 0.0.11 is the first vela CLI release that consumes OD_INSTALLATION_ID (the env forwarded by this PR's daemon change), so bundle it to ship the installationId analytics correlation end-to-end. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(amr): mirror readAppConfig defaults in installationId forwarding Address review: the previous helper bailed out entirely when app-config.json was missing or corrupt, so vela correlation was skipped even though the web analytics config (via readAppConfig) would still emit events with the same installationId. Now match readAppConfig / applyTelemetryDefaults semantics: - a missing/corrupt app-config.json is treated as an empty config, not a hard failure — we still consult the channel-root installation.json for the id; - telemetry defaults to on (opt-out model); the id is withheld only when the user has explicitly set telemetry.metrics to a non-true value. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(nix): refresh pnpm-deps hashes for vela-cli 0.0.11 bump The bundled @powerformer/vela-cli bump changed pnpm-lock.yaml, so the fixed-output pnpm-deps derivation hashes no longer matched. Apply the CI-generated hash refresh (nix-hash-refresh artifact). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(amr): resolve installationId via shared readAppConfigSync Address review: instead of hand-replicating readAppConfig's parsing in the spawn-env helper (which kept diverging on edge cases like invalid telemetry shapes), reuse the real logic. Add a synchronous mirror of readAppConfig: - installation.ts: extract parseInstallationFile + add readInstallationFileSync - app-config.ts: add exported readAppConfigSync (same filterAllowedKeys / validateTelemetry / applyTelemetryDefaults pipeline as the async path; only skips the best-effort migration write) - env.ts: amrAnalyticsIdentityEnv now calls readAppConfigSync and gates on telemetry.metrics === true (matching analytics.ts), so vela correlation can no longer drift from the web analytics config for any config shape. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(nix): refresh pnpm-deps hashes after main merge Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5bcd7d2c26 |
fix(release-beta): pass a valid mac sign mode (on -> sign-only) (#3735)
release-beta.yml passed MAC_SIGN_MODE: "on" to build-mac.sh, which only accepts no | sign-only | notarize and exits with "unsupported MAC_SIGN_MODE: on". That broke every mac beta built directly from main (the green betas came from the release-beta-isomorphism self-hosted lane, not main). Use sign-only: signs the beta with the Apple Developer ID certificate (already wired via APPLE_SIGNING_CERTIFICATE_*) without notarization. Notarization needs APPLE_NOTARY_KEYCHAIN_PROFILE / the direct-credential notarize path that lands with the release-beta-isomorphism mac-lane rework; until then this unblocks signed mac betas from main. Co-authored-by: audit <a@b.c> |
||
|
|
c732084b23 |
feat: newsletter subscribe (landing entry + onboarding email capture) (#3575)
* feat: add newsletter subscribe entry points (landing + client) Add a "Subscribe to our newsletter" form on the marketing landing page (bottom section + dismissable bottom-right popup) and a matching popup in the desktop client. Emails POST to a new /subscribe Cloudflare Pages Function that writes to KV (idempotent via sha256(email)), with CORS for the cross-origin client. i18n covers all locales; analytics fire a newsletter_signup event. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * chore: refine newsletter copy to product-name title Drop the frequency promise ("weekly") and the abstract "Design intelligence" wording in favor of the product-name title "The Open Design newsletter", and change the eyebrow label to "Stay updated" so it no longer echoes the title. Updated across the landing page and all client locales. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * chore: ease landing newsletter popup trigger to 50% scroll / 10s Lower the bottom-right popup trigger from 60% scroll / 25s to 50% / 10s so it surfaces a bit sooner without interrupting the hero LCP. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * refactor(web): move newsletter signup from popup into onboarding The desktop client's newsletter popup only mounted on the main entry view, so first-run users (who land on onboarding) never saw it. Replace it with an optional email field on the onboarding "About you" step instead — a more natural, less interruptive moment to capture an address. - Add an optional email input to the About-you step; on finish, a valid address is POSTed to the subscribe endpoint fire-and-forget (a slow or failing request never blocks completing onboarding). - Endpoint is configurable via NEXT_PUBLIC_NEWSLETTER_URL, defaulting to the marketing site so dev can point at a local wrangler instance. - Remove the NewsletterPopup component, its mount, styles, and popup-only analytics/i18n keys. - Track only a boolean newsletter_opt_in on the onboarding click — the email address itself is never sent to analytics. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * chore(landing): mirror newsletter section into canonical template The newsletter section/popup was added to apps/landing-page/app/page.tsx and globals.css but the source-of-truth example.html was left stale, so future landing/template work would regenerate against a homepage missing the subscription entry point. Mirror the section + popup markup, styles, and signup script into design-templates/open-design-landing/example.html to restore lockstep per apps/landing-page/AGENTS.md. Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) * refactor(web): make newsletter its own onboarding step (3rd) Promote the newsletter email from a cramped field under the About-you dropdowns to a dedicated third onboarding step ("Stay updated"), giving it room for a heading + explainer. Also removes the design-system creation step from onboarding (the home sidebar entry to create a design system is unchanged). - steps array is now Connect / About you / Stay updated; the progress bar uses a 3-column grid so all three sit on one row. - Email submit + completion now fire from the third step. - Drop the onboarding design-system branches and their now-unused helpers (designItems, designSource, deriveOnboardingSourceType); a completion no longer carries a DS request. - Add 'newsletter' to the onboarding analytics area/step-name enums. - zh-CN copy: 了解你 / 订阅更新 / 获取最新动态 / 邮箱地址(选填)/ 完成. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * fix(landing): avoid logging subscriber PII when KV binding is missing The subscribe fallback logged the full record (raw email + referer) to provider logs whenever NEWSLETTER_SUBSCRIBERS was unbound, turning a deploy-time misconfiguration into a privacy leak with no operator signal. Log only non-PII metadata (hashed key, source, country) via console.warn so the missing binding is loud without exposing the address. Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) * chore(i18n): rename zh-CN onboarding step 3 to 获取最新动态 "订阅更新" read awkwardly as the step label; use 获取最新动态. zh-CN only. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * refactor(web): drop dead onboarding design-system renderer prop The newsletter step replaced the step-3 design-system surface in first-run onboarding, leaving `renderDesignSystemCreation` typed but never destructured or rendered in OnboardingView. Remove the stale prop through the App -> EntryView -> EntryShell -> OnboardingView chain and document that first-run design-system creation is intentionally no longer part of onboarding (still reachable via the design-system-create route and the Design Systems tab). Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) * feat: sync newsletter subscribers to Resend --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> Co-authored-by: Claude Opus 4 <noreply@anthropic.com> Co-authored-by: Siri-Ray <2667192167@qq.com> |
||
|
|
e9f5cf9916 | fix AMR OpenCode error presentation (#3729) | ||
|
|
b384c64716 |
test(e2e): align main P0 UI coverage (#3720)
* test(e2e): align main P0 UI coverage * test(web): align BYOK model search assertion Generated-By: looper 0.9.2 (runner=fixer, agent=codex) * fix: address P0 coverage review feedback Generated-By: looper 0.9.2 (runner=fixer, agent=codex) * fix: restore picker keyboard and recent-project coverage Generated-By: looper 0.9.2 (runner=fixer, agent=codex) * fix(web): repair design-system picker type checks Generated-By: looper 0.9.2 (runner=fixer, agent=codex) * ci: classify main CI Feishu alerts * fix: restore active-tab P0 coverage Generated-By: looper 0.9.2 (runner=fixer, agent=codex) * ci: add E2E coverage reminder * ci: run E2E coverage reminder at 18:00 * ci: avoid unsafe E2E reminder pagination exits Generated-By: looper 0.9.2 (runner=fixer, agent=codex) |
||
|
|
7b52480f03 |
Add review-gated token contract rebuild (#3727)
* Add review-gated token contract rebuild * Fix import token rebuild auto-queue handling Generated-By: looper 0.9.2 (runner=fixer, agent=codex) * Handle token rebuild import follow-ups * Make design system revision acceptance atomic --------- Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
556eb7f065 |
chore(release): bump main to 0.10.0 + clear plugin context after send (#3708 residual) (#3731)
* fix(web): clear plugin context after send * chore(release): bump version 0.9.1 -> 0.10.0 (prep main for 0.10.0 beta from main; clears the beta anti-regression gate) --------- Co-authored-by: yinjialu <2481044901@qq.com> Co-authored-by: lefarcen <ontf116@gmail.com> |
||
|
|
2ff65a27d8 |
fix(web): keep in-tab presentation below workspace tabs (#3722)
* Fix in-tab presentation chrome offset * fix(web): sync presentation overlay chrome token Generated-By: looper 0.9.4 (runner=fixer, agent=codex) |
||
|
|
6c7b85a6d0 |
chore(web): re-home in-flight release/v0.10.0 fixes to main (#3716, #3710, #3662) (#3721)
* Close home mention picker before details
(cherry picked from commit 484749e33029999655b9d7fc6c148b63ad8e3dc2)
* fix image export toast offset
(cherry picked from commit 3be9082a878fdddcd6edf476a1748de9639c196b)
* Fix image export format switch save label
(cherry picked from commit
|
||
|
|
2569f4eba9 |
feat(scenarios): od-share-to-community skill + post-completion Share button (#3657)
* feat(scenarios): add od-share-to-community plugin + Share to Open Design button After the user finishes a generation, they currently have to re-prompt the agent to package what they just made. This adds a quiet "Share to Open Design" pill in the assistant-completion-row — same area as the post-feedback Discord prompt — that injects a single trigger prompt into the chat and lets the bundled `od-share-to-community` scenario auto-derive the manifest from `*.artifact.json`, `brand-spec.md`, and the workspace files instead of asking the user fields the project files already answer. The skill mirrors `home-hero/plugin-authoring.ts`'s constraint surface verbatim: no chained CLI suggestions, no `jq` dependency (not in the agent runtime baseline), and after `od plugin install --source`, point the user at the existing 3-button plugin-folder card (Add to My plugins / Publish repo / Open Design PR) instead of recreating those flows freeform — the source of bug #2332. Verified end-to-end via headless browser: - daemon registers the bundled scenario at /api/plugins - button renders in the live DOM, gated on (isLast && showFeedback) - click fires POST /api/runs with the trigger prompt as a user message - Claude Opus picks up the prompt and starts the share flow * fix(web): debounce share to open design action * fix(plugins): register share community scenario pipeline --------- Co-authored-by: kokisanai <kokisanai@users.noreply.github.com> Co-authored-by: Siri-Ray <2667192167@qq.com> |
||
|
|
3c1a8e7bcd |
feat(landing-page): add html-video product page under /html-video/ (#3709)
* feat(landing-page): add html-video product page under /html-video/
Add a sister-project landing page for nexu-io/html-video and surface it in
the Product nav dropdown, mirroring the HTML Anything page.
html-video is the motion counterpart to HTML Anything: an HTML-to-video
meta-layer where a local coding agent turns a prompt, an article link, or a
GitHub repo into a multi-frame animated video, rendered to a real MP4 via the
Hyperframes engine (headless Chromium + ffmpeg). Pluggable engines, 21
templates, optional AI soundtrack, Apache-2.0.
The page is an SEO + direct-link surface, so it leads with the two primary
head terms — "HTML to video" (the category) and "Hyperframes" (the default
engine, a real search term) — across the title, H1, and section copy, and
seeds long-tail like "html to mp4" and "agent video". Content is hardcoded
EN + ZH (this is a separate repo, not a content collection); the other 16
locales derive a keyword-stacked fallback from shared i18n fragments, the
same pattern as the HTML Anything page. At-a-glance stars are pulled from the
GitHub API at build time with a snapshot fallback. Imagery is hosted on the
same R2 bucket (landing/assets/html-video/) and resized through cdn-cgi/image.
Nav: new Product dropdown entry (productMenuCopy.htmlVideoName/Blurb, added to
all 18 locales) linking to /html-video/, plus an 'html-video' active value so
the Product trigger highlights on the page.
Verified: landing-page typecheck (0 errors) and build:static — /html-video/
plus all 18 locale variants build, the Product dropdown links to it on the
home page, and the title/H1/body carry the html-video + Hyperframes terms.
* fix(landing-page): add page-local styles to html-video page
The html-video page reused the HTML Anything page's `ha-*` class names but
not its styles — those live in that page's Astro-scoped <style> block, which
does not apply across pages. Result: at-a-glance collapsed to a bullet list,
cards lost their grid, and the showcase had no layout.
Add a page-local <style> block mirroring the HTML Anything one, adapted to
this page's class names (ha-showcase, ha-surfaces, ha-roadmap-col, ha-tag).
Also fix the at-a-glance stars cell: its fallback was the word "GitHub" under
a "GitHub" label (rendering "GitHubGitHub"); the fallback is now a numeric
snapshot under a "GitHub stars" label.
* style(landing-page): restyle html-video page to Open Design system
Rework the html-video page's layout to match the rest of the marketing
site and fix spacing problems flagged in review.
- Use Open Design's global tokens (--serif / --mono / --ink / --coral /
--line / --paper-warm) throughout instead of hardcoded values and a
GT-Sectra fallback, so the page shares the visual system of the HTML
Anything and Solutions pages rather than drifting into its own look.
- Tighten spacing rhythm: single-edge section padding for a consistent gap
between sections (was doubled top+bottom margins, leaving large empty
bands between sections), tighter title→content spacing, hairline
dividers to group instead of wide gaps.
- Cards for the why / engines blocks (bordered, warm-paper fill) instead of
bare stacked text; coral accent locked to one role (engine status tag,
flow step numbers, roadmap headings, note rules).
- Fold the thin Soundtrack and Quickstart sections into a compact two-up
notes row so they no longer read as empty sections.
- Hero image renders at its natural ratio (dropped the max-height crop that
was cutting off the banner).
- Product menu label is "HTML Video" (title-case product name, matching
"Open Design" / "HTML Anything") across all 18 locales.
- Remove the build-time "stats verified <date> · live where the API is
reachable" dateline — that was internal/developer phrasing on a
user-facing page.
* feat(landing-page): list HTML Video in the footer Products column
Add HTML Video to the Products column in both footers so the third
product in the family is reachable from the page bottom, not just the
Product nav dropdown.
- Sub-page footer (site-footer.astro): append HTML Video after HTML
Anything in the existing Products column.
- Home-page footer (page.tsx): it had no Products column at all, so add
one (Open Design / HTML Anything / HTML Video) before the Studio column.
- New ui.footer.htmlVideo i18n key across all 18 locales (value "HTML
Video"; product name, not localized — same as htmlAnything).
* fix(landing-page): address html-video review feedback
- Remove the unused getCommonCopy import (derivedHtmlVideoCopy only uses
getLandingUiCopy + getHeaderProductMenuCopy).
- Localize the grouped Soundtrack/Quickstart section's aria-label, which
was hardcoded English ("Soundtrack and Quickstart") so every localized
page announced that landmark in English. It now reuses the page's own
localized section titles.
---------
Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
|
||
|
|
2df76ee0c9 |
Improve design system token import contract (#3719)
Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local> |
||
|
+1 |
baa0f57a24 |
chore: back-merge release/v0.10.0 into main (reconcile QA fixes; retiring release branch) (#3715)
* chore(release): prepare 0.10.0 * [codex] Add same-run retry runtime (#3576) * Add same-run retry runtime * fix(daemon): route retried-start and watchdog stall through retry finalizer Two retryable failure paths bypassed the same-run retry finalizer, so they emitted no run_retry_attempted/run_retry_finished telemetry and could report the fallback retry_final_result: 'not_attempted'. - restartSameRunAfterRetry's catch now routes a failed retried start through finishWithRetryDecision instead of design.runs.finish, so it emits terminal retry telemetry and sets run.retryFinalResult. retryAttemptCount is already 1 there, so decideSafeRunRetry suppresses with attempt_limit_reached and cannot loop. - failForInactivity's no-output stall now routes through the finalizer after surfacing stallPayload. A silent first-token hang classifies as a retryable timeout at first_token_wait, so the same-run retry now recovers it. A new watchdogRetryRestarted guard makes the SIGTERM'd stalled child's close bail early (revoking only its own tool token) so it cannot re-finalize the run or delete the new attempt's event sink (both keyed by the shared runId). - finishWithRetryDecision returns whether it restarted so the watchdog can set the guard. Adds a run-retry-runtime test with a low OD_CHAT_RUN_INACTIVITY_TIMEOUT_MS proving the same-run retry fires for a silent first attempt. * fix(web): avoid duplicate style picker group keys * Fix Design Files and sidebar page layout regressions (#3629) Fixes two web UI layout regressions: - Prevent Design Files name cells from collapsing to near-zero width, which caused generated file and folder names to wrap vertically while leaving empty space to the right. - Hide inactive entry views with display: none so Plugins, Integrations, Design Systems, and Automations no longer reserve hidden Home view height above their page content. Validated with web typecheck, focused web component tests, pnpm guard, and local visual checks. * fix(web): copy run error diagnostics (#3630) * fix(web): route project file links to workspace tabs * fix(web): preserve failed retry attempts * Auto-open produced HTML previews (#3636) * test(e2e): cover assistant project file link routing * feat(web): redesign Design Files panel + pick working directory from Home (#3358) [v0.10.0] (#3618) * feat(web): redesign Design Files panel + pick working directory from Home (#3358) * feat(web): align Design Files panel with Claude reference UI Redesign the Design Files panel into a continuous grouped table that mirrors Claude's own Design Files surface: uppercase gray section bands (Folders / Stylesheets / Scripts / Documents / Images …), flush full-width rows with a colored icon block + bold name + type subtitle + right-aligned timestamp, a clean single-line toolbar (breadcrumbs left, New sketch / Paste / Upload right), a right preview card with a centered Open action and `Modified … · size · EXT` stats, and a static USEFUL INFO footer. Removes the old table/sort-header/kind-filter/pagination/group-toggle chrome and the conflicting legacy `.app .df-*` overrides in routines.css that were trumping the panel's own stylesheet via specificity. Preserves batch select/download/delete, rename, the row context menu, live-artifacts, plugin-folders, drag-upload, and the reloading overlay. Adds the designFiles.* section/kind/useful-info i18n keys across all locales. * feat: pick a working directory from Home before the project exists Let users choose a code folder on the Home screen up front, instead of only being able to replace it after a project is created. The HomeHero composer gains a folder pill (pick / clear); the chosen path is threaded through project creation and applied via the working-dir API once the project id exists. On desktop the working-dir POST is gated behind a host-minted token, so add a `dialog:pick-working-dir` IPC handler that shows the native picker and mints a single-use token bound to the folder, plus a `pickHostWorkingDir()` bridge + types/normalizer in `@open-design/host`. The renderer feature-detects the bridge and falls back to the web folder dialog (no token) otherwise. Native dialogs now allow creating a new folder inline (`createDirectory` / `ShowNewFolderButton`), and macOS uses `choose folder` so the panel reliably takes key focus. Wire the WorkingDirPill into the project composer footer and surface a reloading state + breadcrumb root label to the Design Files panel while a replace reindexes. Drop the WorkingDirPill "recent directories" localStorage list in favor of a single Replace action. * fix(web): preserve staged Home attachments when picking a working dir Move the working-dir handoff ahead of the initial upload so staged attachments land in the external folder instead of the temporary managed root, and fall back to the browser folder dialog when the desktop host build does not expose pickWorkingDir. * fix(web): surface host pick errors and normalize Windows dir basenames When the desktop host is present but cannot mint a working-dir token, surface the error instead of falling back to the browser folder dialog — the tokenless raw path would be rejected by the desktop auth gate as a late create-time failure. Only the pure web path (no token gate) keeps the dialog fallback. Also split the Home pill basename on both path separators so Windows paths show the folder name, not the full path. * fix(web,desktop): harden Home working-dir handoff against auth/token failures Run the desktop-auth handshake before minting the Home working-dir token so a missed startup registration fails up front instead of as a rejected deferred POST. Surface a create-time error toast when the working-dir handoff fails (expired ~60s token or daemon rejection) instead of silently leaving the project in the managed root while the user believes their folder was applied. * fix(web): abort create on failed working-dir handoff and always show root crumb When the pre-create working-dir handoff fails, short-circuit the rest of the Home submit path (skip the staged-attachment upload and auto-send) so the first run cannot proceed against the managed `.od/projects/<id>` tree the user did not choose, and reword the error toast accordingly. Always render the Design Files root breadcrumb, falling back to the `designFiles.crumbs` label when no rootDirName exists, so the toolbar is not blank on the default managed-storage view. Adds regressions for the short-circuit and default-root crumb cases. Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) * fix(web): normalize Windows separators in WorkingDirPill basename shortPath() split only on '/', so a Windows working dir like C:\work\repo rendered as the full absolute path in the footer pill instead of the folder name. Split on both separators to match HomeHero/ProjectView, and add a regression covering the backslash path. Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> (cherry picked from commit |
||
|
|
a019bcd5cc |
fix(web): backport release-only fixes to main ahead of v0.10.0 re-cut (batch 1) (#3711)
* fix(web): avoid duplicate style picker group keys (cherry picked from commit |
||
|
|
b9d0f7e966 | ci: add Feishu main alert smoke test (#3704) | ||
|
|
9a25aae339 |
feat(landing-page): add Solution hub at /solutions/ and consolidate Role pages (#3700)
* refactor(landing-page): move Solution → Role pages from /for/ to /roles/ The Solution → Roles pages shipped at /for/<role>/ in #3658. The /for/ prefix reads as an incomplete URL fragment on its own; /roles/<role>/ is a clearer, self-describing path for the audience landing pages. Rename both the default-locale and [locale] page directories, update the header dropdown hrefs and the route docstrings to match. R2 hero image keys stay under landing/assets/for/<role>/ (the bucket key is not user-visible and the assets already exist there), so only the public route changes. Old /for/<role>/ URLs are dropped, not redirected — the pages are hours old with negligible inbound links. * feat(landing-page): add Solution hub at /solutions/ and fold Role pages in Builds on the Solution → Role pages from #3658. Two changes to the Solution information architecture: 1. The Solution nav trigger pointed at /compare/ (the competitor comparison hub), which is unrelated to the dropdown's contents. It now points at a new /solutions/ overview page that indexes every Solution sub-page, grouped exactly like the dropdown: Use cases (what you're making) and Roles (who you are). Each card reuses the sub-page's own breadcrumb + description from getSolutionPageCopy, so the hub never drifts from the pages it links to. The page's own chrome (label, heading, one-line lead) lives in a new solutions-index-i18n module, typed as a Record over every landing locale so a missing translation is a typecheck error; all 18 locales are populated. 2. The Role pages, which shipped at /roles/<role>/, move under /solutions/<role>/ so they sit alongside the use-case pages in one coherent /solutions/ namespace instead of a parallel /roles/ tree. Use-case and role slugs don't collide. Dropdown hrefs and route docstrings updated to match. The interim /roles/ paths are dropped, not redirected (hours old, negligible inbound links). Also: the brand logo's default href was '#top', leaving '/#top' in the URL on the homepage and pointing at a non-existent anchor. It now defaults to '/' so clicking the logo always returns to the localized home, matching what every sub-page caller already passed. Verified: landing-page typecheck (0 errors) and build:static — output has /solutions/ + all 11 sub-pages across 18 locales, the /solutions/ index, no /roles/ or /for/ routes remain, and hero images still resolve to their existing R2 keys. --------- Co-authored-by: Joey-nexu <joeylee12629@gmail.com> |
||
|
|
f1b59b67c6 |
feat(web): streamline Home/project composer chrome and pin the Home tab (#3692)
* feat(web): streamline Home/project composer chrome and pin the Home tab Reduce composer clutter and align the Home and project chat surfaces: - Drop the artifact-specific footer settings (fidelity/ratio/notes/etc.) from the Home composer; the agent now asks for them via the existing discovery flow, so the footer keeps only the design-system picker. - Default the design-system picker to "Auto"; only a user-owned system pre-selects. - Move the CLI (model switcher) into the top-right header next to Discord; unify the composer footer buttons to pill shape. - Extract a shared ComposerPlusMenu (attach / connectors / plugins / MCP, with an extra design-toolbox flyout in the project composer) used by both Home and the project chat composer; remove the project composer's sliders and @ buttons (mentions still trigger by typing @). - Rename the session-mode label to "Design" (full "Design Agent" copy stays in the hover card). - Pin the Home workspace tab to the leftmost slot, make it non-closable, and tighten tab widths. - Fix the truncated Discord online count in the icon-only top bar; ellipsize long plugin/MCP names in the add menu. * fix(web): address composer + menu review regressions and update tests - ComposerPlusMenu: reset the shared search query when the active submenu changes, so a plugin search no longer cross-filters the MCP flyout (restores the old HomeHero behavior). - ChatComposer: opening the "+" menu latches composerEngaged again, so the Plugins / Connectors / MCP submenus aren't empty on a cold composer. - Keep media-surface footer options (model / ratio / resolution / duration / audio type); only prototype/deck fidelity/slide-count/speaker-notes were meant to leave the footer. - Update/trim tests for the removed sliders + tools popover, the @ button, the Import-menu design-system switcher, and the prototype/deck artifact footer controls; rewire the design-toolbox tests through the new "+" menu; assert the Home tab is pinned and non-closable. * fix(web): guard composer + menu picker mousedown to preserve caret The shared ComposerPlusMenu connector/plugin/MCP picker rows ran onPick* handlers (which call insertMention) without cancelling mousedown, so the button stole focus first and Lexical fell back to selectEnd(), inserting mentions at the end of the draft instead of the caret. Add the preventDefault guard and port the deleted caret-regression coverage to the shared menu path. Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) * fix(web): defer prototype/deck artifact inputs and protect + menu caret Address the two blocking review findings on PR #3692: - HomeView.submit() now strips fidelity / slideCount / speakerNotes from the submitted plugin inputs via stripArtifactFooterInputs(), so removing the footer actually defers those questions to first-turn discovery instead of forwarding the plugin manifest defaults. The prose brief still renders them. - ComposerPlusMenu pick rows (connector / plugin / MCP) cancel mousedown so the editor keeps focus and the caller's insertMention lands at the caret, not the draft end — restoring the #3195 contract that the deleted tools-menu-caret test used to cover. - Add ComposerPlusMenu.test.tsx covering the mousedown-preventDefault contract and the submenu query reset; update prefill expectations to assert the artifact fields are no longer in the apply payload. * fix(web): keep Home tab pinned leftmost on tab drop Re-normalize reordered tabs and coerce 'before Home' drop edges to 'after Home' so dragging a project tab onto Home's left edge can no longer persist a tab ahead of the permanent Home tab. Updates the drag spec to assert Home stays first after the drop. Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) * fix(web): always mint a pinned Home tab during tab normalization normalizeTabsState only reordered an existing Home tab, so users who closed/replaced Home before this feature shipped could restore a saved [project, ...] workspace and stay Home-less until manually navigating home. Prepend a Home tab whenever none survives normalization so the "Home always exists and is leftmost" invariant also holds for migrated state. Adds a regression spec booting from saved tabs with no Home entry and updates two specs that encoded the old Home-less behavior. Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> |
||
|
|
0ce9a19bce | Add CI gate workflow placeholders (#3701) | ||
|
|
8f6cdaaba1 |
Harden release-beta-s self-hosted beta lane (#3641)
* Fix Windows smoke launcher payload layout
* Harden release-beta-s runner probe
* Use cmd shell for release-beta-s probe
* Add win beta build script for self-hosted lane
* Keep release-beta-s checkout lightweight
* Use explicit local beta version for release-beta-s
* Install dependencies in beta build script
* Repair Electron dist before Windows beta build
* Add release-beta-s timings and diagnostics
* Polish release-beta-s observability guardrails
* Trace tools-pack cache materialization
* Reuse materialized workspace build cache
* Trace Windows packaging segments
* Trace Windows archive process details
* Reuse installer unpacked materialization
* Preserve reusable Windows unpacked projection
* Add fast smoke telemetry for self-hosted beta
* Cache Windows archive outputs for beta lane
* Tighten fast Windows smoke lane
* Scope Windows beta artifact reporting by target
* Clean stale Windows target artifacts
* Wire Windows Authenticode signing
* Expose self-hosted beta validation modes
* Add core Windows smoke profile
* Decouple core smoke from updater fixture version
* Trace Windows smoke lifecycle steps
* Skip unpacked materialization on NSIS cache hit
* Add Nexu S3 beta publisher
* Harden self-hosted Windows beta lane
* Use Windows PowerShell for publish probe
* Run publish probe via repo script
* Require explicit self-hosted S3 public origin
* Run real installer acceptance for external feeds
* Skip ready-prompt checks for external feeds
* Relax optional self-hosted update inputs
* Tolerate BOM in self-hosted publish probe
* Converge self-hosted beta metadata and signing flow
* Run self-hosted beta metadata prep on the runner lane
* Use Windows PowerShell for self-hosted beta metadata checks
* Bypass execution policy in self-hosted beta metadata checks
* Split self-hosted beta metadata publish
* Suppress mc output in beta publish helpers
* Split Windows NSIS payload cache layers
* Require fresh tool dist metadata
* Preserve Windows overlay payload paths
* Default beta-s gate to core
* Optimize win beta packaging reuse
* simplify windows full smoke lifecycle
* preserve onboarding state after windows upgrade smoke
* fix windows tools-pack test portability
* recover stale tools-pack locks
* Allow auto signing fallback for beta builds
* Add self-hosted beta mac arm64 lane
* Quote self-hosted signing choices
* Run self-hosted beta metadata on mac lane
* Use shallow metadata checkout on self-hosted beta
* Use sparse beta metadata checkout
* Make mac release profile bash-compatible
* Allow file sparse metadata checkout
* Isolate self-hosted metadata checkout
* Clear sparse skip-worktree before mac build
* Isolate self-hosted mac build checkout
* Run self-hosted beta publish without aws cli
* Use unsigned beta prefix for mixed platform publish
* Sparse checkout self-hosted beta publish
* Publish mac beta platform before metadata
* Pass mac publish release profile
* Probe mac signing keychain import
* Expand mac signing preflight variants
* Use sudo keychain helper for self-hosted mac signing
* Route self-hosted mac codesign through sudo wrapper
* Normalize mac signing identity name
* Harden self-hosted mac notarization
* Optimize self-hosted mac release cache
* Fix mac signing helper cleanup
* Retry transient mac notarization uploads
* Keep mac notarization fail-fast
* Reduce mac symlink diagnostics noise
* Normalize self-hosted beta platform inputs
* chore: bump beta base version to 0.9.1
* chore: tune release tools-pack cache retention
* test: add temporary cache validation marker
* chore: key windows nsis base payload by content
* Revert "test: add temporary cache validation marker"
This reverts commit
|
||
|
|
1467a389a3 |
fix(github): tighten bug report preflight (#3688)
Generated-By: looper 0.9.3 (runner=worker, agent=codex) |
||
|
|
d0d9c02763 |
feat(web): Manus-style second-level category rail on Home composer (#3686)
* feat(web): add Manus-style second-level category rail to Home composer Picking Prototype or Slide deck on Home now reveals a compact sub-category pill row (All + the Community facet sub-categories), filtering the example preset cards in place without binding a plugin or stamping a badge. Reuses the existing plugins-home facet taxonomy so the labels match the Community grid exactly; Landing / marketing is floated first for prototypes. Also: reorder the first-level rail (Prototype, Slide deck, HyperFrames, Live artifact, Image, Video, Audio); move the CLI/BYOK execution switcher out of the composer footer up to the top bar beside Discord; restyle the example preset cards into full-bleed thumbnail + name (dropping the prompt blurb, trailing icon, and faux browser chrome); and stop showing the "Example prompts: …" badge when a preset is applied. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * fix(web): derive Home sub-category pills from the displayed preset list Addresses review: a selected child pill could render every preset card instead of its slice. activeSubChips was built from the full install set (pluginOptions) while filtering ran against the curated/sorted/sliced activeExamplePlugins, so a facet category whose plugin wasn't in the Home preset slice produced a pill that, when clicked, hit the all-cards fallback and looked unfiltered. Derive the pills from activeExamplePlugins (the same list that feeds the cards) and drop the fallback, so every pill maps to a non-empty slice. Update the rail test (preset card is now thumbnail + name, no prompt blurb on the face) and add a fixture for a sub-category absent from the displayed list. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> Co-authored-by: Claude Opus 4 <noreply@anthropic.com> |
||
|
|
4cfdc4d7db |
feat(desktop): play white brand splash video on startup (#3674)
* feat(desktop): play white brand splash video on startup
Replace the dark "Waiting for the web runtime URL…" placeholder with the
brand intro animation on a white background. The clip plays once and then
freezes on the settled "Open design" logo. The window only swaps to the web
runtime after the clip has had time to play through (MIN_SPLASH_MS), so it
never flips mid-animation, and it holds the final frame when the runtime
takes longer to boot.
The clip is embedded as a base64 data URL so it renders identically in dev
and in packaged builds without any electron-builder asset wiring — the
packaged app exposes no reliable on-disk asset path from the desktop main
bundle (the previous icon lookup already silently fell back to null there).
* feat(desktop): show splash in parallel with boot, reveal on web mount
Make the white brand splash a dedicated window so it can do real work:
- Packaged cold start now creates the splash BEFORE awaiting the daemon/web
sidecars, so the animation is on screen during the whole boot instead of the
user staring at no window at all for a few seconds. The 2s minimum splash now
overlaps startup rather than being added on top of it.
- The main window starts hidden and loads the web app behind the splash. We
reveal it only once the web bundle reports it has actually mounted
(data-od-app-mounted="1") and the minimum splash time has elapsed, then close
the splash. This removes the dark "Loading Open Design…" web shell that used
to flash between the splash and the app. A hard timeout guarantees the user is
never stranded on the splash if the mount signal never arrives.
tools-dev/dev keeps working unchanged: when no splash window is handed in, the
runtime creates its own.
* fix(desktop): measure splash hold from window creation, not adoption
PerishCode review: in packaged startup the splash window is created before
`await startPackagedSidecars(...)`, but the minimum-hold clock was stamped later
inside `createDesktopRuntime` (after the sidecars had finished booting). The
reveal then waited `MIN_SPLASH_MS` from that post-boot instant, so a fast web
mount still added almost another 2s on top of boot — re-introducing the very
delay the parallel splash was meant to remove.
`createSplashWindow()` now returns a `{ window, startedAt }` handle stamped at
creation; the packaged entry forwards `startedAt` via `splashStartedAt` and the
runtime measures the hold from there. Runtime-created dev splashes stamp their
own creation time, so the hold overlaps boot in every path.
* fix(desktop): gate DesktopRuntime.show() behind the splash reveal
PerishCode review: the main window now starts hidden and is revealed only after
the web app mounts, but `DesktopRuntime.show()` still called `window.show()`
unconditionally. The packaged entry routes a pending second-instance focus
through that method via `onDesktopReady`, so launching the app twice while the
sidecars/web are still booting would surface the half-loaded main window and
bypass the reveal gate — reintroducing the startup flash.
`show()` now focuses the splash while the runtime is pre-reveal and only shows
the main window once `revealWhenReady()` has fired.
|
||
|
|
475b9a480b |
fix(daemon): include user toolchain dirs in agent spawn PATH so shebang interpreters resolve (#3675)
What: `applyAgentLaunchEnv` now appends the user toolchain bin dirs
(Homebrew, ~/.local/bin, ~/.bun/bin, version-manager node dirs, npm
prefixes — the same set binary *resolution* searches) to the end of the
spawn PATH. Exposed via a new `userToolchainBinDirs()` from executables.ts;
injectable param defaults to the real dirs (tests pass []).
Why: agent detection resolved a binary's path using resolvePathDirs()
(PATH + wellKnownUserToolchainBins) but spawned it with a PATH containing
only nodeBinDir + the agent's own dir. An agent whose shebang interpreter
lives in a toolchain dir not on the daemon PATH then failed to execute:
Pi (`/usr/bin/env bun` via @oh-my-pi/pi-coding-agent) resolved fine but its
`--version` probe exited 127 ("env: bun: No such file or directory"), so
detection classified it not-invocable and marked Pi unavailable. claude/codex
only survived because their interpreter (node) happened to be on the spawn
PATH. Resolution and spawn PATH are now symmetric, fixing detection AND the
run/connection-test spawns that share this function.
How: append appendPathDirs into the PATH merge (lowest priority, deduped).
Verified: Pi flips unavailable -> available after the fix (path + version
now populated), alongside claude/codex.
Test: apps/daemon/tests/runtimes/launch.test.ts — "appends toolchain dirs
so shebang interpreters (e.g. bun) resolve at spawn time" (would go red
without the fix). Existing exact-PATH tests pass [] to stay deterministic.
Co-authored-by: ZC Deng <zhic.deng@gmail.com>
|
||
|
|
9fd65efec0 |
fix(web): scope generation-preview override to the empty design-files tab (#3684)
Address review: dropping the DESIGN_FILES_TAB guard outright let the generation card win for every in-flight run on the design-files tab, hiding the file browser of a populated project until a previewable artifact existed. Scope the override to the truly empty tab, mirroring DesignFilesPanel's own empty-state gate (no files, no live artifacts, no folders), so a populated project keeps browsing while generating. Adds a regression test that a populated design-files tab still renders file rows while a run is active. |
||
|
|
668d556097 |
ci(release): throttle the per-push nightly build instead of debouncing it (#3682)
`notify-release-feishu` builds a full nightly (via release-stable, channel=nightly) and posts a Feishu card on every push to `release/**`. Its concurrency used `cancel-in-progress: true`, so a newer push cancelled the in-flight build. When a release branch is busy — pushes spaced closer than a full cross-platform build takes — every build was cancelled by the next push and no nightly was ever cut. (Observed on release/v0.10.0: a run of pushes all cancelled, the last successful nightly was hours old.) Switch to `cancel-in-progress: false` (throttle): the running build finishes, and pushes that arrive during it coalesce — GitHub keeps the in-progress run plus only the newest pending run, cancelling older pending ones. A busy release branch now always cuts a nightly and converges on the latest commit, with at most one build running plus one queued. Trade-off: a newer push no longer interrupts a running build for an older commit; it waits one build cycle. For nightly that's the right call. |
||
|
|
1b47dcd22c |
feat(landing-page): add Solution → Roles pages (/for/<role>) for 5 audiences (#3658)
* feat(landing-page): add Solution → Roles pages (/for/<role>) for 5 audiences Enable the Solution dropdown's Roles group (previously commented out) and ship the five audience landing pages it points to: solo builders, designers, engineers, product managers, and marketing teams. Why: the Solution nav shipped with use-case pages but the Roles group was held back with no destinations. Visitors arriving by job-to-be-done had no "this is for someone like me" entry point, and the use-case pages alone don't speak to a role's full workflow. Each role page is a conversion surface (role search terms have ~zero volume, so these are not SEO-traffic pages) and an internal-link anchor for the Solution cluster. What users see: a Roles group at the bottom of the Solution dropdown with five links. Each page has its own hero, a role-specific TL;DR, a three-step "how a <role> uses Open Design" flow, a feature grid of real catalogue templates curated per role (no overlap between roles — every role shows a distinct set of interactive examples), a role-specific comparison table, and a role-specific FAQ. All copy is translated across the 18 landing locales; the nav group label is localized too. Pages reuse sub-page-layout and emit BreadcrumbList + WebPage + FAQPage JSON-LD with locale-aware canonical URLs. Featured templates are picked by manifest id through pickSolutionPlugins, which fails the build on any missing id, so a renamed or removed example breaks the build loudly instead of shipping a short grid. * fix(landing-page): align nav dropdown caret to the label's optical midline The ▾ caret after each top-level nav label (Product, Solution, Agent, …) rendered as a baseline-aligned inline glyph at 10px, so it dropped to the lower-right of the label and read like a stray comma after each word — especially visible with CJK labels. Make the nav link an inline-flex row centered vertically, bump the caret to 11px with line-height 1, and nudge it up 1px to sit on the text's optical midline. The hover/focus state keeps the same resting position (the color shift to coral remains the open affordance) so the glyph no longer jumps. * refactor(landing-page): split solution-pages-i18n into per-locale modules The Roles pages added five role* keys with full prose across all 18 locales, which grew solution-pages-i18n.ts to ~1.4 MB — over the repo's 1 MiB MAX_CHANGED_FILE_BYTES blob guard (.github/workflows/ci.yml), making the required "Guard changed file sizes" check (and the Validate workspace aggregate that depends on it) red and the PR unmergeable. Move each locale's copy block into solution-pages-i18n/<code>.ts and the shared shapes into solution-pages-i18n/types.ts. solution-pages-i18n.ts is now a thin index: it re-exports the public type API, imports the per-locale modules, assembles BY_LOCALE, and resolves copy with the English fallback. The public API (getSolutionPageCopy, SolutionPageKey, SolutionPageCopy, …) and runtime behavior are unchanged. Largest split file is ~110 KB (ru), the index is ~3 KB, so every tracked source file is now well under the 1 MiB limit. Verified: typecheck clean, build green (8457 pages), and per-locale role-page titles still render translated (zh/ja/de/ru/ar) rather than falling back to EN. --------- Co-authored-by: Joey-nexu <joeylee12629@gmail.com> |