mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-10-29 08:07:48 +09:00
0.294.0
40
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9ec4c820e1 |
fix: Use writable npm cache for previews (#6272)
## Summary - Use a writable `.webstudio/preview/.npm-cache` for npm preview installs when `npm_config_cache` is not explicitly configured. - Preserve explicit npm cache settings and pnpm behavior. - Document a safe recovery path that requires no cache deletion. This removes preview startup failures caused by an unwritable default npm cache. Initial dependency installation and its network/download cost still remain when preview dependencies are not already installed. ## Technical choices - Keep the cache beside the isolated generated preview because that directory is already writable and reused across regenerations. - Let an explicit `npm_config_cache` continue to take precedence. - Do not retry arbitrary install failures or classify package-manager prose. ## Todo - [x] Reproduce npm dependency installation against an unwritable cache before changing code. - [x] Reproduce #6274 at the same dependency-install stage used by session-backed screenshots. - [x] Demonstrate the regression assertion failing before the fix and passing afterward. - [x] Use the preview-local cache only for npm without an explicit cache. - [x] Preserve explicit npm cache configuration and pnpm behavior. - [x] Verify the real dependency installer against an unwritable project npm cache. - [x] Verify session-backed screenshot flow proceeds from successful preview preparation to browser capture. - [x] Review documentation impact and update the CLI manual plus generated MCP documentation. - [x] Review fixture impact; no project fixture inputs or outputs are affected. - [x] Review the final diff for correctness, duplication, and unnecessary complexity. ## Verification - Actual npm install reproduced #6269 and #6274 with `EPERM` against an unwritable cache. - Real preview dependency installation passed after the fix while project npm configuration still pointed at that cache. - Fail-before/pass-after regression demonstrated. - `pnpm --filter webstudio test` — 65 files, 1,044 tests passed. - `pnpm --filter webstudio typecheck` - `pnpm lint` - `pnpm check:generated-docs` - Formatting and diff checks passed. - GitHub CI after rebasing onto current `main` — 30 checks passed, 7 skipped, no failures. - Agent evaluations were not run because they require separate explicit approval. Closes #6269 Closes #6274 |
||
|
|
1b48716ff4 |
docs: Document MDX-backed Content Blocks (#6273)
## Summary - Document how people create, connect, edit, validate, and publish MDX-backed Content Blocks. - Document the complete MCP workflow, including scoped expression sources, frontmatter updates, diagnostics, conflicts, and disconnect behavior. - Add two focused screenshots for the human workflow. - Fix issues found by a low-reasoning MCP agent while executing every documented workflow. Ref #6182 ## Implementation notes - Connection confirmation uses the public `confirmReplacement` field because `confirm` is reserved as a hidden transport field. - MCP edits frontmatter with `update-content-block-frontmatter`; materialized MDX elements are not persistent targets for generic instance mutation tools. - Reload now intentionally discards a conflicted local source and accepts the Asset's latest storage revision before an edit is reapplied. - Generated MCP documentation and runtime contracts are updated from their source files. ## Checklist - [x] Document the human MDX Content Block workflow. - [x] Document MCP discovery, connection, editing, diagnostics, frontmatter, dynamic sources, conflicts, and disconnection. - [x] Add only screenshots that clarify otherwise hard-to-describe UI steps. - [x] Test every documented MDX capability through the local MCP CLI with a low-reasoning agent. - [x] Reproduce and fix the replacement-confirmation schema mismatch. - [x] Reproduce and fix persistent-session conflict reload and reapply. - [x] Add regression tests that failed before each product fix and pass afterward. - [x] Regenerate runtime contracts and generated MCP documentation. - [x] Review authoritative `docs/` content and update affected pages. - [x] Run affected tests, typechecks, formatting, and diff checks. ## Verification - Project Build: 208 affected tests passed. - Content Engine Asset session: 8 tests passed. - CLI documentation tests: 14 tests passed. - MCP docs generator: 3 tests passed. - Content Engine, Project Build, CLI, and MCP docs typechecks passed. - `pnpm oxfmt --check` passed. - `git diff --check` passed. - Low-reasoning MCP evaluation passed all documented workflows, including a real two-client revision conflict, reload, reapply, and final saved inspection. |
||
|
|
f6c524572d |
feat: add Builder dark theme and rebuild colors
## Summary
Rebuilds Webstudio’s color system, migrates the entire Builder to it,
and introduces a complete dark theme.
A small set of theme colors and contrast controls now drives the
interface through relative CSS colors:
```text
Theme colors and contrast
↓
Light/dark derivation bounds
↓
Derived color families
↓
Reusable semantic colors
↓
Component composition
↓
Builder interface
```
CSS is the runtime source of truth. Light and dark modes share the same
theme inputs, so changing a theme color automatically updates its
surfaces, content, borders, states, and component presentation. The
refactor turns dark mode into a first-class Builder theme rather than a
separately maintained palette.
This is an atomic migration. Legacy color names and compatibility
aliases will not remain after all consumers have moved.
## Scope
- The color source, derivation model, semantic vocabulary, validation,
typing, and Storybook overview.
- Every design-system component.
- Builder, dashboard, authentication, shared UI, Query Builder, stories,
and tests that consume the legacy color scale.
- Removal of the legacy Stitches color scale after its final consumer is
migrated.
- A complete dark theme across application UI while keeping authored
canvas content independent.
- Complete light and dark visual verification.
- Unified browser-test infrastructure: Vitest Browser Mode for Design
System browser contracts and standard Playwright Test for all Builder
E2E workflows.
Literal colors remain only where color is the actual content or belongs
to a deliberately separate system, such as user-authored values,
external previews, brand artwork, data visualization, functional canvas
overlays, and source assets. Every remaining exception must have an
explicit owner.
## Architecture decisions
- Theme authors control six color families and three bounded contrast
controls.
- Relative CSS colors derive the rest of the system.
- Dark mode changes derivation bounds instead of maintaining a second
independent palette.
- Components consume a small reusable semantic vocabulary.
- Component states and exceptional presentation are composed inside
components.
- Builder-specific categorical meaning uses focused composite recipes,
not intent semantics or a larger global vocabulary.
- TypeScript validates public semantic CSS-variable names but does not
generate runtime colors.
- No token-manager dependency, compatibility aliases, or
component-specific public color tokens.
- A new semantic or theme variable is added only when existing semantics
and local composition cannot represent a reusable cross-feature
decision.
## Todo
### Color-system foundation
- [x] Establish direct CSS as the runtime source of truth.
- [x] Define bounded theme colors and contrast controls.
- [x] Derive light and dark modes from the same theme inputs.
- [x] Reduce the semantic inventory to reusable decisions and explicit
accessibility pairs.
- [x] Generate only TypeScript names for public semantic CSS variables.
- [x] Validate layers, references, cycles, consumption, naming,
generated types, and browser-computed contrast.
- [x] Add the Storybook color-system overview and theme controls.
- [x] Document the architecture and its relationship to the public Craft
specification.
### Design-system migration
- [x] Replace every active legacy color consumer in design-system
components and Storybook chrome.
- [x] Compose component states locally without component-specific public
tokens.
- [x] Preserve intentional preview and sample-content colors.
- [x] Add complete positive, negative, warning, informative, and accent
accessibility pairings.
- [x] Validate light and dark scheme-bound references independently.
- [x] Verify the design-system package with typecheck, lint, formatting,
Storybook, and 222 tests.
### Inventory and contract
- [x] Inventory all 319 legacy references across 107 Builder, Query
Builder, story, test, and design-system files.
- [x] Classify every reference as a direct semantic replacement, local
composite recipe, documented literal exception, or removable code.
- [x] Record the intentional authored-content, external-preview,
functional-preview, data-visualization, brand, and source-asset
exceptions.
- [x] Treat the public semantic vocabulary as closed by default and
justify any proposed addition by cross-feature reuse and accessibility
need.
- [x] Keep Builder code limited to typed public variables accepted by
`cssVar()`.
### Theme infrastructure
- [x] Add `system` (default), `light`, and `dark` application
preferences.
- [x] Persist the preference in existing client settings and resolve
`system` through `matchMedia`.
- [x] Apply the resolved scheme before paint and respond to
operating-system changes.
- [x] Expose the persisted theme control under **View → Color scheme**.
- [x] Keep authored canvas documents independent from the application
theme.
- [x] Ensure portals, overlays, embedded surfaces, and third-party
controls receive the correct interface scheme.
### Generic interface migration
- [x] Migrate shared dialogs, project settings, notifications, controls,
and Query Builder.
- [x] Migrate dashboard, authentication, publishing, and shared
application UI.
- [x] Migrate the Builder loading state, topbar, sidebars, navigator,
workspace, footer, settings, pages, alerts, and menus.
- [x] Replace fixed interface literals alongside their owning surfaces.
- [x] Remove the old scrollbar variable and hardcoded loading color.
### Style panel and style-source recipes
- [x] Migrate ordinary style-panel inputs, labels, layouts, spacing,
alignment, menus, property states, and value editors.
- [x] Model style-source provenance, kind, interaction, and error as
separate axes.
- [x] Compose categorical style-source colors from neutral and
accent-relative colors.
- [x] Use negative semantics only for actual errors, not overwritten
provenance.
- [x] Reuse one feature-owned recipe across style-source controls,
badges, menus, and values without adding global tokens.
### Canvas and editors
- [x] Migrate canvas selection, reusable outlines, grid guides, resize
handles, labels, badges, and overlays.
- [x] Keep collaborator colors as data visualization while guaranteeing
readable labels.
- [x] Prevent Builder theme values from leaking into authored content.
- [x] Migrate editor surfaces, selections, autocomplete, lint states,
and tooltips.
- [x] Derive syntax visualization from neutral and accent-relative
colors; reserve intent colors for diagnostics.
### Explicit color domains
- [x] Isolate external search and social previews from the application
scheme.
- [x] Preserve user-authored CSS values, functional color previews, and
checkerboards.
- [x] Review brand surfaces independently in both schemes.
- [x] Document every retained literal in the exception ledger.
### Stories, tests, and legacy removal
- [x] Migrate all affected Builder stories and tests.
- [x] Replace the design-system test that intentionally references the
legacy scale.
- [x] Add theme-preference and scheme-resolution behavior tests.
- [x] Remove the legacy `design-tokens.color` registry.
- [x] Remove the Stitches `colors` scale and `rawTheme.colors`.
- [x] Remove color-name conversion code that exists only for the legacy
scale.
- [x] Add a focused repository check that rejects legacy references.
- [x] Confirm no compatibility mappings or deprecated aliases remain.
### Browser-test infrastructure
- [x] Run pure Design System tests in Node and browser-dependent tests
in Vitest Browser Mode with Playwright Chromium.
- [x] Migrate all 79 Builder E2E workflows from the custom harness to
standard Playwright Test.
- [x] Replace filename-based shard discovery with standard Playwright
sharding.
- [x] Preserve clean-backend shard retries and upload Playwright failure
artifacts in CI.
- [x] Remove the custom runner, registry, and timeout infrastructure.
### Verification and documentation
- [x] Compare light-mode visual regressions directly with `main`; review
every difference rather than accepting snapshots wholesale.
- [x] Add representative dark coverage for dashboard, Builder shell,
style panel, dialogs, editors, canvas tools, and status states.
- [x] Test default and extreme custom-theme presets.
- [x] Verify semantic and categorical-recipe contrast.
- [x] Test first paint, persistence, system changes, portals, and canvas
isolation.
- [x] Run affected tests, typechecks, lint, formatting, and Storybook
checks.
- [x] Review fixture impact; no fixture inputs or generated outputs are
affected.
- [x] Review authoritative `docs/` content and update it where needed.
- [x] Review the final diff and make this checklist reflect delivered
scope.
## Current verification
- Design-system typecheck and generated-type freshness: passed.
- Design-system tests: 222 passed, including the full theme-parameter
contrast sweep and browser component coverage.
- Builder typecheck and production build: passed.
- Theme preference and scheme-resolution tests: 10 passed.
- Scoped Oxlint, formatting, and diff checks: passed.
- Design-system Storybook build and representative light/dark visual
review: passed.
- Builder E2E: 80/80 Playwright entries passed (setup plus 79
workflows).
Ref #3818
Closes #6267
|
||
|
|
f9681dc30f |
feat: MDX-backed Content Blocks (#6234)
## Summary Supersede #6182 with a clean implementation of MDX-backed Content Blocks on top of the unchanged `main` Content Block editing model. A connected `.mdx` Asset changes where authored children are loaded and saved; it must not change how Content mode inserts, edits, selects, moves, copies, or deletes instances. The previous implementation remains available in `agent/mdx-content-block-6124` and `agent/mdx-content-block-6124-review`. Reuse its independently tested parsers, converters, schemas, Asset repository, template resolution, publication, MCP, and UI work where those pieces fit the corrected architecture. Do not port its per-operation storage routing, projected editing stores, MDX undo/history, or atomic multi-root machinery. Ref #6124 Ref #6182 Closes #6261 ## Locked behavior - `.md` keeps its existing Markdown behavior; `.mdx` enables MDX. - Standard Markdown structures are stored as Markdown. JSX is used only for structures Markdown cannot represent losslessly. - Generic elements use `<ws.element ws:tag="…">`; template instances use `<ws.element ws:name="…">`. - Invalid, unsafe, or unsupported MDX never prevents editing the file or publishing the project. Builder and publication use the same recovery result: recoverable nodes are skipped with source-located warnings, while an unrecoverable document renders no authored file content in either environment. - Connecting a source never serializes existing Content Block children into the file. **Connect** removes ordinary persisted children, preserves Templates, sets `src`, and uses file content. - Disconnecting resets `src`, discards derived instances, leaves the Content Block empty, and never changes the Asset. - While connected, normal Content Block mutations update in-memory instances synchronously. Asset persistence happens afterward and never blocks rendering. - Genuine external revision conflicts use the standard reload-required flow. Rapid local edits are ordered/coalesced and must never conflict with each other. - Repeated scopes use Content Block ID plus Collection item identity. - Multiple Content Blocks may intentionally share one MDX Asset. They share one revisioned document session and edits propagate to every connected occurrence. - Missing templates show warnings/placeholders only in Builder and are skipped on published sites. ## Reuse strategy - [x] Audit all 62 original implementation commits and 5 later review/fix commits - [x] Reuse the shared Content Engine Markdown/MDX AST, parser, serializer, diagnostics, reference discovery, and tests - [x] Reuse SDK source schemas, instance-name utilities, unique template naming, and source-integrity validation - [x] Reuse template resolution/materialization and authored-tree conversion after removing storage-operation coupling - [x] Reuse revisioned Asset content repository, authorization, limits, and browser/server transport - [x] Reuse publication, document-graph, CLI, MCP, source-control UI, frontmatter UI, and E2E work where contracts remain valid - [x] Reuse tests as behavioral specifications; rewrite tests that assert the rejected projection/routing architecture - [x] Do not port per-operation MDX routing, alternate projected mutation stores, semantic reconciliation after each command, MDX Builder history/undo, atomic multi-file rollback, or canvas loading/saving UI ## Old-branch porting map — do not rewrite Before implementing any checklist batch, inspect the named implementation and tests on `agent/mdx-content-block-6124-review`. Move the implementation and its tests first; change only the boundary that conflicts with the rebuilt architecture. Do not create a second implementation under a new name. When a test encodes the rejected projected-store architecture, retain its behavioral assertion and replace only its setup. ### Already ported - `parseMarkdownAst`, `createMdxDocumentFromMarkdown`, `parseMdxDocument`, `serializeMdxDocument`, `preferMarkdownSyntax`, `discoverMdxBodyAssetReferences`, `discoverMdxAssetReferences`, and `previewMarkdownToMdxConversion` - Asset-reference, byte-stream, document-graph, Markdown, and MDX helpers included in commit `76bc388ba9` - Tests: the corresponding `packages/content-engine/src/**/*.test.ts` files already on this branch ### Port with their existing tests | Area | Functions to move or adapt | Tests to move with them | | --- | --- | --- | | Source contract and integrity | `parseContentBlockSourceProp`, `getContentBlockSource`, `isEqualContentBlockSource`, `formatContentBlockSourceIntegrityIssue`, `getContentBlockSourceIntegrityIssues`, `allocateUniqueContentBlockTemplateName` | `packages/sdk/src/content-block.test.ts`, `packages/sdk/src/schema/content-block.test.ts` | | Existing instance/name utilities | `findChildReferenceIndex`, `findParentInstanceReference`, `getInstanceName` | `packages/sdk/src/instances-utils.test.tsx` | | Template naming in mutations | `assignUniqueBlockTemplateNamesMutable`, `findBlockTemplateNameCollision`, `getSourceBackedBlockTemplateContext`, `getBlockTemplateNameConfirmation`, `getBlockTemplateInsertionIndex` | `packages/project-build/src/runtime/block.test.ts` | | Content-mode property permissions | `getContentModePropEligibility`; preserve its distinction between editable, design-only, incompatible, and unknown props | `packages/project-build/src/runtime/content-mode-permissions.test.ts` | | Template resolution | `resolveMdxTemplates` | `packages/project-build/src/runtime/mdx-template-resolution.test.ts` | | Template materialization | `createMdxScopeIdGenerator`, `materializeMdxTemplates` | `packages/project-build/src/runtime/mdx-materialization.test.ts` | | MDX → instances and instances → MDX | `isMaterializedMdxAuthoredContentRoot`, `preserveMdxAuthoredContentIds`, `materializeMdxAuthoredContent`, `reconcileMdxAuthoredContent`, `omitTransientEmptyParagraphs`, `serializeMdxTemplateInsertion` | `packages/project-build/src/runtime/mdx-authored-content.test.ts`; retain the pure serialization cases from `mdx-storage-adapter.test.ts` | | Revisioned Asset I/O | `createAssetContentRevision`, `readAssetContentBytes`, the package-owned `createHttpAssetContentRepository`, the thin Builder `createBuilderHttpAssetContentRepository`, `createAssetContentBridge`, `initAssetContentBridge`, `getAssetContentBridge`; keep one repository implementation rather than copying the old Builder duplicate | `packages/asset-uploader/src/content-repository.test.ts`, `apps/builder/app/builder/shared/assets/mdx-content-repository.test.ts`, `apps/builder/app/shared/asset-content-bridge.client.test.ts` | | Source lifecycle planning | `createContentBlockBodyRemoval`, `prepareContentBlockConnect`, `prepareContentBlockDisconnect`, `prepareContentBlockSwitch`, `ContentBlockSourceRevisionConflictError` | `packages/project-build/src/runtime/content-block-source-lifecycle.test.ts` | | Per-Asset revision/session behavior | `getContentBlockSessionSource`, `isContentBlockSessionSourceCommitted`; reuse the loading, authorization, revision, queue, conflict, retry, cancellation, and source-replacement internals of `createMdxAssetEditingSession`, but key the rebuilt session by Asset rather than Content Block/render root | Port the applicable cases from `packages/project-build/src/runtime/mdx-asset-session.test.ts`; replace root-projection setup with in-memory snapshot setup | | Template migrations | `validateMdxTemplateMigrationConfirmation`, `planMdxTemplateMigration` | `packages/project-build/src/runtime/mdx-template-migration.test.ts` | | Publication | `createPublishedMdxMaterializationCache`, `materializePublishedMdx`, `getPublishedMdxContentDatabaseMaxBytes`, `getDynamicPublishedMdxSourceBlockIds`, `hasDynamicPublishedMdxSources`, `createPublishedBuildContentCompilationPlan`, `resolvePublishedMdxDependencyClosure`, `resolvePublishedMdxAssetCandidates` | `packages/project-build/src/runtime/published-mdx.test.ts`, `packages/project-build/src/content-database.test.ts` | | Build/import integrity | `assertContentBlockSourceIntegrity` and the Content Block cases in `getBuildIntegrityIssues`/`formatBuildIntegrityIssue` | `packages/project-build/src/build-integrity.test.ts` | | MDX paste/MCP insertion | `insertMdxText` and its input/result schemas; retain parsing, confirmation, template-resolution, and insertion-index logic, then invoke the normal mutation path | `packages/project-build/src/runtime/mdx-paste.test.ts` | | Builder source control | `createContentBlockSourceController`, `createBuilderContentBlockSourceController` and the existing source-control components | `content-block-source-controller.test.ts`, `content-block-source.test.tsx` | | Diagnostics | `formatContentBlockDiagnostic`, `deduplicateContentBlockDiagnostics`, `takeNewContentBlockDiagnostics` | Port only their focused cases from `apps/builder/app/shared/content-block-content.test.ts` | ### Explicitly do not port - `projectContentStorageChanges`, `createContentStorageProjection`, `createContentStorageSelectorProjection`, `executeContentStorageMutation`, `executeContentStorageTextReplacement`, `executeContentStoragePropMutation`, and `executeContentStorageStructuralMutation` - `applyMdxContentStorageChanges` and `prepareMdxContentStorageWrites`; replace them with one post-mutation snapshot serializer built from the reusable pure `reconcileMdxAuthoredContent` converter - `createContentBlockApplicationOperations` and the persistence-plan wrappers that route individual editing commands - Builder `$runtime*` projected stores, materialized mutation functions, alternate selector/tree helpers, pending projected-change state, and MDX-specific mutation sequences from `content-block-content.ts` - Canvas loading/saving/open-file presentation state, MDX history/undo, and atomic rollback machinery ## Implementation checklist ### 1. Preserve the `main` editing architecture - [x] Keep normal synchronous insert, text, Enter, slash menu, property, delete, move, wrap, copy/paste, selection, and focus mutations unchanged - [x] Materialize connected content through the same runtime instance interfaces used by ordinary Content Blocks - [x] Keep connected authored children in memory and exclude them from persisted build data - [x] Route persistence only after a synchronous mutation has updated the canvas - [x] Never wait for Asset loading, conversion, or saving before rendering an interaction - [x] Add no MDX-specific implementation to individual editing commands ### 2. Shared Markdown and MDX conversion - [x] Parse Markdown and the Markdown portion of MDX through one shared AST and plugin configuration - [x] Implement one shared MDX-to-instances converter and one shared instances-to-MDX converter - [x] Serialize headings, paragraphs, links, images, lists, tables, task lists, blockquotes, thematic breaks, code, emphasis, strong, strikethrough, and other supported GFM structures as Markdown - [x] Serialize only non-lossless/custom structures as Webstudio JSX - [x] Preserve nested Markdown in MDX elements, frontmatter, comments, tight/loose list semantics, code whitespace, reference links, and Asset references - [x] Omit transient empty draft paragraphs instead of emitting `<ws.element ws:tag="p" />` - [x] Preserve unsupported source text and authored metadata whenever it cannot be converted safely - [x] Add deterministic round-trip and canonical-output coverage for every supported Markdown structure ### 3. Invalid and unsafe MDX - [x] Preserve file source exactly; never silently repair or rewrite invalid source - [x] Ignore imports, exports, expressions, executable JavaScript, invalid properties, and other unsupported nodes when they can be isolated - [x] Continue rendering valid siblings and report every skipped subtree once with filename, line, and column - [x] Use the same recovery pipeline in Builder and publication so both render the same authored result for the current file revision - [x] When structural syntax prevents recovery, render no authored file content in Builder or publication instead of retaining a stale materialization - [x] Skip an unrecoverable Content Block on published sites and continue the build with a warning - [x] Keep invalid and unsafe files editable and reconnectable - [x] Enforce UTF-8, byte-size, depth, node-count, property-count, and generated-output limits with source-located diagnostics where possible ### 4. File formats and Asset creation - [x] Keep `.md` parsing and raw-HTML behavior unchanged - [x] Support creating, opening, editing, deleting, and recreating `.mdx` files through the normal text-file UI - [x] Open `.mdx` in the same editor experience as `.md` - [x] Always create an independent empty MDX Asset even when identical empty files exist - [x] Allow renaming `.md` to `.mdx` without converting or rewriting its contents; after rename, handle invalid contents through the normal MDX diagnostics and recovery pipeline - [x] Update an already-open MDX editor immediately after canvas persistence - [x] Bound read/write buffering and verify the returned Asset identity and revision ### 5. Source contracts and lifecycle - [x] Support direct Asset bindings and dynamic expression bindings - [x] Keep source mutation controls available only in Design mode; show the connected filename and **Open** action read-only in Content mode - [x] Reject duplicate source props, unsupported prop types, missing Assets, non-MDX Assets, and unauthorized Assets - [x] Analyze selected file diagnostics before confirmation without modifying the block or file; MDX syntax diagnostics do not block connection - [x] For a non-empty block, show **Abort** and **Connect** and explain that ordinary children will be replaced - [x] On connect, remove every non-template child, preserve Templates, set `src`, and materialize file content - [x] Replace disconnect handoff with normal `src` reset; discard derived content and leave the block empty - [x] Remove disconnect confirmation and conversion; resetting a repeated binding leaves every occurrence empty - [x] Switching sources validates/loads the target before replacing the usable binding and leaves both files unchanged - [x] Revalidate Asset revision and project version when confirmation is submitted - [x] Make repeated connect/disconnect operations idempotent - [x] Prevent disposed, stale, or out-of-order loads from replacing the newest source - [x] Keep loading, saving, conflict, empty-file, and open-file actions off canvas ### 6. Asynchronous persistence and conflicts - [x] Snapshot the current in-memory authored root after normal mutations - [x] Serialize/coalesce rapid edits per resolved Asset and always prepare against the latest local snapshot - [x] Allow independent Assets to save concurrently without scope leakage - [x] Use one revisioned document session and one ordered save queue per Asset, even when multiple Content Blocks or render scopes reference it - [x] After a shared Asset changes, rematerialize every connected occurrence without persisting their generated instances to project data - [x] Pin the resolved Asset and exact loaded revision for each write - [x] Recheck authorization immediately before storage - [x] Ensure local queued edits never produce stale-revision conflicts with each other - [x] On a genuine external revision conflict, preserve local content, stop writes, and enter the standard reload-required state - [x] Keep failed non-conflicting writes retryable without discarding local content - [x] Finish already accepted persistence writes after a Content Block unmounts or switches source - [x] Cancel obsolete loads, materializations, and UI updates after unmount, reload, or source switch - [x] Dispose project-scoped roots, queues, parse caches, failure state, generations, and session subscriptions when the Asset session is replaced - [x] Invalidate Asset resources and synchronize open file editors after successful writes - [x] Keep multi-root persistence ordered, serial, and non-atomic; report partial completion without rollback - [x] Do not add Asset-history undo/redo; native text-editor undo remains local to the open editor ### 7. Content mode parity - [x] Empty connected blocks remain selectable and expose the normal Content-mode `+` affordance - [x] First insertion renders immediately - [x] Enter creates and focuses the next paragraph immediately - [x] Slash commands work in newly created empty paragraphs - [x] Deleting one selected instance deletes exactly that instance - [x] Mouse and keyboard moves use the same operation and permissions - [x] Preserve sibling reorder, nested reparenting, and moves between editable Content Blocks where `main` permits them - [x] Preserve content-editable props such as Link `href` - [x] Preserve copy, paste, cut, multi-cut, wrapping, unwrapping, grid insertion, selection, Navigator order, and canvas order - [x] Cover mutation routing centrally, retain the full unconnected Builder suite, and exercise representative connected interactions in real Builder E2E ### 8. Template names and permissions - [x] Resolve only exact user-facing names from the direct flat Templates list - [x] Enforce unique names within each Templates list - [x] Reject duplicate names during rename with inline validation - [x] Allocate unique names during insert, paste, duplicate, move, wrap, and unwrap - [x] Apply valid template properties using the same permissions as Content mode - [x] Preserve and warn about ignored design-only, invalid, or stale properties - [x] Preserve template shell provenance without serializing expanded template internals - [x] Generate deterministic materialized IDs from source identity, render scope, and authored usage path so focus/selection survives saves - [x] Warn before renaming or deleting referenced templates; files remain unchanged - [x] Provide shared AST-based rename/remove migration operations for MCP-assisted multi-file cleanup ### 9. Scope, frontmatter, and diagnostics - [x] Scope materialized content by Content Block ID plus exact Collection-item/render context - [x] Prevent repeated instances and dynamic candidates from leaking generated IDs, template resolution, or diagnostics across scopes while sharing the underlying Asset source and revision where applicable - [x] Remove frontmatter editing from Settings; edit the exact YAML through the MDX Asset file editor - [x] Preserve the exact frontmatter source byte-for-byte during canvas body saves - [x] Route canvas body changes and complete-file editor saves through one revisioned per-Asset coordinator - [x] Show a source warning indicator in Settings and precise source-located diagnostics in the Asset editor - [x] Deduplicate repeated diagnostics without losing distinct locations - [x] Keep unresolved-template placeholders selectable and accessible only in Builder ### 10. Asset references, transfer, and integrity - [x] Discover and rewrite Asset references in frontmatter, Markdown links/images, and MDX properties - [x] Preserve Asset references while editing unrelated content - [x] Include referenced Asset and template revisions in dependency/cache identity - [x] Route referenced Assets through published URL rewriting - [x] Validate Content Block source integrity during project import, fragment/page transfer, copy/paste, build integrity, and pre-publish audit - [x] Allow multiple Content Blocks and dynamic render scopes to reference the same MDX Asset without treating the connection as an integrity error - [x] Preserve Templates when copying a connected Content Block - [x] Preserve direct and dynamic Content Block source bindings when copying or pasting within the same project - [x] When copying only one rendered Collection item, resolve that item’s current MDX Asset and replace the copied Content Block’s dynamic source with a direct binding to that same Asset - [x] When copying an entire Collection, preserve the Collection, its instances, and its dynamic source bindings - [x] Preserve the complete MDX source and frontmatter by reference; copying a connected block must not rewrite the shared file - [x] During cross-project transfer, copy every discoverable distinct bound MDX Asset and rewrite transferred bindings to the destination Assets - [x] If some cross-project dynamic candidates cannot be discovered or copied, continue with successful copies, preserve what can be represented safely, and warn about skipped candidates - [x] Revalidate source revisions and the destination project before applying a cross-project transfer - [x] If cross-project Asset creation or project insertion fails, leave the source project unchanged and clean up any newly reserved destination Asset - [x] Use the same transfer operation through Builder and MCP ### 11. Dynamic sources and publication - [x] Resolve dynamic bindings once per render/save scope - [x] Require finite, discoverable candidate sets for publication and load no unrelated MDX - [x] Warn and skip unbounded, missing, unreadable, malformed, or unsafe sources without failing the complete build - [x] Materialize only rendered Content Blocks; ignore Templates definitions and `src` on non-Content-Block instances - [x] Skip unresolved template subtrees while keeping valid siblings - [x] Include selected template styles, fonts, resources, unresolved names, and referenced Asset revisions in generated dependency output - [x] Keep draft-only MDX Assets out of publication retention ### 12. Builder, MCP, CLI, and shared operations - [x] Use the same converters, source lifecycle, revision checks, persistence service, diagnostics, and template migrations in Builder and MCP - [x] Keep frontmatter editing file-based; retain whole-frontmatter runtime operations only where compatibility requires them - [x] Avoid Builder-only or MCP-only mutation/conversion implementations - [x] Regenerate runtime/API contracts from their source definitions - [x] Update CLI Content Engine reference and generated MCP documentation ### 13. Verification and delivery - [x] Add regression tests that reproduce failures from the previous implementation, including double deletion and blocked rendering - [x] Cover two Content Blocks sharing one Asset: edits from either block serialize once, update both canvases, preserve scope-specific Templates, and cannot overwrite a newer local snapshot - [x] Verify new tests fail against the broken implementation and pass with the corrected behavior - [x] Run SDK, Content Engine, Asset Uploader, Project Build, Builder, React SDK, CLI, Protocol, and HTTP Client affected suites and typechecks - [x] Run real Builder E2E for source lifecycle, live file refresh, empty insertion, Enter/slash focus, Link props, delete, keyboard reorder, switching, disconnect, conflicts, unresolved templates, dynamic sources, and repeated scopes - [x] Regenerate shared project fixture bundles and verify a second generation leaves the tree clean - [x] Run lint, package boundaries, `pnpm oxfmt --check`, and `git diff --check` - [x] Review and update authoritative `docs/` content and navigation - [ ] Run the complete agent evaluation suite — not run because it requires separate explicit approval ### 14. Content-mode parity and disconnect handoff - [x] Allow keyboard reordering in Content mode through the normal move command while keeping the editable Content Block boundary - [x] Let already accepted Asset writes drain independently before resetting the source; disconnect does not load, flush, or convert the file - [x] Remove MDX-to-instance copying from disconnect - [x] Reset `src`, remove the derived tree, and leave the ordinary Content Block empty - [x] Preserve automatic text-editor focus after inserting editable content from the template menu - [x] Remove Builder frontmatter-save UI and report complete-file save failures through the Asset editor - [x] Add regression coverage for keyboard movement, disconnect teardown, source switching, insertion focus, and paragraph deletion focus restoration - [x] Run the complete six-scenario MDX Content Block Builder E2E suite ### 15. Final architecture review fixes - [x] Keep one canonical ordered pending document per Asset so shared Content Block occurrences cannot conflict with one another - [x] Merge ordered local edits from different occurrences while preserving text changes, insertions, deletions, and sibling reordering; keep external revisions on the strict reload-required path - [x] Centralize typed render-scope parsing, repeated-occurrence detection, scoped variable lookup, and dynamic Asset resolution across Canvas, Settings, source lifecycle, and copy/paste - [x] Capture the owning Asset session when a save is accepted so normal unmount/source-switch teardown cannot redirect or lose it - [x] Dispose project-owned roots, queues, caches, generations, failure state, and subscriptions when replacing the project Asset session - [x] Add regression coverage for same-Asset edits from two occurrences, same-node last-write ordering, structural reorder, insertion preservation, scoped source resolution, and project cleanup - [x] Re-run affected full unit suites, typechecks, production build, static checks, and all six MDX Content Block Builder E2E scenarios ### 16. Final persistence and transfer hardening - [x] Drain every accepted per-Asset edit before project-session teardown while retaining the owning authorization context - [x] Drain canvas serialization queues and revisioned Asset writes before pre-publish audit and publication - [x] Block publication on a queued serialization failure or Asset revision conflict - [x] Copy actual Asset bytes during cross-project paste, preserve MDX reference names, rewrite direct and Collection-backed Asset IDs, and clean up newly created Assets when insertion fails - [x] Include every resolved dynamic MDX source when copying an entire Collection and warn while preserving successful copies when individual Assets cannot be transferred - [x] Keep MDX editor save failures visible with retry and route conflicts through the standard reload-required flow - [x] Give keyboard nested reparenting the same editable Content Block boundary used by pointer movement - [x] Add regression coverage and rerun the complete Content Engine and Builder unit suites plus type, lint, formatting, package-boundary, and diff checks ## Current rebuild status - The connected Content Block now owns one complete MDX document: frontmatter feeds designed-shell bindings and the explicit Body outlet owns the authored MDX body. - Builder and published output resolve the same frontmatter document graph, including nested document references and Asset references. - Direct frontmatter text/property edits use the existing ordered per-Asset session; referenced-document values remain file-owned. - Repeated Collection occurrences keep isolated runtime shell/Body identities and occurrence-specific document values. - The local blog article layout has been upgraded to the document/Body model and its bindings validate cleanly. - Full affected package suites and typechecks pass; every new regression was demonstrated fail/pass. - `pnpm lint`, package boundaries, `pnpm oxfmt --check`, generated API/docs checks, fixture builds, and `git diff --check` pass. - Full fixture synchronization is blocked by the development API rejecting this local CLI version before fixture generation; existing fixture bundles build successfully. - Complete agent evaluations remain pending explicit approval. ### 17. Treat Content Block source as a property - [x] Declare Content Block `src` in component metadata as a Design-mode initial property labeled **Source** - [x] Add the short property description: “Create an .mdx file in Assets, then select or bind it here.” - [x] Accept only a direct Asset or an expression resolving to an Asset ID; reject URL/string sources, missing Assets, and non-MDX Assets - [x] Extract and reuse the Image-style Asset picker and binding presentation without duplicating source-control UI - [x] Render Source through the normal properties section and remove the separate source-section placement and special `src` filtering - [x] Route Source changes through Content Block connect, switch, and disconnect lifecycle operations instead of generic prop updates - [x] Keep connect confirmation, Open, diagnostics, and persistence state attached to Source; remove frontmatter and disconnect UI - [x] Add regression coverage for direct Assets, dynamic Asset bindings, invalid resolved values, lifecycle operations, and Design/Content mode visibility - [x] Re-review authoritative `docs/` content for the Source-property UI change and update it if required ### 18. Source property UX - [x] Show one full-width bindable Connect .mdx file button while disconnected - [x] Show equal-width filename and Open buttons while connected - [x] Switch files from the filename button through the source lifecycle - [x] Override PropertyLabel reset and Alt-click with the disconnect lifecycle - [x] Preserve confirmation, pending, failure, repeated-scope, and dynamic-source behavior - [x] Add regression coverage for connect, switch, binding, reset, and disconnect - [x] Update Content Block documentation - [x] Run affected tests, typecheck, lint, formatting, package boundaries, and diff checks ### 19. Reduced file-owned frontmatter follow-up This checklist supersedes the earlier structured-frontmatter and disconnect-copy behavior. Frontmatter remains file-owned and is edited only in the MDX Asset editor. #### A. Remove structured frontmatter UI - [x] Remove the JSON frontmatter editor and unused Builder controller/state - [x] Keep source mutation Design-mode-only; show connected Source read-only in Content mode and allow authorized editors to open the complete file - [x] Retain runtime frontmatter APIs only where compatibility requires them #### B. Preserve source and separate validation - [x] Preserve the exact frontmatter envelope during every canvas body save without parsing/stringifying YAML - [x] Preserve comments, ordering, quoting, whitespace, BOM, newline style, delimiters, and invalid but closed YAML - [x] Keep the existing unsupported-node/property MDX recovery; do not add an ad hoc partial parser - [x] Parse body and frontmatter independently so either valid half remains usable - [x] Keep bounded Asset-query frontmatter extraction unchanged - [x] Treat structurally malformed MDX as having no safe body tree #### C. Share Asset state with the raw editor - [x] Route canvas and complete-file changes through one ordered, non-blocking per-Asset coordinator - [x] Update canvas and clean raw editors immediately from shared in-memory source - [x] Reject stale dirty-editor saves, preserve unsaved text, and require reload; never force-overwrite - [x] Drain accepted writes after source replacement/disconnect and report background failures globally - [x] Dispose sessions only after they have no consumers and no queued work #### D. Connect, replace, and disconnect - [x] Load and diagnose before connect; block only unreadable/unauthorized/non-MDX Assets - [x] Show **Abort / Connect** for non-empty blocks, including diagnostics and the recoverable-content warning - [x] Set `src` and delete persisted children through one runtime mutation - [x] Switch to a loaded source without waiting for the previous Asset's network save - [x] Remove disconnect confirmation and conversion - [x] Reset `src` immediately, discard the derived tree, leave the block empty, and preserve the Asset - [x] Resetting a bound source leaves every repeated occurrence empty #### E. Dynamic and shared sources - [x] Keep one source/revision state per Asset and a separate derived instances tree per occurrence - [x] Resolve Templates independently per Content Block and preserve Builder-only missing-template placeholders - [x] Resolve bound `src` from the selected Collection occurrence - [x] Make **Open** use the occurrence's resolved Asset; update the filename and disable Open when unresolved - [x] Add direct/bound tests including Collection item A opening `a.mdx` and item B opening `b.mdx` #### F. Diagnostics, MCP, and publication - [x] Show an accessible warning icon beside Source with the first diagnostic, line/column, and remaining count - [x] Show precise YAML/MDX diagnostics in the Asset editor without repetitive canvas/toast UI - [x] Reuse parser/diagnostic/revision contracts in Builder, build, publication, and MCP - [x] Keep MCP frontmatter editing file-based and return structured diagnostics for complete-source writes - [x] Emit build warnings; published sites skip invalid/unsupported content without diagnostic UI #### G. Verification and documentation - [x] Add fail/pass regressions for source preservation, independent validation, stale raw saves, lifecycle, dynamic Open, shared Assets, and cleanup - [x] Run affected tests, typechecks, lint, formatting, package boundaries, fixtures, and diff checks - [x] Open Markdown and MDX editors at twice the default dialog size with the right-side preview visible initially - [x] Document canvas body editing, file-owned frontmatter, Content-mode Asset access, and cloning an MDX Asset for a new post - [x] Perform a final correctness, data-loss, DRY, simplification, accessibility, and performance review - [x] Keep this checklist synchronized with implementation status ### 20. Content-mode component properties - [x] Show a connected Content Block Source read-only in Content mode with an active **Open** action - [x] Keep source switching, binding, reset, and disconnect available only in Design mode - [x] Expose HTML Embed code and preserve Code Text's code-editor metadata on authored Text Content - [x] Audit every registered component and expose authored payload while keeping design, structure, and behavior controls in Design mode - [x] Keep media dimensions and Code Text theme Design-only while preserving adapter-owned intrinsic Image metadata during MDX round trips - [x] Add exact component-permission and regression coverage - [x] Update authoritative component documentation - [x] Run affected full suites, typechecks, formatting, lint, package boundaries, and generated contract/documentation checks ### 21. Designed document shell and Body outlet - [x] Add one structural **Content Block Body** outlet and keep legacy Content Blocks without it compatible - [x] Materialize and persist only `document.body` children through the Body outlet while preserving the surrounding designed shell and Templates - [x] Expose the connected document frontmatter through a Content Block `document` parameter for shell text and property bindings - [x] Write direct frontmatter-bound text and properties back through the same ordered per-Asset session without blocking canvas mutations - [x] Resolve document `$ref` dependencies and Asset references consistently in Builder and published output - [x] Keep referenced-document values read-only on canvas and direct editors to the referenced file - [x] Isolate repeated Collection occurrences while retaining occurrence-specific source, frontmatter, shell, and Body content - [x] Render the same designed shell, frontmatter values, and Body substitution in generated/published output - [x] Upgrade the local blog article layout to bind title, excerpt, dates, author data, and images from frontmatter and render MDX through Body - [x] Add fail/pass regressions for nested Body discovery, lifecycle, permissions, repeated values, document references, and generated shell rendering - [x] Update authoritative Content Block documentation - [x] Run affected tests and typechecks, formatting, lint, package boundaries, generated API/docs checks, and fixture builds ### 22. Final nested references and frontmatter editing - [x] Keep direct frontmatter-bound text and property controls editable in Content mode without exposing or replacing their bindings - [x] Keep referenced-document values read-only and preserve legacy instance-property name normalization - [x] Render direct frontmatter text bindings through the plain-text editing path - [x] Resolve nested legacy and structured Asset references from referenced Markdown/MDX frontmatter - [x] Preserve missing Asset references, emit structured `ASSET_NOT_FOUND` diagnostics, and keep them out of the document graph - [x] Add fail/pass regressions for the real Settings control and root/nested missing Asset-reference cases - [x] Fix exact Content Block selection after the Body node appears in Navigator - [x] Run full affected suites/typechecks, all six MDX Content Block E2E scenarios, deterministic fixture builds, generated checks, lint, formatting, package boundaries, and diff checks ### Before merge - [x] Resolve #6261: Nested Asset references in referenced Markdown frontmatter work consistently in Assets queries, previews, publication, and static export ### 23. Explicit writable expression bindings - [x] Add an explicit `readwrite` mode to expression bindings; existing expressions remain read-only by default - [x] Accept `readwrite` only for direct static member paths and centralize their parsing and validation - [x] Require the expression root to provide a writable data source; initially support the connected Content Block document frontmatter - [x] Update Content Block permissions, canvas text editing, and property controls to require a valid writable binding - [x] Persist direct frontmatter edits through the existing ordered per-Asset session - [x] Create new direct frontmatter bindings with `readwrite` mode and migrate existing compatible bindings - [x] Preserve writable mode through schemas, serialization, loading, copy/paste, transfer, and export - [x] Add fail/pass regressions for valid paths, derived expressions, unsupported sources, permissions, persistence, and compatibility - [x] Review authoritative `docs/` content and update it if the persisted binding contract affects user-facing documentation - [x] Reject unsafe frontmatter paths and reject `readwrite` bindings outside a connected Content Block document - [x] Preserve expression binding mode through the public HTTP client and document the MCP authoring contract - [x] Limit frontmatter value write-back to Content mode so Design mode retains normal binding replacement/reset behavior - [x] Keep bindings inside Templates and across nested Content Block ownership boundaries read-only - [x] Upgrade compatible legacy bindings even when the Content Block is disconnected during migration - [x] Run affected tests, typechecks, formatting, lint, package boundaries, fixture checks, and `git diff --check` Verification: full SDK (567), Project Build (2,277), and Builder (2,695) suites pass, along with affected Expression, Migration, Template, HTTP Client, and MCP suites; typechecks, lint, formatting, package boundaries, and diff checks pass. Generated contracts are refreshed. Fixture synchronization remains blocked before generation because the development API rejects this local CLI version as incompatible. The checked-in bundles pass the current Protocol suite and every fixture build with the current bundle version. |
||
|
|
7e7c14868a |
fix: Preserve read-only guides and publish targets (#6266)
## Summary - Route explicit read-only `meta.guide` requests to focused discovery tools and exclude mutations, side-effecting session tools, broad design context, and visual verification. - Require explicit task scope, specialized workflow, authored-fragment routing, and design-system reuse instead of inferring behavior from brief prose. - Persist the requested staging or production target in new SaaS deployment records. - Return the same target from publish list and job status, with backward-compatible inference for historical records. ## Todo - [x] Reproduce the read-only custom-code audit misrouting from #6262. - [x] Add failing regressions and implement strict read-only routing. - [x] Remove behavior-affecting prose inference from CLI/MCP guide routing. - [x] Reproduce the single-domain production target mismatch from #6263. - [x] Add create-to-list/status regressions and persist the explicit target. - [x] Cover historical deployment records that predate the stored target. - [x] Verify production create → list → get-job through the staging deployment. - [x] Regenerate and verify project fixtures against the changed bundle contract. - [x] Review documentation impact and update the generated MCP manual. - [x] Review the complete diff for correctness, compatibility, duplication, and unnecessary complexity. ## Verification - Real staging publish for #6263 — passed; create, list, and get-job consistently reported `production` for a one-domain publish. The supplied project has no custom domains, so the custom-domain variant was not available. The job remained `pending` during this check. - Real local CLI/MCP verification for #6262 — passed; no mutation or side-effecting tools leaked. - `pnpm --filter @webstudio-is/protocol test -- src/fixtures.test.ts` — 17 passed - `pnpm -r fixtures:build` — passed for all eight fixtures - `pnpm --filter @webstudio-is/project-build test` — 2,134 passed - `pnpm --filter webstudio test` — 1,037 passed; the one payload-size regression was fixed and its targeted test passed - `pnpm --filter @webstudio-is/domain test` — 24 passed - `pnpm --filter @webstudio-is/sdk test` — 519 passed - Builder API router test — 30 passed - Relevant package typechecks — passed - `pnpm lint` - `pnpm check:package-boundaries` - `pnpm check:generated-api` - `pnpm check:generated-docs` - Regression tests were demonstrated failing against the previous behavior and passing with the fixes. - Agent evaluations were not run because they require separate explicit approval. Closes #6262 Closes #6263 |
||
|
|
cbe4950cd0 |
fix: Use available package manager for previews (#6251)
## Summary - Use the npm or pnpm launcher that started Webstudio for preview dependency installation, builds, and server startup. - Use pnpm-compatible isolated-install flags and report the selected package-manager path on failure. - Preserve the existing installed-dependency reuse path before package-manager resolution. ## Technical choices - Read the standard `npm_execpath` metadata already supplied by npm and pnpm; users do not need to configure another environment variable. - Run JavaScript launchers such as `pnpm.cjs` with the selected Node runtime, supporting bundled Node distributions without adjacent npm. - Keep the existing npx-to-npm mapping and fallback behavior unchanged. - Distinguish numeric package-manager exit codes from process-launch errors such as `ENOENT`. ## Todo - [x] Reproduce the bundled Node + pnpm + missing adjacent npm failure. - [x] Add fail-before/pass-after coverage for dependency installation, production build, and preview startup. - [x] Reuse the detected pnpm launcher. - [x] Preserve installed-dependency reuse. - [x] Include the selected launcher path in installation failures. - [x] Report package-manager exits and process-launch errors accurately. - [x] Review documentation impact and update the CLI manual plus generated MCP documentation. - [x] Review fixture impact; no fixture inputs or outputs are affected. ## Verification - Focused install diagnostic regression suite — 28 tests passed. - `pnpm --filter webstudio typecheck` - `pnpm lint` - `pnpm --filter webstudio test` — 1,029 of 1,030 tests passed; an existing process-supervisor cleanup test hit a transient `ENOENT`, then passed 4/4 when rerun in isolation. - Generated documentation checks passed. - Real pnpm JavaScript launcher invocation with isolated preview install flags. - Agent evaluations were not run because they require separate approval. Closes #6250 |
||
|
|
981f45fd0d |
docs: Optimize documentation image sizes (#6253)
## Summary Replace ten oversized PNG screenshots in the product documentation with high-quality WebP assets and update their references. The affected assets shrink from 27,813,051 bytes to 2,822,010 bytes (90% smaller) while retaining their original pixel dimensions. ## Technical choices - Encoded screenshots as WebP at quality 88 with sharp YUV conversion. - Kept original dimensions to preserve UI text legibility and zoom detail. - Left animated GIFs unchanged: GIF-native optimization, palette reduction, and resizing tests increased their file sizes, so changing them would add cost or reduce clarity. - Kept documentation content, navigation, and public page paths unchanged. ## Checklist 1. [x] Audit raster assets in `docs/.gitbook/assets`. 2. [x] Optimize referenced PNG assets above 1 MB where conversion materially reduces size. 3. [x] Update every affected documentation reference. 4. [x] Verify replacement dimensions and image decoding. 5. [x] Verify visual quality (SSIM 0.961–0.997 plus manual spot checks). 6. [x] Verify new references resolve and removed filenames are no longer referenced. 7. [x] Review documentation impact; this PR changes documentation assets and their direct references only. 8. [x] Verify no fixture inputs or generated fixture outputs are affected. ## Verification - `git diff --check` - Reference checks for all ten added and removed filenames - Pixel-dimension comparison for all ten replacements - FFmpeg SSIM comparison for all ten replacements - Manual visual review of representative full-resolution screenshots The repository formatter excludes these documentation files, so it reported no matching targets. Agent evaluations were not run because this is a documentation-asset-only change. Closes #6252 |
||
|
|
471f504087 |
feat: Select unused assets before deleting (#6245)
Closes #6243 ## Summary - Add checked-by-default controls for every asset in the **Delete unused assets** dialog. - Add a footer **Select all** control that reflects the complete selection and toggles all assets. - Delete only selected assets that remain unused and disable deletion when the selection is empty. - Keep the Assets documentation aligned with the selective deletion workflow. ## Implementation The dialog owns a set of selected asset IDs initialized from the unused-assets result. Individual checkboxes update that set, while **Select all** replaces it with either every currently unused ID or an empty set. Asset usage inputs remain subscribed while the dialog is open. The deletion payload is intersected with the current unused-assets list, and this cleanup path does not force deletion. If an asset becomes referenced before the mutation executes, the runtime rejects its deletion instead of removing a now-used asset. ## Todo - [x] Add per-asset selection controls. - [x] Add and position the **Select all** footer control. - [x] Limit deletion to selected asset IDs that remain unused. - [x] Protect against assets becoming referenced while the dialog is open. - [x] Add regression tests for individual selection, select-all behavior, empty-selection protection, selective deletion, and live usage changes. - [x] Review documentation impact and update the Assets guides. - [x] Verify formatting, lint, types, and Asset Manager/assets tests. ## Verification - `pnpm --filter @webstudio-is/builder exec vitest run app/builder/shared/asset-manager app/builder/shared/assets` — 26 files, 221 tests passed. - `pnpm --filter @webstudio-is/builder typecheck` — passed. - `pnpm exec oxlint --deny-warnings apps/builder/app/builder/shared/assets/delete-assets.ts apps/builder/app/builder/shared/asset-manager/delete-unused-assets.tsx apps/builder/app/builder/shared/asset-manager/delete-unused-assets.test.tsx` — passed. - `pnpm exec oxfmt --check apps/builder/app/builder/shared/assets/delete-assets.ts apps/builder/app/builder/shared/asset-manager/delete-unused-assets.tsx apps/builder/app/builder/shared/asset-manager/delete-unused-assets.test.tsx` — passed. - Both regression tests were confirmed failing before their respective implementations and passing afterward. ## Compatibility and follow-ups No data migrations, public API changes, fixture changes, or known follow-ups. |
||
|
|
db2175f333 |
fix: transfer pasted assets across deployments (#6228)
Closes #6227 ## What changed Cross-deployment copy/paste now transfers referenced assets into the destination project before inserting instances, pages, templates, or folders. - Add optional source deployment metadata to the existing v0.1 clipboard formats. - Keep old v0.1 payloads readable and keep new payloads readable by older builders, which ignore the additive field. - Reuse the existing asset upload-by-URL flow for images, fonts, videos, and files. - Preserve source video dimensions through the existing upload route. - Replace source asset IDs and font-family references with destination values before runtime insertion. - Include and remap page social images and marketplace thumbnails. - Reject current clipboard payloads whose page metadata references omitted assets. - Leave the public `pageTransfer.insert` runtime input unchanged. - Abort insertion with a paste error when an asset cannot be imported. No clipboard version increase, custom network fetcher, address blocklist, rollback framework, or global paste wrapper is introduced. If a multi-asset import partially uploads before a later upload fails, the completed uploads may remain unused. ## Checklist - [x] Rebased onto `main` - [x] Preserve the existing v0.1 clipboard format - [x] Transfer and remap instance assets - [x] Transfer and remap page, template, and folder assets - [x] Preserve video metadata - [x] Keep runtime page-transfer API compatible - [x] Add regression coverage - [x] Review documentation impact and update page-copy documentation - [x] Run Builder tests and typecheck - [x] Run project-build tests and typecheck - [x] Run lint, package-boundary, and generated-API checks ## Verification - Builder full suite: 219 files, 2,552 tests passed - Project-build full suite: 78 files, 2,129 tests passed - Final affected suite: 84 tests passed - New regressions were confirmed failing before the fixes and passing afterward - Builder and project-build typechecks passed - `pnpm lint` passed - `pnpm check:package-boundaries` passed - `pnpm check:generated-api` passed - Fixture inputs and generated fixture bundles are unaffected |
||
|
|
9e504037fb |
fix: improve MCP reliability across project workflows (#6222)
## Summary Fixes the reproducible MCP, preview, redirect, audit, mutation, and asset-upload failures from the latest issue batch. Historical and non-reproducible reports were investigated without speculative fixes. Visual verification is now opt-in unless the user explicitly requests it. ## Issue checklist - [x] #6207 — report tested recovery when an explicitly selected browser fails to start. - [x] #6208 — accept generic and registered buttons as valid label targets without requiring a separate form label. - [x] #6209 — reject unknown style coordinates such as `breakpointId` and document the supported `breakpoint` field. - [x] #6210 — traced Node 18 access to CLI 0.293.0 predating the launcher guard; closed as already fixed by #6201. - [x] #6211 — verified the supported launcher blocks the reported Node 18 crypto path; closed as already fixed by #6201. - [x] #6212 — give sequential responsive captures the sum of their per-capture timeout budgets. - [x] #6213 — keep preview install, build, and server subprocesses on the parent CLI Node runtime. - [x] #6214 — add safe confirmation and diagnostics for ambiguous mutation responses; this does not claim to remove upstream latency. - [x] #6215 — confirmed as the same historical Node 18 release path as #6210; closed as already fixed by #6201. - [x] #6216 — verified malformed input returns structured errors on current main; closed as not reproducible and improved future failure diagnostics. - [x] #6217 — add transaction-id confirmation for large fragment mutations after ambiguous 5xx responses; this does not make the operation asynchronous. - [x] #6218 — verified the existing DevTools reconnect fix from #6205; closed as already fixed. - [x] #6219 — preserve the incoming pathname and query when a redirect target supplies only a hash. - [x] #6220 — return ordered `uploaded`, `failed`, and `ambiguous` results so partial asset successes are not lost or retried unsafely. - [x] #6221 — verified parser recovery without a Node crash; closed as not reproducible and improved future JSX failure diagnostics. - [x] #6223 — verified browser-session reuse, reconnect, and cleanup; closed as already fixed by #6205 after the reported CLI version. - [x] #6224 — expose both text-asset sources and encode the exactly-one requirement in the standard MCP schema. - [x] #6225 — could not reproduce the project-specific upstream timeout; closed with safe confirmation coverage and improved structured diagnostics, without claiming a latency fix. - [x] #6226 — could not reproduce the project-specific upstream timeout; closed with safe confirmation coverage for insert-fragment, without adding a speculative fragment-specific fix. - [x] #6229 — reproduced the reported two-process sequence with the current local CLI and a real browser; both captures passed, so the 0.293.0 report was closed without a speculative fix. - [x] Require explicit user consent before preview, screenshots, diffs, OCR, or rendered visual audits unless visual verification was requested. ## Technical notes - Ambiguous mutation responses are confirmed only with the same idempotent transaction id. If confirmation is also ambiguous, the session reports `AMBIGUOUS_COMMIT`, refreshes state, and never replays a fresh mutation. - CLI error mapping retains the original remote error as a non-enumerable cause, so JSON gateway status reaches the ambiguity classifier without exposing raw remote context in serialized diagnostics. - Forced asset uploads are not automatically retried after an unknown/network/5xx outcome. Batch results retain the original input index, including duplicate filenames. - Stable issue codes and constraints are retained for diagnostics. Arbitrary validation paths, messages, argument values, project content, and raw contextual data are excluded. - The MCP handshake remains the source of tool input schemas; goal-specific guides avoid duplicating those contracts and reduce model-context cost. - `update-asset-content` now exposes `path` and `content` with a machine-readable `oneOf` constraint, matching the runtime rule that exactly one source is required. - Redirect targets with their own pathname or query still replace those request components. - Generated runtime contracts, CLI documentation, product documentation, and deployment fixtures were regenerated from their sources. ## Verification - [x] Three independent review/test agents exercised visual consent and preview behavior; mutation, asset, and privacy behavior; and accessibility, styles, and redirects. - [x] `pnpm checks` passed after the final transport follow-up: all workspace tests and typechecks, lint with warnings denied, package boundaries, generated API contracts, generated docs and documentation checks, and the complete fixture link/sync/build pipeline. - [x] Changed-package suites passed, including Project Build (2,125 tests), HTTP client (42 tests), CLI, Protocol, and Builder. - [x] Complete `pnpm evaluations` run on the preceding implementation commit: all five real-world fixtures and every behavioral check passed. Four baseline comparisons passed; one font-assets sample exceeded only its model-output token allowance, and its isolated rerun passed. Evaluations were not rerun after the final transport and schema follow-ups because fresh approval is required. - [x] Design evaluation MCP response bytes improved from the 39.8 KB baseline to 37.6 KB after removing duplicated guide contracts. - [x] Documentation impact reviewed; generated MCP docs and multi-file upload guidance are updated. ## Related issues Closes #6207 Closes #6208 Closes #6209 Ref #6210 Ref #6211 Closes #6212 Closes #6213 Ref #6214 Ref #6215 Ref #6216 Ref #6217 Ref #6218 Closes #6219 Closes #6220 Ref #6221 Ref #6223 Closes #6224 Ref #6225 Ref #6226 Ref #6229 |
||
|
|
626b5e741b |
fix: Reduce discovery for authored fragments (#6203)
Ref #6177 Ref #6154 ## Outcome Bounded authored-fragment requests no longer receive broad design/authentication context bundles, registry discovery, or design-token operations through generic keyword matching. The initial ProjectSession synchronization is unchanged. Focused target reads, missing nested schemas, and expression guidance can still add calls when the requested fragment requires them. ## Root cause `meta.guide` treated the generic word `design` as visual intent and allowed workflow-specific context bundle tools to enter ordinary keyword-ranked recommendations. An authored component insertion could therefore be classified as visual work and receive `inspect-design-context` even without a supplied visual reference or a request to reuse the project design system. ## Implementation - Give specialized goal guides stable IDs and return structured routing metadata with the matched workflow and broad context tools. - Keep `inspect-auth-context` and `inspect-design-context` exclusive to their specialized workflows. - Treat Figma, screenshots, supplied designs, and explicit design-system references as visual intent without treating every use of `design` as visual work. - Suppress component/template registry discovery for explicit `insert-fragment` or authored-fragment requests. - Suppress design-token operations for those requests unless the brief explicitly asks for design-system or token reuse. - Preserve the existing design-input workflow for Figma, screenshots, and supplied designs. ## Todo - [x] Add a regression test for the reported authored timer/component workflow. - [x] Demonstrate that the regression test fails before the routing fix and passes afterward. - [x] Preserve explicit design-input discovery and verification behavior. - [x] Add machine-readable workflow routing metadata. - [x] Review documentation impact and update the authoritative MCP manual plus generated GitBook output. - [x] Review fixture impact; no fixture inputs or generated fixture bundles are affected. - [ ] Run the complete local agent evaluation suite. It was not run because repository policy requires separate explicit approval and approval was not provided. ## Verification - Project-session MCP tests: 117 passed. - Project-build and CLI typechecks passed. - Targeted oxlint passed. - Documentation generator tests and documentation typecheck passed. - MCP documentation and CLI generated docs were regenerated twice with stable hashes. - `git diff --check` passed. ## Tradeoffs and limitations - Brief classification remains deterministic intent matching; clients still decide which recommended tools they actually call. - The change prevents broad context tools from being recommended generically but does not enforce a universal discovery-call limit. - A fragment that genuinely needs existing tokens, unfamiliar expressions, or unknown target structure can still require focused discovery. - No schema migration, project-data migration, or fixture regeneration is required. |
||
|
|
b2d62b2e49 |
fix: Restore scoped descendant selectors (#6195)
## Summary Restore custom state selectors that target descendants of the selected instance, including `:hover .button` and `:hover > .icon`. The CSS engine already generated these selectors correctly. #5886 unintentionally rejected them while hardening MCP style inputs against selectors that can escape instance scope. ## Technical choices - Parse exactly one selector with `css-tree`. - Require the selector to begin with a pseudo-class, pseudo-element, or attribute state anchored to the selected instance. - Allow only descendant and direct-child combinators after that anchor. - Continue rejecting selector lists, unanchored type/class/ID selectors, sibling combinators, unknown pseudo-selectors, and pseudo-elements used as ancestors. - Document CSS variables as the preferred parent-child interaction pattern; use descendant selectors when selector-based targeting is specifically required. ## Todo - [x] Restore scoped descendant and direct-child selectors. - [x] Preserve instance-scope protections. - [x] Cover real authoring inputs and generated CSS. - [x] Demonstrate new tests fail without the restored behavior and scope guards. - [x] Verify the reported workflow through the local CLI/MCP and generated preview. - [x] Review documentation impact and update the authoritative Builder docs. - [x] Verify generated API contracts remain current. ## Verification - `pnpm --filter @webstudio-is/css-data test` — 4,623 passed, 1 skipped - `pnpm --filter @webstudio-is/css-data typecheck` - `pnpm --filter @webstudio-is/project-build exec vitest run src/runtime/styles.test.ts src/runtime/audit.test.ts` — 198 passed - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm lint` - `pnpm check:generated-api` - Documentation targets and anchors verified - Local MCP disposable-fixture workflow: - Discovered `insert-fragment` and `update-styles` through MCP metadata. - Inserted a card with a descendant `<button class="button">`. - Dry-run and committed `state: ":hover .button"`; `get-styles` returned the persisted state. - MCP preview generated `.chjrfuf:hover .button` while the card used the `chjrfuf` instance class, proving the selector remained instance-anchored. - Preview screenshot completed and returned HTTP 200. - Agent evaluations were not run because the suite has no custom-selector coverage ## Known limitation Sibling combinators remain unsupported because they can select elements outside the selected instance. Selector lists remain unsupported because later list entries can escape the generated instance prefix. Closes #6175 |
||
|
|
2df130171f |
feat: Resolve asset references as structured metadata (#6184)
## Summary - add exact `$ref` asset values that resolve to Asset Manager metadata - keep plain local asset paths returning URL strings for backward compatibility - derive reference metadata from the canonical asset object so newly added asset fields flow through automatically - let Assets query output fields select only the metadata returned, including nested arrays - carry the same resolved shape through preview, generated preview, published runtime, and static export - document the syntax and accessible image binding in Content Engine and MCP docs ## Design The source document declares only the relationship: ```yaml featureImage: $ref: ./assets/hero.png ``` The Assets query controls projection with fields such as `properties.featureImage.src` and `properties.featureImage.description`. Selecting `properties.featureImage` returns the canonical Asset Manager asset metadata together with the resolved `src`. The Content Engine runtime contract accepts the canonical asset object instead of maintaining a second metadata field list; `url` becomes `src`, and internal `contentRef` is not exposed. Plain strings retain their existing URL-string result. Existing document `$ref` behavior is preserved by resolving structured asset metadata only when the target is a known non-document asset. ## Verification - [x] Content Engine full test suite: 298 tests - [x] SDK full test suite: 517 tests - [x] Asset repository tests: 39 tests - [x] CLI prebuild tests: 58 tests - [x] Content Engine, SDK, Asset Uploader, CLI, and Project Build typechecks - [x] Repository lint - [x] Content Engine and MCP documentation generation and tests - [x] Generated API check - [x] Local fixture build and generated fixture update - [x] New behavior tests demonstrated fail before/pass after the implementation - [ ] Complete fixture sync (development API currently rejects this branch's newer CLI protocol; local fixture build passes) - [ ] Agent evaluations (not run; require explicit approval) ## Checklist - [x] Local structured references return field-selected metadata - [x] Newly added canonical asset fields flow through without a Content Engine whitelist change - [x] Plain-path queries remain backward compatible - [x] Nested object and array projection - [x] External URL strings remain usable - [x] Missing or null descriptions allow `??` fallback to the title - [x] Expanded metadata counts toward query result-size limits - [x] Documentation impact reviewed and Content Engine and MCP docs updated - [ ] Missing asset targets return a non-failing unresolved value and dedicated diagnostic - [ ] Apply the resource and Image binding changes to the separate Webstudio blog project ## Known limitation A `$ref` whose asset target no longer exists is not yet converted into an unresolved asset value with a dedicated diagnostic. This PR intentionally does not claim that acceptance criterion yet. Ref #6179 |
||
|
|
5a57234c75 |
revert: Store Content Block content in MDX assets
Revert the accidental merge of #6125 so the implementation can continue in draft PR #6181. |
||
|
|
5ec3547d36 |
fix: Support JSON content files in Builder (#6168)
## Summary - make the complete asset filename editable in Asset settings - convert existing editable text assets when their extension changes while preserving the asset ID - accept every JSON root type and normalize JSON-compatible syntax into formatted strict JSON - expose the same optional extension change through MCP/API `update-asset-content` - initialize new JSON files and empty text-to-JSON conversions with a valid empty object - distinguish browser URL imports from JSON file uploads so JSON objects with a root `url` field remain file content - update the Assets and Content Engine documentation ## Root cause Asset settings rendered the extension as a fixed suffix outside the name input. The metadata rename mutation could only change the display basename, while content revisions always inherited the current storage extension. As a result, changing `.md` to `.json` was impossible in the UI and unavailable through the shared MCP/API revision command. Asset settings now edits the complete filename. Ordinary renames keep using the metadata mutation. A text-extension change loads the current content, validates it for the target format, and writes a new immutable revision through the existing conflict-safe content endpoint. The existing Acorn-backed `parseJsonExpression` utility accepts JSON-compatible syntax without evaluating code and serializes it as strict JSON. Objects, arrays, strings, numbers, booleans, and `null` are all accepted. ## Checklist - [x] Create JSON files by entering a `.json` filename - [x] Edit the complete filename in Asset settings - [x] Convert editable text-file extensions while preserving the asset ID - [x] Expose extension conversion through `update-asset-content` - [x] Create JSON files and convert empty text files with a valid empty object - [x] Normalize safe JSON-compatible syntax to strict JSON - [x] Accept objects, arrays, and scalar JSON roots - [x] Reject executable or incomplete content - [x] Preserve browser-uploaded JSON object shapes - [x] Review and update authoritative Builder documentation - [x] Add focused UI, revision, HTTP-client, CLI/MCP, protocol, and upload regression tests - [x] Run affected typechecks, lint, documentation checks, and the Builder production build - [ ] Manually verify create, edit, rename `.md` to `.json`, reload persistence, and Content Engine query in a browser - [ ] Run the complete local agent evaluation suite if approved ## Verification - 217 focused tests passed across Builder, asset revisions, HTTP client, CLI/MCP, and protocol - Builder, asset-uploader, HTTP-client, protocol, CLI, and project-build typechecks passed - Builder production build passed - MCP and Content Engine documentation checks passed - `oxlint` on changed TypeScript files passed - `git diff --check` passed - Regression tests were demonstrated failing before the implementation and passing afterward A disposable E2E database and PostgREST stack bootstrapped successfully in the earlier real-path test, but UI automation remained blocked because no controllable browser was available. Fixture inputs and generated fixture outputs are not affected. Agent evaluations were not run because approval is required and was not requested. Closes #6167 |
||
|
|
81d5148046 |
fix: canonicalize trailing-slash page URLs (#6173)
## Outcome Canonical page URLs now omit a trailing slash in Webstudio Cloud sites and exported JavaScript applications. A request such as `/about/?campaign=launch` receives a permanent `301` redirect to `/about?campaign=launch`, preventing both URL variants from serving identical page content. The behavior is implemented once in the generated root redirect handler, so it covers fixed and dynamic application routes without generating an extra route per page. Exact project redirects remain authoritative. Protocol-relative-looking paths such as `//example.com/` are left untouched so canonicalization cannot become an external redirect. Static exports cannot redirect requests themselves. Their URL behavior remains host-specific and is documented for Cloudflare Pages, Netlify, Vercel, and other static hosts. ## Implementation - Add one shared pathname normalizer in the SDK. - Apply canonicalization after exact authored redirect matching in both generated application runtimes. - Ignore repeated leading slashes before constructing a redirect location. - Extend redirect-loop detection to model the implicit canonical redirect. - Regenerate the affected fixture applications from their templates. - Document application canonicalization and host-specific static export behavior. ## Todo 1. [x] Add central trailing-slash canonicalization. 2. [x] Preserve query strings, encoded path segments, and the root path. 3. [x] Cover concrete dynamic URLs without per-route generation. 4. [x] Preserve explicit project redirect precedence. 5. [x] Detect redirect loops that pass through canonicalization. 6. [x] Prevent protocol-relative external redirects. 7. [x] Regenerate and review fixture output. 8. [x] Review documentation impact; document application and SSG behavior. 9. [x] Run targeted and repository-level verification. ## Verification - SDK tests: 548 passed - SDK typecheck: passed - Project Build tests: 2,379 passed - Project Build typecheck: passed - CLI tests: 997 passed; two tests timed out only while three package suites ran concurrently, then both affected files passed in isolation (6/6) - Redirect regression suite after security follow-up: 302 passed - CLI typecheck: passed - `pnpm lint`: passed - `pnpm check:package-boundaries`: passed - `pnpm fixtures`: passed - Documentation internal anchors and Markdown whitespace: checked - New regression tests were confirmed failing before their implementations and passing afterward - Agent evaluations were not run because they require separate explicit approval Closes #6172 Closes https://github.com/webstudio-is/webstudio/issues/4327 |
||
|
|
86b6310fff | feat: Store Content Block content in MDX assets | ||
|
|
af11ec211f |
feat: Search all local project data from MCP (#6165)
Ref #6154 ## What - Add standalone search across all 13 synchronized Builder namespaces. - Search in the CLI ProjectSession and send only paged matches to the model; initial synchronization is unchanged. - Return stable match ids, exact paths, entities, references, and affected routes. - Preserve deprecated `scopes` output, redact recognized credential fields, and document the command. ## Objectives - [x] O1 — Universal Builder namespace search - [x] O2 — Stable identity and actionable location - [x] O3 — Filters, pagination, route impact, and references - [x] O4 — Honest synchronization → local search → model-input boundary - [x] O5 — Standalone command and workflow documentation - [x] O6 — Safety, compatibility, typed contracts, and regression tests Verified by Atlas (implementation), Scribe (docs/workflow), and Sentinel (adversarial review). ## Remaining #6154 work - [ ] Atomic semantic multi-record updates - [ ] Targeted route rendering and assertions - [ ] General slow-operation consent and time budgets - [ ] Full agent evaluation suite after approval ## Verification - Project search + MCP: 129 tests passed - Protocol docs: 8 tests passed - CLI schema/docs: 23 tests passed - Compact MCP handshake budget test passed - Project-build, protocol, and CLI typechecks passed - Generated docs and API checks passed - Agent evaluations not run; approval is required ## Limitation Asset metadata is searchable. Asset binaries and document contents are not Builder namespace data and are not searched. |
||
|
|
dbfb0a9849 |
fix: Preserve variable font styles (#6153)
## Summary Preserve font style metadata for variable fonts so upright and italic files from the same family produce distinct `@font-face` rules. Variable fonts with an `ital` or `slnt` axis are also registered for the matching CSS styles. ## Technical choices - Detect `normal`, `italic`, and `oblique` from the font binary, preferring OS/2 `fsSelection`, then `post.italicAngle`, then the existing subfamily parser. - Add `style` to variable-font metadata while defaulting legacy stored records to `normal`. - Keep update metadata partial and strict, but accept and persist `style` and `variationAxes` together so a `get-asset` result can be written back. - Group generated font faces by family, style, and browser-selectable variable descriptors so separate upright and italic files cannot overwrite each other. - Regenerate the runtime operation contracts from the updated schema. ## Checklist - [x] Add regressions using real upright and italic Inter variable-font binaries. - [x] Cover style detection, metadata compatibility, updates, and generated font-face selection. - [x] Verify the final stylesheet contains distinct upright and italic `@font-face` rules. - [x] Verify the public asset update contract accepts a complete variable-font metadata object. - [x] Review documentation impact and update the custom-font guide. - [x] Regenerate and verify runtime API contracts. ## Verification - `@webstudio-is/fonts`: 14 tests and typecheck passed. - `@webstudio-is/asset-uploader`: 198 tests and typecheck passed. - `@webstudio-is/sdk`: 514 tests and typecheck passed. - `@webstudio-is/project-build`: 2,094 tests and typecheck passed. - CLI: 980 tests and typecheck passed. - Builder typecheck passed. - `pnpm lint`, `pnpm check:package-boundaries`, `pnpm check:generated-api`, and `pnpm check:generated-docs` passed. - Regression tests were demonstrated failing against the previous behavior and passing with the fix. - Fixture builds regenerated successfully with no diff. Full remote fixture sync was attempted, but the deployed API rejected the source CLI contract as incompatible. - Agent evaluations were not run because they require separate explicit approval. Closes #6150 |
||
|
|
a22b23936d |
docs: Explain Content Engine limits (#6123)
## Summary - explain which kinds of blogs, catalogues, directories, and file-based content fit the Content Engine - identify projects better served by an external CMS, commerce backend, or media service - translate the current query, database, and content-loading limits into practical guidance - link readers to the complete Content Engine limits reference ## Why The existing guide explains how to build a Markdown blog but does not help readers decide whether the Content Engine is appropriate for their content volume, media needs, or editorial workflow. This addition sets expectations before readers commit to an architecture. ## Todo - [x] Document suitable Content Engine use cases. - [x] Document cases that should use an external system. - [x] Confirm every stated limit against the current implementation and generated reference. - [x] Review documentation impact: the authoritative Content Engine guide is updated; navigation is unchanged because this is an existing page. - [x] Verify the reference link and anchor. ## Verification - `pnpm docs:content-engine:test` — passed - `pnpm docs:content-engine:check` — generated files are clean - verified `content-engine-reference.md#query-limits` exists - `git diff --check` — passed The repository pre-commit hook was bypassed after its `oxfmt` task rejected the docs-only target because `docs/` is excluded from that formatter. The hook restored the file unchanged; the documentation-specific checks above passed before committing. |
||
|
|
87968f40ff |
fix: Improve MCP authoring and preview reliability (#6105)
## Summary
Fix MCP reliability failures reported in ten issues against CLI 0.288.0
and 0.289.0:
- keep every advertised array input schema client-valid, including
compact and tuple schemas
- report a text asset update as successful when its persisted revision
and bytes confirm that the server committed despite a failed response
- preserve standard package import resolution in generated React Router
previews
- upload variable WOFF2 fonts when callers provide the documented static
font metadata shape
- explain unmatched JSX as a stateless fragment syntax error
- distinguish the `animation` component namespace from value helpers and
reject unsupported CSS at-rules with an actionable validation error
- forward optional session tools such as `download-asset` through
top-level CLI shortcuts
- isolate published generated-preview dependencies from parent
workspaces
- return structured screenshot failures when React Router production
builds fail
Sensitive visual regression checks also run automatically for
organization-authored fork PRs. External fork PRs remain gated by
`safe-to-deploy`.
## Root causes and implementation
The MCP handshake compactor retained an array's type but discarded its
`items` schema. Unconstrained and tuple arrays could also be advertised
without `items`. Schema normalization now adds `items: {}` whenever an
array omits it, while focused discovery retains complete constraints.
Catalog coverage rejects every missing array item, including tuple
schemas, and the handshake remains below its 200 KB budget.
Asset content updates previously treated any failed response as a failed
mutation, even when the server had already swapped the revision.
Recovery now reads the current revision, compares the persisted bytes,
and confirms the revision remains stable across the read. It returns the
updated asset only when all evidence agrees. Otherwise it returns
`ASSET_UPDATE_COMMIT_UNCERTAIN` with guidance not to retry blindly.
Definitive 4xx responses retain their original errors.
The generated React Router Vite config replaced the client and SSR
resolver condition lists without explicitly retaining the standard
`import` condition. Both lists now preserve `import`. The regression
test generates a dynamic route, stages the built React Router SDK as a
published dependency without the local `webstudio` source condition, and
runs the generated build.
Variable fonts are detected with `variationAxes`. Merging the documented
static `style` and `weight` upload metadata into that detected variable
shape made validation fail after the binary was read. Font override
validation and shape-aware merging now live in `@webstudio-is/fonts`.
The SDK delegates to that domain function, which validates the complete
override before applying compatible fields, retains the detected
static-or-variable shape, and keeps the detected format.
Fragment parsing is stateless. Unmatched opening and closing tags now
explain that every opening element must use the same closing tag or be
self-closing, and that refreshing the session cannot repair malformed
JSX.
The `animation` binding is a component namespace, not a callable helper.
Tool schema text, evaluation errors, and the MCP manual now separate
component namespaces from value helpers. The MCP JSX `css` binding
parses the final interpolated CSS with CSS-tree and recursively rejects
selectors and unsupported at-rules such as `@keyframes`, while
preserving supported declarations and case-insensitive `@media` rules.
Keeping this validation at the external binding avoids changing internal
component templates.
CLI shortcut discovery previously omitted optional session tools even
though the runtime registered their handlers. Shortcut discovery now
includes the same optional tool categories as the CLI MCP host, while
real top-level CLI commands keep precedence.
Published generated previews could reuse a stale `node_modules` symlink
into a parent source workspace. Only development manifests containing
the local placeholder version may now reuse the CLI dependency tree.
Published manifests replace symlinks with a local install and disable
npm workspace discovery.
React Router could report a bundler failure while its build command
exited successfully outside CI, allowing screenshot startup to terminate
without a structured result. Managed production builds now set `CI=1`,
so the existing MCP error boundary receives the nonzero build failure
and prints structured JSON.
Visual regression authorization now distinguishes repository members
from external contributors. Organization members' fork PRs run on open,
synchronize, and reopen events; external fork code runs only from a
`safe-to-deploy` label event, and a later commit does not reuse that
approval.
## Implementation checklist
- [x] Preserve valid array item schemas in compact MCP discovery
- [x] Normalize tuple input schemas with an `items` fallback
- [x] Keep the MCP handshake below its 200 KB size budget
- [x] Cover the real `update-props` schema and oversized array
compaction
- [x] Reconcile failed asset-update responses against stable persisted
content
- [x] Reject recovery when a concurrent asset revision is detected
- [x] Preserve `import` resolution in generated React Router client and
SSR builds
- [x] Build a generated dynamic route against a staged published SDK
package
- [x] Regenerate and verify affected React Router fixtures
- [x] Preserve detected variable-font axes with documented upload
metadata
- [x] Add actionable unmatched-tag and unsupported-CSS validation
- [x] Correct animation namespace guidance in tool discovery and errors
- [x] Forward optional session tools through top-level CLI shortcuts
- [x] Replace parent-workspace dependency links for published previews
- [x] Disable npm workspace discovery for isolated preview installs
- [x] Make React Router build failures return nonzero in managed
previews
- [x] Run visual regression automatically for organization-authored PRs
- [x] Verify each regression test fails without its corresponding fix
- [x] Review documentation impact and update the authoritative MCP
manual plus generated outputs
- [x] Confirm no database migration or compatibility migration is
required
- [ ] Run `pnpm evaluations` after explicit approval; not run because
repository policy requires approval before agent evaluations
## Verification
- `packages/cli/src/prebuild.test.ts`: 57 tests passed
- `packages/cli/src/commands/schema.test.ts` and `mcp.test.ts`: 51 tests
passed
- `packages/project-build/src/runtime/components.test.ts` and
`mcp.test.ts`: 194 tests passed
- `packages/asset-uploader`: 196 tests passed
- focused font schema, SDK asset schema, CSS parser, and template CSS
tests passed
- `packages/http-client/src/index.test.ts`: 38 tests passed
- relevant CLI, project-build, asset-uploader, fonts, SDK, CSS data,
template, HTTP client, and React Router SDK typechecks passed
- MCP documentation tests, typecheck, generation, and Markdown source
tests passed
- React Router SDK package build passed
- full fixture link, sync, and generation pipeline passed
- affected Docker and Vercel fixture typechecks and locally bootstrapped
production builds passed
- complete CLI suite: 61 test files and 966 tests passed
- CLI typecheck passed
- preserved nested-workspace dynamic preview installed local `0.289.0`
dependencies and completed its production build
- visual-regression workflow YAML parsing and authorization truth table
passed
- repository lint passed with warnings denied
- formatting and `git diff --check` passed
## Tradeoffs and limitations
Deferred array schemas advertise unconstrained `items` in the compact
handshake to remain client-valid without duplicating detailed
constraints. Agents can retrieve the complete item schema through
focused `meta.get-more-tools` discovery.
Asset reconciliation performs three read requests only after an
uncertain 5xx, malformed response, or transport failure. This keeps the
normal successful path unchanged and avoids claiming success if the
revision changes during recovery.
For variable fonts, detected axes define the metadata shape. Static
`style` and `weight` hints are ignored because they cannot be
represented alongside `variationAxes`; compatible fields such as
`family` still override detection.
Native CSS keyframe authoring remains unsupported in fragment `css`
templates. The tool now rejects it before rendering and directs callers
to editable Webstudio Animation components instead of advertising a
nonexistent callable helper.
Published previews perform one isolated npm install when no valid local
dependency tree is cached. Local source development keeps the fast
workspace symlink path for placeholder-version manifests.
Closes #6104
Closes #6099
Closes #6098
Closes #6106
Closes #6107
Closes #6108
Closes #6114
Closes #6115
Closes #6116
Closes #6117
|
||
|
|
5c6ffd3148 |
docs: document Content Engine workflows (#6097)
## Summary - add a step-by-step Content Engine guide for building a Markdown article overview and dynamic article page - clarify that the example folder structure is optional and link to the Markdown Blog marketplace template - explain that an AI agent can complete the entire workflow through Webstudio MCP and include a ready-to-use prompt - document frontmatter, JSON files, relative and published asset paths, document references, draft filtering, and single-result resources - document Markdown-to-Markdown, Markdown-to-JSON, JSON-to-Markdown, and JSON-to-JSON document references, including fragments and JSON Pointer escaping - add a schema-aware `webstudio man content-engine` reference for fields, operators, saved and preview inputs, result/output/content modes, diagnostics, limits, and reference syntax - generate the GitBook Content Engine reference and the matching MCP manual section from that shared CLI source - fail documentation generation when result modes, output modes, content modes, diagnostic fields, or Content Engine limits drift from the implementation - add four focused visual-editor screenshots - keep the Assets page focused on asset management and link it to the dedicated Content Engine guide - update MCP Assets examples and the Markdown blog recipe to use Markdown files, `result: "one"`, direct detail bindings, page metadata, and visual verification ## Impact Users get one workflow for treating files as the source of truth while designing article listings and detail pages in Webstudio. The generated reference documents the complete Assets query contract and document-reference system. Agents receive the same reference through the MCP manual, so the product and agent documentation no longer need separate factual copies. This does not change product runtime behavior. ## Checklist - [x] Documentation impact reviewed - [x] Added the Content Engine guide and generated reference to `docs/SUMMARY.md` - [x] Updated related Assets, Data variables, and MCP documentation - [x] Verified internal documentation and image targets - [x] Verified the Markdown Blog marketplace URL returns HTTP 200 - [x] Confirmed the MCP recipe test failed before the recipe correction and passed afterward - [x] Confirmed the schema-coverage test fails when an implemented result mode is omitted and passes after restoration - [x] Confirmed both Content Engine generator tests fail without their corresponding generator behavior and pass after restoration - [x] Ran `pnpm --filter @webstudio-is/project-build test -- src/mcp.test.ts` - [x] Ran `pnpm --filter webstudio test -- src/commands/api-command-docs.test.ts` - [x] Ran the Content Engine and MCP generator tests - [x] Ran project-build and CLI typechecks - [x] Ran `pnpm check:package-boundaries` - [x] Ran targeted lint and formatting checks - [x] Ran `pnpm check:generated-docs` - [x] Verified the final diff and working tree - [ ] Agent evaluation suite: not run because it requires explicit approval Ref #5973 |
||
|
|
43a9f824ad |
fix: Resolve published asset paths in structured content (#6096)
## Summary Resolve Markdown frontmatter and JSON values written as published paths such as `./assets/hero.png` or `/assets/hero.png`, even when the content document and asset live in sibling Asset folders. This staging PR replaces #6094 and supersedes #6016. #6016's raw-format changes were unrelated to the reported asset-path problem. ## Technical approach - Keep format-neutral path indexing and resolution in `asset-path-resolution.ts`. - Keep `markdown-assets.ts` limited to Markdown destination parsing. - Normalize both Markdown frontmatter and JSON objects through the shared structured-value reference pipeline. - Keep canonical source-relative resolution as the first choice. - Recognize only the published `assets/<file-name>` path shape as a fallback. - Match the final canonical asset file name only when it uniquely identifies one project asset. - Leave external URLs, missing assets, ambiguous names, and unrelated root-relative paths unchanged. - Resolve recorded asset references to runtime URLs when queries render their results. ## Compatibility This extends resolution for imported/published structured content without changing ordinary source-relative paths or direct asset ID references. Duplicate final file names intentionally remain unresolved to avoid choosing the wrong asset. ## Checklist - [x] Add regression coverage for relative and root-relative published asset paths. - [x] Cover discovery and runtime structured-value resolution. - [x] Add explicit JSON document coverage with the asset in a sibling folder. - [x] Verify ambiguous asset names remain unresolved. - [x] Separate format-neutral resolution from Markdown parsing. - [x] Run the full content-engine test suite. - [x] Run content-engine typecheck and targeted lint/format checks. - [x] Rebuild content runtime and repository fixtures. - [x] Review documentation impact and update the Assets guide. - [ ] Manually verify the published site from `md-assets.staging`. - [ ] Confirm CI checks pass. ## Verification - Regression tests were run with the published-path fallback disabled and failed for both generic structured values and the explicit JSON integration case. - `pnpm --filter @webstudio-is/content-engine test` — 294 tests passed. - `pnpm --filter @webstudio-is/content-engine typecheck` — passed. - `pnpm exec oxlint --deny-warnings ...` — passed. - `pnpm exec oxfmt --check ...` — passed. - `pnpm --filter webstudio build:content-runtime` — passed. - `pnpm -r fixtures:build` — passed; no generated fixture diff. - `git diff --check` — passed. - Agent evaluations were not run because they require separate explicit approval. Closes #6093 |
||
|
|
eb46abf4e5 |
fix: Recover missing preview assets (#6091)
## Summary Fix session-based generated preview startup when the local `.webstudio/assets` directory has not been created yet. - materialize the current session's asset files before compiling the Assets resource index - reuse the existing safe asset downloader so missing parent directories are created and downloads retain retry and temporary-file cleanup behavior - return the stable `PREVIEW_ASSET_DOWNLOAD_FAILED` code with a concrete recovery action when asset access cannot be restored automatically - document the automatic recovery and regenerate the authoritative MCP manual ## Root cause `preview.start` materialized current ProjectSession data and compiled reachable Assets resources before generated-app prebuild. That compilation called `realpath` on the local assets directory, but the session path had never downloaded assets the way `webstudio sync` does. A newly linked project without `.webstudio/assets` therefore failed with `ENOENT` before preview generation. ## Technical choices - Download only after confirming that the project has a reachable Assets resource compilation plan. - Keep canonical path and symlink validation in the filesystem content source after materialization. - Wrap download failures at the preview boundary without exposing local paths or raw remote diagnostics. - Preserve the existing generated-doc source/generator workflow rather than editing generated guidance alone. ## Todo - [x] Reproduce startup from a missing local assets directory - [x] Materialize required session assets before index compilation - [x] Add actionable failure recovery - [x] Add fail/pass regression coverage - [x] Review documentation impact and update the MCP vision guidance - [x] Regenerate the CLI and GitBook MCP manuals - [x] Review fixture impact — no fixture inputs or generated fixture outputs are affected - [x] Run the focused low-reasoning Markdown fixture, including the cold assets-directory scenario - [ ] Deferred: run the remaining agent evaluation fixtures ## Verification - Regression demonstrated failing before the fix with `ENOENT` for the missing assets directory, then passing after the fix. - Recovery regression demonstrated failing with raw `ENOENT`, then passing with `PREVIEW_ASSET_DOWNLOAD_FAILED` and the retry action. - `pnpm --filter webstudio test` — 60 files, 976 tests passed. - `pnpm --filter webstudio exec vitest run src/project-session.test.ts src/mcp-guidance.test.ts` — 25 tests passed after final fixture cleanup. - `pnpm --filter webstudio typecheck` — passed. - Targeted `oxlint --deny-warnings` — passed. - Documentation generation, docs tests, and docs typecheck — passed. The aggregate generated-doc clean-tree guard reports the intentionally changed generated CLI/GitBook outputs included in this PR. - `git diff --check` — passed. - Focused real-world evaluation: `gpt-5.4-mini` with `model_reasoning_effort="low"`, `markdown-blog-v1`, 12/12 MCP calls succeeded, 0 failures, 0 retries, 2 rendered verifications, and all fixture checks passed. - Cold-directory variant: removed `.webstudio/assets` immediately before the first rendered verification; preview restored the required assets, and both verification calls plus content-database checks passed. - Remaining high-impact fixtures were not run; this was the targeted real-world scenario requested for #6090. ## Known limitations Preview startup still requires network and project asset access when required files are not already local. It now reports a stable error and tells the caller to restore access and retry instead of leaking an `ENOENT`. Closes #6090 |
||
|
|
db3b11970f |
fix: Optimize images in Markdown Embed (#6089)
## Summary Markdown Embed now renders image tags with the same optimized attributes and canvas behavior as the SDK Image component. The implementation shares the complete attribute-resolution path without rendering React inside the Markdown pipeline: - `@webstudio-is/image` exposes one framework-independent `getImageAttributes` function for optimization, placeholder fallback, loading, decoding, dimensions, alternative text, and responsive sources. - React-only element props such as `className`, `style`, handlers, context, and refs stay in React callers. - The SDK Image component and Markdown renderer both use `getSdkImageProps` for canvas-specific loading, decoding, asset identity, and incomplete-upload handling. - Markdown retains only the necessary HTML attribute-name conversion, sanitization, and Safari-safe `sizes` / `srcset` / `src` ordering. - The redundant low-level React Image primitive was removed. Its callers now render native `img` elements, and the image package no longer has React runtime or peer dependencies. ## Compatibility and tradeoffs - The SDK Image component remains the public React component because it owns React context and ref forwarding. - The removed low-level `@webstudio-is/image` Image export is replaced by the pure attribute function for internal callers. - No data migration or schema change is required. - Loader output is sanitized after transformation, while unsafe input URLs are sanitized before reaching the loader. ## Todo - [x] Share image attribute resolution between native, SDK, and Markdown images. - [x] Preserve SDK canvas behavior for Markdown images. - [x] Preserve safe URL sanitization and Safari-safe responsive attribute ordering. - [x] Remove the redundant low-level React image primitive and migrate its callers. - [x] Remove the overlapping `getImageProps` abstraction. - [x] Add regression coverage comparing Markdown, SDK Image, and native attribute output. - [x] Review documentation impact and update the Markdown Embed documentation. - [x] Run targeted tests, typechecks, builds, lint, formatting, package-boundary checks, and fixture generation. ## Verification - `pnpm --filter @webstudio-is/image test` - `pnpm --filter @webstudio-is/image typecheck` - `pnpm --filter @webstudio-is/image build` - `pnpm --filter @webstudio-is/image dts` - `pnpm --filter @webstudio-is/sdk-components-react test` - `pnpm --filter @webstudio-is/sdk-components-react typecheck` - `pnpm --filter @webstudio-is/sdk-components-react build` - `pnpm --filter @webstudio-is/sdk-components-react dts` - `pnpm --filter @webstudio-is/builder typecheck` - `pnpm --filter @webstudio-is/design-system typecheck` - Targeted Oxlint and Oxfmt checks - `pnpm check:package-boundaries` - `pnpm fixtures` (no fixture diff) Ref #6014 |
||
|
|
e4983b0d1d |
fix: Report unsupported Node versions (#6058)
Closes #6057 ## Outcome Generated projects now reject Node.js versions older than 22.12 before React Router, Remix, or Vite evaluates SDK components. Users see the package-manager engine error with the current and required versions instead of the indirect `sanitize-html` / `htmlparser2` `ERR_REQUIRE_ESM` stack trace. ## Root cause `sanitize-html@2.17.6` synchronously loads the ESM-only `htmlparser2@12`. That dependency combination relies on synchronous `require(ESM)` support, which Node.js enabled by default in 22.12. Generated projects incorrectly declared the broader `>=22` range, allowing an unsupported runtime to reach SSR evaluation. ## Implementation - Set the CLI and all generated base templates to `engines.node: >=22.12.0`. - Add npm `devEngines.runtime` with `onFail: error`, which runs before install, CI, and run commands. - Enable `engine-strict` in generated npm configuration so pnpm also rejects an unsupported runtime. - Regenerate every tracked CLI fixture package manifest. - Update CLI documentation and the release-smoke manifest contract. - Remove the earlier sanitizer-bundling workaround from the branch; sanitizer code and packaging are unchanged from `main`. ## Checklist - [x] Declare the exact Node.js compatibility floor - [x] Fail before generated development, build, and start commands - [x] Cover the generated engine contract with a fail/pass regression - [x] Regenerate and inspect all affected fixtures - [x] Review documentation impact and update the CLI guide - [x] Keep sanitizer behavior and SDK packaging unchanged ## Verification - Regression demonstrated failing before the template metadata change and passing afterward - `pnpm --filter webstudio test` — 946 passed - `pnpm --filter webstudio typecheck` - `pnpm --filter webstudio build` - `pnpm fixtures` - `pnpm lint` - `pnpm exec oxfmt --check` on changed source, template, fixture, and documentation files - `git diff --check` Agent evaluations were not run because they require separate approval. |
||
|
|
1fe087ed26 |
fix: Improve MCP preview and mutation reliability (#6073)
## Summary Fix the second MCP reliability batch across tool discovery, runtime mutations, preview/screenshot setup, Windows process launching, and stdio recovery. ## Implementation - [x] #6071 Accept canonical dotted/kebab tool names and MCP underscore names in `mcp run`; return near matches and `meta.index` guidance for unknown tools. - [x] #6067 Parse JSON-stringified `tools` arrays in `meta.get-more-tools`. - [x] #6069 Preserve resource-backed variables when renaming without a replacement value. - [x] #6068 Parse CSS declaration strings consistently in design-token style updates. - [x] #6065 Fail immediately for occupied explicit screenshot ports and discover Chromium from the Playwright browser cache. - [x] #6066 Recover the stdio MCP transport after an abandoned partial newline-delimited frame. - [x] #6072 Launch managed Windows previews through Node plus `npm-cli.js`, avoiding `spawn EINVAL`. - [x] #6061 Reuse `npm-cli.js` when launched through `npx`, fall back to the Node-adjacent npm CLI on Windows, forward `npm_config_cache`, and include sanitized package-manager diagnostics. - [x] Address review findings: preserve rebinding on resource scope changes and discover default Playwright caches on Linux, macOS, and Windows. - [x] Complete the DRY pass: remove the dead npm command selector, centralize accepted MCP tool-name lookup, simplify stdio frame recovery, and share Levenshtein distance across MCP suggestions and screenshot text matching. - [x] Complete the follow-up review: centralize preview URL port resolution, use `get-port` instead of custom TCP probing, use named resolver dependencies, and correctly reuse owned previews on default HTTP/HTTPS ports. - [x] Complete the final review: use non-reserving `detect-port` checks for explicit ports and repair the generated-app guidance regression coverage. - [x] Audit new utility code against maintained libraries: use `fastest-levenshtein` for edit distance; retain custom stdio recovery, Playwright cache discovery, and npm launching where no supported library API preserves the required behavior. - [x] Audit Windows/macOS/Linux compatibility helpers: use `path-key` for environment PATH casing and `which` for executable discovery; retain explicit Playwright layouts, browser application paths, npm CLI resolution, symlink types, and process-tree shutdown where behavior is platform- or product-specific. - [x] Add fail/pass regression coverage for every fix. - [x] Review documentation impact and update the CLI MCP sources plus generated GitBook output. - [x] Review fixture impact: no fixture inputs or generated fixture bundles are affected. - [x] Run targeted tests, package type checks, lint, package-boundary checks, generated API checks, and generated documentation checks. - [ ] Agent evaluations — not run because repository policy requires separate explicit approval. ## Verification - Complete CLI suite: 60 files, 968 tests passed. - Project-build affected tests: 4 files, 382 tests passed. - `pnpm --filter webstudio typecheck` - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm lint` - `pnpm check:package-boundaries` - `pnpm check:generated-api` - `pnpm check:generated-docs` Each new regression test was run against the unfixed behavior to confirm the expected failure, then rerun after its fix. ## Compatibility note The stdio recovery layer discards only an unterminated frame that remains idle for five seconds. Complete newline-delimited JSON-RPC frames continue through the SDK transport unchanged. Closes #6072 Closes #6071 Closes #6069 Closes #6065 Closes #6066 Closes #6067 Closes #6068 Closes #6061 |
||
|
|
d5b3f3ab80 |
fix: Improve MCP authoring reliability (#6056)
## Summary This consolidates the reported MCP reliability fixes into one delivery. - validate all inserted fragment expressions with the shared runtime rules and reject text/expression children when component content models require elements - return an actionable error for unsupported existing-resource references in JSX - preserve siblings rendered before expression children - accept unresolved CSS-variable shorthand expansion and eliminate dynamic-alt/`htmlFor` audit false positives - resolve exposed underscore MCP names during focused discovery - omit unavailable stopped-preview fields and restart stale iterative previews for external clients - bound single and responsive screenshot capture, return `SCREENSHOT_TIMEOUT`, and discard failed reusable browser sessions - dispose previews when shared MCP runs fail or stdio clients disconnect, including complete Windows process-tree cleanup - resolve generated route templates from the CLI-managed preview workspace during responsive verification - retry a browser that exits during rendered-audit startup and report sanitized exit diagnostics with a concrete browser-path recovery action - materialize complete current session data before preview generation so route order and project styles cannot collapse from missing lazy namespaces - always include CLI and Node.js version fields in generated issue reports, with explicit legacy-client fallbacks - document the updated preview and screenshot contracts and regenerate the CLI manual The current branch also retains the protections already present on `main` for dry-run isolation, CSS rewrite truncation metadata, stderr-only progress, shortcut argument forwarding, strict MCP schemas, and refreshed conflict diagnostics. ## Technical choices - MCP command orchestration stays in `mcp.ts`; preview port/retry behavior lives with `mcp-preview`, and persisted checkpoint storage lives in `mcp-checkpoint`. Each module owns its matching tests. - Expression validation lives on the shared fragment input schema, reuses `listFragmentExpressions`, and emits the same structured validation issues as prop bindings, so JSX-derived and structured fragments follow one contract across fragment, collection, and runtime UI insertion. - Element-child requirements come from component registry content models during fragment insertion; no component names are hardcoded in the JSX parser. `CollapsibleTrigger` metadata now matches its enforced `asChild` implementation. - Stopped preview status returns only `running: false`; unavailable `url`, `pid`, and `mode` fields are optional and omitted from JSON. - Explicit `preview.start` restarts a stale compatible iterative preview; managed screenshots keep their optimized refresh path. - Screenshot operations share one timeout utility. A single capture or complete responsive batch is bounded after preview readiness; lower-level CDP deadlines use the same stable error code. - Failed managed captures close and forget their browser session. A closed browser session cannot restart itself while cancellation is in progress, which prevents orphaned Chromium processes. - One ownership helper disposes one-shot and multi-project MCP hosts on success or failure. Shared `mcp run` hosts dispose in one `finally` boundary, long-running MCP hosts dispose on connection close, and Windows uses `taskkill /T /F` instead of killing only the npm wrapper. - Framework template readers receive the absolute template directory captured from the build root, so later async work cannot redirect them to the linked project's cwd. The same option drives cleanup for React Router, Remix, and Vike. - Browser startup gets one bounded retry before a rendered capture batch fails. Persistent failures report only the exit code, signal, or spawn error code plus the supported `WEBSTUDIO_BROWSER_PATH` recovery action; local paths and raw browser output are not exposed. - CLI and MCP preview share one session materializer that ensures the canonical Builder namespace set before writing `.webstudio/data.json`. Serialization rejects incomplete snapshots instead of converting missing style/instance namespaces into valid-looking empty arrays, and preview freshness records the post-materialization project version. - The CLI injects its package version and `process.versions.node`; issue formatting now keeps both fields visible even for legacy reports that omit runtime metadata. ## Checklist - [x] Add regression coverage for every changed behavior - [x] Demonstrate new regression tests fail without the corresponding fixes and pass with them - [x] Run affected package test suites and typechecks - [x] Run lint, package-boundary, and generated API checks - [x] Review fixture impact — no fixture inputs or outputs are affected - [x] Review documentation impact and update the authoritative MCP CLI manual source/generated output - [x] Run the complete local agent evaluation suite ## Verification - `@webstudio-is/project-build`: 2,090 tests passed - MCP asset query result modes are preserved across create, read, and update serialization - complete local agent evaluation suite: all 5 fixtures passed, 1,308,276 aggregate tokens - `@webstudio-is/react-sdk`: 140 tests passed - `@webstudio-is/template`: 43 tests passed - `webstudio` CLI: 956 tests passed - issue reporter: 5 targeted tests passed - MCP host disposal regression was demonstrated failing without the shared ownership boundary and passing with it - relevant package typechecks passed - `pnpm lint` passed - `pnpm check:package-boundaries` passed - `pnpm check:generated-api` passed - generated-doc tests, typecheck, sync, and regeneration passed; the aggregate clean-tree command reports the intentionally changed generated CLI manual - stalled single capture, stalled four-viewport capture, startup retry across a four-viewport batch, sanitized browser-exit diagnostics, complete preview materialization, post-refresh version tracking, closed-session restart, Windows process-tree cleanup, and preview-workspace regressions were demonstrated failing without their fixes and passing with them ## Known limitations - External `baseUrl` screenshots remain caller-owned and intentionally do not regenerate, restart, or stop that external server. Closes #6034 Closes #6035 Closes #6038 Closes #6042 Closes #6043 Closes #6044 Closes #6045 Closes #6046 Closes #6047 Closes #6048 Closes #6049 Closes #6050 Closes #6051 Closes #6052 Closes #6059 Closes #6060 |
||
|
|
928867a08b |
fix: Improve MCP CSS variable safety and state feedback (#6018)
Closes #6017 Ref #6019 ## Summary Improve agent-facing CLI/MCP feedback for CSS variables, mutation durability, batch operations, and preview freshness. ## Implementation - Validate structured hex colors as normalized channels and recommend CSS strings for ordinary 0–255 hex input. - Return exact CSS variable values while retaining `valueLength` in compact output for compatibility. - Preserve optional boolean inputs generically in compact MCP SDK schemas, including `withUsage`, `verbose`, `overwrite`, and `force`. - Add multi-variable define/delete examples and document safe batching. - Derive `meta.session.commitStatus` from the session envelope so reads, plans, failed/no-op mutations, and durable mutations are unambiguous. - Retain `committed` on read results for compatibility while reporting `commitStatus: "not-applicable"`. - Report preview `stale` state and `renderedProjectVersion`, and avoid marking a preview fresh when the project changes during regeneration. - Track WSL2/9P cleanup hardening separately in #6019. ## Todo - [x] Reject out-of-range structured hex color channels and alpha. - [x] Add fail-before/pass-after CSS color regression coverage. - [x] Return exact compact CSS variable values without removing `valueLength`. - [x] Clarify mutation durability with `commitStatus`. - [x] Distinguish failed, unchanged, planned, committed, and read-only results. - [x] Distinguish server-backed reads from committed mutations at the session boundary. - [x] Preserve optional boolean schemas without a per-field allowlist. - [x] Add multi-variable define and delete examples. - [x] Report preview freshness and rendered project version. - [x] Investigate WSL cleanup behavior and create follow-up #6019. - [x] Review and update authoritative CLI/MCP documentation. - [x] Verify fixture impact; no fixture inputs or outputs changed. - [x] Run affected tests, typechecks, lint, and generated-file checks. - [ ] Run the complete local agent evaluation suite after explicit approval. ## Verification - [x] Regression tests demonstrated failing before their implementation and passing afterward. - [x] `pnpm --filter @webstudio-is/project-build test` — 82 files, 2,085 tests passed. - [x] `pnpm --filter webstudio test` — 57 files, 939 tests passed. - [x] Project-build and CLI typechecks passed. - [x] `pnpm lint` passed. - [x] `pnpm oxfmt --check` passed. - [x] `pnpm check:generated-api` passed. - [x] `pnpm check:generated-docs` passed. - [ ] `pnpm evaluations` — awaiting explicit approval per repository policy. ## Compatibility and limitations - `committed` remains available on every session result. For reads it is `false` and durability does not apply; use `commitStatus: "not-applicable"`. - Compact CSS-variable records include both exact `value` and `valueLength`. - Structured hex color channels remain normalized `0..1`; CSS color strings such as `"#2d3748"` are the recommended 0–255 representation. - WSL2/9P process cleanup is not changed in this PR and is scoped in #6019. |
||
|
|
8e7a8a21aa |
feat: Report anonymous MCP reliability issues (#6021)
Closes #6020 ## Summary Adds the first end-to-end slice for anonymous, LLM-authored reliability reports from the CLI and MCP. The shared report contract captures the generalized user story, attempted workflow, expectation, actual result, recovery attempts, user impact, technical context, acceptance criteria, and agent runtime (client, provider, model, version, and reasoning effort). Guidance requires removing any user- or project-identifying information before submission. ## Architecture - Adds a project-authenticated `api.reports.issue` tRPC mutation as the reusable product boundary. - Maps that mutation to the public `report-issue` operation for CLI and MCP callers. - Keeps the endpoint directly callable from a future Builder UI through the existing tRPC client. - Publishes through a server-side GitHub App installation, so end users do not need GitHub accounts or tokens. - Discovers the App installation for the fixed Webstudio reporting repository instead of requiring deployment-specific installation or repository configuration. - Searches for a hidden anonymous technical marker before creation to avoid obvious duplicates. ## Todo 1. [x] Define a shared anonymous LLM-authored report contract. 2. [x] Include the user story, attempted workflow, expected and actual behavior, recovery attempts, impact, technical context, and acceptance criteria. 3. [x] Include the LLM client, provider, model, client version when known, and reasoning effort. 4. [x] Attach sanitized CLI, Node.js, operating-system, architecture, execution-mode, and API-contract metadata automatically. 5. [x] Add the Builder-reusable project tRPC mutation. 6. [x] Expose the mutation to CLI and MCP as `report-issue`. 7. [x] Add GitHub App authentication and issue publication. 8. [x] Reduce deployment configuration to the App ID and private key. 9. [x] Add marker-based duplicate detection. 10. [x] Add guidance for explicit user-requested reports and qualifying repeated-friction reports. 11. [x] Review and simplify repeated GitHub request handling and public protocol exports. 12. [ ] Add server-side throttling and harden concurrent duplicate creation. 13. [x] Configure and install the reporting GitHub App in deployed environments. 14. [x] Exercise the deployed endpoint with a controlled test report. 15. [ ] Run the complete agent evaluation suite after explicit approval. 16. [x] Review documentation impact and update the generated MCP documentation. ## Verification - Protocol issue-report contract tests: passed (3) - Builder GitHub reporting tests: passed (4) - Builder API router tests: passed (30) - CLI schema, command-doc, MCP, and project-session tests: passed - Protocol, HTTP client, project-build, CLI, and Builder typechecks: passed - Root lint: passed - Generated API and documentation checks: passed - New and changed regression tests were demonstrated failing against the previous behavior, then passing after implementation - No fixture inputs or outputs are affected - Agent evaluations were not run because they require explicit approval ## Deployment notes The Builder only needs `GITHUB_ISSUE_REPORT_APP_ID` and `GITHUB_ISSUE_REPORT_PRIVATE_KEY`. The server discovers the App installation for `webstudio-is/webstudio` and creates a short-lived installation token. The App needs repository metadata read access and Issues write access. ## Known limitations Duplicate detection currently uses GitHub issue search and can race when identical reports arrive concurrently. The endpoint is project-authenticated, but dedicated server-side throttling remains a follow-up before production rollout. No Builder UI is included yet; the tRPC boundary is intentionally ready for one. |
||
|
|
6385e290c6 |
feat: Add syntax highlighting to Code Text (#6007)
Closes #4119 Supersedes #5999 after GitHub closed it during the head-branch rename. ## Approach Code Text uses one optional public highlighting boundary: - `@webstudio-is/sdk-components-react/code-text` → `src/code-text.tsx` The ordinary `components` entry remains Shiki-free. Canvas loading, metadata options, theme variables, and the plain semantic `<code>` component remain private implementation details. **Code** uses the code editor. **Language** and **Theme** use normal bindable selects. Fixed selections generate direct imports for only the per-page language/theme union; plaintext imports no grammar. Bound selections generate Shiki's lazy language/theme registries. SSR and client rendering share the same factory. Missing bound assets suspend the first render while SSR resolves the selected modules. SSG now waits for Suspense before serializing HTML. During hydration the completed server markup stays in place while the browser fetches only the selected language and theme. Later client-side binding changes load only the new selections and keep the same `<code>` node and focus. Highlighted output preserves the semantic root, ref, author classes/styles, whitespace, escaped source, and legacy children/native `lang` behavior. Shiki's implicit tab stop is disabled. A color-only transformer strips theme typography so asynchronous highlighting cannot change text geometry. ## Bundle impact Measured from same-commit production React Router + Cloudflare builds containing one JavaScript / GitHub Light Code Text instance. Sizes are the sum of emitted JavaScript files; gzip is the sum of each file compressed independently. | Worker output | Files | Raw | Sum gzip | | --- | ---: | ---: | ---: | | Fixed selections | 3 | 1,341,851 B | 288,342 B | | Bound selections | 310 | 10,372,112 B | 1,872,273 B | | Increase | +307 | +9,030,261 B (8.61 MiB) | +1,583,931 B (1.51 MiB) | The bound browser build also emits the catalog as lazy chunks: +9,012,594 raw bytes / +1,578,779 sum-gzip bytes across the complete deployed output. Those chunks are not all delivered on page load. The production SSG regression verifies 100+ catalog chunks are emitted while the HTML directly module-preloads only one shared runtime chunk; the browser fetches the runtime-selected language/theme modules on demand. ## Tradeoffs and compatibility - Instances with both highlighting properties unset keep the legacy plain renderer. - Static highlighting still requires both **Language** and **Theme**. - Binding either selection includes that catalog in deploy output because its runtime value is not known at publish time. - The syntax-highlighting property is `language`; legacy native HTML `lang` remains preserved. - Invalid or unavailable runtime selections render as plain code. - Fixed selections retain the smallest publish output; bound selections trade deploy/worker size for runtime flexibility. ## Todo - [x] Restore the specialized Code Text component and semantic plain fallback - [x] Use a code editor for Code and bindable selects for Language and Theme - [x] Persist JavaScript / GitHub Light template defaults - [x] Collapse highlighting to one public `./code-text` entry - [x] Keep canvas loaders and option/theme helpers private - [x] Generate direct imports for fixed selections and omit plaintext grammar - [x] Generate lazy catalogs when Language or Theme is bound - [x] Preserve highlighted SSR markup during hydration without node/focus movement - [x] Support Suspense-aware highlighted SSG output - [x] Preserve escaping, accessibility, legacy children, and native `lang` - [x] Measure fixed versus bound Cloudflare worker output - [x] Deep-review correctness, DRYness, package surface, and obsolete binding infrastructure - [x] Review documentation impact and update Code Text documentation - [x] Run focused tests, typechecks, production builds, formatting, and staged diff review - [ ] Fixture pipeline — blocked during sync because the current API rejects this local CLI version as incompatible; no fixture output changed ## Verification - [x] New/changed regressions were demonstrated failing without their behavior and passing after restoration - [x] SDK Code Text metadata, rendering, hydration, and bundle tests: 17 passed - [x] Component registry tests: 3 passed - [x] CLI asset collection and full prebuild suite: 59 passed - [x] SDK components, component registry, SDK, and CLI typechecks - [x] SDK components declaration and production builds - [x] Component registry production build - [x] Production Vite + Vike prerender emits highlighted bound SSG HTML with one doctype - [x] Dynamic catalog chunks remain outside the SSG page's direct preload set - [x] Documentation reviewed and updated - [x] Formatting and staged diff checks |
||
|
|
74d88a3fb2 |
fix: Resolve structured Asset paths in queries (#5995)
## Summary Resolve portable relative Asset paths stored in Markdown frontmatter and structured JSON properties to canonical runtime Asset URLs inside the content engine. The authored source remains unchanged. Asset resource consumers now receive canonical URLs without Image, CSS, JSON-LD, or other binding-specific transformations. ## Root cause Markdown body links already recorded relative Asset references for runtime rewriting, but structured values bypassed that pipeline. Browsers therefore resolved values such as `./assets/hero.png` against the page URL instead of the source document folder. ## Implementation - Recursively discover unique structured Asset references using the existing canonical path resolver and the platform URL parser. - Store optional `assetValueReferences` in content artifacts and runtime projections. - Include referenced Assets in publication/runtime dependency collection and validation. - Resolve values before filtering, sorting, and projection in normal and document-graph queries. - Rewrite materialized query items at runtime without mutating canonical documents or compiled rows. - Merge authored query parameters and fragments with canonical Asset URLs. - Keep queries whose filter/sort semantics depend on runtime Asset URLs out of compile-time materialization. - Add an explicit content-compilation cache generation so pre-feature artifacts are recompiled. - Refresh fixture bundle versions and the generated asset-query runtime. - Document relative references in Markdown frontmatter and JSON content. ## Checklist - [x] Add structured reference discovery for nested objects and arrays - [x] Support Markdown frontmatter and JSON document properties - [x] Preserve URL query strings and fragments - [x] Thread references through build/runtime artifacts and publication dependencies - [x] Resolve normal, materialized, and document-graph query results - [x] Apply resolved values to filtering, sorting, and projection - [x] Preserve compatibility with artifacts that omit the optional field - [x] Add fail/pass regression coverage - [x] Run package tests, typechecks, lint, and generated API checks - [x] Regenerate and build all fixtures - [x] Review documentation impact and update the Assets guide ## Verification - `pnpm --filter @webstudio-is/content-engine test` — 269 passed - `pnpm --filter @webstudio-is/content-engine typecheck` — passed - `pnpm --filter @webstudio-is/asset-uploader test` — 184 passed - `pnpm --filter @webstudio-is/asset-uploader typecheck` — passed - `pnpm --filter @webstudio-is/protocol test` — 88 passed - `pnpm lint` — passed - `pnpm check:generated-api` — passed; generated files clean - `pnpm --filter webstudio build:content-runtime && pnpm -r fixtures:build` — passed for all fixtures - Assets documentation — internal links resolve and `git diff --check` passes - Regression proof: neutralizing structured discovery/replacement caused 8 expected failures across source compilation, standard queries, document-graph queries, and materialized queries; restoring the implementation passed all tests. - `pnpm evaluations` — not run because explicit approval is required. ## Compatibility The artifact field is optional, so older artifacts continue to parse and execute. Existing absolute, protocol-relative, root-relative, fragment-only, query-only, external-scheme, malformed, missing, and ambiguous values remain unchanged. |
||
|
|
1f4095cf9a |
fix: Improve generated MCP documentation (#5991)
## Summary
- render the generated MCP version as visible body content immediately
below the page heading
- keep the GitBook navigation label stable as `MCP`
- stamp only the CLI version placeholder during release publication,
leaving Markdown content owned by the template
- remove empty `{}` blocks from the rendered MCP argument examples while
preserving meaningful examples and complete structured JSON data
## Root cause
GitBook uses the `SUMMARY.md` link label as the published page heading
and suppresses the Markdown H1 from the document body. The generated
version was therefore present in source but absent from the rendered
page.
The release workflow also coupled version stamping to the complete
rendered Markdown line. It now replaces and verifies only the standard
`0.0.0-webstudio-version` placeholder.
## Verification
- live page structure inspected: published H1 is `MCP`
- MCP manual regression test demonstrated failing before empty argument
blocks were filtered, then passing after the fix
- release placeholder stamping simulated against the generated page
- `pnpm --filter webstudio exec vitest run src/commands/man.test.ts`
- `pnpm --filter @webstudio-is/project-build typecheck`
- `pnpm --filter webstudio typecheck`
- `pnpm check:generated-docs`
- `pnpm lint`
- `pnpm oxfmt --check packages/project-build/src/mcp.ts
packages/cli/src/commands/man.ts packages/cli/src/commands/man.test.ts`
- `git diff --check`
Fixture inputs and outputs are unaffected.
## Todo
- [x] Generate the release version as visible GitBook body content.
- [x] Decouple release stamping from the rendered Markdown content.
- [x] Remove empty MCP argument example blocks.
- [x] Validate generated output and regression coverage.
- [ ] Merge this pull request.
- [ ] Publish the latest released revision to the `docs` branch.
- [ ] Verify the version on the live GitBook page.
Ref #5986
|
||
|
|
e6a29b5d36 |
fix: Show released CLI version in MCP docs (#5990)
## Summary - make the MCP page generator render the CLI package version directly in the page title - publish `Webstudio MCP v<release>` from the exact generated page in each successful release - merge each successful release tag into the publication-only `docs` branch - serialize publication and ignore reruns or older release tags already contained in `docs` ## Root cause The first publication design advanced `docs` to the release commit without putting the CLI package version into the generated page. The repository uses `0.0.0-webstudio-version` until release time, so the release workflow now replaces that existing version placeholder with the successful tag version before publishing. ## Todo - [x] Generate the CLI version in the MCP page title. - [x] Publish the generated page from the exact release revision. - [x] Make publication idempotent and prevent version downgrades. - [x] Validate generation, formatting, linting, and release-branch behavior. - [ ] Merge this pull request. - [ ] Publish `0.285.0` as the initial version on the existing `docs` branch. ## Verification - `pnpm docs:mcp:test` - `pnpm docs:mcp:typecheck` - `pnpm check:generated-docs` - `pnpm lint` - `pnpm oxfmt --check` - `git diff --check` - isolated Git simulation for release merge, exact generated-page selection, version replacement, and rerun detection - regression tests demonstrated failing without version rendering and validation, then passing after restoration Ref #5986 |
||
|
|
99371187dc |
docs: Move product documentation into Builder (#5987)
## Summary - move the complete GitBook documentation tree and assets into Builder under `/docs` - generate the exhaustive MCP page from the local CLI source in the same change - publish GitBook from a release-gated `docs` branch containing the exact successfully released revision - run MCP documentation tests, typechecking, and stale-output checks with the existing generated-docs check - remove links to the Community Discussions repository ## Technical choices - Import the current documentation as a linear snapshot so the branch satisfies Builder's required-linear-history protection. - Keep the Markdown wrapper separate from the TypeScript generator at `scripts/docs/mcp-page.md`. - Generate through `packages/cli/local.js` so CLI guidance and its documentation are reviewed together. - Let `check:generated-docs` reject CLI changes that leave the committed MCP page stale. - After both GitHub release creation and package publication succeed, fast-forward the read-only `docs` branch to the immutable release tag commit. A divergent update fails instead of publishing a different revision. - Configure GitBook to publish `/docs` from the `docs` branch, not directly from `main`. - Exclude `/docs` from the repository-wide `oxfmt` scan so imported GitBook Markdown retains its established formatting; generator tests and stale-output checks still validate the MCP page. - Exclude `transcripts/` and GitHub Discussions from the migration. ## Todo - [x] Import documentation, navigation, includes, and assets under `/docs`. - [x] Generate the MCP page from the local CLI source. - [x] Move MCP generation and validation into Builder. - [x] Require MCP documentation updates alongside CLI changes. - [x] Publish released revisions through a read-only `docs` branch. - [x] Remove Community repository links from Builder and the migrated docs. - [x] Preserve and verify a final Community Git bundle locally. - [ ] Merge this pull request. - [ ] Let the next successful release create or advance the `docs` branch. - [ ] Repoint GitBook Git Sync to `webstudio-is/webstudio`, branch `docs`, root directory `/docs`. - [ ] Verify `docs.webstudio.is`, navigation, assets, anchors, and the MCP page in production. - [ ] Delete `webstudio-is/webstudio-community`. ## Verification - `pnpm check:generated-docs` - `pnpm lint` - `pnpm oxfmt --check` - `git diff --check origin/main...HEAD` - generator regression test demonstrated failing when the GitBook wrapper behavior was removed, then passing after restoration - no fixture inputs or outputs are affected ## Known limitation All documentation merged after the previous release waits for the next successful release before GitBook publishes it. This deliberately keeps the public MCP reference aligned with an installable CLI revision. Ref #5986 |
||
|
|
310166343b | first working version of designer in turborepo | ||
|
|
c19406ff56 | better testing cases | ||
|
|
5b6ee08a14 | add test cases | ||
|
|
9510684475 | breakpoints test cases | ||
|
|
0123c7598d | Create test-cases.md |