* feat(contracts): agent-ready capability contracts + design RFCs (#5398)
Slice 1 of the "agent-ready OD" proposal (#5398): pure-TypeScript contract
shapes for the assistant's capability layer, plus the design RFCs. No behavior
code.
- packages/contracts/src/agent-tools/: descriptor (declare), actions
(call/result), manifest (list + paged search), registry (port), task
(cross-project AgentTask). Discriminated on `surface`; dual-track law is
structural; action identity is a daemon-minted `invocationId`.
- docs/rfc-drafts/agent-ready.md: umbrella design + slice roadmap, the
MCP/WebMCP-congruent capability model, tool-search options, and
"options considered -> recommendation" for the load-bearing decisions.
- docs/rfc-drafts/agent-ready-cross-project.md: the maintainer's separate
reviewable permissions writeup (AgentTask + permission options).
Registry runtime, endpoints, and behavior are later slices per the roadmap.
* fix(contracts): narrow AgentToolSearchQuery.surface to 'api'
Search is the PULL path over the persistent registry, which per the RFC
holds only api-surface tools — browser availability is PUSH-advertised
per-session and cannot be answered by a session-less search query. Narrow
the searchable surface to 'api' so the contract does not encode a
browser-tool discovery path the runtime would have to special-case or
break. Addresses the blocking review on #5400.
* fix(contracts): address review — narrow search result to api-only; distinct browser vs api call paths
Resolves the two remaining blocking findings on PR #5400:
- manifest.ts: narrow `AgentToolSearchResult.tools` from the full
`AgentToolDescriptor` union to `ApiToolDescriptor[]`, enforcing the
PULL/api-only search invariant on the response side too (the query
`surface` was already narrowed to `'api'`). A registry impl can no
longer type-check while leaking `browser` descriptors into a
session-less search result.
- agent-ready.md: stop presenting `BrowserActionRequest` as the generic
`tools/call` for every capability. The two surfaces now have distinct
request paths: `api` tools are invoked through their declared `/api/*`
route + `od` subcommand (no round-trip envelope), while
`BrowserActionRequest`/`Result` is the browser-surface path only — the
genuinely new inbound seam.
- agent-ready-cross-project.md: reconcile the slice-5 cross-project
routing fields (`taskId?`/`targetProjectId?`) with the distinct-paths
model — added on both the browser envelope and the api-call request,
not bolted onto `BrowserActionRequest` for api tools.
Validation: contracts typecheck pass; pnpm guard pass.
---------
Co-authored-by: LA <la@LAs-MacBook-Pro.lan>
* feat(deck): enhance slide deck functionality with speaker notes and navigation improvements
- Added a switch for including speaker notes in slide decks, defaulting to true.
- Updated keyboard navigation to include 'R' for resetting to the first slide.
- Implemented click navigation for half-slide transitions.
- Enhanced the deck framework to support hidden programmatic prev/next controls.
- Improved handling of file inputs in question forms to support file submissions.
This update aims to improve user experience in creating and presenting slide decks, ensuring better accessibility and functionality.
* feat(artifacts): enforce semantic naming for user-facing deliverables
- Updated guidelines to require semantic filenames derived from user briefs for new artifacts, moving away from defaulting to `index.html`.
- Enhanced documentation to clarify naming conventions for HTML files, emphasizing the use of descriptive names like `investor-pitch-deck.html`.
- Adjusted prompts and hints across the system to reflect these changes, ensuring consistency in user-facing outputs.
- Improved test coverage to validate the new naming conventions and ensure proper implementation in various contexts.
This update aims to enhance clarity and usability in project file management, promoting better organization and user experience.
* feat(file-viewer): enhance speaker notes display and improve file workspace functionality
- Updated the speaker notes section to include a styled placeholder for empty notes, improving user experience.
- Changed the icon in the file workspace from "slides" to "panel-left" for better clarity.
- Introduced new sub-category filtering options in the file workspace, enhancing organization and navigation.
- Improved styling for the page creator search input and added visual feedback for loading states.
These changes aim to enhance usability and visual consistency across the file viewer and workspace components.
* test(web): align workspace tests with pages switcher
* test(e2e): open design files through pages menu
* fix(deck): keep source mode reachable
* fix(workspace): restore uploaded file tabs
* feat(deck-thumbnail): implement virtualized thumbnail rail for improved performance
- Introduced a new `DeckThumbnailRail` component to optimize the rendering of deck thumbnails, reducing memory usage and improving load times.
- Enhanced the `FileViewer` to integrate the new thumbnail rail, allowing for lazy loading of thumbnails based on viewport visibility.
- Added tests for the `DeckThumbnailRail` to ensure correct functionality and caching behavior.
- Updated styles for better visual consistency and performance during thumbnail rendering.
These changes aim to enhance user experience by providing a smoother and more efficient way to navigate through deck slides.
* feat(deck): enhance deck rendering with thumbnail support and keyboard shortcuts
- Integrated `DeckSlideThumbnail` for rendering individual slides in a shadow root, improving performance and reducing main-thread load.
- Updated `DeckThumbnailRail` to utilize the new thumbnail component, allowing for efficient slide navigation.
- Implemented keyboard shortcuts for deck navigation, enhancing user experience during presentations.
- Added tests for `buildDeckRenderInput` to ensure proper functionality of the deck stage fallback.
- Improved styling for loading states in the viewer, providing a smoother visual experience.
These changes aim to optimize the deck viewing experience by reducing resource consumption and enhancing interactivity.
* feat(deck): improve thumbnail loading and speaker notes editing experience
- Refactored `DeckSlideThumbnail` to enhance loading states with a new shimmer effect, improving visual feedback during thumbnail rendering.
- Updated `DeckThumbnailRail` to manage loading states for thumbnails, ensuring a smoother user experience.
- Simplified the speaker notes editing interface by removing the toggle switch, allowing direct editing from the notes body.
- Enhanced accessibility by adding roles and focus states to speaker notes elements.
- Added tests to verify the new loading states and speaker notes functionality.
These changes aim to optimize the user experience in deck navigation and speaker notes management, providing a more intuitive and responsive interface.
* feat(file-viewer): enhance version export functionality and speaker notes interaction
- Introduced new export options for file versions, including PDF and image formats, improving the ability to download and share content.
- Implemented a streamlined process for exporting version content, with progress indicators and error handling for a better user experience.
- Enhanced speaker notes editing by refining event handling to prevent unintended focus shifts, ensuring a smoother editing experience.
- Updated styles for improved visual consistency in the file version download interface.
- Added tests to verify the functionality of version exports and speaker notes interactions.
These changes aim to optimize the file viewer's usability and enhance the overall experience when managing and exporting project files.
* fix(web): polish export menus and creator filters
* fix(file-viewer): fall back to preview exports
* test(file-viewer): cover version export fallbacks
* test(file-viewer): assert loading skeleton by role
* fix(file-viewer): restore html source mode affordance
* fix(file-viewer): capture full version fallback snapshots
* docs: trim slides handoff eof
* test(exports): cover full preview snapshot requests
* test(file-viewer): account for snapshot options arg
* refactor(file-viewer, file-workspace): streamline export functions and enhance page creator dialog visibility
* test(file-workspace): enhance slide template creation and mock plugin responses
* feat(export): add support for versioned exports and enhance HTML export functionality
* feat(export): implement versioned export support across multiple formats and enhance related tests
* feat(file-viewer): enhance manual edit functionality with commit sequence tracking and add test for inline text session saving
* style(speaker-notes): update filmstrip and thumb-frame styles for improved responsiveness and add corresponding tests
* feat(file-viewer): enhance comment composer functionality with portal metrics and improve draw toolbar layout for mobile views
* feat(analytics): track slide deck viewing experience
Add analytics for the new deck/slides experience introduced in this PR:
the deck viewer surface, in-deck slide navigation, thumbnail rail, and
speaker-notes authoring. Presentation entry stays on the existing
present_popover click to avoid double-counting.
- contracts: DeckViewerSurfaceViewProps (surface_view),
DeckViewerClickProps (ui_click), SpeakerNotesSaveResultProps
(new speaker_notes_save_result event), wired into the event unions.
- web: track* wrappers + fire helpers in FileViewer — deck_viewer
surface_view on deck mount, slide_prev/next/reset, thumbnail_select,
thumbnail_rail_toggle (expand/collapse), speaker_notes_edit, and
speaker_notes_save_result (preview + presenter surfaces).
- tests: deck analytics suite asserting the emitted (event, props) pairs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(file-viewer, file-workspace): enhance export toast functionality and improve localization for page creation
* feat(home-view, plugins-home-section, agent-skill): update default facet preference, enhance category selection handling, and improve localization support
- Set `preferDefaultFacet` to true in HomeView component for better user experience.
- Introduced `handlePickCategory` function in PluginsHomeSection to manage category selection based on card layout visibility.
- Updated PRIMARY_CATEGORIES to reflect the new order and added localization for titles and descriptions in adaptAgentSkill.
- Enhanced tests to verify the correct handling of display copy and tags from SKILL frontmatter.
* feat(plugins-home, file-workspace): introduce commercial category labels and enhance deck handling
- Added a new module for resolving and localizing commercial category labels for plugins.
- Updated the FileWorkspace and PluginCard components to display the commercial category label on deck cards.
- Enhanced the PageCreatorPresetFrame to adjust frame classes based on deck presets.
- Refactored subcategory handling in facets to align with the new commercial category taxonomy.
- Improved localization support for new category labels across multiple languages.
* feat(deck-preview): implement deck preview scaling and enhance home hero layout
- Introduced `useDeckPreviewScale` hook to manage scaling of deck previews within a fixed 1280×720 logical viewport, ensuring proportional rendering across various templates.
- Updated `FileWorkspace`, `HomeHero`, and `PluginCard` components to utilize the new scaling functionality for improved visual consistency.
- Enhanced the layout of the home hero section to accommodate new subtype chips and descriptions, including a "More" dropdown for overflow handling.
- Improved localization support for new UI elements across multiple languages.
* fix(PreviewModal): clarify sidebar prop documentation and update test description
- Updated the documentation for the `PreviewSidebar` interface to specify that the sidebar's stage-edge handles are not shown when the sidebar prop is absent.
- Modified the test suite description for `PreviewModal` to be more concise and relevant.
* test(e2e): select prototype visual card
---------
Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* add post-update what's new card on home with release feed highlights
After an update, the home surface shows a one-time bottom-right card with
the release highlights (title, copy, optional image) and a "See what's new"
link. Content ships in the release feed metadata.json as an optional
whatsNew block sourced from tools/release/whats-new/<baseVersion>.json;
versions without highlights fall back to generic copy linking the release
notes. The card shows once per version, keyed on a locally stored
last-seen version, and never on fresh installs.
- packages/contracts: WhatsNewContent/WhatsNewResponse DTOs + analytics props
- daemon: GET /api/whats-new (channel feed fetch, 1h cache, stale/null
degradation) + od whats-new CLI mirror
- web: WhatsNewPopup card (CSS Module, i18n chrome in 19 locales,
surface_view/ui_click tracking), lastSeen decision logic in lib/whats-new
- release tooling: publish-metadata forwards the optional whatsNew block and
fails loudly on malformed files; docs in tools/pack/AGENTS.md and
tools/release/whats-new/README.md
* fix: gate whats-new card on active home view, soften Escape, validate locale overrides
Address review feedback on the post-update what's-new card:
- EntryShell passes `active={view === 'home'}` into WhatsNewPopup, and the
component defers its fetch/show decision (and `page_name: 'home'`
analytics) until Home is the active entry view, so direct routes like
/projects no longer surface the card or emit home-page events.
- The document-level Escape listener now ignores already-handled events
(`defaultPrevented`) and hides the card without marking the version as
seen or firing the dismiss analytics event, so a stray Escape no longer
permanently spends the once-per-version card.
- publish-metadata validates the optional `locales` block at publish time
(plain-object shape, non-empty `title`/`body`, HTTPS `linkUrl`) so
malformed locale overrides fail the publish loudly instead of being
silently dropped by the daemon parser; README documents the contract.
Generated-By: looper 0.9.11 (runner=fixer, agent=claude-code)
* fix(release): validate whats-new URLs by parsing, not prefix check
Replace the startsWith("https://") checks in readWhatsNewBlock with a
shared assertHttpsUrl helper that trims, constructs new URL(...), and
requires protocol === "https:", mirroring the daemon readHttpsUrl parser
so values it would silently drop (e.g. "https://") fail the publish
loudly for imageUrl, linkUrl, and locale linkUrl.
Generated-By: looper 0.9.11 (runner=fixer, agent=claude-code)
* fix(web): stop whats-new card fetch race from swallowing the card on first Home load
The card's fetch effect armed its once-guard when the fetch STARTED, and the
effect teardown re-armed it — so React StrictMode's double-invoke (dev) or a
Home toggle mid-fetch cancelled the first fetch, the second effect run saw the
guard still set and bailed, and the resolved-but-cancelled fetch re-armed the
guard without ever showing the card. The card then never appeared until the
Home view toggled again.
Arm the guard only once a decision is actually REACHED (fetch resolved with a
payload); keep the `cancelled` flag purely as a state-update guard that no
longer re-arms the fetch. A superseded fetch drops and the surviving one
records the decision, so the card shows on first Home activation and a genuine
mid-fetch Home exit still retries on the next activation.
Red spec: apps/web/tests/components/WhatsNewPopup.test.tsx renders under
StrictMode and asserts the card appears — red on the previous effect, green now.
* feat: add silent updater preference
* fix: block posthog in beta dry runs
* refactor(whats-new): drive the home card from a dedicated R2 document
Source the post-update "what's new" card from a single hand-curated document
on a dedicated R2 bucket (https://whatsnew.open-design.ai/whats-new.json,
overridable via OD_WHATS_NEW_URL) instead of per-version release metadata.
Operators edit that one file after a release; there is no publish tooling.
- Show-once is keyed on the document's `id`, not the app version: the card
shows whenever the id differs from the last one the client recorded, first
sight on a fresh profile included. This removes the version gating that could
never tell a fresh install from an existing profile upgrading across the
feature boundary (the reviewer's blocking finding) -- content identity
settles it instead.
- Daemon service just fetches the document and parses {id, ...content}; no
channel feed or release-version matching. Graceful degrade to no card on any
failure is preserved.
- Drop the now-dead release publish tooling: tools/release/whats-new/*, the
whatsNew forwarding in publish-metadata.ts, and its tests. Ops flow documented
in docs/whats-new.md.
- Remove the generic no-content fallback card and its two i18n keys; the card
shows only when the document has content.
Contracts, `od whats-new` CLI, and analytics updated to the {version,id,content}
shape.
* style(whats-new): align the home card with the marketing design
Match the reference card: brand serif body copy (var(--serif), same face as
the home hero), body + CTA stacked in a left column with the illustration
stretching to the card's full height on the right so there is no dead space,
a subtle CTA, and a slightly wider, softer card. CSS-module + markup only;
no behavior change (test ids and flow are untouched).
* style(whats-new): drop the title row, float the close over the card
Per design feedback the "Design system sync" label row is removed so the serif
body copy starts at the top edge; the ✕ now floats top-right as a bordered chip
that stays legible over the illustration. The title still labels the dialog via
aria-label for screen readers. Test asserts on the body + dialog name instead.
* style(whats-new): version eyebrow + release title as the card copy
Per design feedback: the top row is the "Open Design x.y.z" version eyebrow
(left) with the close button (right); the release title renders as the main
serif line (1-2 lines) and the illustration stretches to the card height; the
long body is dropped from the card. CTA + release-notes action unchanged.
* fix(whats-new): gate the card to release channels so it can't intrude on CI
The R2 rearchitecture dropped the daemon's channel gate, so development/CI
builds fetched the live document and showed the card on Home. That broke the
P0 "settings dialog reachable" smoke (getByRole('dialog') matched both the
settings modal and the what's-new card, which also carries role="dialog") and
would have dirtied every Home visual baseline. Restore the gate: only
beta/prerelease/preview/stable fetch the document; other channels resolve to no
card and never touch the network. OD_WHATS_NEW_URL still opts any channel in
for e2e fixtures that exercise the card on purpose.
* fix(whats-new): use role="complementary" instead of "dialog" for the toast
The card is a non-modal, dismissible announcement — not a dialog. As
role="dialog" it collided with getByRole('dialog') in the P0 Settings smokes
(settings-dialog-reachable, AMR reopen, Local CLI Codex fallback), which
strict-mode-failed the moment the card rendered on Home. A complementary
landmark is the correct a11y role for supporting content and never matches a
dialog query, so those P0s pass regardless of whether the card is showing. The
daemon channel gate (5f17873e0) still keeps the card off development builds.
---------
Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com>
Co-authored-by: PerishCode <perishcode@gmail.com>
Co-authored-by: lefarcen <935902669@qq.com>
Bring docs/i18n/README.zh-TW.md back in line with README.md:
- Add the hosted `curl ... install.sh | sh` install path plus the
install.sh wrapper note (#4866).
- Add the WSL2 note in the coding-agent install section and the
WSL2 / wsl-setup.md pointer in the run-from-source line.
- Add the macOS Docker Desktop bridge-networking note.
- Add utm_source / utm_medium / utm_content attribution to the six
open-design.ai links (#4792).
Headings and structure unchanged; all referenced docs (wsl-setup.md,
deploy/README.md#docker-desktop-on-macos, windows-troubleshooting.md)
exist.
* docs: align README positioning with the Vibe Design Workspace umbrella
Lead with the product's own category (The Vibe Design Workspace) instead of the
competitor keyword, keeping 'open-source Claude Design alternative' as the
subtitle / SEO phrase. Move 'local-first' off the front of the main keyword to
describe the desktop app, and replace the hardcoded skill/system/plugin counts
in the hero alt and intro line with keyword phrasing (the counts stay in the
dedicated Skills / Design Systems sections). Scoped to the README top; the
translated READMEs under docs/i18n/ are a follow-up.
* docs: refresh the README release callout to 0.13.0 (Stay in Flow)
The top-of-README release blurb was still on 0.10.0, three releases behind
(0.11 The Bazaar, 0.12 Brand-backed Design System, 0.13 Stay in Flow). Update
it to 0.13.0 with its session-resume / model-picker / export-handoff theme and
point the links at the 0.13.0 download and release notes.
* docs: rename AMR to Open Design Cloud across the README
AMR (Agentic Model Router) has been folded into Open Design Cloud, so the
callout, top-nav link, and roadmap entry now say Open Design Cloud and point at
/cloud/ instead of /amr/. Also normalizes the one-word OpenDesign Cloud mention
in the 0.13.0 blurb.
* docs(i18n): rename AMR to Open Design Cloud across the translated READMEs
Mirror the EN README rename in all 13 localized READMEs (ar de es fr ja-JP ko
pt-BR ru th tr uk zh-CN zh-TW): the model-service callout, CTA, top-nav link,
and roadmap entry now say Open Design Cloud and point at /cloud/ instead of
/amr/. Brand name kept in English per convention.
* docs: join the README H1 value props with '&' instead of an em dash
* docs: unlink Claude Design mentions in the READMEs
The 'Claude Design' text was a reference link to an X/Twitter post. Drop the
link (and the shared [cd] reference definition) across the EN and 13 localized
READMEs so 'Claude Design' stays plain keyword text and we don't hand a
competitor an outbound backlink.
* docs: make the hero image alt text descriptive for screen readers
The hero alt had drifted into positioning/SEO copy that also no longer matched
the image. Rewrite it to describe what the banner actually shows — the
headline, the classical columns-and-figures artwork, and the stat cards — so
screen readers get an accurate description. Categories are named without
hard-coding counts.
* docs(i18n): refresh the translated README release callouts to 0.13.0
Sync the localized release banners from the stale 0.10.0 blurb to the 0.13.0
'Stay in Flow' announcement (session resume / faster model pick / export
handoff) across all 13 locales, matching the EN README and pointing at the
0.13.0 download + release notes. Resolves the EN/localized version divergence
at the README entry point.
---------
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* feat(landing-page): add 5 design-agent alternative comparison pages
Add /alternatives/{stitch,genspark,figma-make,qoder,trae}/ pages comparing
Open Design with five AI design/coding tools. Each page carries deeply
researched, fact-specific copy (pricing, usage limits, lock-in, honest
trade-offs), real competitor screenshots plus current Open Design product
screenshots, a feature table, and a decision matrix.
Rebuild the shared alternative-detail renderer onto an editorial band layout
(full-width alternating bands, one unified content column, dark closing CTA
band) so every /alternatives/ page is visually consistent. Render list and
table block text through set:html so inline <b> emphasis works.
Localise all five pages into the 11 landing locales (machine-translated then
native-audited) and re-shard into alternatives-i18n.part-*. Wire the new slugs
into the /compare/ hub and the footer. Save the reusable current Open Design
UI screenshots under docs/screenshots/current-2026-06/.
* fix(landing-page): address review on alternatives layout
- clip page-level horizontal overflow on .v4 pages so the 100vw full-bleed
shell no longer jitters when a vertical scrollbar is present
- port the FAQ accordion refinements (border, padding, type scale) under .v4
using the landing token set, since the rich wrapper moved off .solution-page
---------
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* feat(analytics): design-system tracking foundation (project_kind, entry source, brand picker)
Implements the first slices of the design-system tracking spec:
- §1 project_kind: brand-extraction backing projects now report
project_kind=design_system so DS-project runs (creation + edits)
drill down cleanly instead of collapsing into 'brand'.
- U3/U4: report design_system_source from the real selection source
(request->user_selected, plugin->template_inherited, project->
project_saved, app-default->default) instead of the hard-wired
unknown/not_applicable; add design_system_kind (official/custom,
derived from the user:<id> shape) and design_system_slug (official).
- §3.1 create entry source: thread the real entry (onboarding /
design_systems_page / composer_picker / home_card / library /
project_canvas) from each navigate() call site into the create
page_view and create_result, replacing the binary heuristic.
- C7-C9 preset-brand picker: instrument the "Start from a brand"
trigger click, picker surface_view, and brand_pick with
preset_brand_category (never the domain).
Contracts: add TrackingDesignSystemKind, TrackingDesignSystemEditSurface,
DesignSystemsPresetBrandPicker{Click,SurfaceView}Props; extend
RunCreatedProps with design_system_kind/slug/edit_surface and both
entry_from enums with composer_picker/project_canvas/library.
Adds docs/design-system-tracking-spec.md.
Verified: contracts build + 170 tests, web typecheck + full suite (3463),
daemon typecheck + run-analytics/brand-extraction tests (70).
* feat(analytics): track AI-optimize (design_system_enrich) click
C13 (tracking spec §3.3): instrument the "AI Optimize" banner CTA on a
programmatically-extracted DS-as-project so the AI-conversion rate
(clicked ÷ programmatic creates) is visible.
Contracts: add design_system_enrich area, DesignSystemEnrichClickProps,
DesignSystemEnrichResultProps, and the design_system_enrich_result event
name (result event reserved for the C14 follow-up).
Adds an implementation-status table to the spec. C14 (enrich_result) and
C15 (ProjectMetadata.enrichmentStatus) remain follow-ups since they need
correlation with the async enrichment run's completion.
Verified: contracts build, web typecheck, brand-enrichment + analytics
tests (89).
* feat(analytics): report all design-system create sources (ds_source_origins)
Comment ②: multi-source creates were flattened to a single `mixed`
design_system_source, hiding which sources combined. Add a comma-joined
`ds_source_origins` (e.g. `source_url,local_code`) on create_result that
lists every source actually used, keeping the singular field for
back-compat. Mirrors the target_platforms/connectors multi-value convention.
Verified: contracts build, web typecheck.
* feat(analytics): distinguish onboarding build-DS vs skip-to-home (C2)
C2 (tracking spec §3.1): the final onboarding step forks into "Build a
design system" and going straight Home, but both reported
completion_type=completed_without_design_system, so the skip rate was
invisible. Parameterize runOnboardingCompletion so the build fork reports
completed_with_design_system and the home forks report
completed_without_design_system. Update the EntryShell onboarding test,
which clicked "Build a design system" yet asserted the without value.
Verified: web typecheck, EntryShell onboarding tests (24).
* feat(analytics): instrument design-system edit lifecycle (E1-E3)
Tracking spec §3.4/§3.6:
- E3 (direct module edits, ui_click area=design_system_edit, all carrying
edit_surface=direct_module + artifact_kind=design_system + the DS id):
DesignSystemsTab general ops (edit-with-agent / refresh / download / reset),
DesignKitView module buttons via the parent handlers (logo/font/image
upload incl. paste, color edit, logo/image delete, design_md edit-save),
and the BrandPreviewCard three actions (use-in-chat / open-project / delete).
- E1 (agent-routed edits): a DS-project run editing an EXISTING design system
now carries edit_surface — comment/mark from their entry_from, otherwise
chat. First-generation runs get none.
Contracts: DesignSystemEditClickProps (+ union); reuses the
TrackingDesignSystemEditSurface added earlier and RunCreatedProps.edit_surface.
Not wired (enum reserved / no handler today): kit_import, kit_open (external
link in the stateless kit view), design_md_copy/upload.
Verified: contracts build; web + daemon typecheck; DS/Brand/Kit web tests
(89) + daemon run-analytics tests (44).
* feat(analytics): AI-optimize result + enrichment status (C14/C15)
Closes the programmatic-vs-ai_refined comparison gap (tracking spec §6):
- C14: the AI-optimize run is tagged (analyticsHints.dsEnrichment) from the
ProjectView banner CTA; when it settles, the daemon emits
design_system_enrich_result (result / design_system_id / project_id /
run_id / duration_ms / error_code).
- C15: on a successful enrichment run the daemon flags the backing project
metadata enrichmentStatus='ai_refined' + enrichmentCompletedAt, so the two
DS cohorts can be split for retention/usage analysis.
Contracts: ProjectMetadata.enrichmentStatus/enrichmentCompletedAt; reuses
the design_system_enrich_result event + DesignSystemEnrichResultProps added
earlier. ProjectChatSendMeta gains dsEnrichment.
Verified: contracts build; web + daemon typecheck; daemon run-analytics +
brand-extraction tests (70); web brand-enrichment tests.
* fix(contracts): declare dsEnrichment hint in ChatAnalyticsHints
The daemon run route reads analyticsHints.dsEnrichment and ProjectView's
AI-optimize path sends it, but the shared ChatAnalyticsHints DTO did not
declare the flag — leaving the web/daemon HTTP shape ahead of the contract
layer so typed ChatRequest callers could not discover or type-check the hint
that drives design_system_enrich_result and the ai_refined metadata stamp.
Declare dsEnrichment?: boolean with analytics-only semantics and add a
request-shape test that compile-fails if the field is dropped again.
Addresses review feedback on PR #4740.
* chore: ignore .playwright-mcp capture output
Local Playwright MCP runs write YAML page snapshots and PNG screenshots to
.playwright-mcp/. These are ad-hoc local visual-check output (including local
UI/session state), not a maintained test fixture, and per the root AGENTS.md
local runtime data must stay out of git. Add the ignore rule so the directory
is never accidentally staged again.
* fix: repair AI optimize enrichment tracking
Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex)
* fix: track design kit module edit clicks
Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex)
* fix: stabilize project P0 catalog loading
Stub unrelated catalog endpoints in the scoped project workspace and runtime Playwright flows so the P0 checks assert their target behavior instead of waiting on large registry responses.\n\nGenerated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex)
* fix: guard design-system tracking repairs
Generated-By: looper 0.9.10+codex.autoclean (runner=fixer, agent=codex)
---------
Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com>
Co-authored-by: Looper <looper@noreply.github.com>
Windows users running agent CLIs inside WSL were landing on the native Windows guide and copying the README MCP command directly, which left Linux /usr/bin/od shadowing, daemon origin, Node ABI, and Codex config parse failures unexplained. Add a WSL2 guide and teach the Codex config normalizer to drop nested feature tables that current Codex parses as maps instead of boolean flags.
Constraint: WSL agent CLIs need the same Linux environment for the wrapper, daemon, Node modules, and credentials
Rejected: Docs-only workaround | would leave daemon-launched Codex runs failing on nested features tables
Confidence: high
Scope-risk: narrow
Directive: Keep WSL-specific guidance separate from native Windows PowerShell troubleshooting
Tested: pnpm --filter @open-design/daemon exec vitest run -c vitest.config.ts tests/codex-config-normalize.test.ts
Tested: pnpm --filter @open-design/daemon typecheck
Tested: pnpm guard
Tested: git diff --check
Not-tested: Manual WSL2 end-to-end MCP install on a Windows host
Related: Fixes#4648
The "install into your coding agent" sections pointed users at
`curl -fsSL https://open-design.ai/install.sh | sh -s <agent>`, but that
URL returns 404 — the bootstrap script was never published, and a
standalone `od` CLI is not yet distributed. Every README (English + 12
i18n) shipped a copy-paste command that fails.
Replace it with the real, shipped command `od mcp install <agent>`,
matching the Platform Compatibility table already present in each file
("Once OD is installed, a single `od mcp install <agent>` ..."). The
surrounding "one-line install" comment stays accurate and the
install-OD-first prerequisite is covered by that table.
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New Windows users hit a blue Defender SmartScreen dialog the first time they
run the packaged installer, with Run anyway hidden behind More info. The
Windows troubleshooting guide only covered the dev/source setup, so there was
no answer for the very first thing an end user sees. Add a section that
explains why the warning appears (unsigned build, not a threat), how to
proceed (More info then Run anyway), and how to verify the download source and
SHA-256 checksum first.
Co-authored-by: Nagendhra <nagendhra405@gmail.com>
* feat(daemon): add Amp CLI as a coding-agent adapter
Amp (ampcode.com) runs headless via `amp -x --stream-json`, which emits
the Claude Code-compatible stream JSON format the daemon already parses,
with the prompt delivered over stdin. Add it as a coding-agent adapter
reusing the claude-stream-json parser; the model picker maps to Amp's
agent --mode (smart/deep/rush).
- new ampAgentDef + registry entry + install metadata
- web agent label/alias
- replay mock (renders via the claude renderer)
- docs adapter-catalog row + README CLI count (21 -> 22)
- adapter buildArgs/stream-format test
* fix(daemon): order Amp adapter at P2, not first-run default
Move ampAgentDef next to copilot (the other P2 local headless CLI adapter)
instead of the head of BASE_AGENT_DEFS. The daemon preserves AGENT_DEFS
order in /api/agents and the web app fills an empty config with
agents.find((a) => a.available), so listing Amp first made it the default
engine ahead of AMR/Claude/Codex for any user with amp on PATH and no
persisted agentId — inconsistent with its P2 classification. Reordering
restores the prior first-run default. Addresses PR review feedback.
---------
Co-authored-by: Siri-Ray <2667192167@qq.com>
* docs(readme): announce 0.10.0 and add AMR entry across all READMEs
* docs(readme): link Gemini CLI and Kimi CLI rows in agent compatibility table
* docs(readme): expand AMR acronym to Open Design Model Router in the AMR blockquote
* docs(readme): rename nav AMR link to Model Router and correct acronym to Agentic Model Router
---------
Co-authored-by: qiongyu1999 <2694684348@qq.com>
* fix(bake): classify deck-vs-scroll by viewport, real-wheel pan, motion config
Systematic audit of all 126 baked previews surfaced three capture bugs:
- 2 vertical pages misread as decks (the input probe wheel-scrolled them and the
scroll-driven animation looked like a slide change), so they got walked
sideways. Classify by viewport height instead: a fixed-viewport page is a deck,
a vertically-scrollable page is a landing page (pan it) even with a horizontal
marquee/carousel sub-component.
- 9 scroll-hijack landing pages (custom/transform scroll) that window.scrollTo
can't move, so the pan was static. Pan those with REAL wheel events
(page.mouse.wheel), which drive the page's own scroll handler.
- single-screen pages now hold (static) instead of being forced down a deck path.
Plus an opt-in override: authors can declare od.preview.motion ('scroll' | 'deck'
| 'static') and the bake honors it, auto-detecting only when it's absent. Schema
+ plugins-spec document the field. (Also strips a stray NUL byte from the hash
line that made the file read as binary.) BAKE_VERSION -> 4 re-bakes everything.
* perf(plugins-home): only decode visible gallery clips + stream first frame
Two cheap wins for the baked gallery videos:
- Decouple mount from play. The tile mounts the <video> across the wider inView
margin (so scroll-in/hover never remounts + reloads), but only PLAYS while
truly visible — off-screen tiles in the mount margin hold their poster frame
paused instead of all running a simultaneous decode. Adds a 0-margin visible
observer in PreviewSurface alongside the existing near one.
- preload=metadata instead of auto: paints the first frame off the +faststart
header instead of eagerly buffering the whole clip up front, so tiles show fast
and don't saturate the network. The idle hold buffers the pan before hover.
* perf(plugins-home): keep baked clips mounted across a scroll window
Scrolling a tile out of view and back re-showed a load even though the clip
bytes are HTTP-cached (R2 immutable): the <video> unmounted at the tight 120px
margin, so scroll-back remounted a fresh element that re-fetches metadata and
re-decodes the first frame. Add a wide keep-mounted observer (~1500/1800px) so a
clip stays mounted for a few screens — instant scroll-back — while iframes keep
the tight margin and play stays gated to the truly-visible zone (paused, not
unmounted, off screen).
* fix(bake,contracts): probe scroll mechanism before recording; validate motion
Address review:
- Move the window.scrollTo probe before Page.startScreencast so its scrollTo
160 -> 0 jump isn't baked into the head of the pan as a visible lurch.
- Type od.preview.motion in the Zod PluginManifestSchema (enum scroll|deck|
static) so an invalid value fails doctor/install instead of silently parsing
via passthrough and being ignored by the bake; add contract test coverage.
* fix(bake): auto-detect single-screen fixed pages as static, not deck
A fixed-viewport page is only a deck if an input actually advances it; probe the
driver during auto-detect and fall back to 'static' (default viewport + a hold)
when nothing moves it, instead of routing every non-scrollable page through the
deck path where walkSlides(null) just held at the deck-sized capture. Extracted
the arrow/wheel probe into probeDeckDriver(). Verified: a waitlist page now bakes
a 2.5s static hold, guizang still walks, acreage still pans.
---------
Co-authored-by: audit <a@b.c>
* chore(docs): move translated docs into docs/i18n/
Collect the translated README/QUICKSTART/CONTRIBUTING/MAINTAINERS files
(including the Korean set) into docs/i18n/, leaving only the English sources
in the repo root so the GitHub project home page file list stays clean.
Rewrite internal links for the new layout (../../ for repo-root resources,
sibling filenames between translations), update both switcher conventions,
the i18n-check mixed-layout support, the contributors-wall workflow globs,
TRANSLATIONS.md guidance, and drop now-dead root translation paths from the
fork-PR docs allowlist.
* fix(docs): correct root-relative links in Korean contribution guide
Prefix repo-root targets (scripts/sync-design-systems.ts, TRANSLATIONS.md,
package.json, .github/pull_request_template.md) with ../../ so they resolve
from the new docs/i18n/ depth; sibling translated docs stay bare.
Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code)
---------
Co-authored-by: qiongyu1999 <2694684348@qq.com>
* docs: add Alibaba Cloud (阿里云) deployment guide
Adds docs/deployment/cloud/aliyun.md with:
- ECS single-machine deployment using the existing Docker Compose stack
- ACK (Kubernetes) reference manifest and multi-replica caveats
- Image acceleration setup via Alibaba Cloud Container Registry
- ICP filing (备案) overview for mainland China public hosting
- Common pitfalls and references to existing Docker / install-guide docs
Docs-only slice for #1025. Live ROS templates, one-click scripts, and
verification screenshots are out of scope here and tracked as follow-up
work in the issue.
* docs: fix ACK manifest reachability and OD_ALLOWED_ORIGINS alias
Address PerishCode review on PR #3275:
- The daemon defaults to OD_BIND_HOST=127.0.0.1 (apps/daemon/src/server.ts),
so the readinessProbe and ClusterIP Service in the previous manifest could
never reach the Pod. Add OD_BIND_HOST=0.0.0.0 + OD_API_TOKEN (required by
the bound-API-token guard for non-loopback binds) and a kubectl secret step.
- The daemon reads OD_ALLOWED_ORIGINS, not OPEN_DESIGN_ALLOWED_ORIGINS.
OPEN_DESIGN_* names are Compose-only aliases mapped in deploy/docker-compose.yml.
Use OD_ALLOWED_ORIGINS for the direct-container ACK path and call out both
names in the network-exposure section and the pitfalls table.
Also adds an Ingress / Bearer-token note for operators fronting the
Service externally.
* docs: document OD_API_TOKEN bearer-token forwarding in Nginx block
PerishCode follow-up review on PR #3275:
The Path A Nginx block as written would 401 every UI call except the
three open probes (/api/health, /api/version, /api/daemon/status). Same
root cause as the ACK fix in 9d5f6ec — the auth model affects both paths,
not just direct-container deployments.
Verified against source:
- deploy/scripts/install.sh:386 always writes a generated OD_API_TOKEN
into deploy/.env (no opt-out flag).
- deploy/docker-compose.yml:18 requires OD_API_TOKEN (Compose ? syntax)
and binds OD_BIND_HOST=0.0.0.0, so the daemon-side bearer middleware
is always active for the Compose path.
- apps/daemon/src/server.ts:3777 keys the loopback short-circuit on
isLoopbackPeerAddress(req.socket?.remoteAddress) — the TCP peer, not
X-Forwarded-For — so a reverse-proxied request from a Docker bridge
IP never gets the localhost bypass.
Adds proxy_set_header Authorization to the Nginx block, a paragraph
explaining where OD_API_TOKEN comes from, and updates the pitfalls row
that previously only mentioned CORS to also list the missing-bearer
cause.